diff options
Diffstat (limited to 'test')
25 files changed, 1011 insertions, 186 deletions
diff --git a/test/busted/outputHandlers/TAP.lua b/test/busted/outputHandlers/TAP.lua index 8dc4ff55b6..5de48c0ad3 100644 --- a/test/busted/outputHandlers/TAP.lua +++ b/test/busted/outputHandlers/TAP.lua @@ -7,7 +7,7 @@ return function(options) local handler = require 'busted.outputHandlers.TAP'(options) local suiteEnd = function() - io.write(global_helpers.read_nvim_log()) + io.write(global_helpers.read_nvim_log(nil, true)) return nil, true end busted.subscribe({ 'suite', 'end' }, suiteEnd) diff --git a/test/busted/outputHandlers/nvim.lua b/test/busted/outputHandlers/nvim.lua index 8f3aad776e..5456e9ca98 100644 --- a/test/busted/outputHandlers/nvim.lua +++ b/test/busted/outputHandlers/nvim.lua @@ -196,7 +196,7 @@ return function(options) local tests = (testCount == 1 and 'test' or 'tests') local files = (fileCount == 1 and 'file' or 'files') io.write(globalTeardown) - io.write(global_helpers.read_nvim_log()) + io.write(global_helpers.read_nvim_log(nil, true)) io.write(suiteEndString:format(testCount, tests, fileCount, files, elapsedTime_ms)) io.write(getSummaryString()) io.flush() diff --git a/test/functional/eval/ctx_functions_spec.lua b/test/functional/eval/ctx_functions_spec.lua index c81dad9645..f23adbc556 100644 --- a/test/functional/eval/ctx_functions_spec.lua +++ b/test/functional/eval/ctx_functions_spec.lua @@ -6,7 +6,7 @@ local command = helpers.command local eq = helpers.eq local eval = helpers.eval local feed = helpers.feed -local map = helpers.map +local map = helpers.tbl_map local nvim = helpers.nvim local parse_context = helpers.parse_context local redir_exec = helpers.redir_exec diff --git a/test/functional/ex_cmds/echo_spec.lua b/test/functional/ex_cmds/echo_spec.lua index 10c7230896..408ce52b8c 100644 --- a/test/functional/ex_cmds/echo_spec.lua +++ b/test/functional/ex_cmds/echo_spec.lua @@ -11,31 +11,57 @@ local dedent = helpers.dedent local command = helpers.command local exc_exec = helpers.exc_exec local redir_exec = helpers.redir_exec +local matches = helpers.matches + +describe(':echo :echon :echomsg :echoerr', function() + local fn_tbl = {'String', 'StringN', 'StringMsg', 'StringErr'} + local function assert_same_echo_dump(expected, input, use_eval) + for _,v in pairs(fn_tbl) do + eq(expected, use_eval and eval(v..'('..input..')') or funcs[v](input)) + end + end + local function assert_matches_echo_dump(expected, input, use_eval) + for _,v in pairs(fn_tbl) do + matches(expected, use_eval and eval(v..'('..input..')') or funcs[v](input)) + end + end -describe(':echo', function() before_each(function() clear() source([[ function String(s) return execute('echo a:s')[1:] endfunction + function StringMsg(s) + return execute('echomsg a:s')[1:] + endfunction + function StringN(s) + return execute('echon a:s') + endfunction + function StringErr(s) + try + execute 'echoerr a:s' + catch + return substitute(v:exception, '^Vim(echoerr):', '', '') + endtry + endfunction ]]) end) describe('used to represent floating-point values', function() it('dumps NaN values', function() - eq('str2float(\'nan\')', eval('String(str2float(\'nan\'))')) + assert_same_echo_dump("str2float('nan')", "str2float('nan')", true) end) it('dumps infinite values', function() - eq('str2float(\'inf\')', eval('String(str2float(\'inf\'))')) - eq('-str2float(\'inf\')', eval('String(str2float(\'-inf\'))')) + assert_same_echo_dump("str2float('inf')", "str2float('inf')", true) + assert_same_echo_dump("-str2float('inf')", "str2float('-inf')", true) end) it('dumps regular values', function() - eq('1.5', funcs.String(1.5)) - eq('1.56e-20', funcs.String(1.56000e-020)) - eq('0.0', eval('String(0.0)')) + assert_same_echo_dump('1.5', 1.5) + assert_same_echo_dump('1.56e-20', 1.56000e-020) + assert_same_echo_dump('0.0', '0.0', true) end) it('dumps special v: values', function() @@ -45,69 +71,81 @@ describe(':echo', function() eq('v:true', funcs.String(true)) eq('v:false', funcs.String(false)) eq('v:null', funcs.String(NIL)) + eq('true', eval('StringMsg(v:true)')) + eq('false', eval('StringMsg(v:false)')) + eq('null', eval('StringMsg(v:null)')) + eq('true', funcs.StringMsg(true)) + eq('false', funcs.StringMsg(false)) + eq('null', funcs.StringMsg(NIL)) + eq('true', eval('StringErr(v:true)')) + eq('false', eval('StringErr(v:false)')) + eq('null', eval('StringErr(v:null)')) + eq('true', funcs.StringErr(true)) + eq('false', funcs.StringErr(false)) + eq('null', funcs.StringErr(NIL)) end) it('dumps values with at most six digits after the decimal point', function() - eq('1.234568e-20', funcs.String(1.23456789123456789123456789e-020)) - eq('1.234568', funcs.String(1.23456789123456789123456789)) + assert_same_echo_dump('1.234568e-20', 1.23456789123456789123456789e-020) + assert_same_echo_dump('1.234568', 1.23456789123456789123456789) end) it('dumps values with at most seven digits before the decimal point', function() - eq('1234567.891235', funcs.String(1234567.89123456789123456789)) - eq('1.234568e7', funcs.String(12345678.9123456789123456789)) + assert_same_echo_dump('1234567.891235', 1234567.89123456789123456789) + assert_same_echo_dump('1.234568e7', 12345678.9123456789123456789) end) it('dumps negative values', function() - eq('-1.5', funcs.String(-1.5)) - eq('-1.56e-20', funcs.String(-1.56000e-020)) - eq('-1.234568e-20', funcs.String(-1.23456789123456789123456789e-020)) - eq('-1.234568', funcs.String(-1.23456789123456789123456789)) - eq('-1234567.891235', funcs.String(-1234567.89123456789123456789)) - eq('-1.234568e7', funcs.String(-12345678.9123456789123456789)) + assert_same_echo_dump('-1.5', -1.5) + assert_same_echo_dump('-1.56e-20', -1.56000e-020) + assert_same_echo_dump('-1.234568e-20', -1.23456789123456789123456789e-020) + assert_same_echo_dump('-1.234568', -1.23456789123456789123456789) + assert_same_echo_dump('-1234567.891235', -1234567.89123456789123456789) + assert_same_echo_dump('-1.234568e7', -12345678.9123456789123456789) end) end) describe('used to represent numbers', function() it('dumps regular values', function() - eq('0', funcs.String(0)) - eq('-1', funcs.String(-1)) - eq('1', funcs.String(1)) + assert_same_echo_dump('0', 0) + assert_same_echo_dump('-1', -1) + assert_same_echo_dump('1', 1) end) it('dumps large values', function() - eq('2147483647', funcs.String(2^31-1)) - eq('-2147483648', funcs.String(-2^31)) + assert_same_echo_dump('2147483647', 2^31-1) + assert_same_echo_dump('-2147483648', -2^31) end) end) describe('used to represent strings', function() it('dumps regular strings', function() - eq('test', funcs.String('test')) + assert_same_echo_dump('test', 'test') end) it('dumps empty strings', function() - eq('', funcs.String('')) + assert_same_echo_dump('', '') end) - it('dumps strings with \' inside', function() - eq('\'\'\'', funcs.String('\'\'\'')) - eq('a\'b\'\'', funcs.String('a\'b\'\'')) - eq('\'b\'\'d', funcs.String('\'b\'\'d')) - eq('a\'b\'c\'d', funcs.String('a\'b\'c\'d')) + it("dumps strings with ' inside", function() + assert_same_echo_dump("'''", "'''") + assert_same_echo_dump("a'b''", "a'b''") + assert_same_echo_dump("'b''d", "'b''d") + assert_same_echo_dump("a'b'c'd", "a'b'c'd") end) it('dumps NULL strings', function() - eq('', eval('String($XXX_UNEXISTENT_VAR_XXX)')) + assert_same_echo_dump('', '$XXX_UNEXISTENT_VAR_XXX', true) end) it('dumps NULL lists', function() - eq('[]', eval('String(v:_null_list)')) + assert_same_echo_dump('[]', 'v:_null_list', true) end) it('dumps NULL dictionaries', function() - eq('{}', eval('String(v:_null_dict)')) + assert_same_echo_dump('{}', 'v:_null_dict', true) end) end) @@ -129,15 +167,27 @@ describe(':echo', function() it('dumps references to built-in functions', function() eq('function', eval('String(function("function"))')) + eq("function('function')", eval('StringMsg(function("function"))')) + eq("function('function')", eval('StringErr(function("function"))')) end) it('dumps references to user functions', function() eq('Test1', eval('String(function("Test1"))')) eq('g:Test3', eval('String(function("g:Test3"))')) + eq("function('Test1')", eval("StringMsg(function('Test1'))")) + eq("function('g:Test3')", eval("StringMsg(function('g:Test3'))")) + eq("function('Test1')", eval("StringErr(function('Test1'))")) + eq("function('g:Test3')", eval("StringErr(function('g:Test3'))")) end) it('dumps references to script functions', function() eq('<SNR>2_Test2', eval('String(Test2_f)')) + eq("function('<SNR>2_Test2')", eval('StringMsg(Test2_f)')) + eq("function('<SNR>2_Test2')", eval('StringErr(Test2_f)')) + end) + + it('dump references to lambdas', function() + assert_matches_echo_dump("function%('<lambda>%d+'%)", '{-> 1234}', true) end) it('dumps partials with self referencing a partial', function() @@ -156,19 +206,23 @@ describe(':echo', function() end) it('dumps automatically created partials', function() - eq('function(\'<SNR>2_Test2\', {\'f\': function(\'<SNR>2_Test2\')})', - eval('String({"f": Test2_f}.f)')) - eq('function(\'<SNR>2_Test2\', [1], {\'f\': function(\'<SNR>2_Test2\', [1])})', - eval('String({"f": function(Test2_f, [1])}.f)')) + assert_same_echo_dump( + "function('<SNR>2_Test2', {'f': function('<SNR>2_Test2')})", + '{"f": Test2_f}.f', + true) + assert_same_echo_dump( + "function('<SNR>2_Test2', [1], {'f': function('<SNR>2_Test2', [1])})", + '{"f": function(Test2_f, [1])}.f', + true) end) it('dumps manually created partials', function() - eq('function(\'Test3\', [1, 2], {})', - eval('String(function("Test3", [1, 2], {}))')) - eq('function(\'Test3\', {})', - eval('String(function("Test3", {}))')) - eq('function(\'Test3\', [1, 2])', - eval('String(function("Test3", [1, 2]))')) + assert_same_echo_dump("function('Test3', [1, 2], {})", + "function('Test3', [1, 2], {})", true) + assert_same_echo_dump("function('Test3', [1, 2])", + "function('Test3', [1, 2])", true) + assert_same_echo_dump("function('Test3', {})", + "function('Test3', {})", true) end) it('does not crash or halt when dumping partials with reference cycles in self', @@ -225,15 +279,19 @@ describe(':echo', function() describe('used to represent lists', function() it('dumps empty list', function() - eq('[]', funcs.String({})) + assert_same_echo_dump('[]', {}) + end) + + it('dumps non-empty list', function() + assert_same_echo_dump('[1, 2]', {1,2}) end) it('dumps nested lists', function() - eq('[[[[[]]]]]', funcs.String({{{{{}}}}})) + assert_same_echo_dump('[[[[[]]]]]', {{{{{}}}}}) end) it('dumps nested non-empty lists', function() - eq('[1, [[3, [[5], 4]], 2]]', funcs.String({1, {{3, {{5}, 4}}, 2}})) + assert_same_echo_dump('[1, [[3, [[5], 4]], 2]]', {1, {{3, {{5}, 4}}, 2}}) end) it('does not error when dumping recursive lists', function() @@ -252,18 +310,18 @@ describe(':echo', function() describe('used to represent dictionaries', function() it('dumps empty dictionary', function() - eq('{}', eval('String({})')) + assert_same_echo_dump('{}', '{}', true) end) it('dumps list with two same empty dictionaries, also in partials', function() command('let d = {}') - eq('[{}, {}]', eval('String([d, d])')) + assert_same_echo_dump('[{}, {}]', '[d, d]', true) eq('[function(\'tr\', {}), {}]', eval('String([function("tr", d), d])')) eq('[{}, function(\'tr\', {})]', eval('String([d, function("tr", d)])')) end) it('dumps non-empty dictionary', function() - eq('{\'t\'\'est\': 1}', funcs.String({['t\'est']=1})) + assert_same_echo_dump("{'t''est': 1}", {["t'est"]=1}) end) it('does not error when dumping recursive dictionaries', function() @@ -297,11 +355,20 @@ describe(':echo', function() eq('<8e>', funcs.String(chr(0x8e))) eq('<c2>', funcs.String(('«'):sub(1, 1))) eq('«', funcs.String(('«'):sub(1, 2))) + + eq('<80>', funcs.StringMsg(chr(0x80))) + eq('<81>', funcs.StringMsg(chr(0x81))) + eq('<8e>', funcs.StringMsg(chr(0x8e))) + eq('<c2>', funcs.StringMsg(('«'):sub(1, 1))) + eq('«', funcs.StringMsg(('«'):sub(1, 2))) end) it('displays ASCII control characters using ^X notation', function() eq('^C', funcs.String(ctrl('c'))) eq('^A', funcs.String(ctrl('a'))) eq('^F', funcs.String(ctrl('f'))) + eq('^C', funcs.StringMsg(ctrl('c'))) + eq('^A', funcs.StringMsg(ctrl('a'))) + eq('^F', funcs.StringMsg(ctrl('f'))) end) it('prints CR, NL and tab as-is', function() eq('\n', funcs.String('\n')) @@ -311,11 +378,15 @@ describe(':echo', function() it('prints non-printable UTF-8 in <> notation', function() -- SINGLE SHIFT TWO, unicode control eq('<8e>', funcs.String(funcs.nr2char(0x8E))) + eq('<8e>', funcs.StringMsg(funcs.nr2char(0x8E))) -- Surrogate pair: U+1F0A0 PLAYING CARD BACK is represented in UTF-16 as -- 0xD83C 0xDCA0. This is not valid in UTF-8. eq('<d83c>', funcs.String(funcs.nr2char(0xD83C))) eq('<dca0>', funcs.String(funcs.nr2char(0xDCA0))) eq('<d83c><dca0>', funcs.String(funcs.nr2char(0xD83C) .. funcs.nr2char(0xDCA0))) + eq('<d83c>', funcs.StringMsg(funcs.nr2char(0xD83C))) + eq('<dca0>', funcs.StringMsg(funcs.nr2char(0xDCA0))) + eq('<d83c><dca0>', funcs.StringMsg(funcs.nr2char(0xD83C) .. funcs.nr2char(0xDCA0))) end) end) end) diff --git a/test/functional/fixtures/lsp-test-rpc-server.lua b/test/functional/fixtures/fake-lsp-server.lua index 798883ced0..dca7f35923 100644 --- a/test/functional/fixtures/lsp-test-rpc-server.lua +++ b/test/functional/fixtures/fake-lsp-server.lua @@ -1,23 +1,14 @@ local protocol = require 'vim.lsp.protocol' --- Internal utility methods. --- TODO replace with a better implementation. -local function json_encode(data) - local status, result = pcall(vim.fn.json_encode, data) - if status then - return result - else - return nil, result - end -end -local function json_decode(data) - local status, result = pcall(vim.fn.json_decode, data) - if status then - return result - else - return nil, result - end +-- Logs to $NVIM_LOG_FILE. +-- +-- TODO(justinmk): remove after https://github.com/neovim/neovim/pull/7062 +local function log(loglevel, area, msg) + vim.fn.writefile( + {string.format('%s %s: %s', loglevel, area, msg)}, + vim.env.NVIM_LOG_FILE, + 'a') end local function message_parts(sep, ...) @@ -49,16 +40,14 @@ local function format_message_with_content_length(encoded_message) } end --- Server utility methods. - local function read_message() local line = io.read("*l") local length = line:lower():match("content%-length:%s*(%d+)") - return assert(json_decode(io.read(2 + length):sub(2)), "read_message.json_decode") + return vim.fn.json_decode(io.read(2 + length):sub(2)) end local function send(payload) - io.stdout:write(format_message_with_content_length(json_encode(payload))) + io.stdout:write(format_message_with_content_length(vim.fn.json_encode(payload))) end local function respond(id, err, result) @@ -390,7 +379,7 @@ function tests.basic_check_buffer_open_and_change_incremental() } end -function tests.basic_check_buffer_open_and_change_incremental_editting() +function tests.basic_check_buffer_open_and_change_incremental_editing() skeleton { on_init = function(params) local expected_capabilities = protocol.make_client_capabilities() @@ -443,6 +432,7 @@ local kill_timer = vim.loop.new_timer() kill_timer:start(_G.TIMEOUT or 1e3, 0, function() kill_timer:stop() kill_timer:close() + log('ERROR', 'LSP', 'TIMEOUT') io.stderr:write("TIMEOUT") os.exit(100) end) @@ -453,7 +443,8 @@ local status, err = pcall(assert(tests[test_name], "Test not found")) kill_timer:stop() kill_timer:close() if not status then + log('ERROR', 'LSP', tostring(err)) io.stderr:write(err) - os.exit(1) + os.exit(101) end os.exit(0) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 53c4d140b6..e8435cd3b7 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -15,9 +15,9 @@ local check_cores = global_helpers.check_cores local check_logs = global_helpers.check_logs local dedent = global_helpers.dedent local eq = global_helpers.eq -local filter = global_helpers.filter +local filter = global_helpers.tbl_filter local is_os = global_helpers.is_os -local map = global_helpers.map +local map = global_helpers.tbl_map local ok = global_helpers.ok local sleep = global_helpers.sleep local tbl_contains = global_helpers.tbl_contains diff --git a/test/functional/legacy/expand_spec.lua b/test/functional/legacy/expand_spec.lua index 1b735080f4..f238128b31 100644 --- a/test/functional/legacy/expand_spec.lua +++ b/test/functional/legacy/expand_spec.lua @@ -70,6 +70,40 @@ describe('expand file name', function() call assert_match('\~', expand('%:p')) bwipe! endfunc + + func Test_expandcmd() + let $FOO = 'Test' + call assert_equal('e x/Test/y', expandcmd('e x/$FOO/y')) + unlet $FOO + + new + edit Xfile1 + call assert_equal('e Xfile1', expandcmd('e %')) + edit Xfile2 + edit Xfile1 + call assert_equal('e Xfile2', expandcmd('e #')) + edit Xfile2 + edit Xfile3 + edit Xfile4 + let bnum = bufnr('Xfile2') + call assert_equal('e Xfile2', expandcmd('e #' . bnum)) + call setline('.', 'Vim!@#') + call assert_equal('e Vim', expandcmd('e <cword>')) + call assert_equal('e Vim!@#', expandcmd('e <cWORD>')) + enew! + edit Xfile.java + call assert_equal('e Xfile.py', expandcmd('e %:r.py')) + call assert_equal('make abc.java', expandcmd('make abc.%:e')) + call assert_equal('make Xabc.java', expandcmd('make %:s?file?abc?')) + edit a1a2a3.rb + call assert_equal('make b1b2b3.rb a1a2a3 Xfile.o', expandcmd('make %:gs?a?b? %< #<.o')) + + call assert_fails('call expandcmd("make <afile>")', 'E495:') + call assert_fails('call expandcmd("make <afile>")', 'E495:') + enew + call assert_fails('call expandcmd("make %")', 'E499:') + close + endfunc ]]) end) @@ -87,4 +121,9 @@ describe('expand file name', function() call('Test_expand_tilde_filename') expected_empty() end) + + it('works with expandcmd()', function() + call('Test_expandcmd') + expected_empty() + end) end) diff --git a/test/functional/lua/treesitter_spec.lua b/test/functional/lua/treesitter_spec.lua index 494d6c84bb..f93185d1f6 100644 --- a/test/functional/lua/treesitter_spec.lua +++ b/test/functional/lua/treesitter_spec.lua @@ -245,6 +245,11 @@ static int nlua_schedule(lua_State *const lstate) (primitive_type) @type (sized_type_specifier) @type +; defaults to very magic syntax, for best compatibility +((identifier) @Identifier (match? @Identifier "^l(u)a_")) +; still support \M etc prefixes +((identifier) @Constant (match? @Constant "\M^\[A-Z_]\+$")) + ((binary_expression left: (identifier) @WarningMsg.left right: (identifier) @WarningMsg.right) (eq? @WarningMsg.left @WarningMsg.right)) (comment) @comment @@ -263,7 +268,7 @@ static int nlua_schedule(lua_State *const lstate) [8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red}, [9] = {foreground = Screen.colors.Magenta, background = Screen.colors.Red}, [10] = {foreground = Screen.colors.Red, background = Screen.colors.Red}, - + [11] = {foreground = Screen.colors.Cyan4}, }) insert(hl_text) @@ -297,10 +302,10 @@ static int nlua_schedule(lua_State *const lstate) {2:/// Schedule Lua callback on main loop's event queue} | {3:static} {3:int} nlua_schedule(lua_State *{3:const} lstate) | { | - {4:if} (lua_type(lstate, {5:1}) != LUA_TFUNCTION | + {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} | || {6:lstate} != {6:lstate}) { | - lua_pushliteral(lstate, {5:"vim.schedule: expected function"}); | - {4:return} lua_error(lstate); | + {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); | + {4:return} {11:lua_error}(lstate); | } | | {7:LuaRef} cb = nlua_ref(lstate, {5:1}); | @@ -319,10 +324,10 @@ static int nlua_schedule(lua_State *const lstate) {2:/// Schedule Lua callback on main loop's event queue} | {3:static} {3:int} nlua_schedule(lua_State *{3:const} lstate) | { | - {4:if} (lua_type(lstate, {5:1}) != LUA_TFUNCTION | + {4:if} ({11:lua_type}(lstate, {5:1}) != {5:LUA_TFUNCTION} | || {6:lstate} != {6:lstate}) { | - lua_pushliteral(lstate, {5:"vim.schedule: expected function"}); | - {4:return} lua_error(lstate); | + {11:lua_pushliteral}(lstate, {5:"vim.schedule: expected function"}); | + {4:return} {11:lua_error}(lstate); | {8:*^/} | } | | diff --git a/test/functional/lua/uri_spec.lua b/test/functional/lua/uri_spec.lua index 19b1eb1f61..128c7c6137 100644 --- a/test/functional/lua/uri_spec.lua +++ b/test/functional/lua/uri_spec.lua @@ -85,6 +85,15 @@ describe('URI methods', function() eq('C:\\Foo\\Bar\\Baz.txt', exec_lua(test_case)) end) + it('file path includes only ascii charactors with encoded colon character', function() + local test_case = [[ + local uri = 'file:///C%3A/Foo/Bar/Baz.txt' + return vim.uri_to_fname(uri) + ]] + + eq('C:\\Foo\\Bar\\Baz.txt', exec_lua(test_case)) + end) + it('file path including white space', function() local test_case = [[ local uri = 'file:///C:/Foo%20/Bar/Baz.txt' diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua index e879f8b925..ca74d185cd 100644 --- a/test/functional/lua/vim_spec.lua +++ b/test/functional/lua/vim_spec.lua @@ -7,6 +7,7 @@ local meths = helpers.meths 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 @@ -310,18 +311,52 @@ describe('lua stdlib', function() end) it("vim.deepcopy", function() - local is_dc = exec_lua([[ + ok(exec_lua([[ local a = { x = { 1, 2 }, y = 5} local b = vim.deepcopy(a) - local count = 0 - for _ in pairs(b) do count = count + 1 end - - return b.x[1] == 1 and b.x[2] == 2 and b.y == 5 and count == 2 + return b.x[1] == 1 and b.x[2] == 2 and b.y == 5 and vim.tbl_count(b) == 2 and tostring(a) ~= tostring(b) - ]]) + ]])) + + ok(exec_lua([[ + local a = {} + local b = vim.deepcopy(a) + + return vim.tbl_islist(b) and vim.tbl_count(b) == 0 and tostring(a) ~= tostring(b) + ]])) - assert(is_dc) + ok(exec_lua([[ + local a = vim.empty_dict() + local b = vim.deepcopy(a) + + return not vim.tbl_islist(b) and vim.tbl_count(b) == 0 + ]])) + + ok(exec_lua([[ + local a = {x = vim.empty_dict(), y = {}} + local b = vim.deepcopy(a) + + return not vim.tbl_islist(b.x) and vim.tbl_islist(b.y) + and vim.tbl_count(b) == 2 + and tostring(a) ~= tostring(b) + ]])) + + ok(exec_lua([[ + local f1 = function() return 1 end + local f2 = function() return 2 end + local t1 = {f = f1} + local t2 = vim.deepcopy(t1) + t1.f = f2 + return t1.f() ~= t2.f() + ]])) + + eq('Error executing lua: .../shared.lua: Cannot deepcopy object of type thread', + pcall_err(exec_lua, [[ + local thread = coroutine.create(function () return 0 end) + local t = {thr = thread} + vim.deepcopy(t) + ]])) end) it('vim.pesc', function() @@ -353,6 +388,30 @@ describe('lua stdlib', function() end end) + it('vim.tbl_map', function() + eq({}, exec_lua([[ + return vim.tbl_map(function(v) return v * 2 end, {}) + ]])) + eq({2, 4, 6}, exec_lua([[ + return vim.tbl_map(function(v) return v * 2 end, {1, 2, 3}) + ]])) + eq({{i=2}, {i=4}, {i=6}}, exec_lua([[ + return vim.tbl_map(function(v) return { i = v.i * 2 } end, {{i=1}, {i=2}, {i=3}}) + ]])) + end) + + it('vim.tbl_filter', function() + eq({}, exec_lua([[ + return vim.tbl_filter(function(v) return (v % 2) == 0 end, {}) + ]])) + eq({2}, exec_lua([[ + return vim.tbl_filter(function(v) return (v % 2) == 0 end, {1, 2, 3}) + ]])) + eq({{i=2}}, exec_lua([[ + return vim.tbl_filter(function(v) return (v.i % 2) == 0 end, {{i=1}, {i=2}, {i=3}}) + ]])) + end) + it('vim.tbl_islist', function() eq(true, exec_lua("return vim.tbl_islist({})")) eq(false, exec_lua("return vim.tbl_islist(vim.empty_dict())")) @@ -369,6 +428,88 @@ describe('lua stdlib', function() eq(false, exec_lua("return vim.tbl_isempty({a=1, b=2, c=3})")) end) + it('vim.tbl_extend', function() + ok(exec_lua([[ + local a = {x = 1} + local b = {y = 2} + local c = vim.tbl_extend("keep", a, b) + + return c.x == 1 and b.y == 2 and vim.tbl_count(c) == 2 + ]])) + + ok(exec_lua([[ + local a = {x = 1} + local b = {y = 2} + local c = {z = 3} + local d = vim.tbl_extend("keep", a, b, c) + + return d.x == 1 and d.y == 2 and d.z == 3 and vim.tbl_count(d) == 3 + ]])) + + ok(exec_lua([[ + local a = {x = 1} + local b = {x = 3} + local c = vim.tbl_extend("keep", a, b) + + return c.x == 1 and vim.tbl_count(c) == 1 + ]])) + + ok(exec_lua([[ + local a = {x = 1} + local b = {x = 3} + local c = vim.tbl_extend("force", a, b) + + return c.x == 3 and vim.tbl_count(c) == 1 + ]])) + + ok(exec_lua([[ + local a = vim.empty_dict() + local b = {} + local c = vim.tbl_extend("keep", a, b) + + return not vim.tbl_islist(c) and vim.tbl_count(c) == 0 + ]])) + + ok(exec_lua([[ + local a = {} + local b = vim.empty_dict() + local c = vim.tbl_extend("keep", a, b) + + return vim.tbl_islist(c) and vim.tbl_count(c) == 0 + ]])) + + eq('Error executing lua: .../shared.lua: invalid "behavior": nil', + pcall_err(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, [[ + 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, [[ + return vim.tbl_extend("keep", {}) + ]]) + ) + end) + + it('vim.tbl_count', function() + eq(0, exec_lua [[ return vim.tbl_count({}) ]]) + eq(0, exec_lua [[ return vim.tbl_count(vim.empty_dict()) ]]) + eq(0, exec_lua [[ return vim.tbl_count({nil}) ]]) + eq(0, exec_lua [[ return vim.tbl_count({a=nil}) ]]) + eq(1, exec_lua [[ return vim.tbl_count({1}) ]]) + eq(2, exec_lua [[ return vim.tbl_count({1, 2}) ]]) + eq(2, exec_lua [[ return vim.tbl_count({1, nil, 3}) ]]) + eq(1, exec_lua [[ return vim.tbl_count({a=1}) ]]) + eq(2, exec_lua [[ return vim.tbl_count({a=1, b=2}) ]]) + eq(2, exec_lua [[ return vim.tbl_count({a=1, b=nil, c=3}) ]]) + end) + it('vim.deep_equal', function() eq(true, exec_lua [[ return vim.deep_equal({a=1}, {a=1}) ]]) eq(true, exec_lua [[ return vim.deep_equal({a={b=1}}, {a={b=1}}) ]]) @@ -545,6 +686,8 @@ describe('lua stdlib', function() ]])) eq("{ {}, vim.empty_dict() }", exec_lua("return vim.inspect({{}, vim.empty_dict()})")) + eq('{}', exec_lua([[ return vim.fn.json_encode(vim.empty_dict()) ]])) + eq('{"a": {}, "b": []}', exec_lua([[ return vim.fn.json_encode({a=vim.empty_dict(), b={}}) ]])) end) it('vim.validate', function() @@ -700,4 +843,22 @@ describe('lua stdlib', function() eq('2', funcs.luaeval "BUF") eq(2, funcs.luaeval "#vim.api.nvim_list_bufs()") end) + + it('vim.regex', function() + exec_lua [[ + re1 = vim.regex"ab\\+c" + vim.cmd "set nomagic ignorecase" + re2 = vim.regex"xYz" + ]] + eq({}, exec_lua[[return {re1:match_str("x ac")}]]) + eq({3,7}, exec_lua[[return {re1:match_str("ac abbc")}]]) + + meths.buf_set_lines(0, 0, -1, true, {"yy", "abc abbc"}) + eq({}, exec_lua[[return {re1:match_line(0, 0)}]]) + eq({0,3}, exec_lua[[return {re1:match_line(0, 1)}]]) + eq({3,7}, exec_lua[[return {re1:match_line(0, 1, 1)}]]) + eq({3,7}, exec_lua[[return {re1:match_line(0, 1, 1, 8)}]]) + eq({}, exec_lua[[return {re1:match_line(0, 1, 1, 7)}]]) + eq({0,3}, exec_lua[[return {re1:match_line(0, 1, 0, 7)}]]) + end) end) diff --git a/test/functional/normal/put_spec.lua b/test/functional/normal/put_spec.lua index 357fafec44..26967ecbba 100644 --- a/test/functional/normal/put_spec.lua +++ b/test/functional/normal/put_spec.lua @@ -6,8 +6,8 @@ local insert = helpers.insert local feed = helpers.feed local expect = helpers.expect local eq = helpers.eq -local map = helpers.map -local filter = helpers.filter +local map = helpers.tbl_map +local filter = helpers.tbl_filter local feed_command = helpers.feed_command local curbuf_contents = helpers.curbuf_contents local funcs = helpers.funcs diff --git a/test/functional/options/num_options_spec.lua b/test/functional/options/num_options_spec.lua index deda5c9118..4754c14f5b 100644 --- a/test/functional/options/num_options_spec.lua +++ b/test/functional/options/num_options_spec.lua @@ -65,14 +65,12 @@ describe(':set validation', function() should_succeed('regexpengine', 2) should_fail('report', -1, 'E487') should_succeed('report', 0) - should_fail('scrolloff', -1, 'E49') - should_fail('sidescrolloff', -1, 'E487') should_fail('sidescroll', -1, 'E487') should_fail('cmdwinheight', 0, 'E487') should_fail('updatetime', -1, 'E487') should_fail('foldlevel', -5, 'E487') - should_fail('foldcolumn', 13, 'E474') + should_fail('foldcolumn', '13', 'E474') should_fail('conceallevel', 4, 'E474') should_fail('numberwidth', 21, 'E474') should_fail('numberwidth', 0, 'E487') @@ -82,6 +80,22 @@ describe(':set validation', function() meths.set_option('window', -10) eq(23, meths.get_option('window')) eq('', eval("v:errmsg")) + + -- 'scrolloff' and 'sidescrolloff' can have a -1 value when + -- set for the current window, but not globally + feed_command('setglobal scrolloff=-1') + eq('E487', eval("v:errmsg"):match("E%d*")) + + feed_command('setglobal sidescrolloff=-1') + eq('E487', eval("v:errmsg"):match("E%d*")) + + feed_command('let v:errmsg=""') + + feed_command('setlocal scrolloff=-1') + eq('', eval("v:errmsg")) + + feed_command('setlocal sidescrolloff=-1') + eq('', eval("v:errmsg")) end) it('set wmh/wh wmw/wiw checks', function() diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 4829a33861..a57443f909 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -1,12 +1,13 @@ local helpers = require('test.functional.helpers')(after_each) +local assert_log = helpers.assert_log local clear = helpers.clear local buf_lines = helpers.buf_lines local dedent = helpers.dedent local exec_lua = helpers.exec_lua local eq = helpers.eq +local pesc = helpers.pesc local insert = helpers.insert -local iswin = helpers.iswin local retry = helpers.retry local NIL = helpers.NIL @@ -14,20 +15,27 @@ local NIL = helpers.NIL -- yield. local run, stop = helpers.run, helpers.stop +-- TODO(justinmk): hangs on Windows https://github.com/neovim/neovim/pull/11837 if helpers.pending_win32(pending) then return end -local lsp_test_rpc_server_file = "test/functional/fixtures/lsp-test-rpc-server.lua" -if iswin() then - lsp_test_rpc_server_file = lsp_test_rpc_server_file:gsub("/", "\\") -end +-- Fake LSP server. +local fake_lsp_code = 'test/functional/fixtures/fake-lsp-server.lua' +local fake_lsp_logfile = 'Xtest-fake-lsp.log' + +teardown(function() + os.remove(fake_lsp_logfile) +end) -local function test_rpc_server_setup(test_name, timeout_ms) +local function fake_lsp_server_setup(test_name, timeout_ms) exec_lua([=[ lsp = require('vim.lsp') - local test_name, fixture_filename, timeout = ... + local test_name, fixture_filename, logfile, timeout = ... TEST_RPC_CLIENT_ID = lsp.start_client { + cmd_env = { + NVIM_LOG_FILE = logfile; + }; cmd = { - vim.api.nvim_get_vvar("progpath"), '-Es', '-u', 'NONE', '--headless', + vim.v.progpath, '-Es', '-u', 'NONE', '--headless', "-c", string.format("lua TEST_NAME = %q", test_name), "-c", string.format("lua TIMEOUT = %d", timeout), "-c", "luafile "..fixture_filename, @@ -48,13 +56,13 @@ local function test_rpc_server_setup(test_name, timeout_ms) vim.rpcnotify(1, "exit", ...) end; } - ]=], test_name, lsp_test_rpc_server_file, timeout_ms or 1e3) + ]=], test_name, fake_lsp_code, fake_lsp_logfile, timeout_ms or 1e3) end local function test_rpc_server(config) if config.test_name then clear() - test_rpc_server_setup(config.test_name, config.timeout_ms or 1e3) + fake_lsp_server_setup(config.test_name, config.timeout_ms or 1e3) end local client = setmetatable({}, { __index = function(_, name) @@ -114,11 +122,14 @@ describe('LSP', function() local test_name = "basic_init" exec_lua([=[ lsp = require('vim.lsp') - local test_name, fixture_filename = ... + local test_name, fixture_filename, logfile = ... function test__start_client() return lsp.start_client { + cmd_env = { + NVIM_LOG_FILE = logfile; + }; cmd = { - vim.api.nvim_get_vvar("progpath"), '-Es', '-u', 'NONE', '--headless', + vim.v.progpath, '-Es', '-u', 'NONE', '--headless', "-c", string.format("lua TEST_NAME = %q", test_name), "-c", "luafile "..fixture_filename; }; @@ -126,7 +137,7 @@ describe('LSP', function() } end TEST_CLIENT1 = test__start_client() - ]=], test_name, lsp_test_rpc_server_file) + ]=], test_name, fake_lsp_code, fake_lsp_logfile) end) after_each(function() @@ -195,7 +206,8 @@ describe('LSP', function() end; -- If the program timed out, then code will be nil. on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; -- Note that NIL must be used here. -- on_callback(err, method, result, client_id) @@ -216,7 +228,10 @@ describe('LSP', function() client.stop() end; on_exit = function(code, signal) - eq(1, code, "exit code") eq(0, signal, "exit signal") + eq(101, code, "exit code", fake_lsp_logfile) -- See fake-lsp-server.lua + eq(0, signal, "exit signal", fake_lsp_logfile) + assert_log(pesc([[assert_eq failed: left == "\"shutdown\"", right == "\"test\""]]), + fake_lsp_logfile) end; on_callback = function(...) eq(table.remove(expected_callbacks), {...}, "expected callback") @@ -226,7 +241,7 @@ describe('LSP', function() it('should succeed with manual shutdown', function() local expected_callbacks = { - {NIL, "shutdown", {}, 1}; + {NIL, "shutdown", {}, 1, NIL}; {NIL, "test", {}, 1}; } test_rpc_server { @@ -237,7 +252,8 @@ describe('LSP', function() client.notify('exit') end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(...) eq(table.remove(expected_callbacks), {...}, "expected callback") @@ -255,7 +271,8 @@ describe('LSP', function() client.stop() end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(...) eq(table.remove(expected_callbacks), {...}, "expected callback") @@ -294,7 +311,8 @@ describe('LSP', function() client.notify('finish') end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback") @@ -336,7 +354,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) if method == 'start' then @@ -378,7 +397,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) if method == 'start' then @@ -420,7 +440,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) if method == 'start' then @@ -468,7 +489,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) if method == 'start' then @@ -516,7 +538,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) if method == 'start' then @@ -536,7 +559,7 @@ describe('LSP', function() end) -- TODO(askhan) we don't support full for now, so we can disable these tests. - pending('should check the body and didChange incremental normal mode editting', function() + pending('should check the body and didChange incremental normal mode editing', function() local expected_callbacks = { {NIL, "shutdown", {}, 1}; {NIL, "finish", {}, 1}; @@ -544,7 +567,7 @@ describe('LSP', function() } local client test_rpc_server { - test_name = "basic_check_buffer_open_and_change_incremental_editting"; + test_name = "basic_check_buffer_open_and_change_incremental_editing"; on_setup = function() exec_lua [[ BUFFER = vim.api.nvim_create_buf(false, true) @@ -564,7 +587,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) if method == 'start' then @@ -607,7 +631,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) if method == 'start' then @@ -657,7 +682,8 @@ describe('LSP', function() ]] end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) if method == 'start' then @@ -699,7 +725,8 @@ describe('LSP', function() client.stop(true) end; on_exit = function(code, signal) - eq(0, code, "exit code") eq(0, signal, "exit signal") + eq(0, code, "exit code", fake_lsp_logfile) + eq(0, signal, "exit signal", fake_lsp_logfile) end; on_callback = function(err, method, params, client_id) eq(table.remove(expected_callbacks), {err, method, params, client_id}, "expected callback") @@ -785,4 +812,53 @@ describe('LSP', function() }, buf_lines(1)) end) end) + + describe('completion_list_to_complete_items', function() + -- Completion option precedence: + -- textEdit.newText > insertText > label + -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion + it('should choose right completion option', function () + local prefix = 'foo' + local completion_list = { + -- resolves into label + { label='foobar' }, + { label='foobar', textEdit={} }, + -- resolves into insertText + { label='foocar', insertText='foobar' }, + { label='foocar', insertText='foobar', textEdit={} }, + -- resolves into textEdit.newText + { label='foocar', insertText='foodar', textEdit={newText='foobar'} }, + { label='foocar', textEdit={newText='foobar'} } + } + local completion_list_items = {items=completion_list} + local expected = { + { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = '', menu = '', word = 'foobar'}, + { abbr = 'foobar', dup = 1, empty = 1, icase = 1, info = ' ', kind = '', menu = '', word = 'foobar'}, + { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = '', menu = '', word = 'foobar'}, + { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = '', menu = '', word = 'foobar'}, + { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = '', menu = '', word = 'foobar'}, + { abbr = 'foocar', dup = 1, empty = 1, icase = 1, info = ' ', kind = '', menu = '', word = 'foobar'}, + } + + eq(expected, exec_lua([[return vim.lsp.util.text_document_completion_list_to_complete_items(...)]], completion_list, prefix)) + eq(expected, exec_lua([[return vim.lsp.util.text_document_completion_list_to_complete_items(...)]], completion_list_items, prefix)) + eq({}, exec_lua([[return vim.lsp.util.text_document_completion_list_to_complete_items(...)]], {}, prefix)) + end) + end) + describe('buf_diagnostics_save_positions', function() + it('stores the diagnostics in diagnostics_by_buf', function () + local diagnostics = { + { range = {}; message = "diag1" }, + { range = {}; message = "diag2" }, + } + exec_lua([[ + vim.lsp.util.buf_diagnostics_save_positions(...)]], 0, diagnostics) + eq(1, exec_lua [[ return #vim.lsp.util.diagnostics_by_buf ]]) + eq(diagnostics, exec_lua [[ + for _, diagnostics in pairs(vim.lsp.util.diagnostics_by_buf) do + return diagnostics + end + ]]) + end) + end) end) diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua index ee3db7ae97..0eb5901b3b 100644 --- a/test/functional/terminal/mouse_spec.lua +++ b/test/functional/terminal/mouse_spec.lua @@ -87,6 +87,36 @@ describe(':terminal mouse', function() {3:-- TERMINAL --} | ]]) end) + + it('will forward mouse clicks to the program with the correct even if set nu', function() + if helpers.pending_win32(pending) then return end + nvim('command', 'set number') + -- When the display area such as a number is clicked, it returns to the + -- normal mode. + feed('<LeftMouse><3,0>') + eq('n', eval('mode()')) + screen:expect([[ + {7: 11 }^line28 | + {7: 12 }line29 | + {7: 13 }line30 | + {7: 14 }mouse enabled | + {7: 15 }rows: 6, cols: 46 | + {7: 16 }{2: } | + | + ]]) + -- If click on the coordinate (0,1) of the region of the terminal + -- (i.e. the coordinate (4,1) of vim), 'CSI !"' is sent to the terminal. + feed('i<LeftMouse><4,1>') + screen:expect([[ + {7: 11 }line28 | + {7: 12 }line29 | + {7: 13 }line30 | + {7: 14 }mouse enabled | + {7: 15 }rows: 6, cols: 46 | + {7: 16 } !"{1: } | + {3:-- TERMINAL --} | + ]]) + end) end) describe('with a split window and other buffer', function() @@ -148,7 +178,7 @@ describe(':terminal mouse', function() end) it('wont lose focus if another window is scrolled', function() - feed('<ScrollWheelUp><0,0><ScrollWheelUp><0,0>') + feed('<ScrollWheelUp><4,0><ScrollWheelUp><4,0>') screen:expect([[ {7: 21 }line │line30 | {7: 22 }line │rows: 5, cols: 25 | @@ -158,7 +188,7 @@ describe(':terminal mouse', function() ========== ========== | {3:-- TERMINAL --} | ]]) - feed('<S-ScrollWheelDown><0,0>') + feed('<S-ScrollWheelDown><4,0>') screen:expect([[ {7: 26 }line │line30 | {7: 27 }line │rows: 5, cols: 25 | diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 7a5569c14b..639e311ae6 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -976,6 +976,28 @@ describe('floatwin', function() {2:~ }| ]], float_pos={ [5] = {{id = 1002}, "NE", 4, 0, 50, true} + }, win_viewport = { + [2] = { + topline = 0, + botline = 3, + curline = 0, + curcol = 3, + win = { id = 1000 } + }, + [4] = { + topline = 0, + botline = 3, + curline = 0, + curcol = 3, + win = { id = 1001 } + }, + [5] = { + topline = 0, + botline = 2, + curline = 0, + curcol = 0, + win = { id = 1002 } + } }} else screen:expect([[ diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index 0b788e7afb..6ec45064da 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -96,8 +96,20 @@ describe("folded lines", function() {1: ~}| :set rightleft | ]]} - end) + feed_command("set norightleft") + meths.input_mouse('left', 'press', '', 0, 0, 1) + screen:expect{grid=[[ + {7:▾▸}{5:^+--- 5 lines: aa··························}| + {7:│ }ff | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + :set norightleft | + ]]} + end) it("works with multibyte text", function() -- Currently the only allowed value of 'maxcombine' @@ -283,4 +295,64 @@ describe("folded lines", function() ]]) end) + + it("work with autoresize", function() + + funcs.setline(1, 'line 1') + funcs.setline(2, 'line 2') + funcs.setline(3, 'line 3') + funcs.setline(4, 'line 4') + + feed("zfj") + command("set foldcolumn=0") + screen:expect{grid=[[ + {5:^+-- 2 lines: line 1·························}| + line 3 | + line 4 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + -- should adapt to the current nesting of folds (e.g., 1) + command("set foldcolumn=auto:1") + screen:expect{grid=[[ + {7:+}{5:^+-- 2 lines: line 1························}| + {7: }line 3 | + {7: }line 4 | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + -- fdc should not change with a new fold as the maximum is 1 + feed("zf3j") + + screen:expect{grid=[[ + {7:+}{5:^+-- 4 lines: line 1························}| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + + -- relax the maximum fdc thus fdc should expand to + -- accomodate the current number of folds + command("set foldcolumn=auto:4") + screen:expect{grid=[[ + {7:+ }{5:^+-- 4 lines: line 1·······················}| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + | + ]]} + end) end) diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 0b822bc2f2..efc02db159 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -969,6 +969,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim -- edge case: only one window was set NOT_VALID. Orginal report -- used :make, but fake it using one command to set the current -- window NOT_VALID and another to show a long message. + command("set more") feed(':new<cr><c-w><c-w>') screen:expect{grid=[[ | @@ -982,16 +983,16 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim feed(':set colorcolumn=10 | digraphs<cr>') screen:expect{grid=[[ - er {5:ㄦ} 12582 i4 {5:ㄧ} 12583 u4 {5:ㄨ} 12584 iu {5:ㄩ} 12585 | - v4 {5:ㄪ} 12586 nG {5:ㄫ} 12587 gn {5:ㄬ} 12588 1c {5:㈠} 12832 | - 2c {5:㈡} 12833 3c {5:㈢} 12834 4c {5:㈣} 12835 5c {5:㈤} 12836 | - 6c {5:㈥} 12837 7c {5:㈦} 12838 8c {5:㈧} 12839 9c {5:㈨} 12840 | - ff {5:ff} 64256 fi {5:fi} 64257 fl {5:fl} 64258 ft {5:ſt} 64261 | - st {5:st} 64262 | - {4:Press ENTER or type command to continue}^ | + :set colorcolumn=10 | digraphs | + NU {5:^@} 10 SH {5:^A} 1 SX {5:^B} 2 EX {5:^C} 3 | + ET {5:^D} 4 EQ {5:^E} 5 AK {5:^F} 6 BL {5:^G} 7 | + BS {5:^H} 8 HT {5:^I} 9 LF {5:^@} 10 VT {5:^K} 11 | + FF {5:^L} 12 CR {5:^M} 13 SO {5:^N} 14 SI {5:^O} 15 | + DL {5:^P} 16 D1 {5:^Q} 17 D2 {5:^R} 18 D3 {5:^S} 19 | + {4:-- More --}^ | ]]} - feed('<cr>') + feed('q') screen:expect{grid=[[ | {1:~ }| diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua index 01ffe80be3..e4d1187dea 100644 --- a/test/functional/ui/multigrid_spec.lua +++ b/test/functional/ui/multigrid_spec.lua @@ -1962,4 +1962,191 @@ describe('ext_multigrid', function() {1:~ }| ]]} end) + + it('has viewport information', function() + screen:try_resize(48, 8) + screen:expect{grid=[[ + ## grid 1 + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + {11:[No Name] }| + [3:------------------------------------------------]| + ## grid 2 + ^ | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + ## grid 3 + | + ]], win_viewport={ + [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0} + }} + insert([[ + Lorem ipsum dolor sit amet, consectetur + adipisicing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex + ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum + dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa + qui officia deserunt mollit anim id est + laborum.]]) + + screen:expect{grid=[[ + ## grid 1 + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + {11:[No Name] [+] }| + [3:------------------------------------------------]| + ## grid 2 + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + occaecat cupidatat non proident, sunt in culpa | + qui officia deserunt mollit anim id est | + laborum^. | + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7}, + }} + + + feed('<c-u>') + screen:expect{grid=[[ + ## grid 1 + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + {11:[No Name] [+] }| + [3:------------------------------------------------]| + ## grid 2 + incididunt ut labore et dolore magna aliqua. | + Ut enim ad minim veniam, quis nostrud | + exercitation ullamco laboris nisi ut aliquip ex | + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse cillum | + ^dolore eu fugiat nulla pariatur. Excepteur sint | + ## grid 3 + | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 2, botline = 9, curline = 7, curcol = 0}, + }} + + command("split") + screen:expect{grid=[[ + ## grid 1 + [4:------------------------------------------------]| + [4:------------------------------------------------]| + [4:------------------------------------------------]| + {11:[No Name] [+] }| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + {12:[No Name] [+] }| + [3:------------------------------------------------]| + ## grid 2 + reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + ## grid 3 + | + ## grid 4 + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse cillum | + ^dolore eu fugiat nulla pariatur. Excepteur sint | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0}, + [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 7, curcol = 0}, + }} + + feed("b") + screen:expect{grid=[[ + ## grid 1 + [4:------------------------------------------------]| + [4:------------------------------------------------]| + [4:------------------------------------------------]| + {11:[No Name] [+] }| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + {12:[No Name] [+] }| + [3:------------------------------------------------]| + ## grid 2 + reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + ## grid 3 + | + ## grid 4 + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse ^cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0}, + [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 6, curcol = 38}, + }} + + feed("2k") + screen:expect{grid=[[ + ## grid 1 + [4:------------------------------------------------]| + [4:------------------------------------------------]| + [4:------------------------------------------------]| + {11:[No Name] [+] }| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + {12:[No Name] [+] }| + [3:------------------------------------------------]| + ## grid 2 + reprehenderit in voluptate velit esse cillum | + dolore eu fugiat nulla pariatur. Excepteur sint | + ## grid 3 + | + ## grid 4 + exercitation ullamco laboris nisi ut a^liquip ex | + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse cillum | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0}, + [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38}, + }} + + -- handles non-current window + meths.win_set_cursor(1000, {1, 10}) + screen:expect{grid=[[ + ## grid 1 + [4:------------------------------------------------]| + [4:------------------------------------------------]| + [4:------------------------------------------------]| + {11:[No Name] [+] }| + [2:------------------------------------------------]| + [2:------------------------------------------------]| + {12:[No Name] [+] }| + [3:------------------------------------------------]| + ## grid 2 + Lorem ipsum dolor sit amet, consectetur | + adipisicing elit, sed do eiusmod tempor | + ## grid 3 + | + ## grid 4 + exercitation ullamco laboris nisi ut a^liquip ex | + ea commodo consequat. Duis aute irure dolor in | + reprehenderit in voluptate velit esse cillum | + ]], win_viewport={ + [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10}, + [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38}, + }} + end) end) diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua index 581e196bbb..9646c3fdad 100644 --- a/test/functional/ui/options_spec.lua +++ b/test/functional/ui/options_spec.lua @@ -20,6 +20,8 @@ describe('UI receives option updates', function() pumblend=0, showtabline=1, termguicolors=false, + ttimeout=true, + ttimeoutlen=50, ext_cmdline=false, ext_popupmenu=false, ext_tabline=false, @@ -108,6 +110,18 @@ describe('UI receives option updates', function() eq(expected, screen.options) end) + command("set nottimeout") + expected.ttimeout = false + screen:expect(function() + eq(expected, screen.options) + end) + + command("set ttimeoutlen=100") + expected.ttimeoutlen = 100 + screen:expect(function() + eq(expected, screen.options) + end) + command("set all&") screen:expect(function() eq(defaults, screen.options) diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index b2ebf7af19..11c3f4123e 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -1338,7 +1338,7 @@ describe('builtin popupmenu', function() end) it('with rightleft window', function() - command("set rl") + command("set rl wildoptions+=pum") feed('isome rightleft ') screen:expect([[ ^ tfelthgir emos| @@ -1435,6 +1435,55 @@ describe('builtin popupmenu', function() {1: ~}| {2:-- INSERT --} | ]]) + + -- not rightleft on the cmdline + feed('<esc>:sign ') + screen:expect{grid=[[ + drow tfelthgir emos| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + :sign ^ | + ]]} + + feed('<tab>') + screen:expect{grid=[[ + drow tfelthgir emos| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: ~}| + {1: }{s: define }{1: ~}| + {1: }{n: jump }{1: ~}| + {1: }{n: list }{1: ~}| + {1: }{n: place }{1: ~}| + {1: }{n: undefine }{1: ~}| + {1: }{n: unplace }{1: ~}| + :sign define^ | + ]]} end) it('with multiline messages', function() diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 64f784afe3..bf979e89f4 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -158,6 +158,7 @@ function Screen.new(width, height) wildmenu_items = nil, wildmenu_selected = nil, win_position = {}, + win_viewport = {}, float_pos = {}, msg_grid = nil, msg_grid_pos = nil, @@ -254,7 +255,7 @@ end -- canonical order of ext keys, used to generate asserts local ext_keys = { 'popupmenu', 'cmdline', 'cmdline_block', 'wildmenu_items', 'wildmenu_pos', - 'messages', 'showmode', 'showcmd', 'ruler', 'float_pos', + 'messages', 'showmode', 'showcmd', 'ruler', 'float_pos', 'win_viewport' } -- Asserts that the screen state eventually matches an expected state. @@ -421,6 +422,9 @@ screen:redraw_debug() to show all intermediate screen states. ]]) if expected.mode ~= nil then extstate.mode = self.mode end + if expected.win_viewport == nil then + extstate.win_viewport = nil + end -- Convert assertion errors into invalid screen state descriptions. for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do @@ -726,6 +730,7 @@ function Screen:_handle_grid_destroy(grid) self._grids[grid] = nil if self._options.ext_multigrid then self.win_position[grid] = nil + self.win_viewport[grid] = nil end end @@ -746,14 +751,24 @@ function Screen:_handle_grid_cursor_goto(grid, row, col) end function Screen:_handle_win_pos(grid, win, startrow, startcol, width, height) - self.win_position[grid] = { - win = win, - startrow = startrow, - startcol = startcol, - width = width, - height = height - } - self.float_pos[grid] = nil + self.win_position[grid] = { + win = win, + startrow = startrow, + startcol = startcol, + width = width, + height = height + } + self.float_pos[grid] = nil +end + +function Screen:_handle_win_viewport(grid, win, topline, botline, curline, curcol) + self.win_viewport[grid] = { + win = win, + topline = topline, + botline = botline, + curline = curline, + curcol = curcol + } end function Screen:_handle_win_float_pos(grid, ...) @@ -1130,6 +1145,8 @@ function Screen:_extstate_repr(attr_state) messages[i] = {kind=entry[1], content=self:_chunks_repr(entry[2], attr_state)} end + local win_viewport = (next(self.win_viewport) and self.win_viewport) or nil + return { popupmenu=self.popupmenu, cmdline=cmdline, @@ -1141,7 +1158,8 @@ function Screen:_extstate_repr(attr_state) showcmd=self:_chunks_repr(self.showcmd, attr_state), ruler=self:_chunks_repr(self.ruler, attr_state), msg_history=msg_history, - float_pos=self.float_pos + float_pos=self.float_pos, + win_viewport=win_viewport, } end @@ -1216,10 +1234,6 @@ function Screen:render(headers, attr_state, preview) return rv end -local remove_all_metatables = function(item, path) - if path[#path] ~= inspect.METATABLE then return item end -end - -- Returns the current screen state in the form of a screen:expect() -- keyword-args map. function Screen:get_snapshot(attrs, ignore) @@ -1269,6 +1283,26 @@ function Screen:get_snapshot(attrs, ignore) return kwargs, ext_state, attr_state end +local function fmt_ext_state(name, state) + if name == "win_viewport" then + local str = "{\n" + for k,v in pairs(state) do + str = (str.." ["..k.."] = {win = {id = "..v.win.id.."}, topline = " + ..v.topline..", botline = "..v.botline..", curline = "..v.curline + ..", curcol = "..v.curcol.."},\n") + end + return str .. "}" + else + -- TODO(bfredl): improve formatting of more states + local function remove_all_metatables(item, path) + if path[#path] ~= inspect.METATABLE then + return item + end + end + return inspect(state,{process=remove_all_metatables}) + end +end + function Screen:print_snapshot(attrs, ignore) local kwargs, ext_state, attr_state = self:get_snapshot(attrs, ignore) local attrstr = "" @@ -1291,9 +1325,8 @@ function Screen:print_snapshot(attrs, ignore) print(kwargs.grid) io.stdout:write( "]]"..attrstr) for _, k in ipairs(ext_keys) do - if ext_state[k] ~= nil then - -- TODO(bfredl): improve formatting - io.stdout:write(", "..k.."="..inspect(ext_state[k],{process=remove_all_metatables})) + if ext_state[k] ~= nil and not (k == "win_viewport" and not self.options.ext_multigrid) then + io.stdout:write(", "..k.."="..fmt_ext_state(k, ext_state[k])) end end print("}\n") diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index 56987d7bc2..99ebc4971e 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -16,6 +16,44 @@ describe("'wildmenu'", function() screen:attach() end) + it('C-E to cancel wildmenu completion restore original input', function() + feed(':sign <tab>') + screen:expect([[ + | + ~ | + ~ | + define jump list > | + :sign define^ | + ]]) + feed('<C-E>') + screen:expect([[ + | + ~ | + ~ | + ~ | + :sign ^ | + ]]) + end) + + it('C-Y to apply selection and end wildmenu completion', function() + feed(':sign <tab>') + screen:expect([[ + | + ~ | + ~ | + define jump list > | + :sign define^ | + ]]) + feed('<tab><C-Y>') + screen:expect([[ + | + ~ | + ~ | + ~ | + :sign jump^ | + ]]) + end) + it(':sign <tab> shows wildmenu completions', function() command('set wildmenu wildmode=full') feed(':sign <tab>') diff --git a/test/helpers.lua b/test/helpers.lua index 98f003f208..40b93d9935 100644 --- a/test/helpers.lua +++ b/test/helpers.lua @@ -55,17 +55,32 @@ local check_logs_useless_lines = { ['See README_MISSING_SYSCALL_OR_IOCTL for guidance']=3, } -function module.eq(expected, actual, context) - return assert.are.same(expected, actual, context) +--- Invokes `fn` and includes the tail of `logfile` in the error message if it +--- fails. +--- +--@param logfile Log file, defaults to $NVIM_LOG_FILE or '.nvimlog' +--@param fn Function to invoke +--@param ... Function arguments +local function dumplog(logfile, fn, ...) + -- module.validate({ + -- logfile={logfile,'s',true}, + -- fn={fn,'f',false}, + -- }) + local status, rv = pcall(fn, ...) + if status == false then + logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog' + local logtail = module.read_nvim_log(logfile) + error(string.format('%s\n%s', rv, logtail)) + end end -function module.neq(expected, actual, context) - return assert.are_not.same(expected, actual, context) +function module.eq(expected, actual, context, logfile) + return dumplog(logfile, assert.are.same, expected, actual, context) end -function module.ok(res, msg) - return assert.is_true(res, msg) +function module.neq(expected, actual, context, logfile) + return dumplog(logfile, assert.are_not.same, expected, actual, context) end -function module.near(actual, expected, tolerance) - return assert.is.near(actual, expected, tolerance) +function module.ok(res, msg, logfile) + return dumplog(logfile, assert.is_true, res, msg) end function module.matches(pat, actual) if nil ~= string.match(actual, pat) then @@ -74,6 +89,22 @@ function module.matches(pat, actual) error(string.format('Pattern does not match.\nPattern:\n%s\nActual:\n%s', pat, actual)) end +--- Asserts that `pat` matches one or more lines in the tail of $NVIM_LOG_FILE. +--- +--@param pat (string) Lua pattern to search for in the log file. +--@param logfile (string, default=$NVIM_LOG_FILE) full path to log file. +function module.assert_log(pat, logfile) + logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog' + local nrlines = 10 + local lines = module.read_file_list(logfile, -nrlines) or {} + for _,line in ipairs(lines) do + if line:match(pat) then return end + end + local logtail = module.read_nvim_log(logfile) + error(string.format('Pattern %q not found in log (last %d lines): %s:\n%s', + pat, nrlines, logfile, logtail)) +end + -- Invokes `fn` and returns the error string (may truncate full paths), or -- raises an error if `fn` succeeds. -- @@ -259,24 +290,6 @@ module.tmpname = (function() end) end)() -function module.map(func, tab) - local rettab = {} - for k, v in pairs(tab) do - rettab[k] = func(v) - end - return rettab -end - -function module.filter(filter_func, tab) - local rettab = {} - for _, entry in pairs(tab) do - if filter_func(entry) then - table.insert(rettab, entry) - end - end - return rettab -end - function module.hasenv(name) local env = os.getenv(name) if env and env ~= '' then @@ -737,10 +750,10 @@ function module.isCI(name) end --- Gets the contents of $NVIM_LOG_FILE for printing to the build log. +-- Gets the (tail) contents of `logfile`. -- Also moves the file to "${NVIM_LOG_FILE}.displayed" on CI environments. -function module.read_nvim_log() - local logfile = os.getenv('NVIM_LOG_FILE') or '.nvimlog' +function module.read_nvim_log(logfile, ci_rename) + logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog' local is_ci = module.isCI() local keep = is_ci and 999 or 10 local lines = module.read_file_list(logfile, -keep) or {} @@ -751,7 +764,7 @@ function module.read_nvim_log() log = log..line..'\n' end log = log..('-'):rep(78)..'\n' - if is_ci then + if is_ci and ci_rename then os.rename(logfile, logfile .. '.displayed') end return log diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua index 4535d6a0b2..1651eb9bcc 100644 --- a/test/unit/eval/typval_spec.lua +++ b/test/unit/eval/typval_spec.lua @@ -14,7 +14,7 @@ local cimport = helpers.cimport local to_cstr = helpers.to_cstr local alloc_log_new = helpers.alloc_log_new local concat_tables = helpers.concat_tables -local map = helpers.map +local map = helpers.tbl_map local a = eval_helpers.alloc_logging_helpers local int = eval_helpers.int diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua index bacdc54416..a77a089763 100644 --- a/test/unit/helpers.lua +++ b/test/unit/helpers.lua @@ -13,7 +13,7 @@ local syscall = nil local check_cores = global_helpers.check_cores local dedent = global_helpers.dedent local neq = global_helpers.neq -local map = global_helpers.map +local map = global_helpers.tbl_map local eq = global_helpers.eq local trim = global_helpers.trim |