overrides_spec.lua 13 KB

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