overrides_spec.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. -- Test for Vim overrides of lua built-ins
  2. local helpers = require('test.functional.helpers')(after_each)
  3. local Screen = require('test.functional.ui.screen')
  4. local eq = helpers.eq
  5. local NIL = helpers.NIL
  6. local feed = helpers.feed
  7. local clear = helpers.clear
  8. local funcs = helpers.funcs
  9. local meths = helpers.meths
  10. local iswin = helpers.iswin
  11. local command = helpers.command
  12. local write_file = helpers.write_file
  13. local exec_capture = helpers.exec_capture
  14. local exec_lua = helpers.exec_lua
  15. local pcall_err = helpers.pcall_err
  16. local screen
  17. local fname = 'Xtest-functional-lua-overrides-luafile'
  18. before_each(clear)
  19. after_each(function()
  20. os.remove(fname)
  21. end)
  22. describe('print', function()
  23. it('returns nothing', function()
  24. eq(NIL, funcs.luaeval('print("abc")'))
  25. eq(0, funcs.luaeval('select("#", print("abc"))'))
  26. end)
  27. it('allows catching printed text with :execute', function()
  28. eq('\nabc', funcs.execute('lua print("abc")'))
  29. eq('\nabc', funcs.execute('luado print("abc")'))
  30. eq('\nabc', funcs.execute('call luaeval("print(\'abc\')")'))
  31. write_file(fname, 'print("abc")')
  32. eq('\nabc', funcs.execute('luafile ' .. fname))
  33. eq('abc', exec_capture('lua print("abc")'))
  34. eq('abc', exec_capture('luado print("abc")'))
  35. eq('abc', exec_capture('call luaeval("print(\'abc\')")'))
  36. write_file(fname, 'print("abc")')
  37. eq('abc', exec_capture('luafile ' .. fname))
  38. end)
  39. it('handles errors in __tostring', function()
  40. write_file(fname, [[
  41. local meta_nilerr = { __tostring = function() error(nil) end }
  42. local meta_abcerr = { __tostring = function() error("abc") end }
  43. local meta_tblout = { __tostring = function() return {"TEST"} end }
  44. v_nilerr = setmetatable({}, meta_nilerr)
  45. v_abcerr = setmetatable({}, meta_abcerr)
  46. v_tblout = setmetatable({}, meta_tblout)
  47. ]])
  48. eq('', exec_capture('luafile ' .. fname))
  49. -- TODO(bfredl): these look weird, print() should not use "E5114:" style errors..
  50. eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: [NULL]',
  51. pcall_err(command, 'lua print("foo", v_nilerr, "bar")'))
  52. eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:0: abc',
  53. pcall_err(command, 'lua print("foo", v_abcerr, "bar")'))
  54. eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>',
  55. pcall_err(command, 'lua print("foo", v_tblout, "bar")'))
  56. end)
  57. it('coerces error values into strings', function()
  58. write_file(fname, [[
  59. function string_error() error("my mistake") end
  60. function number_error() error(1234) end
  61. function nil_error() error(nil) end
  62. function table_error() error({message = "my mistake"}) end
  63. function custom_error()
  64. local err = {message = "my mistake", code = 11234}
  65. setmetatable(err, {
  66. __tostring = function(t)
  67. return "Internal Error [" .. t.code .. "] " .. t.message
  68. end
  69. })
  70. error(err)
  71. end
  72. function bad_custom_error()
  73. local err = {message = "my mistake", code = 11234}
  74. setmetatable(err, {
  75. -- intentionally not a function, downstream programmer has made an mistake
  76. __tostring = "Internal Error [" .. err.code .. "] " .. err.message
  77. })
  78. error(err)
  79. end
  80. ]])
  81. eq('', exec_capture('luafile ' .. fname))
  82. eq('Vim(lua):E5108: Error executing lua Xtest-functional-lua-overrides-luafile:0: my mistake',
  83. pcall_err(command, 'lua string_error()'))
  84. eq('Vim(lua):E5108: Error executing lua Xtest-functional-lua-overrides-luafile:0: 1234',
  85. pcall_err(command, 'lua number_error()'))
  86. eq('Vim(lua):E5108: Error executing lua [NULL]',
  87. pcall_err(command, 'lua nil_error()'))
  88. eq('Vim(lua):E5108: Error executing lua [NULL]',
  89. pcall_err(command, 'lua table_error()'))
  90. eq('Vim(lua):E5108: Error executing lua Internal Error [11234] my mistake',
  91. pcall_err(command, 'lua custom_error()'))
  92. eq('Vim(lua):E5108: Error executing lua [NULL]',
  93. pcall_err(command, 'lua bad_custom_error()'))
  94. end)
  95. it('prints strings with NULs and NLs correctly', function()
  96. meths.set_option('more', true)
  97. eq('abc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n',
  98. exec_capture([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\n")]]))
  99. eq('abc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT^@',
  100. exec_capture([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]]))
  101. eq('T^@', exec_capture([[lua print("T\0")]]))
  102. eq('T\n', exec_capture([[lua print("T\n")]]))
  103. end)
  104. it('prints empty strings correctly', function()
  105. -- Regression: first test used to crash
  106. eq('', exec_capture('lua print("")'))
  107. eq(' def', exec_capture('lua print("", "def")'))
  108. eq('abc ', exec_capture('lua print("abc", "")'))
  109. eq('abc def', exec_capture('lua print("abc", "", "def")'))
  110. end)
  111. it('defers printing in luv event handlers', function()
  112. exec_lua([[
  113. local cmd = ...
  114. function test()
  115. local timer = vim.loop.new_timer()
  116. local done = false
  117. timer:start(10, 0, function()
  118. print("very fast")
  119. timer:close()
  120. done = true
  121. end)
  122. -- be kind to slow travis OS X jobs:
  123. -- loop until we know for sure the callback has been executed
  124. while not done do
  125. os.execute(cmd)
  126. vim.loop.run("nowait") -- fake os_breakcheck()
  127. end
  128. print("very slow")
  129. vim.api.nvim_command("sleep 1m") -- force deferred event processing
  130. end
  131. ]], (iswin() and "timeout 1") or "sleep 0.1")
  132. eq('very slow\nvery fast', exec_capture('lua test()'))
  133. end)
  134. end)
  135. describe('debug.debug', function()
  136. before_each(function()
  137. screen = Screen.new()
  138. screen:attach()
  139. screen:set_default_attr_ids({
  140. [0] = {bold=true, foreground=255},
  141. E = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
  142. cr = {bold = true, foreground = Screen.colors.SeaGreen4},
  143. })
  144. command("set display-=msgsep")
  145. end)
  146. it('works', function()
  147. command([[lua
  148. function Test(a)
  149. print(a)
  150. debug.debug()
  151. print(a * 100)
  152. end
  153. ]])
  154. feed(':lua Test()\n')
  155. screen:expect([[
  156. {0:~ }|
  157. {0:~ }|
  158. {0:~ }|
  159. {0:~ }|
  160. {0:~ }|
  161. {0:~ }|
  162. {0:~ }|
  163. {0:~ }|
  164. {0:~ }|
  165. {0:~ }|
  166. {0:~ }|
  167. {0:~ }|
  168. nil |
  169. lua_debug> ^ |
  170. ]])
  171. feed('print("TEST")\n')
  172. screen:expect([[
  173. {0:~ }|
  174. {0:~ }|
  175. {0:~ }|
  176. {0:~ }|
  177. {0:~ }|
  178. {0:~ }|
  179. {0:~ }|
  180. {0:~ }|
  181. {0:~ }|
  182. {0:~ }|
  183. nil |
  184. lua_debug> print("TEST") |
  185. TEST |
  186. lua_debug> ^ |
  187. ]])
  188. feed('<C-c>')
  189. screen:expect{grid=[[
  190. {0:~ }|
  191. {0:~ }|
  192. {0:~ }|
  193. {0:~ }|
  194. nil |
  195. lua_debug> print("TEST") |
  196. TEST |
  197. |
  198. {E:E5108: Error executing lua [string ":lua"]:5: attempt}|
  199. {E: to perform arithmetic on local 'a' (a nil value)} |
  200. {E:stack traceback:} |
  201. {E: [string ":lua"]:5: in function 'Test'} |
  202. {E: [string ":lua"]:1: in main chunk} |
  203. Interrupt: {cr:Press ENTER or type command to continue}^ |
  204. ]]}
  205. feed('<C-l>:lua Test()\n')
  206. screen:expect([[
  207. {0:~ }|
  208. {0:~ }|
  209. {0:~ }|
  210. {0:~ }|
  211. {0:~ }|
  212. {0:~ }|
  213. {0:~ }|
  214. {0:~ }|
  215. {0:~ }|
  216. {0:~ }|
  217. {0:~ }|
  218. {0:~ }|
  219. nil |
  220. lua_debug> ^ |
  221. ]])
  222. feed('\n')
  223. screen:expect{grid=[[
  224. {0:~ }|
  225. {0:~ }|
  226. {0:~ }|
  227. {0:~ }|
  228. {0:~ }|
  229. {0:~ }|
  230. nil |
  231. lua_debug> |
  232. {E:E5108: Error executing lua [string ":lua"]:5: attempt}|
  233. {E: to perform arithmetic on local 'a' (a nil value)} |
  234. {E:stack traceback:} |
  235. {E: [string ":lua"]:5: in function 'Test'} |
  236. {E: [string ":lua"]:1: in main chunk} |
  237. {cr:Press ENTER or type command to continue}^ |
  238. ]]}
  239. end)
  240. it("can be safely exited with 'cont'", function()
  241. feed('<cr>')
  242. feed(':lua debug.debug() print("x")<cr>')
  243. screen:expect{grid=[[
  244. |
  245. {0:~ }|
  246. {0:~ }|
  247. {0:~ }|
  248. {0:~ }|
  249. {0:~ }|
  250. {0:~ }|
  251. {0:~ }|
  252. {0:~ }|
  253. {0:~ }|
  254. {0:~ }|
  255. {0:~ }|
  256. {0:~ }|
  257. lua_debug> ^ |
  258. ]]}
  259. feed("conttt<cr>") -- misspelled cont; invalid syntax
  260. screen:expect{grid=[[
  261. {0:~ }|
  262. {0:~ }|
  263. {0:~ }|
  264. {0:~ }|
  265. {0:~ }|
  266. {0:~ }|
  267. {0:~ }|
  268. {0:~ }|
  269. {0:~ }|
  270. {0:~ }|
  271. lua_debug> conttt |
  272. {E:E5115: Error while loading debug string: (debug comma}|
  273. {E:nd):1: '=' expected near '<eof>'} |
  274. lua_debug> ^ |
  275. ]]}
  276. feed("cont<cr>") -- exactly "cont", exit now
  277. screen:expect{grid=[[
  278. {0:~ }|
  279. {0:~ }|
  280. {0:~ }|
  281. {0:~ }|
  282. {0:~ }|
  283. {0:~ }|
  284. {0:~ }|
  285. {0:~ }|
  286. lua_debug> conttt |
  287. {E:E5115: Error while loading debug string: (debug comma}|
  288. {E:nd):1: '=' expected near '<eof>'} |
  289. lua_debug> cont |
  290. x |
  291. {cr:Press ENTER or type command to continue}^ |
  292. ]]}
  293. feed('<cr>')
  294. screen:expect{grid=[[
  295. ^ |
  296. {0:~ }|
  297. {0:~ }|
  298. {0:~ }|
  299. {0:~ }|
  300. {0:~ }|
  301. {0:~ }|
  302. {0:~ }|
  303. {0:~ }|
  304. {0:~ }|
  305. {0:~ }|
  306. {0:~ }|
  307. {0:~ }|
  308. |
  309. ]]}
  310. end)
  311. end)
  312. describe('os.getenv', function()
  313. it('returns nothing for undefined env var', function()
  314. eq(NIL, funcs.luaeval('os.getenv("XTEST_1")'))
  315. end)
  316. it('returns env var set by the parent process', function()
  317. local value = 'foo'
  318. clear({env = {['XTEST_1']=value}})
  319. eq(value, funcs.luaeval('os.getenv("XTEST_1")'))
  320. end)
  321. it('returns env var set by let', function()
  322. local value = 'foo'
  323. meths.command('let $XTEST_1 = "'..value..'"')
  324. eq(value, funcs.luaeval('os.getenv("XTEST_1")'))
  325. end)
  326. end)