overrides_spec.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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 neq = helpers.neq
  6. local NIL = helpers.NIL
  7. local feed = helpers.feed
  8. local clear = helpers.clear
  9. local funcs = helpers.funcs
  10. local meths = helpers.meths
  11. local iswin = helpers.iswin
  12. local command = helpers.command
  13. local write_file = helpers.write_file
  14. local redir_exec = helpers.redir_exec
  15. local alter_slashes = helpers.alter_slashes
  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('\nabc', redir_exec('lua print("abc")'))
  34. eq('\nabc', redir_exec('luado print("abc")'))
  35. eq('\nabc', redir_exec('call luaeval("print(\'abc\')")'))
  36. write_file(fname, 'print("abc")')
  37. eq('\nabc', redir_exec('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('', redir_exec('luafile ' .. fname))
  49. eq('\nE5114: Error while converting print argument #2: [NULL]',
  50. redir_exec('lua print("foo", v_nilerr, "bar")'))
  51. eq('\nE5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc',
  52. redir_exec('lua print("foo", v_abcerr, "bar")'))
  53. eq('\nE5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>',
  54. redir_exec('lua print("foo", v_tblout, "bar")'))
  55. end)
  56. it('prints strings with NULs and NLs correctly', function()
  57. meths.set_option('more', true)
  58. eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n',
  59. redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\n")]]))
  60. eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT^@',
  61. redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]]))
  62. eq('\nT^@', redir_exec([[lua print("T\0")]]))
  63. eq('\nT\n', redir_exec([[lua print("T\n")]]))
  64. end)
  65. it('prints empty strings correctly', function()
  66. -- Regression: first test used to crash
  67. eq('', redir_exec('lua print("")'))
  68. eq('\n def', redir_exec('lua print("", "def")'))
  69. eq('\nabc ', redir_exec('lua print("abc", "")'))
  70. eq('\nabc def', redir_exec('lua print("abc", "", "def")'))
  71. end)
  72. end)
  73. describe('debug.debug', function()
  74. before_each(function()
  75. screen = Screen.new()
  76. screen:attach()
  77. screen:set_default_attr_ids({
  78. [0] = {bold=true, foreground=255},
  79. E = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
  80. cr = {bold = true, foreground = Screen.colors.SeaGreen4},
  81. })
  82. command("set display-=msgsep")
  83. end)
  84. it('works', function()
  85. command([[lua
  86. function Test(a)
  87. print(a)
  88. debug.debug()
  89. print(a * 100)
  90. end
  91. ]])
  92. feed(':lua Test()\n')
  93. screen:expect([[
  94. {0:~ }|
  95. {0:~ }|
  96. {0:~ }|
  97. {0:~ }|
  98. {0:~ }|
  99. {0:~ }|
  100. {0:~ }|
  101. {0:~ }|
  102. {0:~ }|
  103. {0:~ }|
  104. {0:~ }|
  105. {0:~ }|
  106. nil |
  107. lua_debug> ^ |
  108. ]])
  109. feed('print("TEST")\n')
  110. screen:expect([[
  111. {0:~ }|
  112. {0:~ }|
  113. {0:~ }|
  114. {0:~ }|
  115. {0:~ }|
  116. {0:~ }|
  117. {0:~ }|
  118. {0:~ }|
  119. {0:~ }|
  120. {0:~ }|
  121. nil |
  122. lua_debug> print("TEST") |
  123. TEST |
  124. lua_debug> ^ |
  125. ]])
  126. feed('<C-c>')
  127. screen:expect([[
  128. {0:~ }|
  129. {0:~ }|
  130. {0:~ }|
  131. {0:~ }|
  132. {0:~ }|
  133. {0:~ }|
  134. nil |
  135. lua_debug> print("TEST") |
  136. TEST |
  137. |
  138. {E:E5105: Error while calling lua chunk: [string "<VimL }|
  139. {E:compiled string>"]:5: attempt to perform arithmetic o}|
  140. {E:n local 'a' (a nil value)} |
  141. Interrupt: {cr:Press ENTER or type command to continue}^ |
  142. ]])
  143. feed('<C-l>:lua Test()\n')
  144. screen:expect([[
  145. {0:~ }|
  146. {0:~ }|
  147. {0:~ }|
  148. {0:~ }|
  149. {0:~ }|
  150. {0:~ }|
  151. {0:~ }|
  152. {0:~ }|
  153. {0:~ }|
  154. {0:~ }|
  155. {0:~ }|
  156. {0:~ }|
  157. nil |
  158. lua_debug> ^ |
  159. ]])
  160. feed('\n')
  161. screen:expect([[
  162. {0:~ }|
  163. {0:~ }|
  164. {0:~ }|
  165. {0:~ }|
  166. {0:~ }|
  167. {0:~ }|
  168. {0:~ }|
  169. {0:~ }|
  170. nil |
  171. lua_debug> |
  172. {E:E5105: Error while calling lua chunk: [string "<VimL }|
  173. {E:compiled string>"]:5: attempt to perform arithmetic o}|
  174. {E:n local 'a' (a nil value)} |
  175. {cr:Press ENTER or type command to continue}^ |
  176. ]])
  177. end)
  178. end)
  179. describe('package.path/package.cpath', function()
  180. local sl = alter_slashes
  181. local function get_new_paths(sufs, runtimepaths)
  182. runtimepaths = runtimepaths or meths.list_runtime_paths()
  183. local new_paths = {}
  184. local sep = package.config:sub(1, 1)
  185. for _, v in ipairs(runtimepaths) do
  186. for _, suf in ipairs(sufs) do
  187. new_paths[#new_paths + 1] = v .. sep .. 'lua' .. suf
  188. end
  189. end
  190. return new_paths
  191. end
  192. local function execute_lua(cmd, ...)
  193. return meths.execute_lua(cmd, {...})
  194. end
  195. local function eval_lua(expr, ...)
  196. return meths.execute_lua('return ' .. expr, {...})
  197. end
  198. local function set_path(which, value)
  199. return execute_lua('package[select(1, ...)] = select(2, ...)', which, value)
  200. end
  201. it('contains directories from &runtimepath on first invocation', function()
  202. local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'})
  203. local new_paths_str = table.concat(new_paths, ';')
  204. eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
  205. local new_cpaths = get_new_paths(iswin() and {'\\?.dll'} or {'/?.so'})
  206. local new_cpaths_str = table.concat(new_cpaths, ';')
  207. eq(new_cpaths_str, eval_lua('package.cpath'):sub(1, #new_cpaths_str))
  208. end)
  209. it('puts directories from &runtimepath always at the start', function()
  210. meths.set_option('runtimepath', 'a,b')
  211. local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a', 'b'})
  212. local new_paths_str = table.concat(new_paths, ';')
  213. eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
  214. set_path('path', sl'foo/?.lua;foo/?/init.lua;' .. new_paths_str)
  215. neq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
  216. command('set runtimepath+=c')
  217. new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a', 'b', 'c'})
  218. new_paths_str = table.concat(new_paths, ';')
  219. eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
  220. end)
  221. it('understands uncommon suffixes', function()
  222. set_path('cpath', './?/foo/bar/baz/x.nlua')
  223. meths.set_option('runtimepath', 'a')
  224. local new_paths = get_new_paths({'/?/foo/bar/baz/x.nlua'}, {'a'})
  225. local new_paths_str = table.concat(new_paths, ';')
  226. eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str))
  227. set_path('cpath', './yyy?zzz/x')
  228. meths.set_option('runtimepath', 'b')
  229. new_paths = get_new_paths({'/yyy?zzz/x'}, {'b'})
  230. new_paths_str = table.concat(new_paths, ';')
  231. eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str))
  232. set_path('cpath', './yyy?zzz/123?ghi/x')
  233. meths.set_option('runtimepath', 'b')
  234. new_paths = get_new_paths({'/yyy?zzz/123?ghi/x'}, {'b'})
  235. new_paths_str = table.concat(new_paths, ';')
  236. eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str))
  237. end)
  238. it('preserves empty items', function()
  239. local many_empty_path = ';;;;;;'
  240. local many_empty_cpath = ';;;;;;./?.luaso'
  241. set_path('path', many_empty_path)
  242. set_path('cpath', many_empty_cpath)
  243. meths.set_option('runtimepath', 'a')
  244. local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a'})
  245. local new_paths_str = table.concat(new_paths, ';')
  246. eq(new_paths_str .. ';' .. many_empty_path, eval_lua('package.path'))
  247. local new_cpaths = get_new_paths({'/?.luaso'}, {'a'})
  248. local new_cpaths_str = table.concat(new_cpaths, ';')
  249. eq(new_cpaths_str .. ';' .. many_empty_cpath, eval_lua('package.cpath'))
  250. end)
  251. it('preserves empty value', function()
  252. set_path('path', '')
  253. meths.set_option('runtimepath', 'a')
  254. local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a'})
  255. local new_paths_str = table.concat(new_paths, ';')
  256. eq(new_paths_str .. ';', eval_lua('package.path'))
  257. end)
  258. it('purges out all additions if runtimepath is set to empty', function()
  259. local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'})
  260. local new_paths_str = table.concat(new_paths, ';')
  261. local path = eval_lua('package.path')
  262. eq(new_paths_str, path:sub(1, #new_paths_str))
  263. local new_cpaths = get_new_paths(iswin() and {'\\?.dll'} or {'/?.so'})
  264. local new_cpaths_str = table.concat(new_cpaths, ';')
  265. local cpath = eval_lua('package.cpath')
  266. eq(new_cpaths_str, cpath:sub(1, #new_cpaths_str))
  267. meths.set_option('runtimepath', '')
  268. eq(path:sub(#new_paths_str + 2, -1), eval_lua('package.path'))
  269. eq(cpath:sub(#new_cpaths_str + 2, -1), eval_lua('package.cpath'))
  270. end)
  271. it('works with paths with escaped commas', function()
  272. meths.set_option('runtimepath', '\\,')
  273. local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {','})
  274. local new_paths_str = table.concat(new_paths, ';')
  275. eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
  276. end)
  277. it('ignores paths with semicolons', function()
  278. meths.set_option('runtimepath', 'foo;bar,\\,')
  279. local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {','})
  280. local new_paths_str = table.concat(new_paths, ';')
  281. eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str))
  282. end)
  283. end)