diff options
Diffstat (limited to 'test/functional/lua/overrides_spec.lua')
-rw-r--r-- | test/functional/lua/overrides_spec.lua | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua new file mode 100644 index 0000000000..8ca5fe57ba --- /dev/null +++ b/test/functional/lua/overrides_spec.lua @@ -0,0 +1,301 @@ +-- Test for Vim overrides of lua built-ins +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') + +local eq = helpers.eq +local neq = helpers.neq +local NIL = helpers.NIL +local feed = helpers.feed +local clear = helpers.clear +local funcs = helpers.funcs +local meths = helpers.meths +local iswin = helpers.iswin +local command = helpers.command +local write_file = helpers.write_file +local redir_exec = helpers.redir_exec +local alter_slashes = helpers.alter_slashes + +local screen + +local fname = 'Xtest-functional-lua-overrides-luafile' + +before_each(clear) + +after_each(function() + os.remove(fname) +end) + +describe('print', function() + it('returns nothing', function() + eq(NIL, funcs.luaeval('print("abc")')) + eq(0, funcs.luaeval('select("#", print("abc"))')) + end) + it('allows catching printed text with :execute', function() + eq('\nabc', funcs.execute('lua print("abc")')) + eq('\nabc', funcs.execute('luado print("abc")')) + eq('\nabc', funcs.execute('call luaeval("print(\'abc\')")')) + write_file(fname, 'print("abc")') + eq('\nabc', funcs.execute('luafile ' .. fname)) + + eq('\nabc', redir_exec('lua print("abc")')) + eq('\nabc', redir_exec('luado print("abc")')) + eq('\nabc', redir_exec('call luaeval("print(\'abc\')")')) + write_file(fname, 'print("abc")') + eq('\nabc', redir_exec('luafile ' .. fname)) + end) + it('handles errors in __tostring', function() + write_file(fname, [[ + local meta_nilerr = { __tostring = function() error(nil) end } + local meta_abcerr = { __tostring = function() error("abc") end } + local meta_tblout = { __tostring = function() return {"TEST"} end } + v_nilerr = setmetatable({}, meta_nilerr) + v_abcerr = setmetatable({}, meta_abcerr) + v_tblout = setmetatable({}, meta_tblout) + ]]) + eq('', redir_exec('luafile ' .. fname)) + eq('\nE5114: Error while converting print argument #2: [NULL]', + redir_exec('lua print("foo", v_nilerr, "bar")')) + eq('\nE5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc', + redir_exec('lua print("foo", v_abcerr, "bar")')) + eq('\nE5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>', + redir_exec('lua print("foo", v_tblout, "bar")')) + end) + it('prints strings with NULs and NLs correctly', function() + meths.set_option('more', true) + eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT\n', + redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\n")]])) + eq('\nabc ^@ def\nghi^@^@^@jkl\nTEST\n\n\nT^@', + redir_exec([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]])) + eq('\nT^@', redir_exec([[lua print("T\0")]])) + eq('\nT\n', redir_exec([[lua print("T\n")]])) + end) + it('prints empty strings correctly', function() + -- Regression: first test used to crash + eq('', redir_exec('lua print("")')) + eq('\n def', redir_exec('lua print("", "def")')) + eq('\nabc ', redir_exec('lua print("abc", "")')) + eq('\nabc def', redir_exec('lua print("abc", "", "def")')) + end) +end) + +describe('debug.debug', function() + before_each(function() + screen = Screen.new() + screen:attach() + screen:set_default_attr_ids({ + [0] = {bold=true, foreground=255}, + E = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, + cr = {bold = true, foreground = Screen.colors.SeaGreen4}, + }) + end) + it('works', function() + command([[lua + function Test(a) + print(a) + debug.debug() + print(a * 100) + end + ]]) + feed(':lua Test()\n') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> ^ | + ]]) + feed('print("TEST")\n') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> print("TEST") | + TEST | + lua_debug> ^ | + ]]) + feed('<C-c>') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> print("TEST") | + TEST | + | + {E:E5105: Error while calling lua chunk: [string "<VimL }| + {E:compiled string>"]:5: attempt to perform arithmetic o}| + {E:n local 'a' (a nil value)} | + Interrupt: {cr:Press ENTER or type command to continue}^ | + ]]) + feed('<C-l>:lua Test()\n') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> ^ | + ]]) + feed('\n') + screen:expect([[ + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + nil | + lua_debug> | + {E:E5105: Error while calling lua chunk: [string "<VimL }| + {E:compiled string>"]:5: attempt to perform arithmetic o}| + {E:n local 'a' (a nil value)} | + {cr:Press ENTER or type command to continue}^ | + ]]) + end) +end) + +describe('package.path/package.cpath', function() + local sl = alter_slashes + + local function get_new_paths(sufs, runtimepaths) + runtimepaths = runtimepaths or meths.list_runtime_paths() + local new_paths = {} + local sep = package.config:sub(1, 1) + for _, v in ipairs(runtimepaths) do + for _, suf in ipairs(sufs) do + new_paths[#new_paths + 1] = v .. sep .. 'lua' .. suf + end + end + return new_paths + end + local function execute_lua(cmd, ...) + return meths.execute_lua(cmd, {...}) + end + local function eval_lua(expr, ...) + return meths.execute_lua('return ' .. expr, {...}) + end + local function set_path(which, value) + return execute_lua('package[select(1, ...)] = select(2, ...)', which, value) + end + + it('contains directories from &runtimepath on first invocation', function() + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + + local new_cpaths = get_new_paths(iswin() and {'\\?.dll'} or {'/?.so'}) + local new_cpaths_str = table.concat(new_cpaths, ';') + eq(new_cpaths_str, eval_lua('package.cpath'):sub(1, #new_cpaths_str)) + end) + it('puts directories from &runtimepath always at the start', function() + meths.set_option('runtimepath', 'a,b') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a', 'b'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + + set_path('path', sl'foo/?.lua;foo/?/init.lua;' .. new_paths_str) + + neq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + + command('set runtimepath+=c') + new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a', 'b', 'c'}) + new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + end) + it('understands uncommon suffixes', function() + set_path('cpath', './?/foo/bar/baz/x.nlua') + meths.set_option('runtimepath', 'a') + local new_paths = get_new_paths({'/?/foo/bar/baz/x.nlua'}, {'a'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str)) + + set_path('cpath', './yyy?zzz/x') + meths.set_option('runtimepath', 'b') + new_paths = get_new_paths({'/yyy?zzz/x'}, {'b'}) + new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str)) + + set_path('cpath', './yyy?zzz/123?ghi/x') + meths.set_option('runtimepath', 'b') + new_paths = get_new_paths({'/yyy?zzz/123?ghi/x'}, {'b'}) + new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.cpath'):sub(1, #new_paths_str)) + end) + it('preserves empty items', function() + local many_empty_path = ';;;;;;' + local many_empty_cpath = ';;;;;;./?.luaso' + set_path('path', many_empty_path) + set_path('cpath', many_empty_cpath) + meths.set_option('runtimepath', 'a') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str .. ';' .. many_empty_path, eval_lua('package.path')) + local new_cpaths = get_new_paths({'/?.luaso'}, {'a'}) + local new_cpaths_str = table.concat(new_cpaths, ';') + eq(new_cpaths_str .. ';' .. many_empty_cpath, eval_lua('package.cpath')) + end) + it('preserves empty value', function() + set_path('path', '') + meths.set_option('runtimepath', 'a') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {'a'}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str .. ';', eval_lua('package.path')) + end) + it('purges out all additions if runtimepath is set to empty', function() + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}) + local new_paths_str = table.concat(new_paths, ';') + local path = eval_lua('package.path') + eq(new_paths_str, path:sub(1, #new_paths_str)) + + local new_cpaths = get_new_paths(iswin() and {'\\?.dll'} or {'/?.so'}) + local new_cpaths_str = table.concat(new_cpaths, ';') + local cpath = eval_lua('package.cpath') + eq(new_cpaths_str, cpath:sub(1, #new_cpaths_str)) + + meths.set_option('runtimepath', '') + eq(path:sub(#new_paths_str + 2, -1), eval_lua('package.path')) + eq(cpath:sub(#new_cpaths_str + 2, -1), eval_lua('package.cpath')) + end) + it('works with paths with escaped commas', function() + meths.set_option('runtimepath', '\\,') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {','}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + end) + it('ignores paths with semicolons', function() + meths.set_option('runtimepath', 'foo;bar,\\,') + local new_paths = get_new_paths(sl{'/?.lua', '/?/init.lua'}, {','}) + local new_paths_str = table.concat(new_paths, ';') + eq(new_paths_str, eval_lua('package.path'):sub(1, #new_paths_str)) + end) +end) |