diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/functional/api/vim_spec.lua | 12 | ||||
-rw-r--r-- | test/functional/helpers.lua | 19 | ||||
-rw-r--r-- | test/functional/legacy/display_spec.lua | 31 | ||||
-rw-r--r-- | test/functional/legacy/visual_mode_spec.lua | 42 | ||||
-rw-r--r-- | test/functional/lua/buffer_updates_spec.lua | 18 | ||||
-rw-r--r-- | test/functional/lua/commands_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/lua/luaeval_spec.lua | 4 | ||||
-rw-r--r-- | test/functional/lua/treesitter_spec.lua | 102 | ||||
-rw-r--r-- | test/functional/lua/vim_spec.lua | 252 | ||||
-rw-r--r-- | test/functional/normal/meta_key_spec.lua | 22 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 12 | ||||
-rw-r--r-- | test/functional/ui/decorations_spec.lua | 118 | ||||
-rw-r--r-- | test/functional/ui/float_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/viml/errorlist_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/visual/meta_key_spec.lua | 22 | ||||
-rw-r--r-- | test/helpers.lua | 45 | ||||
-rw-r--r-- | test/symbolic/klee/nvim/charset.c | 4 |
17 files changed, 574 insertions, 135 deletions
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 72e810e3e4..246ee5c86c 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -449,19 +449,19 @@ describe('API', function() end) it('reports errors', function() - eq([[Error loading lua: [string "<nvim>"]:1: '=' expected near '+']], + eq([[Error loading lua: [string "<nvim>"]:0: '=' expected near '+']], pcall_err(meths.exec_lua, 'a+*b', {})) - eq([[Error loading lua: [string "<nvim>"]:1: unexpected symbol near '1']], + eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol near '1']], pcall_err(meths.exec_lua, '1+2', {})) - eq([[Error loading lua: [string "<nvim>"]:1: unexpected symbol]], + eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol]], pcall_err(meths.exec_lua, 'aa=bb\0', {})) - eq([[Error executing lua: [string "<nvim>"]:1: attempt to call global 'bork' (a nil value)]], + eq([[Error executing lua: [string "<nvim>"]:0: attempt to call global 'bork' (a nil value)]], pcall_err(meths.exec_lua, 'bork()', {})) - eq('Error executing lua: [string "<nvim>"]:1: did\nthe\nfail', + eq('Error executing lua: [string "<nvim>"]:0: did\nthe\nfail', pcall_err(meths.exec_lua, 'error("did\\nthe\\nfail")', {})) end) @@ -605,7 +605,7 @@ describe('API', function() end) it('vim.paste() failure', function() nvim('exec_lua', 'vim.paste = (function(lines, phase) error("fake fail") end)', {}) - eq([[Error executing lua: [string "<nvim>"]:1: fake fail]], + eq([[Error executing lua: [string "<nvim>"]:0: fake fail]], pcall_err(request, 'nvim_paste', 'line 1\nline 2\nline 3', false, 1)) end) end) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index e4fb95442c..99cbf30c7c 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -22,6 +22,7 @@ local ok = global_helpers.ok local sleep = global_helpers.sleep local tbl_contains = global_helpers.tbl_contains local write_file = global_helpers.write_file +local fail = global_helpers.fail local module = { NIL = mpack.NIL, @@ -592,6 +593,24 @@ function module.expect_any(contents) return ok(nil ~= string.find(module.curbuf_contents(), contents, 1, true)) end +function module.expect_events(expected, received, kind) + local inspect = require'vim.inspect' + if not pcall(eq, expected, received) then + local msg = 'unexpected '..kind..' received.\n\n' + + msg = msg .. 'received events:\n' + for _, e in ipairs(received) do + msg = msg .. ' ' .. inspect(e) .. ';\n' + end + msg = msg .. '\nexpected events:\n' + for _, e in ipairs(expected) do + msg = msg .. ' ' .. inspect(e) .. ';\n' + end + fail(msg) + end + return received +end + -- Checks that the Nvim session did not terminate. function module.assert_alive() assert(2 == module.eval('1+1'), 'crash? request failed') diff --git a/test/functional/legacy/display_spec.lua b/test/functional/legacy/display_spec.lua new file mode 100644 index 0000000000..aafcda67dc --- /dev/null +++ b/test/functional/legacy/display_spec.lua @@ -0,0 +1,31 @@ +local helpers = require('test.functional.helpers')(after_each) + +local Screen = require('test.functional.ui.screen') +local clear = helpers.clear +local wait = helpers.wait +local feed = helpers.feed +local feed_command = helpers.feed_command + +describe('display', function() + local screen + + it('scroll when modified at topline', function() + clear() + screen = Screen.new(20, 4) + screen:attach() + screen:set_default_attr_ids({ + [1] = {bold = true}, + }) + + feed_command([[call setline(1, repeat('a', 21))]]) + wait() + feed('O') + screen:expect([[ + ^ | + aaaaaaaaaaaaaaaaaaaa| + a | + {1:-- INSERT --} | + ]]) + end) +end) + diff --git a/test/functional/legacy/visual_mode_spec.lua b/test/functional/legacy/visual_mode_spec.lua new file mode 100644 index 0000000000..c8e83ed649 --- /dev/null +++ b/test/functional/legacy/visual_mode_spec.lua @@ -0,0 +1,42 @@ +-- Test visual line mode selection redraw after scrolling + +local helpers = require('test.functional.helpers')(after_each) + +local Screen = require('test.functional.ui.screen') +local call = helpers.call +local clear = helpers.clear +local feed = helpers.feed +local feed_command = helpers.feed_command +local funcs = helpers.funcs +local meths = helpers.meths +local eq = helpers.eq + +describe('visual line mode', function() + local screen + + it('redraws properly after scrolling with matchparen loaded and scrolloff=1', function() + clear{args={'-u', 'NORC'}} + screen = Screen.new(30, 7) + screen:attach() + screen:set_default_attr_ids({ + [1] = {bold = true}, + [2] = {background = Screen.colors.LightGrey}, + }) + + eq(1, meths.get_var('loaded_matchparen')) + feed_command('set scrolloff=1') + funcs.setline(1, {'a', 'b', 'c', 'd', 'e', '', '{', '}', '{', 'f', 'g', '}'}) + call('cursor', 5, 1) + + feed('V<c-d><c-d>') + screen:expect([[ + {2:{} | + {2:}} | + {2:{} | + {2:f} | + ^g | + } | + {1:-- VISUAL LINE --} | + ]]) + end) +end) diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua index fa31880782..7e4de7c39a 100644 --- a/test/functional/lua/buffer_updates_spec.lua +++ b/test/functional/lua/buffer_updates_spec.lua @@ -1,8 +1,6 @@ -- Test suite for testing interactions with API bindings local helpers = require('test.functional.helpers')(after_each) -local inspect = require'vim.inspect' - local command = helpers.command local meths = helpers.meths local funcs = helpers.funcs @@ -12,6 +10,7 @@ local fail = helpers.fail local exec_lua = helpers.exec_lua local feed = helpers.feed local deepcopy = helpers.deepcopy +local expect_events = helpers.expect_events local origlines = {"original line 1", "original line 2", @@ -297,20 +296,7 @@ describe('lua: nvim_buf_attach on_bytes', function() local verify_name = "test1" local function check_events(expected) local events = exec_lua("return get_events(...)" ) - - if not pcall(eq, expected, events) then - local msg = 'unexpected byte updates received.\n\n' - - msg = msg .. 'received events:\n' - for _, e in ipairs(events) do - msg = msg .. ' ' .. inspect(e) .. ';\n' - end - msg = msg .. '\nexpected events:\n' - for _, e in ipairs(expected) do - msg = msg .. ' ' .. inspect(e) .. ';\n' - end - fail(msg) - end + expect_events(expected, events, "byte updates") if not verify then return diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua index cbc3aee557..f2a1b7dede 100644 --- a/test/functional/lua/commands_spec.lua +++ b/test/functional/lua/commands_spec.lua @@ -43,7 +43,7 @@ describe(':lua command', function() eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false)) end) it('throws catchable errors', function() - eq([[Vim(lua):E5107: Error loading lua [string ":lua"]:1: unexpected symbol near ')']], + eq([[Vim(lua):E5107: Error loading lua [string ":lua"]:0: unexpected symbol near ')']], pcall_err(command, 'lua ()')) eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: TEST]], exc_exec('lua error("TEST")')) diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua index 75966393b1..2ec48777fd 100644 --- a/test/functional/lua/luaeval_spec.lua +++ b/test/functional/lua/luaeval_spec.lua @@ -477,14 +477,14 @@ describe('v:lua', function() eq(NIL, eval('v:lua.mymod.noisy("eval")')) eq("hey eval", meths.get_current_line()) - eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:10: attempt to call global 'nonexistent' (a nil value)", + eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)", pcall_err(eval, 'v:lua.mymod.crashy()')) end) it('works in :call', function() command(":call v:lua.mymod.noisy('command')") eq("hey command", meths.get_current_line()) - eq("Vim(call):E5108: Error executing lua [string \"<nvim>\"]:10: attempt to call global 'nonexistent' (a nil value)", + eq("Vim(call):E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)", pcall_err(command, 'call v:lua.mymod.crashy()')) end) diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua index 74ae6cde2b..3526b64395 100644 --- a/test/functional/lua/treesitter_spec.lua +++ b/test/functional/lua/treesitter_spec.lua @@ -15,17 +15,16 @@ before_each(clear) describe('treesitter API', function() -- error tests not requiring a parser library it('handles missing language', function() - eq("Error executing lua: .../language.lua: no parser for 'borklang' language, see :help treesitter-parsers", + eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers", pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')")) -- actual message depends on platform matches("Error executing lua: Failed to load parser: uv_dlopen: .+", pcall_err(exec_lua, "parser = vim.treesitter.require_language('borklang', 'borkbork.so')")) - eq("Error executing lua: .../language.lua: no parser for 'borklang' language, see :help treesitter-parsers", + eq("Error executing lua: .../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers", pcall_err(exec_lua, "parser = vim.treesitter.inspect_language('borklang')")) end) - end) describe('treesitter API with C parser', function() @@ -186,6 +185,16 @@ void ui_refresh(void) (field_expression argument: (identifier) @fieldarg) ]] + it("supports runtime queries", function() + if not check_parser() then return end + + local ret = exec_lua [[ + return require"vim.treesitter.query".get_query("c", "highlights").captures[1] + ]] + + eq('variable', ret) + end) + it('support query and iter by capture', function() if not check_parser() then return end @@ -420,9 +429,10 @@ static int nlua_schedule(lua_State *const lstate) ]]} exec_lua([[ + local parser = vim.treesitter.get_parser(0, "c") local highlighter = vim.treesitter.highlighter local query = ... - test_hl = highlighter.new(query, 0, "c") + test_hl = highlighter.new(parser, query) ]], hl_query) screen:expect{grid=[[ {2:/// Schedule Lua callback on main loop's event queue} | @@ -559,6 +569,72 @@ static int nlua_schedule(lua_State *const lstate) ]]} end) + it("supports highlighting with custom parser", function() + if not check_parser() then return end + + local screen = Screen.new(65, 18) + screen:attach() + screen:set_default_attr_ids({ {bold = true, foreground = Screen.colors.SeaGreen4} }) + + insert(test_text) + + screen:expect{ grid= [[ + int width = INT_MAX, height = INT_MAX; | + bool ext_widgets[kUIExtCount]; | + for (UIExtension i = 0; (int)i < kUIExtCount; i++) { | + ext_widgets[i] = true; | + } | + | + bool inclusive = ui_override(); | + for (size_t i = 0; i < ui_count; i++) { | + UI *ui = uis[i]; | + width = MIN(ui->width, width); | + height = MIN(ui->height, height); | + foo = BAR(ui->bazaar, bazaar); | + for (UIExtension j = 0; (int)j < kUIExtCount; j++) { | + ext_widgets[j] &= (ui->ui_ext[j] || inclusive); | + } | + } | + ^} | + | + ]] } + + exec_lua([[ + parser = vim.treesitter.get_parser(0, "c") + query = vim.treesitter.parse_query("c", "(declaration) @decl") + + local nodes = {} + for _, node in query:iter_captures(parser:parse():root(), 0, 0, 19) do + table.insert(nodes, node) + end + + parser:set_included_ranges(nodes) + + local hl = vim.treesitter.highlighter.new(parser, "(identifier) @type") + ]]) + + screen:expect{ grid = [[ + int {1:width} = {1:INT_MAX}, {1:height} = {1:INT_MAX}; | + bool {1:ext_widgets}[{1:kUIExtCount}]; | + for (UIExtension {1:i} = 0; (int)i < kUIExtCount; i++) { | + ext_widgets[i] = true; | + } | + | + bool {1:inclusive} = {1:ui_override}(); | + for (size_t {1:i} = 0; i < ui_count; i++) { | + UI *{1:ui} = {1:uis}[{1:i}]; | + width = MIN(ui->width, width); | + height = MIN(ui->height, height); | + foo = BAR(ui->bazaar, bazaar); | + for (UIExtension {1:j} = 0; (int)j < kUIExtCount; j++) { | + ext_widgets[j] &= (ui->ui_ext[j] || inclusive); | + } | + } | + ^} | + | + ]] } + end) + it('inspects language', function() if not check_parser() then return end @@ -604,23 +680,29 @@ static int nlua_schedule(lua_State *const lstate) insert(test_text) - local res = exec_lua([[ + local res = exec_lua [[ parser = vim.treesitter.get_parser(0, "c") return { parser:parse():root():range() } - ]]) + ]] eq({0, 0, 19, 0}, res) -- The following sets the included ranges for the current parser -- As stated here, this only includes the function (thus the whole buffer, without the last line) - local res2 = exec_lua([[ + local res2 = exec_lua [[ local root = parser:parse():root() parser:set_included_ranges({root:child(0)}) parser.valid = false return { parser:parse():root():range() } - ]]) + ]] eq({0, 0, 18, 1}, res2) + + local range = exec_lua [[ + return parser:included_ranges() + ]] + + eq(range, { { 0, 0, 18, 1 } }) end) it("allows to set complex ranges", function() if not check_parser() then return end @@ -628,7 +710,7 @@ static int nlua_schedule(lua_State *const lstate) insert(test_text) - local res = exec_lua([[ + local res = exec_lua [[ parser = vim.treesitter.get_parser(0, "c") query = vim.treesitter.parse_query("c", "(declaration) @decl") @@ -646,7 +728,7 @@ static int nlua_schedule(lua_State *const lstate) table.insert(res, { root:named_child(i):range() }) end return res - ]]) + ]] eq({ { 2, 2, 2, 40 }, diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index 61447f1152..1cbf6b21e3 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -4,13 +4,14 @@ local Screen = require('test.functional.ui.screen') local funcs = helpers.funcs local meths = helpers.meths +local dedent = helpers.dedent local command = helpers.command local clear = helpers.clear local eq = helpers.eq local ok = helpers.ok local eval = helpers.eval local feed = helpers.feed -local pcall_err = helpers.pcall_err +local pcall_err_withfile = helpers.pcall_err_withfile local exec_lua = helpers.exec_lua local matches = helpers.matches local source = helpers.source @@ -128,8 +129,8 @@ describe('lua stdlib', function() eq(false, funcs.luaeval('vim.startswith("123", "2")')) eq(false, funcs.luaeval('vim.startswith("123", "1234")')) - eq("string", type(pcall_err(funcs.luaeval, 'vim.startswith("123", nil)'))) - eq("string", type(pcall_err(funcs.luaeval, 'vim.startswith(nil, "123")'))) + eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.startswith("123", nil)'))) + eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.startswith(nil, "123")'))) end) it('vim.endswith', function() @@ -142,8 +143,8 @@ describe('lua stdlib', function() eq(false, funcs.luaeval('vim.endswith("123", "2")')) eq(false, funcs.luaeval('vim.endswith("123", "1234")')) - eq("string", type(pcall_err(funcs.luaeval, 'vim.endswith("123", nil)'))) - eq("string", type(pcall_err(funcs.luaeval, 'vim.endswith(nil, "123")'))) + eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.endswith("123", nil)'))) + eq("string", type(pcall_err_withfile(funcs.luaeval, 'vim.endswith(nil, "123")'))) end) it("vim.str_utfindex/str_byteindex", function() @@ -182,10 +183,10 @@ describe('lua stdlib', function() eq({"yy","xx"}, exec_lua("return test_table")) -- Validates args. - eq('Error executing lua: vim.schedule: expected function', - pcall_err(exec_lua, "vim.schedule('stringly')")) - eq('Error executing lua: vim.schedule: expected function', - pcall_err(exec_lua, "vim.schedule()")) + eq('.../helpers.lua:0: Error executing lua: vim.schedule: expected function', + pcall_err_withfile(exec_lua, "vim.schedule('stringly')")) + eq('.../helpers.lua:0: Error executing lua: vim.schedule: expected function', + pcall_err_withfile(exec_lua, "vim.schedule()")) exec_lua([[ vim.schedule(function() @@ -257,17 +258,29 @@ describe('lua stdlib', function() } for _, t in ipairs(loops) do - matches(".*Infinite loop detected", pcall_err(split, t[1], t[2])) + matches(".*Infinite loop detected", pcall_err_withfile(split, t[1], t[2])) end -- Validates args. eq(true, pcall(split, 'string', 'string')) - eq('Error executing lua: .../shared.lua: s: expected string, got number', - pcall_err(split, 1, 'string')) - eq('Error executing lua: .../shared.lua: sep: expected string, got number', - pcall_err(split, 'string', 1)) - eq('Error executing lua: .../shared.lua: plain: expected boolean, got number', - pcall_err(split, 'string', 'string', 1)) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: shared.lua:0: s: expected string, got number + stack traceback: + shared.lua:0: in function 'gsplit' + shared.lua:0: in function <shared.lua:0>]]), + pcall_err_withfile(split, 1, 'string')) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: shared.lua:0: sep: expected string, got number + stack traceback: + shared.lua:0: in function 'gsplit' + shared.lua:0: in function <shared.lua:0>]]), + pcall_err_withfile(split, 'string', 1)) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: shared.lua:0: plain: expected boolean, got number + stack traceback: + shared.lua:0: in function 'gsplit' + shared.lua:0: in function <shared.lua:0>]]), + pcall_err_withfile(split, 'string', 'string', 1)) end) it('vim.trim', function() @@ -287,8 +300,11 @@ describe('lua stdlib', function() end -- Validates args. - eq('Error executing lua: .../shared.lua: s: expected string, got number', - pcall_err(trim, 2)) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: shared.lua:0: s: expected string, got number + stack traceback: + shared.lua:0: in function <shared.lua:0>]]), + pcall_err_withfile(trim, 2)) end) it('vim.inspect', function() @@ -353,8 +369,8 @@ describe('lua stdlib', function() return t1.f() ~= t2.f() ]])) - eq('Error executing lua: .../shared.lua: Cannot deepcopy object of type thread', - pcall_err(exec_lua, [[ + eq('.../helpers.lua:0: Error executing lua: shared.lua:0: Cannot deepcopy object of type thread', + pcall_err_withfile(exec_lua, [[ local thread = coroutine.create(function () return 0 end) local t = {thr = thread} vim.deepcopy(t) @@ -366,8 +382,11 @@ describe('lua stdlib', function() eq('foo%%%-bar', exec_lua([[return vim.pesc(vim.pesc('foo-bar'))]])) -- Validates args. - eq('Error executing lua: .../shared.lua: s: expected string, got number', - pcall_err(exec_lua, [[return vim.pesc(2)]])) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: shared.lua:0: s: expected string, got number + stack traceback: + shared.lua:0: in function <shared.lua:0>]]), + pcall_err_withfile(exec_lua, [[return vim.pesc(2)]])) end) it('vim.tbl_keys', function() @@ -491,20 +510,20 @@ describe('lua stdlib', function() return c.x.a == 1 and c.x.b == 2 and c.x.c == nil and count == 1 ]])) - eq('Error executing lua: .../shared.lua: invalid "behavior": nil', - pcall_err(exec_lua, [[ + eq('.../helpers.lua:0: Error executing lua: shared.lua:0: invalid "behavior": nil', + pcall_err_withfile(exec_lua, [[ return vim.tbl_extend() ]]) ) - eq('Error executing lua: .../shared.lua: wrong number of arguments (given 1, expected at least 3)', - pcall_err(exec_lua, [[ + eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 1, expected at least 3)', + pcall_err_withfile(exec_lua, [[ return vim.tbl_extend("keep") ]]) ) - eq('Error executing lua: .../shared.lua: wrong number of arguments (given 2, expected at least 3)', - pcall_err(exec_lua, [[ + eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 2, expected at least 3)', + pcall_err_withfile(exec_lua, [[ return vim.tbl_extend("keep", {}) ]]) ) @@ -579,20 +598,20 @@ describe('lua stdlib', function() return vim.tbl_islist(c) and count == 0 ]])) - eq('Error executing lua: .../shared.lua: invalid "behavior": nil', - pcall_err(exec_lua, [[ + eq('.../helpers.lua:0: Error executing lua: shared.lua:0: invalid "behavior": nil', + pcall_err_withfile(exec_lua, [[ return vim.tbl_deep_extend() ]]) ) - eq('Error executing lua: .../shared.lua: wrong number of arguments (given 1, expected at least 3)', - pcall_err(exec_lua, [[ + eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 1, expected at least 3)', + pcall_err_withfile(exec_lua, [[ return vim.tbl_deep_extend("keep") ]]) ) - eq('Error executing lua: .../shared.lua: wrong number of arguments (given 2, expected at least 3)', - pcall_err(exec_lua, [[ + eq('.../helpers.lua:0: Error executing lua: shared.lua:0: wrong number of arguments (given 2, expected at least 3)', + pcall_err_withfile(exec_lua, [[ return vim.tbl_deep_extend("keep", {}) ]]) ) @@ -624,8 +643,11 @@ describe('lua stdlib', function() it('vim.list_extend', function() eq({1,2,3}, exec_lua [[ return vim.list_extend({1}, {2,3}) ]]) - eq('Error executing lua: .../shared.lua: src: expected table, got nil', - pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]])) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: shared.lua:0: src: expected table, got nil + stack traceback: + shared.lua:0: in function <shared.lua:0>]]), + pcall_err_withfile(exec_lua, [[ return vim.list_extend({1}, nil) ]])) eq({1,2}, exec_lua [[ return vim.list_extend({1}, {2;a=1}) ]]) eq(true, exec_lua [[ local a = {1} return vim.list_extend(a, {2;a=1}) == a ]]) eq({2}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1) ]]) @@ -648,8 +670,8 @@ describe('lua stdlib', function() assert(vim.deep_equal(a, { A = 1; [1] = 'A'; })) vim.tbl_add_reverse_lookup(a) ]] - matches('Error executing lua: .../shared.lua: The reverse lookup found an existing value for "[1A]" while processing key "[1A]"', - pcall_err(exec_lua, code)) + matches('.../helpers.lua:0: Error executing lua: shared.lua:0: The reverse lookup found an existing value for "[1A]" while processing key "[1A]"', + pcall_err_withfile(exec_lua, code)) end) it('vim.call, vim.fn', function() @@ -820,34 +842,77 @@ describe('lua stdlib', function() exec_lua("vim.validate{arg1={{}, 't' }, arg2={ 'foo', 's' }}") exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}") - eq("Error executing lua: .../shared.lua: 1: expected table, got number", - pcall_err(exec_lua, "vim.validate{ 1, 'x' }")) - eq("Error executing lua: .../shared.lua: invalid type name: x", - pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}")) - eq("Error executing lua: .../shared.lua: invalid type name: 1", - pcall_err(exec_lua, "vim.validate{ arg1={ 1, 1 }}")) - eq("Error executing lua: .../shared.lua: invalid type name: nil", - pcall_err(exec_lua, "vim.validate{ arg1={ 1 }}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: opt[1]: expected table, got number + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{ 1, 'x' }")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: invalid type name: x + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{ arg1={ 1, 'x' }}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: invalid type name: 1 + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{ arg1={ 1, 1 }}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: invalid type name: nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{ arg1={ 1 }}")) -- Validated parameters are required by default. - eq("Error executing lua: .../shared.lua: arg1: expected string, got nil", - pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{ arg1={ nil, 's' }}")) -- Explicitly required. - eq("Error executing lua: .../shared.lua: arg1: expected string, got nil", - pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}")) - - eq("Error executing lua: .../shared.lua: arg1: expected table, got number", - pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}")) - eq("Error executing lua: .../shared.lua: arg2: expected string, got number", - pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}")) - eq("Error executing lua: .../shared.lua: arg2: expected string, got nil", - pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")) - eq("Error executing lua: .../shared.lua: arg2: expected string, got nil", - pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")) - eq("Error executing lua: .../shared.lua: arg1: expected even number, got 3", - pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}")) - eq("Error executing lua: .../shared.lua: arg1: expected ?, got 3", - pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected string, got nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{ arg1={ nil, 's', false }}")) + + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected table, got number + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{arg1={1, 't'}}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg2: expected string, got number + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg2: expected string, got nil + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected even number, got 3 + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}")) + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3 + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}")) + + -- Pass an additional message back. + eq(dedent([[ + .../helpers.lua:0: Error executing lua: [string "<nvim>"]:0: arg1: expected ?, got 3. Info: TEST_MSG + stack traceback: + [string "<nvim>"]:0: in main chunk]]), + pcall_err_withfile(exec_lua, "vim.validate{arg1={3, function(a) return a == 1, 'TEST_MSG' end}}")) end) it('vim.is_callable', function() @@ -992,10 +1057,10 @@ describe('lua stdlib', function() ]] eq('', funcs.luaeval "vim.bo.filetype") eq(true, funcs.luaeval "vim.bo[BUF].modifiable") - matches("^Error executing lua: .*: Invalid option name: 'nosuchopt'$", - pcall_err(exec_lua, 'return vim.bo.nosuchopt')) - matches("^Error executing lua: .*: Expected lua string$", - pcall_err(exec_lua, 'return vim.bo[0][0].autoread')) + matches("^.../helpers.lua:0: Error executing lua: .*: Invalid option name: 'nosuchopt'$", + pcall_err_withfile(exec_lua, 'return vim.bo.nosuchopt')) + matches("^.../helpers.lua:0: Error executing lua: .*: Expected lua string$", + pcall_err_withfile(exec_lua, 'return vim.bo[0][0].autoread')) end) it('vim.wo', function() @@ -1011,10 +1076,10 @@ describe('lua stdlib', function() eq(0, funcs.luaeval "vim.wo.cole") eq(0, funcs.luaeval "vim.wo[0].cole") eq(0, funcs.luaeval "vim.wo[1001].cole") - matches("^Error executing lua: .*: Invalid option name: 'notanopt'$", - pcall_err(exec_lua, 'return vim.wo.notanopt')) - matches("^Error executing lua: .*: Expected lua string$", - pcall_err(exec_lua, 'return vim.wo[0][0].list')) + matches("^.../helpers.lua:0: Error executing lua: .*: Invalid option name: 'notanopt'$", + pcall_err_withfile(exec_lua, 'return vim.wo.notanopt')) + matches("^.../helpers.lua:0: Error executing lua: .*: Expected lua string$", + pcall_err_withfile(exec_lua, 'return vim.wo[0][0].list')) eq(2, funcs.luaeval "vim.wo[1000].cole") exec_lua [[ vim.wo[1000].cole = 0 @@ -1214,6 +1279,23 @@ describe('lua stdlib', function() ]]) end) + it('should not process non-fast events when commanded', function() + eq({wait_result = false}, exec_lua[[ + start_time = get_time() + + vim.g.timer_result = false + timer = vim.loop.new_timer() + timer:start(100, 0, vim.schedule_wrap(function() + vim.g.timer_result = true + end)) + + wait_result = vim.wait(300, function() return vim.g.timer_result end, nil, true) + + return { + wait_result = wait_result, + } + ]]) + end) it('should work with vim.defer_fn', function() eq({time = true, wait_result = true}, exec_lua[[ start_time = get_time() @@ -1228,22 +1310,38 @@ describe('lua stdlib', function() ]]) end) - it('should require functions to be passed', function() + it('should not crash when callback errors', function() local pcall_result = exec_lua [[ - return {pcall(function() vim.wait(1000, 13) end)} + return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)} ]] eq(pcall_result[1], false) - matches('condition must be a function', pcall_result[2]) + matches('As Expected', pcall_result[2]) end) - it('should not crash when callback errors', function() + it('if callback is passed, it must be a function', function() local pcall_result = exec_lua [[ - return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)} + return {pcall(function() vim.wait(1000, 13) end)} ]] eq(pcall_result[1], false) - matches('As Expected', pcall_result[2]) + matches('if passed, condition must be a function', pcall_result[2]) + end) + + it('should allow waiting with no callback, explicit', function() + eq(true, exec_lua [[ + local start_time = vim.loop.hrtime() + vim.wait(50, nil) + return vim.loop.hrtime() - start_time > 25000 + ]]) + end) + + it('should allow waiting with no callback, implicit', function() + eq(true, exec_lua [[ + local start_time = vim.loop.hrtime() + vim.wait(50) + return vim.loop.hrtime() - start_time > 25000 + ]]) end) it('should call callbacks exactly once if they return true immediately', function() diff --git a/test/functional/normal/meta_key_spec.lua b/test/functional/normal/meta_key_spec.lua new file mode 100644 index 0000000000..9f9fad67d2 --- /dev/null +++ b/test/functional/normal/meta_key_spec.lua @@ -0,0 +1,22 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert +local command = helpers.command +local expect = helpers.expect + +describe('meta-keys-in-normal-mode', function() + before_each(function() + clear() + end) + + it('ALT/META', function() + -- Unmapped ALT-chords behave as Esc+c + insert('hello') + feed('0<A-x><M-x>') + expect('llo') + -- Mapped ALT-chord behaves as mapped. + command('nnoremap <M-l> Ameta-l<Esc>') + command('nnoremap <A-j> Aalt-j<Esc>') + feed('<A-j><M-l>') + expect('lloalt-jmeta-l') + end) +end) diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index f514f4ea6f..f07a2d18a2 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -747,8 +747,16 @@ describe('LSP', function() end) it('should invalid cmd argument', function() - eq('Error executing lua: .../shared.lua: cmd: expected list, got nvim', pcall_err(_cmd_parts, "nvim")) - eq('Error executing lua: .../shared.lua: cmd argument: expected string, got number', pcall_err(_cmd_parts, {"nvim", 1})) + eq(dedent([[ + Error executing lua: .../lsp.lua:0: cmd: expected list, got nvim + stack traceback: + .../lsp.lua:0: in function .../lsp.lua:0>]]), + pcall_err(_cmd_parts, 'nvim')) + eq(dedent([[ + Error executing lua: .../lsp.lua:0: cmd argument: expected string, got number + stack traceback: + .../lsp.lua:0: in function .../lsp.lua:0>]]), + pcall_err(_cmd_parts, {'nvim', 1})) end) end) end) diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua new file mode 100644 index 0000000000..304c5aecb1 --- /dev/null +++ b/test/functional/ui/decorations_spec.lua @@ -0,0 +1,118 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') + +local clear = helpers.clear +local feed = helpers.feed +local insert = helpers.insert +local exec_lua = helpers.exec_lua +local expect_events = helpers.expect_events + +describe('decorations provider', function() + local screen + before_each(function() + clear() + screen = Screen.new(40, 8) + screen:attach() + screen:set_default_attr_ids({ + [1] = {bold=true, foreground=Screen.colors.Blue}, + }) + end) + + local mudholland = [[ + // just to see if there was an accident + // on Mulholland Drive + try_start(); + bufref_T save_buf; + switch_buffer(&save_buf, buf); + posp = getmark(mark, false); + restore_buffer(&save_buf); ]] + + local function setup_provider(code) + exec_lua ([[ + local a = vim.api + test1 = a.nvim_create_namespace "test1" + ]] .. (code or [[ + beamtrace = {} + function on_do(kind, ...) + table.insert(beamtrace, {kind, ...}) + end + ]]) .. [[ + a.nvim_set_decoration_provider( + test1, { + on_start = on_do; on_buf = on_do; + on_win = on_do; on_line = on_do; + on_end = on_do; + }) + ]]) + end + + local function check_trace(expected) + local actual = exec_lua [[ local b = beamtrace beamtrace = {} return b ]] + expect_events(expected, actual, "beam trace") + end + + it('leaves a trace', function() + insert(mudholland) + + setup_provider() + + screen:expect{grid=[[ + // just to see if there was an accident | + // on Mulholland Drive | + try_start(); | + bufref_T save_buf; | + switch_buffer(&save_buf, buf); | + posp = getmark(mark, false); | + restore_buffer(&save_buf);^ | + | + ]]} + check_trace { + { "start", 4, 40 }; + { "win", 1000, 1, 0, 8 }; + { "line", 1000, 1, 0 }; + { "line", 1000, 1, 1 }; + { "line", 1000, 1, 2 }; + { "line", 1000, 1, 3 }; + { "line", 1000, 1, 4 }; + { "line", 1000, 1, 5 }; + { "line", 1000, 1, 6 }; + { "end", 4 }; + } + + feed "iü<esc>" + screen:expect{grid=[[ + // just to see if there was an accident | + // on Mulholland Drive | + try_start(); | + bufref_T save_buf; | + switch_buffer(&save_buf, buf); | + posp = getmark(mark, false); | + restore_buffer(&save_buf);^ü | + | + ]]} + check_trace { + { "start", 5, 10 }; + { "buf", 1 }; + { "win", 1000, 1, 0, 8 }; + { "line", 1000, 1, 6 }; + { "end", 5 }; + } + end) + + it('single provider', function() + insert(mudholland) + setup_provider [[ + local hl = a.nvim_get_hl_id_by_name "ErrorMsg" + function do_it(event, ...) + if event == "line" then + local win, buf, line = ... + a.nvim_buf_set_extmark(buf, test_ns, line, line, + { end_line = line, end_col = line+1, + hl_group = hl, + ephemeral = true + }) + end + end + ]] + end) +end) diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 11fe861de8..eec8eb93d4 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -59,7 +59,7 @@ describe('floatwin', function() end) it('closed immediately by autocmd #11383', function() - eq('Error executing lua: [string "<nvim>"]:4: Window was closed immediately', + eq('Error executing lua: [string "<nvim>"]:0: Window was closed immediately', pcall_err(exec_lua, [[ local a = vim.api local function crashes(contents) diff --git a/test/functional/viml/errorlist_spec.lua b/test/functional/viml/errorlist_spec.lua index c5390cbd12..9acc61e398 100644 --- a/test/functional/viml/errorlist_spec.lua +++ b/test/functional/viml/errorlist_spec.lua @@ -27,7 +27,7 @@ describe('setqflist()', function() setqflist({''}, 'r', 'foo') command('copen') eq('foo', get_cur_win_var('quickfix_title')) - setqflist({''}, 'r', {['title'] = 'qf_title'}) + setqflist({}, 'r', {['title'] = 'qf_title'}) eq('qf_title', get_cur_win_var('quickfix_title')) end) diff --git a/test/functional/visual/meta_key_spec.lua b/test/functional/visual/meta_key_spec.lua new file mode 100644 index 0000000000..11f7203da0 --- /dev/null +++ b/test/functional/visual/meta_key_spec.lua @@ -0,0 +1,22 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert +local command = helpers.command +local expect = helpers.expect + +describe('meta-keys-in-visual-mode', function() + before_each(function() + clear() + end) + + it('ALT/META', function() + -- Unmapped ALT-chords behave as Esc+c + insert('peaches') + feed('viw<A-x>viw<M-x>') + expect('peach') + -- Mapped ALT-chord behaves as mapped. + command('vnoremap <M-l> Ameta-l<Esc>') + command('vnoremap <A-j> Aalt-j<Esc>') + feed('viw<A-j>viw<M-l>') + expect('peachalt-jmeta-l') + end) +end) diff --git a/test/helpers.lua b/test/helpers.lua index 5acd2ea0bd..68f0c92244 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -116,8 +116,12 @@ function module.assert_log(pat, logfile) pat, nrlines, logfile, logtail)) end --- Invokes `fn` and returns the error string (may truncate full paths), or --- raises an error if `fn` succeeds. +-- Invokes `fn` and returns the error string (with truncated paths), or raises +-- an error if `fn` succeeds. +-- +-- Replaces line/column numbers with zero: +-- shared.lua:0: in function 'gsplit' +-- shared.lua:0: in function <shared.lua:0>' -- -- Usage: -- -- Match exact string. @@ -125,29 +129,36 @@ end -- -- Match Lua pattern. -- matches('e[or]+$', pcall_err(function(a, b) error('some error') end, 'arg1', 'arg2')) -- -function module.pcall_err(fn, ...) +function module.pcall_err_withfile(fn, ...) assert(type(fn) == 'function') local status, rv = pcall(fn, ...) if status == true then error('expected failure, but got success') end - -- From this: - -- /home/foo/neovim/runtime/lua/vim/shared.lua:186: Expected string, got number - -- to this: - -- Expected string, got number - local errmsg = tostring(rv):gsub('^[^:]+:%d+: ', '') - -- From this: - -- Error executing lua: /very/long/foo.lua:186: Expected string, got number - -- to this: - -- Error executing lua: .../foo.lua:186: Expected string, got number - errmsg = errmsg:gsub([[lua: [a-zA-Z]?:?[^:]-[/\]([^:/\]+):%d+: ]], 'lua: .../%1: ') - -- Compiled modules will not have a path and will just be a name like - -- shared.lua:186, so strip the number. - errmsg = errmsg:gsub([[lua: ([^:/\ ]+):%d+: ]], 'lua: .../%1: ') - -- ^ Windows drive-letter (C:) + -- From: + -- C:/long/path/foo.lua:186: Expected string, got number + -- to: + -- .../foo.lua:0: Expected string, got number + local errmsg = tostring(rv):gsub('[^%s]-[/\\]([^%s:/\\]+):%d+', '.../%1:0') + -- Scrub numbers in paths/stacktraces: + -- shared.lua:0: in function 'gsplit' + -- shared.lua:0: in function <shared.lua:0>' + errmsg = errmsg:gsub('([^%s]):%d+', '%1:0') + -- Scrub tab chars: + errmsg = errmsg:gsub('\t', ' ') + -- In Lua 5.1, we sometimes get a "(tail call): ?" on the last line. + -- We remove this so that the tests are not lua dependent. + errmsg = errmsg:gsub('%s*%(tail call%): %?', '') + return errmsg end +function module.pcall_err(fn, ...) + local errmsg = module.pcall_err_withfile(fn, ...) + + return errmsg:gsub('.../helpers.lua:0: ', '') +end + -- initial_path: directory to recurse into -- re: include pattern (string) -- exc_re: exclude pattern(s) (string or table) diff --git a/test/symbolic/klee/nvim/charset.c b/test/symbolic/klee/nvim/charset.c index 95853a6834..f9bc3fabc4 100644 --- a/test/symbolic/klee/nvim/charset.c +++ b/test/symbolic/klee/nvim/charset.c @@ -69,7 +69,7 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, && !STRING_ENDED(ptr + 1) && ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9') { pre = ptr[1]; - // Detect hexadecimal: 0x or 0X follwed by hex digit + // Detect hexadecimal: 0x or 0X followed by hex digit if ((what & STR2NR_HEX) && !STRING_ENDED(ptr + 2) && (pre == 'X' || pre == 'x') @@ -77,7 +77,7 @@ void vim_str2nr(const char_u *const start, int *const prep, int *const len, ptr += 2; goto vim_str2nr_hex; } - // Detect binary: 0b or 0B follwed by 0 or 1 + // Detect binary: 0b or 0B followed by 0 or 1 if ((what & STR2NR_BIN) && !STRING_ENDED(ptr + 2) && (pre == 'B' || pre == 'b') |