diff options
Diffstat (limited to 'test')
227 files changed, 5720 insertions, 768 deletions
diff --git a/test/benchmark/bench_re_freeze_spec.lua b/test/benchmark/bench_re_freeze_spec.lua index d40d9f9ece..a194b5f44c 100644 --- a/test/benchmark/bench_re_freeze_spec.lua +++ b/test/benchmark/bench_re_freeze_spec.lua @@ -25,8 +25,8 @@ local measure_script = [[ endfunc]] describe('regexp search', function() - -- The test cases rely on a small Vim script, which we source here, and also - -- on a temporary result file, which we prepare and write to disk. + -- The test cases rely on a temporary result file, which we prepare and write + -- to disk. setup(function() clear() source(measure_script) diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index 0eefa25a13..cf8a83ad81 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -1,5 +1,5 @@ -- Sanity checks for buffer_* API calls via msgpack-rpc -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq local curbufmeths, ok = helpers.curbufmeths, helpers.ok diff --git a/test/functional/api/menu_spec.lua b/test/functional/api/menu_spec.lua index 5b414fb559..d55b7b118a 100644 --- a/test/functional/api/menu_spec.lua +++ b/test/functional/api/menu_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear = helpers.clear diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua index 6791fbb4ba..88e8c60560 100644 --- a/test/functional/api/server_notifications_spec.lua +++ b/test/functional/api/server_notifications_spec.lua @@ -1,8 +1,9 @@ -- Tests for nvim notifications -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eq, clear, eval, execute, nvim, next_message = helpers.eq, helpers.clear, helpers.eval, helpers.execute, helpers.nvim, helpers.next_message +local meths = helpers.meths describe('notify', function() local channel @@ -36,5 +37,33 @@ describe('notify', function() eval('rpcnotify(0, "event1", 13, 14, 15)') eq({'notification', 'event1', {13, 14, 15}}, next_message()) end) + + it('does not crash for deeply nested variable', function() + meths.set_var('l', {}) + local nest_level = 1000 + meths.command(('call map(range(%u), "extend(g:, {\'l\': [g:l]})")'):format(nest_level - 1)) + eval('rpcnotify('..channel..', "event", g:l)') + local msg = next_message() + eq('notification', msg[1]) + eq('event', msg[2]) + local act_ret = msg[3] + local act_nest_level = 0 + while act_ret do + if type(act_ret) == 'table' then + local cur_act_ret = nil + for k, v in pairs(act_ret) do + eq(1, k) + cur_act_ret = v + end + if cur_act_ret then + act_nest_level = act_nest_level + 1 + end + act_ret = cur_act_ret + else + eq(nil, act_ret) + end + end + eq(nest_level, act_nest_level) + end) end) end) diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua index 1b33275803..54095112fb 100644 --- a/test/functional/api/server_requests_spec.lua +++ b/test/functional/api/server_requests_spec.lua @@ -1,7 +1,7 @@ -- Tests for some server->client RPC scenarios. Note that unlike with -- `rpcnotify`, to evaluate `rpcrequest` calls we need the client event loop to -- be running. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, nvim, eval = helpers.clear, helpers.nvim, helpers.eval local eq, neq, run, stop = helpers.eq, helpers.neq, helpers.run, helpers.stop local nvim_prog = helpers.nvim_prog diff --git a/test/functional/api/tabpage_spec.lua b/test/functional/api/tabpage_spec.lua index c782107714..7b97c7f067 100644 --- a/test/functional/api/tabpage_spec.lua +++ b/test/functional/api/tabpage_spec.lua @@ -1,5 +1,5 @@ -- Sanity checks for tabpage_* API calls via msgpack-rpc -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, nvim, tabpage, curtab, eq, ok = helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq, helpers.ok diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 20de6d0072..c4976ea06b 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -1,5 +1,5 @@ -- Sanity checks for vim_* API calls via msgpack-rpc -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local NIL = helpers.NIL local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 92a33b4cdb..d90323181c 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -1,5 +1,5 @@ -- Sanity checks for window_* API calls via msgpack-rpc -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq, ok, feed, insert, eval = helpers.clear, helpers.nvim, helpers.curbuf, helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq, diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 3c813abc2e..72aff58d73 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local command = helpers.command diff --git a/test/functional/autocmd/tabclose_spec.lua b/test/functional/autocmd/tabclose_spec.lua index bf609d1846..65182ad859 100644 --- a/test/functional/autocmd/tabclose_spec.lua +++ b/test/functional/autocmd/tabclose_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, nvim, eq = helpers.clear, helpers.nvim, helpers.eq describe('TabClosed', function() diff --git a/test/functional/autocmd/tabnew_spec.lua b/test/functional/autocmd/tabnew_spec.lua index aaf9db0a99..8c94dee49b 100644 --- a/test/functional/autocmd/tabnew_spec.lua +++ b/test/functional/autocmd/tabnew_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local command = helpers.command diff --git a/test/functional/autocmd/tabnewentered_spec.lua b/test/functional/autocmd/tabnewentered_spec.lua index 64b9a22f41..53bbca9f39 100644 --- a/test/functional/autocmd/tabnewentered_spec.lua +++ b/test/functional/autocmd/tabnewentered_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, nvim, eq = helpers.clear, helpers.nvim, helpers.eq describe('TabNewEntered', function() diff --git a/test/functional/autocmd/termclose_spec.lua b/test/functional/autocmd/termclose_spec.lua index 4de3f039c1..02ea0dbd95 100644 --- a/test/functional/autocmd/termclose_spec.lua +++ b/test/functional/autocmd/termclose_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, execute, feed, nvim, nvim_dir = helpers.clear, diff --git a/test/functional/autocmd/textyankpost_spec.lua b/test/functional/autocmd/textyankpost_spec.lua index c26ceeaedc..bd5f1912c5 100644 --- a/test/functional/autocmd/textyankpost_spec.lua +++ b/test/functional/autocmd/textyankpost_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq local feed, execute, expect, command = helpers.feed, helpers.execute, helpers.expect, helpers.command local curbufmeths, funcs, neq = helpers.curbufmeths, helpers.funcs, helpers.neq diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua index 898ec556a2..b4febe4bfb 100644 --- a/test/functional/clipboard/clipboard_provider_spec.lua +++ b/test/functional/clipboard/clipboard_provider_spec.lua @@ -1,6 +1,6 @@ -- Test clipboard provider support -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect, eq, eval = helpers.execute, helpers.expect, helpers.eq, helpers.eval diff --git a/test/functional/dict_notifications_spec.lua b/test/functional/dict_notifications_spec.lua index 2540929126..dc87312911 100644 --- a/test/functional/dict_notifications_spec.lua +++ b/test/functional/dict_notifications_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, nvim, source = helpers.clear, helpers.nvim, helpers.source local eq, next_msg = helpers.eq, helpers.next_message local exc_exec = helpers.exc_exec diff --git a/test/functional/eval/capture_spec.lua b/test/functional/eval/capture_spec.lua new file mode 100644 index 0000000000..d9265f1b5b --- /dev/null +++ b/test/functional/eval/capture_spec.lua @@ -0,0 +1,86 @@ +local helpers = require('test.functional.helpers')(after_each) +local eq = helpers.eq +local eval = helpers.eval +local clear = helpers.clear +local source = helpers.source +local redir_exec = helpers.redir_exec +local exc_exec = helpers.exc_exec +local funcs = helpers.funcs +local Screen = require('test.functional.ui.screen') +local feed = helpers.feed + +describe('capture()', function() + before_each(clear) + + it('returns the same result with :redir', function() + eq(redir_exec('messages'), funcs.capture('messages')) + end) + + it('returns the output of the commands if the argument is List', function() + eq("foobar", funcs.capture({'echon "foo"', 'echon "bar"'})) + eq("\nfoo\nbar", funcs.capture({'echo "foo"', 'echo "bar"'})) + end) + + it('supports the nested redirection', function() + source([[ + function! g:Foo() + let a = '' + redir => a + silent echon "foo" + redir END + return a + endfunction + function! g:Bar() + let a = '' + redir => a + call g:Foo() + redir END + return a + endfunction + ]]) + eq('foo', funcs.capture('call g:Bar()')) + + eq('42', funcs.capture([[echon capture("echon capture('echon 42')")]])) + end) + + it('returns the transformed string', function() + eq('^A', funcs.capture('echon "\\<C-a>"')) + end) + + it('returns the empty string if the argument list is empty', function() + eq('', funcs.capture({})) + eq(0, exc_exec('let g:ret = capture(v:_null_list)')) + eq('', eval('g:ret')) + end) + + it('returns the errors', function() + local ret + ret = exc_exec('call capture(0.0)') + eq('Vim(call):E806: using Float as a String', ret) + ret = exc_exec('call capture(v:_null_dict)') + eq('Vim(call):E731: using Dictionary as a String', ret) + ret = exc_exec('call capture(function("tr"))') + eq('Vim(call):E729: using Funcref as a String', ret) + ret = exc_exec('call capture(["echo 42", 0.0, "echo 44"])') + eq('Vim(call):E806: using Float as a String', ret) + ret = exc_exec('call capture(["echo 42", v:_null_dict, "echo 44"])') + eq('Vim(call):E731: using Dictionary as a String', ret) + ret = exc_exec('call capture(["echo 42", function("tr"), "echo 44"])') + eq('Vim(call):E729: using Funcref as a String', ret) + end) + + it('silences command run inside', function() + local screen = Screen.new(20, 5) + screen:attach() + screen:set_default_attr_ignore({{bold=true, foreground=255}}) + feed(':let g:mes = capture("echon 42")<CR>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + | + ]]) + eq('42', eval('g:mes')) + end) +end) diff --git a/test/functional/eval/glob_spec.lua b/test/functional/eval/glob_spec.lua index c6bba46424..599b3dcdc3 100644 --- a/test/functional/eval/glob_spec.lua +++ b/test/functional/eval/glob_spec.lua @@ -1,5 +1,5 @@ local lfs = require('lfs') -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, eval, eq = helpers.clear, helpers.execute, helpers.eval, helpers.eq before_each(function() diff --git a/test/functional/eval/json_functions_spec.lua b/test/functional/eval/json_functions_spec.lua index b32688a9d2..159d775ff1 100644 --- a/test/functional/eval/json_functions_spec.lua +++ b/test/functional/eval/json_functions_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local funcs = helpers.funcs local meths = helpers.meths @@ -10,8 +10,8 @@ local redir_exec = helpers.redir_exec local NIL = helpers.NIL describe('json_decode() function', function() - local restart = function(cmd) - clear(cmd) + local restart = function(...) + clear(...) execute('language C') execute([[ function Eq(exp, act) @@ -490,13 +490,13 @@ describe('json_decode() function', function() end) it('converts strings to latin1 when &encoding is latin1', function() - restart('set encoding=latin1') + restart('--cmd', 'set encoding=latin1') eq('\171', funcs.json_decode('"\\u00AB"')) sp_decode_eq({_TYPE='string', _VAL={'\n\171\n'}}, '"\\u0000\\u00AB\\u0000"') end) it('fails to convert string to latin1 if it is impossible', function() - restart('set encoding=latin1') + restart('--cmd', 'set encoding=latin1') eq('Vim(call):E474: Failed to convert string "ꯍ" from UTF-8', exc_exec('call json_decode(\'"\\uABCD"\')')) end) @@ -532,7 +532,7 @@ describe('json_decode() function', function() -- When &encoding is latin1 string "«" is U+00C2 U+00AB U+00C2: «Â. So if -- '"«"' was parsed as latin1 json_decode would return three characters, and -- only one U+00AB when this string is parsed as latin1. - restart('set encoding=latin1') + restart('--cmd', 'set encoding=latin1') eq(('%c'):format(0xAB), funcs.json_decode('"«"')) end) @@ -763,7 +763,7 @@ describe('json_encode() function', function() end) it('converts strings from latin1 when &encoding is latin1', function() - clear('set encoding=latin1') + clear('--cmd', 'set encoding=latin1') eq('"\\u00AB"', funcs.json_encode('\171')) eq('"\\u0000\\u00AB\\u0000"', eval('json_encode({"_TYPE": v:msgpack_types.string, "_VAL": ["\\n\171\\n"]})')) end) diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/eval/msgpack_functions_spec.lua index 9e501353a5..5b87b05652 100644 --- a/test/functional/eval/msgpack_functions_spec.lua +++ b/test/functional/eval/msgpack_functions_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local funcs = helpers.funcs local eval, eq = helpers.eval, helpers.eq diff --git a/test/functional/eval/operators_spec.lua b/test/functional/eval/operators_spec.lua index bc9a17935c..4d07bc1b05 100644 --- a/test/functional/eval/operators_spec.lua +++ b/test/functional/eval/operators_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eq = helpers.eq local eval = helpers.eval local clear = helpers.clear diff --git a/test/functional/eval/printf_spec.lua b/test/functional/eval/printf_spec.lua index 6180f4156a..c84290ceef 100644 --- a/test/functional/eval/printf_spec.lua +++ b/test/functional/eval/printf_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq local funcs = helpers.funcs diff --git a/test/functional/eval/reltime_spec.lua b/test/functional/eval/reltime_spec.lua index da55a3fac3..0b19d372ec 100644 --- a/test/functional/eval/reltime_spec.lua +++ b/test/functional/eval/reltime_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, eq, ok = helpers.clear, helpers.eq, helpers.ok local neq, execute, funcs = helpers.neq, helpers.execute, helpers.funcs local reltime, reltimestr, reltimefloat = funcs.reltime, funcs.reltimestr, funcs.reltimefloat diff --git a/test/functional/eval/server_spec.lua b/test/functional/eval/server_spec.lua index 7f53522c08..0fd55ce2f9 100644 --- a/test/functional/eval/server_spec.lua +++ b/test/functional/eval/server_spec.lua @@ -1,5 +1,5 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim, eq, neq, eval = helpers.nvim, helpers.eq, helpers.neq, helpers.eval local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths local os_name = helpers.os_name diff --git a/test/functional/eval/special_vars_spec.lua b/test/functional/eval/special_vars_spec.lua index 2526483830..4c5d63ce23 100644 --- a/test/functional/eval/special_vars_spec.lua +++ b/test/functional/eval/special_vars_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local exc_exec = helpers.exc_exec local execute = helpers.execute local funcs = helpers.funcs diff --git a/test/functional/eval/string_spec.lua b/test/functional/eval/string_spec.lua index abda2c59cb..9e2dc4e111 100644 --- a/test/functional/eval/string_spec.lua +++ b/test/functional/eval/string_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq local command = helpers.command diff --git a/test/functional/eval/timer_spec.lua b/test/functional/eval/timer_spec.lua new file mode 100644 index 0000000000..a31e942cdf --- /dev/null +++ b/test/functional/eval/timer_spec.lua @@ -0,0 +1,129 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval +local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run +local clear, execute, funcs = helpers.clear, helpers.execute, helpers.funcs + +describe('timers', function() + before_each(function() + clear() + source([[ + let g:val = 0 + func MyHandler(timer) + let g:val += 1 + endfunc + ]]) + end) + + it('works one-shot', function() + execute("call timer_start(50, 'MyHandler')") + eq(0,eval("g:val")) + run(nil, nil, nil, 200) + eq(1,eval("g:val")) + end) + + it('works with repeat two', function() + execute("call timer_start(50, 'MyHandler', {'repeat': 2})") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + eq(2,eval("g:val")) + end) + + it('are triggered during sleep', function() + execute("call timer_start(50, 'MyHandler', {'repeat': 2})") + nvim_async("command", "sleep 10") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + eq(2,eval("g:val")) + end) + + it('can be started during sleep', function() + nvim_async("command", "sleep 10") + -- this also tests that remote requests works during sleep + eval("timer_start(50, 'MyHandler', {'repeat': 2})") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + eq(2,eval("g:val")) + end) + + it('are paused when event processing is disabled', function() + -- this is not the intended behavior, but at least there will + -- not be a burst of queued up callbacks + execute("call timer_start(50, 'MyHandler', {'repeat': 2})") + run(nil, nil, nil, 100) + local count = eval("g:val") + nvim_async("command", "let g:c = getchar()") + run(nil, nil, nil, 300) + feed("c") + local diff = eval("g:val") - count + ok(0 <= diff and diff <= 2) + eq(99, eval("g:c")) + end) + + it('can be stopped', function() + local t = eval("timer_start(50, 'MyHandler', {'repeat': -1})") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + funcs.timer_stop(t) + local count = eval("g:val") + run(nil, nil, nil, 300) + local count2 = eval("g:val") + ok(4 <= count and count <= 7) + -- when count is eval:ed after timer_stop this should be non-racy + eq(count, count2) + end) + + it('can be stopped from the handler', function() + source([[ + func! MyHandler(timer) + let g:val += 1 + if g:val == 3 + call timer_stop(a:timer) + " check double stop is ignored + call timer_stop(a:timer) + endif + endfunc + ]]) + execute("call timer_start(50, 'MyHandler', {'repeat': -1})") + eq(0,eval("g:val")) + run(nil, nil, nil, 300) + eq(3,eval("g:val")) + end) + + it('can have two timers', function() + source([[ + let g:val2 = 0 + func! MyHandler2(timer) + let g:val2 += 1 + endfunc + ]]) + execute("call timer_start(50, 'MyHandler', {'repeat': 3})") + execute("call timer_start(100, 'MyHandler2', {'repeat': 2})") + run(nil, nil, nil, 300) + eq(3,eval("g:val")) + eq(2,eval("g:val2")) + end) + + it("doesn't mess up the cmdline", function() + local screen = Screen.new(40, 6) + screen:attach() + screen:set_default_attr_ignore({{bold=true, foreground=Screen.colors.Blue}}) + source([[ + func! MyHandler(timer) + echo "evil" + endfunc + ]]) + execute("call timer_start(100, 'MyHandler', {'repeat': 1})") + feed(":good") + screen:sleep(200) + screen:expect([[ + | + ~ | + ~ | + ~ | + ~ | + :good^ | + ]]) + end) + +end) diff --git a/test/functional/eval/vvar_event_spec.lua b/test/functional/eval/vvar_event_spec.lua index bbac86524f..eec8aa917a 100644 --- a/test/functional/eval/vvar_event_spec.lua +++ b/test/functional/eval/vvar_event_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq local command = helpers.command describe('v:event', function() diff --git a/test/functional/ex_cmds/append_spec.lua b/test/functional/ex_cmds/append_spec.lua index 2d5ab8e8c8..3e326d9460 100644 --- a/test/functional/ex_cmds/append_spec.lua +++ b/test/functional/ex_cmds/append_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eq = helpers.eq local feed = helpers.feed diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua index 69467632a4..fcd826c25d 100644 --- a/test/functional/ex_cmds/cd_spec.lua +++ b/test/functional/ex_cmds/cd_spec.lua @@ -1,49 +1,145 @@ -- Specs for :cd, :tcd, :lcd and getcwd() -local helpers = require('test.functional.helpers') -local execute, eq, clear, eval, exc_exec = - helpers.execute, helpers.eq, helpers.clear, helpers.eval, helpers.exc_exec local lfs = require('lfs') +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local call = helpers.call +local clear = helpers.clear +local execute = helpers.execute +local exc_exec = helpers.exc_exec -- These directories will be created for testing local directories = { - 'Xtest-functional-ex_cmds-cd_spec.1', -- Tab - 'Xtest-functional-ex_cmds-cd_spec.2', -- Window - 'Xtest-functional-ex_cmds-cd_spec.3', -- New global + tab = 'Xtest-functional-ex_cmds-cd_spec.tab', -- Tab + window = 'Xtest-functional-ex_cmds-cd_spec.window', -- Window + global = 'Xtest-functional-ex_cmds-cd_spec.global', -- New global } -- Shorthand writing to get the current working directory -local cwd = function() return eval('getcwd( )') end -- effective working dir -local wcwd = function() return eval('getcwd( 0 )') end -- window dir -local tcwd = function() return eval('getcwd(-1, 0)') end -- tab dir ---local gcwd = function() return eval('getcwd(-1, -1)') end -- global dir +local cwd = function(...) return call('getcwd', ...) end -- effective working dir +local wcwd = function() return cwd(0) end -- window dir +local tcwd = function() return cwd(-1, 0) end -- tab dir -- Same, except these tell us if there is a working directory at all ---local lwd = function() return eval('haslocaldir( )') end -- effective working dir -local wlwd = function() return eval('haslocaldir( 0 )') end -- window dir -local tlwd = function() return eval('haslocaldir(-1, 0)') end -- tab dir +local lwd = function(...) return call('haslocaldir', ...) end -- effective working dir +local wlwd = function() return lwd(0) end -- window dir +local tlwd = function() return lwd(-1, 0) end -- tab dir --local glwd = function() return eval('haslocaldir(-1, -1)') end -- global dir -- Test both the `cd` and `chdir` variants for _, cmd in ipairs {'cd', 'chdir'} do - describe(':*' .. cmd, function() + describe(':' .. cmd, function() before_each(function() clear() - for _, d in ipairs(directories) do + for _, d in pairs(directories) do lfs.mkdir(d) end + directories.start = cwd() end) after_each(function() - for _, d in ipairs(directories) do + for _, d in pairs(directories) do lfs.rmdir(d) end end) - it('works', function() - -- Store the initial working directory - local globalDir = cwd() + describe('using explicit scope', function() + it('for window', function() + local globalDir = directories.start + local globalwin = call('winnr') + local tabnr = call('tabpagenr') + + -- Everything matches globalDir to start + eq(globalDir, cwd(globalwin)) + eq(globalDir, cwd(globalwin, tabnr)) + eq(0, lwd(globalwin)) + eq(0, lwd(globalwin, tabnr)) + + execute('bot split') + local localwin = call('winnr') + -- Initial window is still using globalDir + eq(globalDir, cwd(localwin)) + eq(globalDir, cwd(localwin, tabnr)) + eq(0, lwd(globalwin)) + eq(0, lwd(globalwin, tabnr)) + + execute('silent l' .. cmd .. ' ' .. directories.window) + -- From window with local dir, the original window + -- is still reporting the global dir + eq(globalDir, cwd(globalwin)) + eq(globalDir, cwd(globalwin, tabnr)) + eq(0, lwd(globalwin)) + eq(0, lwd(globalwin, tabnr)) + + -- Window with local dir reports as such + eq(globalDir .. '/' .. directories.window, cwd(localwin)) + eq(globalDir .. '/' .. directories.window, cwd(localwin, tabnr)) + eq(1, lwd(localwin)) + eq(1, lwd(localwin, tabnr)) + + execute('tabnew') + -- From new tab page, original window reports global dir + eq(globalDir, cwd(globalwin, tabnr)) + eq(0, lwd(globalwin, tabnr)) + + -- From new tab page, local window reports as such + eq(globalDir .. '/' .. directories.window, cwd(localwin, tabnr)) + eq(1, lwd(localwin, tabnr)) + end) + + it('for tab page', function() + local globalDir = directories.start + local globaltab = call('tabpagenr') + + -- Everything matches globalDir to start + eq(globalDir, cwd(-1, 0)) + eq(globalDir, cwd(-1, globaltab)) + eq(0, lwd(-1, 0)) + eq(0, lwd(-1, globaltab)) + + execute('tabnew') + execute('silent t' .. cmd .. ' ' .. directories.tab) + local localtab = call('tabpagenr') + + -- From local tab page, original tab reports globalDir + eq(globalDir, cwd(-1, globaltab)) + eq(0, lwd(-1, globaltab)) + + -- new tab reports local + eq(globalDir .. '/' .. directories.tab, cwd(-1, 0)) + eq(globalDir .. '/' .. directories.tab, cwd(-1, localtab)) + eq(1, lwd(-1, 0)) + eq(1, lwd(-1, localtab)) + + execute('tabnext') + -- From original tab page, local reports as such + eq(globalDir .. '/' .. directories.tab, cwd(-1, localtab)) + eq(1, lwd(-1, localtab)) + end) + end) + describe('getcwd(-1, -1)', function() + it('works', function() + eq(directories.start, cwd(-1, -1)) + eq(0, lwd(-1, -1)) + end) + + it('works with tab-local pwd', function() + execute('silent t' .. cmd .. ' ' .. directories.tab) + eq(directories.start, cwd(-1, -1)) + eq(0, lwd(-1, -1)) + end) + + it('works with window-local pwd', function() + execute('silent l' .. cmd .. ' ' .. directories.window) + eq(directories.start, cwd(-1, -1)) + eq(0, lwd(-1, -1)) + end) + end) + + it('works', function() + local globalDir = directories.start -- Create a new tab first and verify that is has the same working dir execute('tabnew') eq(globalDir, cwd()) @@ -53,8 +149,8 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(0, wlwd()) -- Change tab-local working directory and verify it is different - execute('silent t' .. cmd .. ' ' .. directories[1]) - eq(globalDir .. '/' .. directories[1], cwd()) + execute('silent t' .. cmd .. ' ' .. directories.tab) + eq(globalDir .. '/' .. directories.tab, cwd()) eq(cwd(), tcwd()) -- working directory maches tab directory eq(1, tlwd()) eq(cwd(), wcwd()) -- still no window-directory @@ -64,16 +160,16 @@ for _, cmd in ipairs {'cd', 'chdir'} do execute('new') eq(1, tlwd()) -- Still tab-local working directory eq(0, wlwd()) -- Still no window-local working directory - eq(globalDir .. '/' .. directories[1], cwd()) - execute('silent l' .. cmd .. ' ../' .. directories[2]) - eq(globalDir .. '/' .. directories[2], cwd()) - eq(globalDir .. '/' .. directories[1], tcwd()) + eq(globalDir .. '/' .. directories.tab, cwd()) + execute('silent l' .. cmd .. ' ../' .. directories.window) + eq(globalDir .. '/' .. directories.window, cwd()) + eq(globalDir .. '/' .. directories.tab, tcwd()) eq(1, wlwd()) -- Verify the first window still has the tab local directory execute('wincmd w') - eq(globalDir .. '/' .. directories[1], cwd()) - eq(globalDir .. '/' .. directories[1], tcwd()) + eq(globalDir .. '/' .. directories.tab, cwd()) + eq(globalDir .. '/' .. directories.tab, tcwd()) eq(0, wlwd()) -- No window-local directory -- Change back to initial tab and verify working directory has stayed @@ -83,11 +179,11 @@ for _, cmd in ipairs {'cd', 'chdir'} do eq(0, wlwd()) -- Verify global changes don't affect local ones - execute('silent ' .. cmd .. ' ' .. directories[3]) - eq(globalDir .. '/' .. directories[3], cwd()) + execute('silent ' .. cmd .. ' ' .. directories.global) + eq(globalDir .. '/' .. directories.global, cwd()) execute('tabnext') - eq(globalDir .. '/' .. directories[1], cwd()) - eq(globalDir .. '/' .. directories[1], tcwd()) + eq(globalDir .. '/' .. directories.tab, cwd()) + eq(globalDir .. '/' .. directories.tab, tcwd()) eq(0, wlwd()) -- Still no window-local directory in this window -- Unless the global change happened in a tab with local directory @@ -101,9 +197,9 @@ for _, cmd in ipairs {'cd', 'chdir'} do -- But not in a window with its own local directory execute('tabnext | wincmd w') - eq(globalDir .. '/' .. directories[2], cwd() ) + eq(globalDir .. '/' .. directories.window, cwd() ) eq(0 , tlwd()) - eq(globalDir .. '/' .. directories[2], wcwd()) + eq(globalDir .. '/' .. directories.window, wcwd()) end) end) end diff --git a/test/functional/ex_cmds/encoding_spec.lua b/test/functional/ex_cmds/encoding_spec.lua index 6d402b7974..e2b3e7e31d 100644 --- a/test/functional/ex_cmds/encoding_spec.lua +++ b/test/functional/ex_cmds/encoding_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, feed = helpers.clear, helpers.execute, helpers.feed local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval @@ -22,7 +22,7 @@ describe('&encoding', function() end) it('can be changed before startup', function() - clear('set enc=latin1') + clear('--cmd', 'set enc=latin1') execute('set encoding=utf-8') -- error message expected feed('<cr>') @@ -32,7 +32,7 @@ describe('&encoding', function() it('is not changed by `set all&`', function() -- we need to set &encoding to something non-default. Use 'latin1' - clear('set enc=latin1') + clear('--cmd', 'set enc=latin1') execute('set all&') eq('latin1', eval('&encoding')) eq(4, eval('strwidth("Bär")')) diff --git a/test/functional/ex_cmds/grep_spec.lua b/test/functional/ex_cmds/grep_spec.lua index f3ff0a3817..13f88b7e03 100644 --- a/test/functional/ex_cmds/grep_spec.lua +++ b/test/functional/ex_cmds/grep_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, feed, ok, eval = helpers.clear, helpers.execute, helpers.feed, helpers.ok, helpers.eval diff --git a/test/functional/ex_cmds/menu_spec.lua b/test/functional/ex_cmds/menu_spec.lua index f5fd30465d..52df9e1592 100644 --- a/test/functional/ex_cmds/menu_spec.lua +++ b/test/functional/ex_cmds/menu_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, nvim = helpers.clear, helpers.execute, helpers.nvim local expect, feed, command = helpers.expect, helpers.feed, helpers.command local eq, eval = helpers.eq, helpers.eval @@ -39,7 +39,7 @@ describe(':emenu', function() end) it('executes correct bindings in command mode', function() - feed('ithis is a sentence<esc>^"+yiwo<esc>') + feed('ithis is a sentence<esc>^yiwo<esc>') -- Invoke "Edit.Paste" in normal-mode. nvim('command', 'emenu Edit.Paste') diff --git a/test/functional/ex_cmds/oldfiles_spec.lua b/test/functional/ex_cmds/oldfiles_spec.lua index 5bba1a0e7c..b7109f2f98 100644 --- a/test/functional/ex_cmds/oldfiles_spec.lua +++ b/test/functional/ex_cmds/oldfiles_spec.lua @@ -1,5 +1,5 @@ local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local buf, eq, execute = helpers.curbufmeths, helpers.eq, helpers.execute local feed, nvim_prog, wait = helpers.feed, helpers.nvim_prog, helpers.wait diff --git a/test/functional/ex_cmds/profile_spec.lua b/test/functional/ex_cmds/profile_spec.lua index 744b22621f..d390806679 100644 --- a/test/functional/ex_cmds/profile_spec.lua +++ b/test/functional/ex_cmds/profile_spec.lua @@ -1,7 +1,7 @@ require('os') local lfs = require('lfs') -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eval = helpers.eval local command = helpers.command local eq, neq = helpers.eq, helpers.neq diff --git a/test/functional/ex_cmds/quit_spec.lua b/test/functional/ex_cmds/quit_spec.lua index a8156228d3..016a607743 100644 --- a/test/functional/ex_cmds/quit_spec.lua +++ b/test/functional/ex_cmds/quit_spec.lua @@ -1,9 +1,9 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear describe(':qa', function() before_each(function() - clear('qa') + clear('--cmd', 'qa') end) it('verify #3334', function() diff --git a/test/functional/ex_cmds/recover_spec.lua b/test/functional/ex_cmds/recover_spec.lua index e1d01f6896..60673d25ef 100644 --- a/test/functional/ex_cmds/recover_spec.lua +++ b/test/functional/ex_cmds/recover_spec.lua @@ -1,6 +1,6 @@ -- Tests for :recover -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local lfs = require('lfs') local execute, eq, clear, eval, feed, expect, source = helpers.execute, helpers.eq, helpers.clear, helpers.eval, helpers.feed, diff --git a/test/functional/ex_cmds/sign_spec.lua b/test/functional/ex_cmds/sign_spec.lua index c50704504d..b37e6e8563 100644 --- a/test/functional/ex_cmds/sign_spec.lua +++ b/test/functional/ex_cmds/sign_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, nvim, eq = helpers.clear, helpers.nvim, helpers.eq describe('sign', function() diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua index d90b297ca8..b38ae29f7d 100644 --- a/test/functional/ex_cmds/write_spec.lua +++ b/test/functional/ex_cmds/write_spec.lua @@ -1,15 +1,18 @@ -- Specs for :write -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eq, eval, clear, write_file, execute, source = helpers.eq, helpers.eval, helpers.clear, helpers.write_file, helpers.execute, helpers.source describe(':write', function() - it('&backupcopy=auto preserves symlinks', function() - clear('set backupcopy=auto') + after_each(function() os.remove('test_bkc_file.txt') os.remove('test_bkc_link.txt') + end) + + it('&backupcopy=auto preserves symlinks', function() + clear('--cmd', 'set backupcopy=auto') write_file('test_bkc_file.txt', 'content0') execute("silent !ln -s test_bkc_file.txt test_bkc_link.txt") source([[ @@ -22,9 +25,7 @@ describe(':write', function() end) it('&backupcopy=no replaces symlink with new file', function() - clear('set backupcopy=no') - os.remove('test_bkc_file.txt') - os.remove('test_bkc_link.txt') + clear('--cmd', 'set backupcopy=no') write_file('test_bkc_file.txt', 'content0') execute("silent !ln -s test_bkc_file.txt test_bkc_link.txt") source([[ diff --git a/test/functional/ex_cmds/wundo_spec.lua b/test/functional/ex_cmds/wundo_spec.lua index 969dfea3d9..e1216fa5d4 100644 --- a/test/functional/ex_cmds/wundo_spec.lua +++ b/test/functional/ex_cmds/wundo_spec.lua @@ -1,6 +1,6 @@ -- Specs for :wundo and underlying functions -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local execute, clear, eval, feed, spawn, nvim_prog, set_session = helpers.execute, helpers.clear, helpers.eval, helpers.feed, helpers.spawn, helpers.nvim_prog, helpers.set_session diff --git a/test/functional/ex_cmds/wviminfo_spec.lua b/test/functional/ex_cmds/wviminfo_spec.lua index 21f14be62c..37f45da2d4 100644 --- a/test/functional/ex_cmds/wviminfo_spec.lua +++ b/test/functional/ex_cmds/wviminfo_spec.lua @@ -1,4 +1,5 @@ -local helpers, lfs = require('test.functional.helpers'), require('lfs') +local helpers = require('test.functional.helpers')(after_each) +local lfs = require('lfs') local execute, eq, neq, spawn, nvim_prog, set_session, wait, write_file = helpers.execute, helpers.eq, helpers.neq, helpers.spawn, helpers.nvim_prog, helpers.set_session, helpers.wait, helpers.write_file diff --git a/test/functional/ex_getln/history_spec.lua b/test/functional/ex_getln/history_spec.lua index 532c81dab9..c1d2ffda53 100644 --- a/test/functional/ex_getln/history_spec.lua +++ b/test/functional/ex_getln/history_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, meths, funcs, eq = helpers.clear, helpers.meths, helpers.funcs, helpers.eq diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 37b7bf664c..6e750b31a9 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -1,8 +1,13 @@ require('coxpcall') local lfs = require('lfs') -local assert = require('luassert') local ChildProcessStream = require('nvim.child_process_stream') local Session = require('nvim.session') +local global_helpers = require('test.helpers') + +local check_logs = global_helpers.check_logs +local neq = global_helpers.neq +local eq = global_helpers.eq +local ok = global_helpers.ok local nvim_prog = os.getenv('NVIM_PROG') or 'build/bin/nvim' local nvim_argv = {nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N', @@ -30,7 +35,7 @@ if os.getenv('VALGRIND') then prepend_argv = {'valgrind', '-q', '--tool=memcheck', '--leak-check=yes', '--track-origins=yes', '--show-possibly-lost=no', - '--suppressions=.valgrind.supp', + '--suppressions=src/.valgrind.supp', '--log-file='..log_file} if os.getenv('GDB') then table.insert(prepend_argv, '--vgdb=yes') @@ -216,11 +221,10 @@ local function spawn(argv, merge) return Session.new(child_stream) end -local function clear(extra_cmd) +local function clear(...) local args = {unpack(nvim_argv)} - if extra_cmd ~= nil then - table.insert(args, '--cmd') - table.insert(args, extra_cmd) + for _, arg in ipairs({...}) do + table.insert(args, arg) end set_session(spawn(args)) end @@ -267,18 +271,6 @@ local function source(code) return tmpname end -local function eq(expected, actual) - return assert.are.same(expected, actual) -end - -local function neq(expected, actual) - return assert.are_not.same(expected, actual) -end - -local function ok(expr) - assert.is_true(expr) -end - local function nvim(method, ...) return request('vim_'..method, ...) end @@ -345,10 +337,18 @@ local function rmdir(path) end for file in lfs.dir(path) do if file ~= '.' and file ~= '..' then - local ret, err = os.remove(path..'/'..file) - if not ret then - error('os.remove: '..err) - return nil + local abspath = path..'/'..file + if lfs.attributes(abspath, 'mode') == 'directory' then + local ret = rmdir(abspath) -- recurse + if not ret then + return nil + end + else + local ret, err = os.remove(abspath) + if not ret then + error('os.remove: '..err) + return nil + end end end end @@ -404,54 +404,59 @@ local curbufmeths = create_callindex(curbuf) local curwinmeths = create_callindex(curwin) local curtabmeths = create_callindex(curtab) -return { - prepend_argv = prepend_argv, - clear = clear, - spawn = spawn, - dedent = dedent, - source = source, - rawfeed = rawfeed, - insert = insert, - feed = feed, - execute = execute, - eval = nvim_eval, - call = nvim_call, - command = nvim_command, - request = request, - next_message = next_message, - run = run, - stop = stop, - eq = eq, - neq = neq, - expect = expect, - ok = ok, - nvim = nvim, - nvim_async = nvim_async, - nvim_prog = nvim_prog, - nvim_dir = nvim_dir, - buffer = buffer, - window = window, - tabpage = tabpage, - curbuf = curbuf, - curwin = curwin, - curtab = curtab, - curbuf_contents = curbuf_contents, - wait = wait, - set_session = set_session, - write_file = write_file, - os_name = os_name, - rmdir = rmdir, - mkdir = lfs.mkdir, - exc_exec = exc_exec, - redir_exec = redir_exec, - merge_args = merge_args, - funcs = funcs, - meths = meths, - bufmeths = bufmeths, - winmeths = winmeths, - tabmeths = tabmeths, - curbufmeths = curbufmeths, - curwinmeths = curwinmeths, - curtabmeths = curtabmeths, - NIL = mpack.NIL -} +return function(after_each) + if after_each then + after_each(check_logs) + end + return { + prepend_argv = prepend_argv, + clear = clear, + spawn = spawn, + dedent = dedent, + source = source, + rawfeed = rawfeed, + insert = insert, + feed = feed, + execute = execute, + eval = nvim_eval, + call = nvim_call, + command = nvim_command, + request = request, + next_message = next_message, + run = run, + stop = stop, + eq = eq, + neq = neq, + expect = expect, + ok = ok, + nvim = nvim, + nvim_async = nvim_async, + nvim_prog = nvim_prog, + nvim_dir = nvim_dir, + buffer = buffer, + window = window, + tabpage = tabpage, + curbuf = curbuf, + curwin = curwin, + curtab = curtab, + curbuf_contents = curbuf_contents, + wait = wait, + set_session = set_session, + write_file = write_file, + os_name = os_name, + rmdir = rmdir, + mkdir = lfs.mkdir, + exc_exec = exc_exec, + redir_exec = redir_exec, + merge_args = merge_args, + funcs = funcs, + meths = meths, + bufmeths = bufmeths, + winmeths = winmeths, + tabmeths = tabmeths, + curbufmeths = curbufmeths, + curwinmeths = curwinmeths, + curtabmeths = curtabmeths, + NIL = mpack.NIL, + } +end diff --git a/test/functional/job/job_spec.lua b/test/functional/job/job_spec.lua index d21b9051e2..b54d5166ac 100644 --- a/test/functional/job/job_spec.lua +++ b/test/functional/job/job_spec.lua @@ -1,11 +1,11 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, eq, eval, execute, feed, insert, neq, next_msg, nvim, - nvim_dir, ok, source, write_file = helpers.clear, + nvim_dir, ok, source, write_file, mkdir, rmdir = helpers.clear, helpers.eq, helpers.eval, helpers.execute, helpers.feed, helpers.insert, helpers.neq, helpers.next_message, helpers.nvim, helpers.nvim_dir, helpers.ok, helpers.source, - helpers.write_file + helpers.write_file, helpers.mkdir, helpers.rmdir local Screen = require('test.functional.ui.screen') @@ -37,6 +37,32 @@ describe('jobs', function() eq({'notification', 'exit', {0, 0}}, next_msg()) end) + it('changes to given / directory', function() + nvim('command', "let g:job_opts.cwd = '/'") + nvim('command', "let j = jobstart('pwd', g:job_opts)") + eq({'notification', 'stdout', {0, {'/', ''}}}, next_msg()) + eq({'notification', 'exit', {0, 0}}, next_msg()) + end) + + it('changes to given `cwd` directory', function() + local dir = eval('resolve(tempname())') + mkdir(dir) + nvim('command', "let g:job_opts.cwd = '" .. dir .. "'") + nvim('command', "let j = jobstart('pwd', g:job_opts)") + eq({'notification', 'stdout', {0, {dir, ''}}}, next_msg()) + eq({'notification', 'exit', {0, 0}}, next_msg()) + rmdir(dir) + end) + + it('fails to change to invalid `cwd`', function() + local dir = eval('resolve(tempname())."-bogus"') + local _, err = pcall(function() + nvim('command', "let g:job_opts.cwd = '" .. dir .. "'") + nvim('command', "let j = jobstart('pwd', g:job_opts)") + end) + ok(string.find(err, "E475: Invalid argument: expected valid directory$") ~= nil) + end) + it('returns 0 when it fails to start', function() local status, rv = pcall(eval, "jobstart([])") eq(false, status) diff --git a/test/functional/legacy/002_filename_recognition_spec.lua b/test/functional/legacy/002_filename_recognition_spec.lua index 569e748631..5a833281e7 100644 --- a/test/functional/legacy/002_filename_recognition_spec.lua +++ b/test/functional/legacy/002_filename_recognition_spec.lua @@ -1,7 +1,7 @@ -- Test if URLs are recognized as filenames by commands such as "gf". Here -- we'll use `expand("<cfile>")` since "gf" would need to open the file. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/003_cindent_spec.lua b/test/functional/legacy/003_cindent_spec.lua index 4b838eda1d..83388bd1eb 100644 --- a/test/functional/legacy/003_cindent_spec.lua +++ b/test/functional/legacy/003_cindent_spec.lua @@ -3,7 +3,7 @@ -- There are 50+ test command blocks (the stuff between STARTTEST and ENDTEST) -- in the original test. These have been converted to "it" test cases here. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/004_bufenter_with_modelines_spec.lua b/test/functional/legacy/004_bufenter_with_modelines_spec.lua index 34e702b798..3e5cdd2ff2 100644 --- a/test/functional/legacy/004_bufenter_with_modelines_spec.lua +++ b/test/functional/legacy/004_bufenter_with_modelines_spec.lua @@ -2,7 +2,7 @@ -- Test for autocommand that changes current buffer on BufEnter event. -- Check if modelines are interpreted for the correct buffer. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/005_bufleave_delete_buffer_spec.lua b/test/functional/legacy/005_bufleave_delete_buffer_spec.lua index e6989a6674..895f4ad181 100644 --- a/test/functional/legacy/005_bufleave_delete_buffer_spec.lua +++ b/test/functional/legacy/005_bufleave_delete_buffer_spec.lua @@ -1,7 +1,7 @@ -- Test for autocommand that deletes the current buffer on BufLeave event. -- Also test deleting the last buffer, should give a new, empty buffer. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/006_argument_list_spec.lua b/test/functional/legacy/006_argument_list_spec.lua index 1266a876d4..764854314f 100644 --- a/test/functional/legacy/006_argument_list_spec.lua +++ b/test/functional/legacy/006_argument_list_spec.lua @@ -1,6 +1,6 @@ -- Test for autocommand that redefines the argument list, when doing ":all". -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, dedent, eq = helpers.execute, helpers.dedent, helpers.eq local curbuf_contents = helpers.curbuf_contents diff --git a/test/functional/legacy/007_ball_buffer_list_spec.lua b/test/functional/legacy/007_ball_buffer_list_spec.lua index 295f63f044..07e3fe6e7a 100644 --- a/test/functional/legacy/007_ball_buffer_list_spec.lua +++ b/test/functional/legacy/007_ball_buffer_list_spec.lua @@ -1,6 +1,6 @@ -- Test for autocommand that changes the buffer list, when doing ":ball". -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/009_bufleave_autocommand_spec.lua b/test/functional/legacy/009_bufleave_autocommand_spec.lua index 8c18639c8f..7481c639cf 100644 --- a/test/functional/legacy/009_bufleave_autocommand_spec.lua +++ b/test/functional/legacy/009_bufleave_autocommand_spec.lua @@ -1,6 +1,6 @@ -- Test for Bufleave autocommand that deletes the buffer we are about to edit. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, insert = helpers.clear, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/010_errorformat_spec.lua b/test/functional/legacy/010_errorformat_spec.lua new file mode 100644 index 0000000000..785bf136b5 --- /dev/null +++ b/test/functional/legacy/010_errorformat_spec.lua @@ -0,0 +1,156 @@ +-- Test for 'errorformat'. This will fail if the quickfix feature was +-- disabled. + +local helpers = require('test.functional.helpers')(after_each) +local feed, clear, execute = helpers.feed, helpers.clear, helpers.execute +local expect, write_file = helpers.expect, helpers.write_file + +describe('errorformat', function() + setup(function() + clear() + local error_file_text = [[ + start of errorfile + "Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set. + "Xtestfile", line 6 col 19; this is an error + gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c + Xtestfile:9: parse error before `asd' + make: *** [vim] Error 1 + in file "Xtestfile" linenr 10: there is an error + + 2 returned + "Xtestfile", line 11 col 1; this is an error + "Xtestfile", line 12 col 2; this is another error + "Xtestfile", line 14:10; this is an error in column 10 + =Xtestfile=, line 15:10; this is another error, but in vcol 10 this time + "Xtestfile", linenr 16: yet another problem + Error in "Xtestfile" at line 17: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 + ^ + Error in "Xtestfile" at line 18: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 + .............^ + Error in "Xtestfile" at line 19: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 + --------------^ + Error in "Xtestfile" at line 20: + x should be a dot + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 + ^ + + Does anyone know what is the problem and how to correction it? + "Xtestfile", line 21 col 9: What is the title of the quickfix window? + "Xtestfile", line 22 col 9: What is the title of the quickfix window? + ]] + write_file('Xerrorfile1', error_file_text .. 'end of errorfile\n') + write_file('Xerrorfile2', error_file_text) + write_file('Xtestfile', [[ + start of testfile + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 4 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 6 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 9 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 10 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 12 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 14 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 15 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 21 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 22 + end of testfile + ]]) + end) + teardown(function() + os.remove('Xerrorfile1') + os.remove('Xerrorfile2') + os.remove('Xtestfile') + end) + + it('is working', function() + -- Also test a BOM is ignored. + execute( + 'set encoding=utf-8', + [[set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m]], + [[set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m]], + 'cf Xerrorfile2', + 'clast', + 'copen', + 'let a=w:quickfix_title', + 'wincmd p' + ) + feed('lgR<C-R>=a<CR><esc>') + execute('cf Xerrorfile1') + feed('grA<cr>') + execute('cn') + feed('gRLINE 6, COL 19<esc>') + execute('cn') + feed('gRNO COLUMN SPECIFIED<esc>') + execute('cn') + feed('gRAGAIN NO COLUMN<esc>') + execute('cn') + feed('gRCOL 1<esc>') + execute('cn') + feed('gRCOL 2<esc>') + execute('cn') + feed('gRCOL 10<esc>') + execute('cn') + feed('gRVCOL 10<esc>') + execute('cn') + feed('grI<cr>') + execute('cn') + feed('gR. SPACE POINTER<esc>') + execute('cn') + feed('gR. DOT POINTER<esc>') + execute('cn') + feed('gR. DASH POINTER<esc>') + execute('cn') + feed('gR. TAB-SPACE POINTER<esc>') + execute( + 'clast', + 'cprev', + 'cprev', + 'wincmd w', + 'let a=w:quickfix_title', + 'wincmd p' + ) + feed('lgR<C-R>=a<CR><esc>') + + -- Assert buffer contents. + expect([[ + start of testfile + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3 + xxxxxxxxxxAxxxxxxxxxxxxxxxxxxx line 4 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5 + xxxxxxxxxxxxxxxxxLINE 6, COL 19 line 6 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8 + NO COLUMN SPECIFIEDxxxxxxxxxxx line 9 + AGAIN NO COLUMNxxxxxxxxxxxxxxx line 10 + COL 1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11 + COL 2xxxxxxxxxxxxxxxxxxxxxxxxx line 12 + xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13 + xxxxxxxxCOL 10xxxxxxxxxxxxxxxx line 14 + xVCOL 10xxxxxxxxxxxxxxxxxxxxxx line 15 + Ixxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16 + xxxx. SPACE POINTERxxxxxxxxxxx line 17 + xxxxx. DOT POINTERxxxxxxxxxxxx line 18 + xxxxxx. DASH POINTERxxxxxxxxxx line 19 + xxxxxxx. TAB-SPACE POINTERxxxx line 20 + xxxxxxxx:cf Xerrorfile1xxxxxxx line 21 + xxxxxxxx:cf Xerrorfile2xxxxxxx line 22 + end of testfile]]) + end) +end) diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua index 483e465cee..6e613c85df 100644 --- a/test/functional/legacy/011_autocommands_spec.lua +++ b/test/functional/legacy/011_autocommands_spec.lua @@ -12,7 +12,8 @@ -- Use a FileChangedShell autocommand to avoid a prompt for "Xtestfile.gz" -- being modified outside of Vim (noticed on Solaris). -local helpers, lfs = require('test.functional.helpers'), require('lfs') +local helpers= require('test.functional.helpers')(after_each) +local lfs = require('lfs') local clear, execute, expect, eq, neq, dedent, write_file, feed = helpers.clear, helpers.execute, helpers.expect, helpers.eq, helpers.neq, helpers.dedent, helpers.write_file, helpers.feed diff --git a/test/functional/legacy/015_alignment_spec.lua b/test/functional/legacy/015_alignment_spec.lua index 3b19f4ff42..48d4042ff2 100644 --- a/test/functional/legacy/015_alignment_spec.lua +++ b/test/functional/legacy/015_alignment_spec.lua @@ -2,7 +2,7 @@ -- Also test formatting a paragraph. -- Also test undo after ":%s" and formatting. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/018_unset_smart_indenting_spec.lua b/test/functional/legacy/018_unset_smart_indenting_spec.lua index 6975cb7f26..ba1eac02cb 100644 --- a/test/functional/legacy/018_unset_smart_indenting_spec.lua +++ b/test/functional/legacy/018_unset_smart_indenting_spec.lua @@ -1,6 +1,6 @@ -- Tests for not doing smart indenting when it isn't set. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/019_smarttab_expandtab_spec.lua b/test/functional/legacy/019_smarttab_expandtab_spec.lua index a33bd0c3ae..2287a9f786 100644 --- a/test/functional/legacy/019_smarttab_expandtab_spec.lua +++ b/test/functional/legacy/019_smarttab_expandtab_spec.lua @@ -1,7 +1,7 @@ -- Tests for "r<Tab>" with 'smarttab' and 'expandtab' set/not set. -- Also test that dv_ works correctly -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/020_blockwise_visual_spec.lua b/test/functional/legacy/020_blockwise_visual_spec.lua index 95574a0957..660348a792 100644 --- a/test/functional/legacy/020_blockwise_visual_spec.lua +++ b/test/functional/legacy/020_blockwise_visual_spec.lua @@ -3,7 +3,7 @@ -- First test for undo working properly when executing commands from a register. -- Also test this in an empty buffer. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/021_control_wi_spec.lua b/test/functional/legacy/021_control_wi_spec.lua index 9fd83fec5f..787a384fca 100644 --- a/test/functional/legacy/021_control_wi_spec.lua +++ b/test/functional/legacy/021_control_wi_spec.lua @@ -1,7 +1,7 @@ -- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests for [ CTRL-I with a count and CTRL-W CTRL-I with a count -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/022_line_ending_spec.lua b/test/functional/legacy/022_line_ending_spec.lua index a841378a82..092440bb16 100644 --- a/test/functional/legacy/022_line_ending_spec.lua +++ b/test/functional/legacy/022_line_ending_spec.lua @@ -1,6 +1,6 @@ -- Tests for file with some lines ending in CTRL-M, some not -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed = helpers.clear, helpers.feed local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/023_edit_arguments_spec.lua b/test/functional/legacy/023_edit_arguments_spec.lua index 15b30bfa3a..95ab983d24 100644 --- a/test/functional/legacy/023_edit_arguments_spec.lua +++ b/test/functional/legacy/023_edit_arguments_spec.lua @@ -1,6 +1,6 @@ -- Tests for complicated + argument to :edit command -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, insert = helpers.clear, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/025_jump_tag_hidden_spec.lua b/test/functional/legacy/025_jump_tag_hidden_spec.lua index bd434c013c..7b7ddb07b9 100644 --- a/test/functional/legacy/025_jump_tag_hidden_spec.lua +++ b/test/functional/legacy/025_jump_tag_hidden_spec.lua @@ -1,7 +1,7 @@ -- Test for jumping to a tag with 'hidden' set, with symbolic link in path of tag. -- This only works for Unix, because of the symbolic link. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/026_execute_while_if_spec.lua b/test/functional/legacy/026_execute_while_if_spec.lua index f17bb79702..74ef34bb20 100644 --- a/test/functional/legacy/026_execute_while_if_spec.lua +++ b/test/functional/legacy/026_execute_while_if_spec.lua @@ -1,6 +1,6 @@ -- Test for :execute, :while and :if -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local execute, expect = helpers.execute, helpers.expect local source = helpers.source diff --git a/test/functional/legacy/027_expand_file_names_spec.lua b/test/functional/legacy/027_expand_file_names_spec.lua deleted file mode 100644 index 4778d16d43..0000000000 --- a/test/functional/legacy/027_expand_file_names_spec.lua +++ /dev/null @@ -1,37 +0,0 @@ --- Test for expanding file names - -local helpers = require('test.functional.helpers') -local clear, feed = helpers.clear, helpers.feed -local execute = helpers.execute -local curbuf_contents = helpers.curbuf_contents -local eq = helpers.eq - -describe('expand file name', function() - setup(clear) - - it('is working', function() - execute('!mkdir Xdir1') - execute('!mkdir Xdir2') - execute('!mkdir Xdir3') - execute('cd Xdir3') - execute('!mkdir Xdir4') - execute('cd ..') - execute('w Xdir1/file') - execute('w Xdir3/Xdir4/file') - execute('n Xdir?/*/file') - - -- Yank current file path to @a register - feed('i<C-R>%<Esc>V"ad') - - -- Put @a and current file path in the current buffer - execute('n! Xdir?/*/nofile') - feed('V"ap') - feed('o<C-R>%<Esc>') - - eq("Xdir3/Xdir4/file\nXdir?/*/nofile", curbuf_contents()) - end) - - teardown(function() - os.execute('rm -rf Xdir1 Xdir2 Xdir3') - end) -end) diff --git a/test/functional/legacy/028_source_ctrl_v_spec.lua b/test/functional/legacy/028_source_ctrl_v_spec.lua index fc36b436ef..a8c43260be 100644 --- a/test/functional/legacy/028_source_ctrl_v_spec.lua +++ b/test/functional/legacy/028_source_ctrl_v_spec.lua @@ -1,6 +1,6 @@ -- Test for sourcing a file with CTRL-V's at the end of the line -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/029_join_spec.lua b/test/functional/legacy/029_join_spec.lua index 25a072ad6e..7a183fcbec 100644 --- a/test/functional/legacy/029_join_spec.lua +++ b/test/functional/legacy/029_join_spec.lua @@ -1,6 +1,6 @@ -- Test for joining lines with marks in them (and with 'joinspaces' set/reset) -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/031_close_commands_spec.lua b/test/functional/legacy/031_close_commands_spec.lua index 3597cba12a..eaf4e2982f 100644 --- a/test/functional/legacy/031_close_commands_spec.lua +++ b/test/functional/legacy/031_close_commands_spec.lua @@ -9,9 +9,14 @@ -- :buf -- :edit -local helpers = require('test.functional.helpers') -local feed, insert = helpers.feed, helpers.insert -local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect +local helpers = require('test.functional.helpers')(after_each) + +local feed = helpers.feed +local clear = helpers.clear +local source = helpers.source +local insert = helpers.insert +local expect = helpers.expect +local execute = helpers.execute describe('Commands that close windows and/or buffers', function() setup(clear) @@ -84,6 +89,28 @@ describe('Commands that close windows and/or buffers', function() feed('GA 4<Esc>:all!<CR>') execute('1wincmd w') expect('testtext 2 2 2') + + -- Test ":q!" and hidden buffer. + execute('bw! Xtest1 Xtest2 Xtest3 Xtest4') + execute('sp Xtest1') + execute('wincmd w') + execute('bw!') + execute('set modified') + execute('bot sp Xtest2') + execute('set modified') + execute('bot sp Xtest3') + execute('set modified') + execute('wincmd t') + execute('hide') + execute('q!') + expect('testtext 3') + execute('q!') + feed('<CR>') + expect('testtext 1') + source([[ + q! + " Now nvim should have exited + throw "Oh, Not finished yet."]]) end) teardown(function() diff --git a/test/functional/legacy/033_lisp_indent_spec.lua b/test/functional/legacy/033_lisp_indent_spec.lua index 0a5577fad3..b4abb02ac2 100644 --- a/test/functional/legacy/033_lisp_indent_spec.lua +++ b/test/functional/legacy/033_lisp_indent_spec.lua @@ -2,7 +2,7 @@ -- Test for 'lisp' -- If the lisp feature is not enabled, this will fail! -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/034_user_function_spec.lua b/test/functional/legacy/034_user_function_spec.lua new file mode 100644 index 0000000000..38989cd982 --- /dev/null +++ b/test/functional/legacy/034_user_function_spec.lua @@ -0,0 +1,102 @@ +-- Test for user functions. +-- Also test an <expr> mapping calling a function. +-- Also test that a builtin function cannot be replaced. +-- Also test for regression when calling arbitrary expression. + +local helpers = require('test.functional.helpers')(after_each) +local feed, insert, source = helpers.feed, helpers.insert, helpers.source +local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect + +describe('user functions, expr-mappings, overwrite protected builtin functions and regression on calling expressions', function() + setup(clear) + + it('are working', function() + insert('here') + + source([[ + function Table(title, ...) + let ret = a:title + let idx = 1 + while idx <= a:0 + exe "let ret = ret . a:" . idx + let idx = idx + 1 + endwhile + return ret + endfunction + function Compute(n1, n2, divname) + if a:n2 == 0 + return "fail" + endif + exe "let g:" . a:divname . " = ". a:n1 / a:n2 + return "ok" + endfunction + func Expr1() + normal! v + return "111" + endfunc + func Expr2() + call search('XX', 'b') + return "222" + endfunc + func ListItem() + let g:counter += 1 + return g:counter . '. ' + endfunc + func ListReset() + let g:counter = 0 + return '' + endfunc + func FuncWithRef(a) + unlet g:FuncRef + return a:a + endfunc + let g:FuncRef=function("FuncWithRef") + let counter = 0 + inoremap <expr> ( ListItem() + inoremap <expr> [ ListReset() + imap <expr> + Expr1() + imap <expr> * Expr2() + let retval = "nop" + /^here + ]]) + feed('C<C-R>=Table("xxx", 4, "asdf")<cr>') + -- Using a actual space will not work as feed() calls dedent on the input. + feed('<space><C-R>=Compute(45, 0, "retval")<cr>') + feed('<space><C-R>=retval<cr>') + feed('<space><C-R>=Compute(45, 5, "retval")<cr>') + feed('<space><C-R>=retval<cr>') + feed('<space><C-R>=g:FuncRef(333)<cr>') + feed('<cr>') + feed('XX+-XX<cr>') + feed('---*---<cr>') + feed('(one<cr>') + feed('(two<cr>') + feed('[(one again<esc>') + execute('call append(line("$"), max([1, 2, 3]))') + execute('call extend(g:, {"max": function("min")})') + execute('call append(line("$"), max([1, 2, 3]))') + execute('try') + -- Regression: the first line below used to throw "E110: Missing ')'" + -- Second is here just to prove that this line is correct when not + -- skipping rhs of &&. + execute([[ $put =(0&&(function('tr'))(1, 2, 3))]]) + execute([[ $put =(1&&(function('tr'))(1, 2, 3))]]) + execute('catch') + execute([[ $put ='!!! Unexpected exception:']]) + execute(' $put =v:exception') + execute('endtry') + + -- Assert buffer contents. + expect([[ + xxx4asdf fail nop ok 9 333 + XX111-XX + ---222--- + 1. one + 2. two + 1. one again + 3 + 3 + 0 + 1]]) + end) +end) diff --git a/test/functional/legacy/035_increment_and_decrement_spec.lua b/test/functional/legacy/035_increment_and_decrement_spec.lua index e6252c384b..3b9f7a9d85 100644 --- a/test/functional/legacy/035_increment_and_decrement_spec.lua +++ b/test/functional/legacy/035_increment_and_decrement_spec.lua @@ -1,7 +1,7 @@ -- Test Ctrl-A and Ctrl-X, which increment and decrement decimal, hexadecimal, -- and octal numbers. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/036_regexp_character_classes_spec.lua b/test/functional/legacy/036_regexp_character_classes_spec.lua index de080f4b43..3d5e69d1e5 100644 --- a/test/functional/legacy/036_regexp_character_classes_spec.lua +++ b/test/functional/legacy/036_regexp_character_classes_spec.lua @@ -1,6 +1,6 @@ -- Test character classes in regexp using regexpengine 0, 1, 2. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect local source, write_file = helpers.source, helpers.write_file local os_name = helpers.os_name diff --git a/test/functional/legacy/038_virtual_replace_spec.lua b/test/functional/legacy/038_virtual_replace_spec.lua index 10d42f0cea..dcbc9c39f7 100644 --- a/test/functional/legacy/038_virtual_replace_spec.lua +++ b/test/functional/legacy/038_virtual_replace_spec.lua @@ -1,6 +1,6 @@ -- Test Virtual replace mode. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed = helpers.feed local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/039_visual_block_mode_commands_spec.lua b/test/functional/legacy/039_visual_block_mode_commands_spec.lua index 7195d7d11d..63335985cc 100644 --- a/test/functional/legacy/039_visual_block_mode_commands_spec.lua +++ b/test/functional/legacy/039_visual_block_mode_commands_spec.lua @@ -1,7 +1,7 @@ -- Test Visual block mode commands -- And test "U" in Visual mode, also on German sharp S. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim, eq = helpers.meths, helpers.eq local insert, feed = helpers.insert, helpers.feed local clear, expect = helpers.clear, helpers.expect diff --git a/test/functional/legacy/041_writing_and_reading_hundred_kbyte_spec.lua b/test/functional/legacy/041_writing_and_reading_hundred_kbyte_spec.lua index 42fb5ed2b3..b6451eb720 100644 --- a/test/functional/legacy/041_writing_and_reading_hundred_kbyte_spec.lua +++ b/test/functional/legacy/041_writing_and_reading_hundred_kbyte_spec.lua @@ -1,6 +1,6 @@ -- Test for writing and reading a file of over 100 Kbyte -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/043_magic_settings_spec.lua b/test/functional/legacy/043_magic_settings_spec.lua index 27694e3754..f174751de2 100644 --- a/test/functional/legacy/043_magic_settings_spec.lua +++ b/test/functional/legacy/043_magic_settings_spec.lua @@ -1,7 +1,7 @@ -- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests for regexp with various magic settings. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua b/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua index 2a4c0149fa..4189e8a33a 100644 --- a/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua +++ b/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua @@ -3,7 +3,7 @@ -- -- This test contains both "test44" and "test99" from the old test suite. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/045_folding_spec.lua b/test/functional/legacy/045_folding_spec.lua index 04b623ff3b..cefd7c0d42 100644 --- a/test/functional/legacy/045_folding_spec.lua +++ b/test/functional/legacy/045_folding_spec.lua @@ -1,6 +1,6 @@ -- Tests for folding. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, clear, execute, expect = helpers.feed, helpers.insert, helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/046_multi_line_regexps_spec.lua b/test/functional/legacy/046_multi_line_regexps_spec.lua index b17ab42fe3..30ec76ea3e 100644 --- a/test/functional/legacy/046_multi_line_regexps_spec.lua +++ b/test/functional/legacy/046_multi_line_regexps_spec.lua @@ -1,7 +1,7 @@ -- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests for multi-line regexps with ":s" -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local expect = helpers.expect diff --git a/test/functional/legacy/051_highlight_spec.lua b/test/functional/legacy/051_highlight_spec.lua index 94c42b73e5..5bf3b51b90 100644 --- a/test/functional/legacy/051_highlight_spec.lua +++ b/test/functional/legacy/051_highlight_spec.lua @@ -2,7 +2,7 @@ -- Tests for ":highlight". local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed = helpers.clear, helpers.feed local execute, expect = helpers.execute, helpers.expect local wait = helpers.wait diff --git a/test/functional/legacy/054_buffer_local_autocommands_spec.lua b/test/functional/legacy/054_buffer_local_autocommands_spec.lua index bcedb26b7e..494ea8f927 100644 --- a/test/functional/legacy/054_buffer_local_autocommands_spec.lua +++ b/test/functional/legacy/054_buffer_local_autocommands_spec.lua @@ -1,6 +1,6 @@ -- Some tests for buffer-local autocommands -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, eq = helpers.clear, helpers.execute, helpers.eq local curbuf_contents = helpers.curbuf_contents diff --git a/test/functional/legacy/055_list_and_dict_types_spec.lua b/test/functional/legacy/055_list_and_dict_types_spec.lua new file mode 100644 index 0000000000..dee138e6d8 --- /dev/null +++ b/test/functional/legacy/055_list_and_dict_types_spec.lua @@ -0,0 +1,949 @@ +-- Tests for List and Dictionary types. + +local helpers = require('test.functional.helpers')(after_each) +local feed, source = helpers.feed, helpers.source +local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect + +describe('list and dictionary types', function() + before_each(clear) + + it('creating list directly with different types', function() + source([[ + lang C + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + $put =string(l) + $put =string(l[-1]) + $put =string(l[-4]) + try + $put =string(l[-5]) + catch + $put =v:exception[:14] + endtry]]) + expect([[ + + [1, 'as''d', [1, 2, function('strlen')], {'a': 1}] + {'a': 1} + 1 + Vim(put):E684: ]]) + end) + + it('list slices', function() + source([[ + lang C + " The list from the first test repeated after splitting the tests. + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + $put =string(l[:]) + $put =string(l[1:]) + $put =string(l[:-2]) + $put =string(l[0:8]) + $put =string(l[8:-1])]]) + expect([=[ + + [1, 'as''d', [1, 2, function('strlen')], {'a': 1}] + ['as''d', [1, 2, function('strlen')], {'a': 1}] + [1, 'as''d', [1, 2, function('strlen')]] + [1, 'as''d', [1, 2, function('strlen')], {'a': 1}] + []]=]) + end) + + it('list identity', function() + source([[ + lang C + " The list from the first test repeated after splitting the tests. + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + let ll = l + let lx = copy(l) + try + $put =(l == ll) . (l isnot ll) . (l is ll) . (l == lx) . + \ (l is lx) . (l isnot lx) + catch + $put =v:exception + endtry]]) + expect('\n101101') + end) + + it('creating dictionary directly with different types', function() + source([[ + lang C + let d = {001: 'asd', 'b': [1, 2, function('strlen')], -1: {'a': 1},} + $put =string(d) . d.1 + $put =string(sort(keys(d))) + $put =string (values(d)) + for [key, val] in items(d) + $put =key . ':' . string(val) + unlet key val + endfor + call extend (d, {3:33, 1:99}) + call extend(d, {'b':'bbb', 'c':'ccc'}, "keep") + try + call extend(d, {3:333,4:444}, "error") + catch + $put =v:exception[:15] . v:exception[-1:-1] + endtry + $put =string(d) + call filter(d, 'v:key =~ ''[ac391]''') + $put =string(d)]]) + expect([[ + + {'1': 'asd', 'b': [1, 2, function('strlen')], '-1': {'a': 1}}asd + ['-1', '1', 'b'] + ['asd', [1, 2, function('strlen')], {'a': 1}] + 1:'asd' + b:[1, 2, function('strlen')] + -1:{'a': 1} + Vim(call):E737: 3 + {'c': 'ccc', '1': 99, 'b': [1, 2, function('strlen')], '3': 33, '-1': {'a': 1}} + {'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}}]]) + end) + + it('dictionary identity', function() + source([[ + lang C + " The dict from the first test repeated after splitting the tests. + let d = {'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}} + let dd = d + let dx = copy(d) + try + $put =(d == dd) . (d isnot dd) . (d is dd) . (d == dx) . (d is dx) . + \ (d isnot dx) + catch + $put =v:exception + endtry]]) + expect('\n101101') + end) + + it('changing var type should fail', function() + source([[ + lang C + " The list from the first test repeated after splitting the tests. + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + " The dict from the first test repeated after splitting the tests. + let d = {'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}} + try + let d = [] + catch + $put =v:exception[:14] . v:exception[-1:-1] + endtry + try + let l = {} + catch + $put =v:exception[:14] . v:exception[-1:-1] + endtry]]) + expect([[ + + Vim(let):E706: d + Vim(let):E706: l]]) + end) + + it('removing items with :unlet', function() + source([[ + lang C + " The list from the first test repeated after splitting the tests. + let l = [1, 'as''d', [1, 2, function("strlen")], {'a': 1},] + " The dict from the first test repeated after splitting the tests. + let d = {'c': 'ccc', '1': 99, '3': 33, '-1': {'a': 1}} + unlet l[2] + $put =string(l) + let l = range(8) + try + unlet l[:3] + unlet l[1:] + catch + $put =v:exception + endtry + $put =string(l) + + unlet d.c + unlet d[-1] + $put =string(d)]]) + expect([[ + + [1, 'as''d', {'a': 1}] + [4] + {'1': 99, '3': 33}]]) + end) + + it("removing items out of range: silently skip items that don't exist", function() + -- We can not use source() here as we want to ignore all errors. + execute('lang C') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:1]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:3]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:4]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[2:5]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-1:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-2:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-3:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-4:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-5:2]') + execute('$put =string(l)') + execute('let l = [0, 1, 2, 3]') + execute('unlet l[-6:2]') + execute('$put =string(l)') + expect([=[ + + [0, 1, 2, 3] + [0, 1, 3] + [0, 1] + [0, 1] + [0, 1] + [0, 1, 2, 3] + [0, 1, 3] + [0, 3] + [3] + [3] + [3]]=]) + end) + + it('assignment to a list', function() + source([[ + let l = [0, 1, 2, 3] + let [va, vb] = l[2:3] + $put =va + $put =vb + try + let [va, vb] = l + catch + $put =v:exception[:14] + endtry + try + let [va, vb] = l[1:1] + catch + $put =v:exception[:14] + endtry]]) + expect([[ + + 2 + 3 + Vim(let):E687: + Vim(let):E688: ]]) + end) + + it('manipulating a big dictionary', function() + -- Manipulating a big Dictionary (hashtable.c has a border of 1000 + -- entries). + source([[ + let d = {} + for i in range(1500) + let d[i] = 3000 - i + endfor + $put =d[0] . ' ' . d[100] . ' ' . d[999] . ' ' . d[1400] . ' ' . + \ d[1499] + try + let n = d[1500] + catch + $put =substitute(v:exception, '\v(.{14}).*( \d{4}).*', '\1\2', '') + endtry + " Lookup each items. + for i in range(1500) + if d[i] != 3000 - i + $put =d[i] + endif + endfor + let i += 1 + " Delete even items. + while i >= 2 + let i -= 2 + unlet d[i] + endwhile + $put =get(d, 1500 - 100, 'NONE') . ' ' . d[1] + " Delete odd items, checking value, one intentionally wrong. + let d[33] = 999 + let i = 1 + while i < 1500 + if d[i] != 3000 - i + $put =i . '=' . d[i] + else + unlet d[i] + endif + let i += 2 + endwhile + " Must be almost empty now. + $put =string(d)]]) + expect([[ + + 3000 2900 2001 1600 1501 + Vim(let):E716: 1500 + NONE 2999 + 33=999 + {'33': 999}]]) + end) + + it('dictionary function', function() + source([[ + let dict = {} + func dict.func(a) dict + $put =a:a . len(self.data) + endfunc + let dict.data = [1,2,3] + call dict.func("len: ") + let x = dict.func("again: ") + try + let Fn = dict.func + call Fn('xxx') + catch + $put =v:exception[:15] + endtry]]) + expect([[ + + len: 3 + again: 3 + Vim(call):E725: ]]) + end) + + it('Function in script-local List or Dict', function() + source([[ + let g:dict = {} + function g:dict.func() dict + $put ='g:dict.func'.self.foo[1].self.foo[0]('asdf') + endfunc + let g:dict.foo = ['-', 2, 3] + call insert(g:dict.foo, function('strlen')) + call g:dict.func()]]) + expect('\ng:dict.func-4') + end) + + it("remove func from dict that's being called (works)", function() + source([[ + let d = {1:1} + func d.func(a) + return "a:". a:a + endfunc + $put =d.func(string(remove(d, 'func')))]]) + -- The function number changed from 3 to 1 because we split the test. + -- There were two other functions in the old test before this. + expect("\na:function('1')") + end) + + it('deepcopy() dict that refers to itself', function() + -- Nasty: deepcopy() dict that refers to itself (fails when noref used). + source([[ + let d = {1:1, 2:2} + let l = [4, d, 6] + let d[3] = l + let dc = deepcopy(d) + try + let dc = deepcopy(d, 1) + catch + $put =v:exception[:14] + endtry + let l2 = [0, l, l, 3] + let l[1] = l2 + let l3 = deepcopy(l2) + $put ='same list: ' . (l3[1] is l3[2])]]) + expect([[ + + Vim(let):E698: + same list: 1]]) + end) + + it('locked variables (part 1)', function() + source([=[ + let l = [] + for depth in range(5) + $put ='depth is ' . depth + for u in range(3) + unlet l + let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] + exe "lockvar " . depth . " l" + if u == 1 + exe "unlockvar l" + elseif u == 2 + exe "unlockvar " . depth . " l" + endif + let ps = islocked("l") . islocked("l[1]") . islocked("l[1][1]") . + \ islocked("l[1][1][0]") . '-' . islocked("l[2]") . + \ islocked("l[2]['6']") . islocked("l[2]['6'][7]") + $put =ps + let ps = '' + try + let l[1][1][0] = 99 + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[1][1] = [99] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[1] = [99] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[2]['6'][7] = 99 + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[2][6] = {99: 99} + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l[2] = {99: 99} + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + let l = [99] + let ps .= 'p' + catch + let ps .= 'F' + endtry + $put =ps + endfor + endfor]=]) + expect([[ + + depth is 0 + 0000-000 + ppppppp + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 1 + 1000-000 + ppppppF + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 2 + 1100-100 + ppFppFF + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 3 + 1110-110 + pFFpFFF + 0010-010 + pFppFpp + 0000-000 + ppppppp + depth is 4 + 1111-111 + FFFFFFF + 0011-011 + FFpFFpp + 0000-000 + ppppppp]]) + end) + + -- TODO In the original test the 5th line of this source() call was used. + -- But now the test only passes if I comment it. + it('unletting locked variables', function() + source([=[ + let l = [] + for depth in range(5) + $put ='depth is ' . depth + for u in range(3) + "unlet l + let l = [0, [1, [2, 3]], {4: 5, 6: {7: 8}}] + exe "lockvar " . depth . " l" + if u == 1 + exe "unlockvar l" + elseif u == 2 + exe "unlockvar " . depth . " l" + endif + let ps = islocked("l") . islocked("l[1]") . islocked("l[1][1]") . + \ islocked("l[1][1][0]") . '-' . islocked("l[2]") . + \ islocked("l[2]['6']") . islocked("l[2]['6'][7]") + $put =ps + let ps = '' + try + unlet l[2]['6'][7] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[2][6] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[2] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[1][1][0] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[1][1] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l[1] + let ps .= 'p' + catch + let ps .= 'F' + endtry + try + unlet l + let ps .= 'p' + catch + let ps .= 'F' + endtry + $put =ps + endfor + endfor]=]) + expect([[ + + depth is 0 + 0000-000 + ppppppp + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 1 + 1000-000 + ppFppFp + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 2 + 1100-100 + pFFpFFp + 0000-000 + ppppppp + 0000-000 + ppppppp + depth is 3 + 1110-110 + FFFFFFp + 0010-010 + FppFppp + 0000-000 + ppppppp + depth is 4 + 1111-111 + FFFFFFp + 0011-011 + FppFppp + 0000-000 + ppppppp]]) + end) + + it('locked variables and :unlet or list / dict functions', function() + source([[ + $put ='Locks and commands or functions:' + + $put ='No :unlet after lock on dict:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar 1 d + try + unlet d.a + $put ='did :unlet' + catch + $put =v:exception[:16] + endtry + $put =string(d) + + $put =':unlet after lock on dict item:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar d.a + try + unlet d.a + $put ='did :unlet' + catch + $put =v:exception[:16] + endtry + $put =string(d) + + $put ='filter() after lock on dict item:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar d.a + try + call filter(d, 'v:key != "a"') + $put ='did filter()' + catch + $put =v:exception[:16] + endtry + $put =string(d) + + $put ='map() after lock on dict:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar 1 d + try + call map(d, 'v:val + 200') + $put ='did map()' + catch + $put =v:exception[:16] + endtry + $put =string(d) + + $put ='No extend() after lock on dict item:' + unlet! d + let d = {'a': 99, 'b': 100} + lockvar d.a + try + $put =string(extend(d, {'a': 123})) + $put ='did extend()' + catch + $put =v:exception[:14] + endtry + $put =string(d) + + $put ='No remove() of write-protected scope-level variable:' + fun! Tfunc(this_is_a_loooooooooong_parameter_name) + try + $put =string(remove(a:, 'this_is_a_loooooooooong_parameter_name')) + $put ='did remove()' + catch + $put =v:exception[:14] + endtry + endfun + call Tfunc('testval') + + $put ='No extend() of write-protected scope-level variable:' + fun! Tfunc(this_is_a_loooooooooong_parameter_name) + try + $put =string(extend(a:, {'this_is_a_loooooooooong_parameter_name': 1234})) + $put ='did extend()' + catch + $put =v:exception[:14] + endtry + endfun + call Tfunc('testval') + + $put ='No :unlet of variable in locked scope:' + let b:testvar = 123 + lockvar 1 b: + try + unlet b:testvar + $put ='b:testvar was :unlet: '. (!exists('b:testvar')) + catch + $put =v:exception[:16] + endtry + unlockvar 1 b: + unlet! b:testvar + + $put ='No :let += of locked list variable:' + let l = ['a', 'b', 3] + lockvar 1 l + try + let l += ['x'] + $put ='did :let +=' + catch + $put =v:exception[:14] + endtry + $put =string(l)]]) + + expect([=[ + + Locks and commands or functions: + No :unlet after lock on dict: + Vim(unlet):E741: + {'a': 99, 'b': 100} + :unlet after lock on dict item: + did :unlet + {'b': 100} + filter() after lock on dict item: + did filter() + {'b': 100} + map() after lock on dict: + did map() + {'a': 299, 'b': 300} + No extend() after lock on dict item: + Vim(put):E741: + {'a': 99, 'b': 100} + No remove() of write-protected scope-level variable: + Vim(put):E795: + No extend() of write-protected scope-level variable: + Vim(put):E742: + No :unlet of variable in locked scope: + Vim(unlet):E741: + No :let += of locked list variable: + Vim(let):E741: + ['a', 'b', 3]]=]) + end) + + it('locked variables (part 2)', function() + execute( + 'let l = [1, 2, 3, 4]', + 'lockvar! l', + '$put =string(l)', + 'unlockvar l[1]', + 'unlet l[0:1]', + '$put =string(l)', + 'unlet l[1:2]', + '$put =string(l)', + 'unlockvar l[1]', + 'let l[0:1] = [0, 1]', + '$put =string(l)', + 'let l[1:2] = [0, 1]', + '$put =string(l)') + expect([=[ + + [1, 2, 3, 4] + [1, 2, 3, 4] + [1, 2, 3, 4] + [1, 2, 3, 4] + [1, 2, 3, 4]]=]) + end) + + it(':lockvar/islocked() triggering script autoloading.', function() + source([[ + set rtp+=test/functional/fixtures + lockvar g:footest#x + unlockvar g:footest#x + $put ='locked g:footest#x:'.islocked('g:footest#x') + $put ='exists g:footest#x:'.exists('g:footest#x') + $put ='g:footest#x: '.g:footest#x]]) + expect([[ + + locked g:footest#x:-1 + exists g:footest#x:0 + g:footest#x: 1]]) + end) + + it('a:000 function argument', function() + source([[ + function Test(...) + " First the tests that should fail. + try + let a:000 = [1, 2] + catch + $put ='caught a:000' + endtry + try + let a:000[0] = 9 + catch + $put ='caught a:000[0]' + endtry + try + let a:000[2] = [9, 10] + catch + $put ='caught a:000[2]' + endtry + try + let a:000[3] = {9: 10} + catch + $put ='caught a:000[3]' + endtry + " Now the tests that should pass. + try + let a:000[2][1] = 9 + call extend(a:000[2], [5, 6]) + let a:000[3][5] = 8 + let a:000[3]['a'] = 12 + $put =string(a:000) + catch + $put ='caught ' . v:exception + endtry + endfunction]]) + execute('call Test(1, 2, [3, 4], {5: 6})') + expect([=[ + + caught a:000 + caught a:000[0] + caught a:000[2] + caught a:000[3] + [1, 2, [3, 9, 5, 6], {'a': 12, '5': 8}]]=]) + end) + + it('reverse(), sort(), uniq()', function() + source([=[ + let l = ['-0', 'A11', 2, 2, 'xaaa', 4, 'foo', 'foo6', 'foo', + \ [0, 1, 2], 'x8', [0, 1, 2], 1.5] + $put =string(uniq(copy(l))) + $put =string(reverse(l)) + $put =string(reverse(reverse(l))) + $put =string(sort(l)) + $put =string(reverse(sort(l))) + $put =string(sort(reverse(sort(l)))) + $put =string(uniq(sort(l))) + let l=[7, 9, 'one', 18, 12, 22, 'two', 10.0e-16, -1, 'three', 0xff, + \ 0.22, 'four'] + $put =string(sort(copy(l), 'n')) + let l=[7, 9, 18, 12, 22, 10.0e-16, -1, 0xff, 0, -0, 0.22, 'bar', + \ 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', {}, []] + $put =string(sort(copy(l), 1)) + $put =string(sort(copy(l), 'i')) + $put =string(sort(copy(l)))]=]) + expect([=[ + + ['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5] + [1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'] + [1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0'] + ['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]] + [[0, 1, 2], [0, 1, 2], 4, 2, 2, 1.5, 'xaaa', 'x8', 'foo6', 'foo', 'foo', 'A11', '-0'] + ['-0', 'A11', 'foo', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 2, 4, [0, 1, 2], [0, 1, 2]] + ['-0', 'A11', 'foo', 'foo6', 'x8', 'xaaa', 1.5, 2, 4, [0, 1, 2]] + [-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255] + ['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}] + ['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}] + ['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}]]=]) + end) + + it('splitting a string to a list', function() + source([[ + $put =string(split(' aa bb ')) + $put =string(split(' aa bb ', '\W\+', 0)) + $put =string(split(' aa bb ', '\W\+', 1)) + $put =string(split(' aa bb ', '\W', 1)) + $put =string(split(':aa::bb:', ':', 0)) + $put =string(split(':aa::bb:', ':', 1)) + $put =string(split('aa,,bb, cc,', ',\s*', 1)) + $put =string(split('abc', '\zs')) + $put =string(split('abc', '\zs', 1))]]) + expect([=[ + + ['aa', 'bb'] + ['aa', 'bb'] + ['', 'aa', 'bb', ''] + ['', '', 'aa', '', 'bb', '', ''] + ['aa', '', 'bb'] + ['', 'aa', '', 'bb', ''] + ['aa', '', 'bb', 'cc', ''] + ['a', 'b', 'c'] + ['', 'a', '', 'b', '', 'c', '']]=]) + end) + + it('compare recursively linked list and dict', function() + source([[ + let l = [1, 2, 3, 4] + let d = {'1': 1, '2': l, '3': 3} + let l[1] = d + $put =(l == l) + $put =(d == d) + $put =(l != deepcopy(l)) + $put =(d != deepcopy(d))]]) + expect([[ + + 1 + 1 + 0 + 0]]) + end) + + it('compare complex recursively linked list and dict', function() + source([[ + let l = [] + call add(l, l) + let dict4 = {"l": l} + call add(dict4.l, dict4) + let lcopy = deepcopy(l) + let dict4copy = deepcopy(dict4) + $put =(l == lcopy) + $put =(dict4 == dict4copy)]]) + expect([[ + + 1 + 1]]) + end) + + it('pass the same list to extend()', function() + source([[ + let l = [1, 2, 3, 4, 5] + call extend(l, l) + $put =string(l)]]) + expect([=[ + + [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]]=]) + end) + + it('pass the same dict to extend()', function() + source([[ + let d = { 'a': {'b': 'B'}} + call extend(d, d) + $put =string(d)]]) + expect([[ + + {'a': {'b': 'B'}}]]) + end) + + it('pass the same dict to extend() with "error"', function() + source([[ + " Copy dict from previous test. + let d = { 'a': {'b': 'B'}} + try + call extend(d, d, "error") + catch + $put =v:exception[:15] . v:exception[-1:-1] + endtry + $put =string(d)]]) + expect([[ + + Vim(call):E737: a + {'a': {'b': 'B'}}]]) + end) + + it('test for range assign', function() + source([[ + let l = [0] + let l[:] = [1, 2] + $put =string(l)]]) + expect([=[ + + [1, 2]]=]) + end) + + it('vim patch 7.3.637', function() + execute('let a = "No error caught"') + execute('try') + execute(' foldopen') + execute('catch') + execute(" let a = matchstr(v:exception,'^[^ ]*')") + execute('endtry') + feed('o<C-R>=a<CR><esc>') + execute('lang C') + execute('redir => a') + -- The test failes if this is not in one line. + execute("try|foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry") + execute('redir END') + feed('o<C-R>=a<CR><esc>') + expect([[ + + Vim(foldopen):E490: + + + Error detected while processing : + E492: Not an editor command: foobar|catch|let a = matchstr(v:exception,'^[^ ]*')|endtry + ]]) + end) +end) diff --git a/test/functional/legacy/056_script_local_function_spec.lua b/test/functional/legacy/056_script_local_function_spec.lua index dec88e8001..084817ad7a 100644 --- a/test/functional/legacy/056_script_local_function_spec.lua +++ b/test/functional/legacy/056_script_local_function_spec.lua @@ -1,7 +1,7 @@ -- vim: set foldmethod=marker foldmarker=[[,]] : -- Test for script-local function. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local expect = helpers.expect diff --git a/test/functional/legacy/057_sort_spec.lua b/test/functional/legacy/057_sort_spec.lua index 36062ded3a..6984ad0de2 100644 --- a/test/functional/legacy/057_sort_spec.lua +++ b/test/functional/legacy/057_sort_spec.lua @@ -1,6 +1,6 @@ -- Tests for :sort command. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert, execute, clear, expect, eq, eval, source = helpers.insert, helpers.execute, helpers.clear, helpers.expect, helpers.eq, helpers.eval, helpers.source diff --git a/test/functional/legacy/059_utf8_spell_checking_spec.lua b/test/functional/legacy/059_utf8_spell_checking_spec.lua index 63df387be3..c44ab44b3c 100644 --- a/test/functional/legacy/059_utf8_spell_checking_spec.lua +++ b/test/functional/legacy/059_utf8_spell_checking_spec.lua @@ -1,6 +1,6 @@ -- Tests for spell checking with 'encoding' set to "utf-8". -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect local write_file, call = helpers.write_file, helpers.call diff --git a/test/functional/legacy/060_exists_and_has_functions_spec.lua b/test/functional/legacy/060_exists_and_has_functions_spec.lua index 7f44b35a4e..cbd857c524 100644 --- a/test/functional/legacy/060_exists_and_has_functions_spec.lua +++ b/test/functional/legacy/060_exists_and_has_functions_spec.lua @@ -1,6 +1,6 @@ -- Tests for the exists() and has() functions. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local source = helpers.source local clear, expect = helpers.clear, helpers.expect local write_file = helpers.write_file diff --git a/test/functional/legacy/061_undo_tree_spec.lua b/test/functional/legacy/061_undo_tree_spec.lua index 6db37bf1ff..9bf69ccba1 100644 --- a/test/functional/legacy/061_undo_tree_spec.lua +++ b/test/functional/legacy/061_undo_tree_spec.lua @@ -1,10 +1,15 @@ -- Tests for undo tree and :earlier and :later. +local helpers = require('test.functional.helpers')(after_each) -local helpers = require('test.functional.helpers') -local feed, source, eq, eval, clear, execute, expect, wait, write_file = - helpers.feed, helpers.source, helpers.eq, helpers.eval, - helpers.clear, helpers.execute, helpers.expect, helpers.wait, - helpers.write_file +local write_file = helpers.write_file +local execute = helpers.execute +local command = helpers.command +local source = helpers.source +local expect = helpers.expect +local clear = helpers.clear +local feed = helpers.feed +local eval = helpers.eval +local eq = helpers.eq local function expect_empty_buffer() -- The space will be removed by helpers.dedent but is needed because dedent @@ -57,8 +62,7 @@ describe('undo tree:', function() -- Delete three other characters and go back in time step by step. feed('$xxx') expect_line('123456') - execute('sleep 1') - wait() + command('sleep 1') feed('g-') expect_line('1234567') feed('g-') @@ -79,8 +83,7 @@ describe('undo tree:', function() expect_line('123456') -- Delay for two seconds and go some seconds forward and backward. - execute('sleep 2') - wait() + command('sleep 2') feed('Aa<esc>') feed('Ab<esc>') feed('Ac<esc>') diff --git a/test/functional/legacy/062_tab_pages_spec.lua b/test/functional/legacy/062_tab_pages_spec.lua index f1c8b8d58b..d5b10b160e 100644 --- a/test/functional/legacy/062_tab_pages_spec.lua +++ b/test/functional/legacy/062_tab_pages_spec.lua @@ -1,6 +1,6 @@ -- Tests for tab pages -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, source, clear, execute, expect, eval, eq = helpers.feed, helpers.insert, helpers.source, helpers.clear, helpers.execute, helpers.expect, helpers.eval, helpers.eq diff --git a/test/functional/legacy/063_match_and_matchadd_spec.lua b/test/functional/legacy/063_match_and_matchadd_spec.lua index 23b4f4551b..298e0a31ea 100644 --- a/test/functional/legacy/063_match_and_matchadd_spec.lua +++ b/test/functional/legacy/063_match_and_matchadd_spec.lua @@ -1,6 +1,6 @@ -- Tests for adjusting window and contents -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local feed, insert = helpers.feed, helpers.insert local eval, clear, execute = helpers.eval, helpers.clear, helpers.execute diff --git a/test/functional/legacy/065_float_and_logic_operators_spec.lua b/test/functional/legacy/065_float_and_logic_operators_spec.lua index e78b230956..d12ea502f3 100644 --- a/test/functional/legacy/065_float_and_logic_operators_spec.lua +++ b/test/functional/legacy/065_float_and_logic_operators_spec.lua @@ -1,6 +1,6 @@ -- Test for floating point and logical operators. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert, source = helpers.insert, helpers.source local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/066_visual_block_tab_spec.lua b/test/functional/legacy/066_visual_block_tab_spec.lua index 82bb988c67..72fa7d881b 100644 --- a/test/functional/legacy/066_visual_block_tab_spec.lua +++ b/test/functional/legacy/066_visual_block_tab_spec.lua @@ -1,7 +1,7 @@ -- vim: set foldmethod=marker foldmarker=[[,]] : -- Test for visual block shift and tab characters. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/067_augroup_exists_spec.lua b/test/functional/legacy/067_augroup_exists_spec.lua index dc4c9c7eeb..8f6b881ed8 100644 --- a/test/functional/legacy/067_augroup_exists_spec.lua +++ b/test/functional/legacy/067_augroup_exists_spec.lua @@ -1,7 +1,7 @@ -- Test that groups and patterns are tested correctly when calling exists() for -- autocommands. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/068_text_formatting_spec.lua b/test/functional/legacy/068_text_formatting_spec.lua new file mode 100644 index 0000000000..e232e5073d --- /dev/null +++ b/test/functional/legacy/068_text_formatting_spec.lua @@ -0,0 +1,211 @@ +local helpers = require('test.functional.helpers')(after_each) + +local feed = helpers.feed +local clear = helpers.clear +local insert = helpers.insert +local execute = helpers.execute +local expect = helpers.expect + +describe('text formatting', function() + setup(clear) + + it('is working', function() + -- The control character <C-A> (byte \x01) needs to be put in the buffer + -- directly. But the insert function sends the text to nvim in insert + -- mode so it has to be escaped with <C-V>. + insert([[ + Results of test68: + + + { + + + } + + + { + a b + + a + } + + + { + a + } + + + { + a b + #a b + } + + + { + 1 a + # 1 a + } + + + { + + x a + b + c + + } + + + { + # 1 a b + } + + + { + # x + # a b + } + + + { + 1aa + 2bb + } + + + /* abc def ghi jkl + * mno pqr stu + */ + + + # 1 xxxxx + ]]) + + execute('/^{/+1') + execute('set noai tw=2 fo=t') + feed('gRa b<esc>') + + execute('/^{/+1') + execute('set ai tw=2 fo=tw') + feed('gqgqjjllab<esc>') + + execute('/^{/+1') + execute('set tw=3 fo=t') + feed('gqgqo<cr>') + feed('a <C-V><C-A><esc><esc>') + + execute('/^{/+1') + execute('set tw=2 fo=tcq1 comments=:#') + feed('gqgqjgqgqo<cr>') + feed('a b<cr>') + feed('#a b<esc>') + + execute('/^{/+1') + execute('set tw=5 fo=tcn comments=:#') + feed('A b<esc>jA b<esc>') + + execute('/^{/+3') + execute('set tw=5 fo=t2a si') + feed('i <esc>A_<esc>') + + execute('/^{/+1') + execute('set tw=5 fo=qn comments=:#') + feed('gwap<cr>') + + execute('/^{/+1') + execute('set tw=5 fo=q2 comments=:#') + feed('gwap<cr>') + + execute('/^{/+2') + execute('set tw& fo=a') + feed('I^^<esc><esc>') + + execute('/mno pqr/') + execute('setl tw=20 fo=an12wcq comments=s1:/*,mb:*,ex:*/') + feed('A vwx yz<esc>') + + execute('/^#/') + execute('setl tw=12 fo=tqnc comments=:#') + feed('A foobar<esc>') + + -- Assert buffer contents. + expect([[ + Results of test68: + + + { + a + b + } + + + { + a + b + + a + b + } + + + { + a + + + a + + } + + + { + a b + #a b + + a b + #a b + } + + + { + 1 a + b + # 1 a + # b + } + + + { + + x a + b_ + c + + } + + + { + # 1 a + # b + } + + + { + # x a + # b + } + + + { 1aa ^^2bb } + + + /* abc def ghi jkl + * mno pqr stu + * vwx yz + */ + + + # 1 xxxxx + # foobar + ]]) + end) +end) diff --git a/test/functional/legacy/072_undo_file_spec.lua b/test/functional/legacy/072_undo_file_spec.lua index efcc2f2cc3..4682a82008 100644 --- a/test/functional/legacy/072_undo_file_spec.lua +++ b/test/functional/legacy/072_undo_file_spec.lua @@ -2,7 +2,7 @@ -- Since this script is sourced we need to explicitly break changes up in -- undo-able pieces. Do that by setting 'undolevels'. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/074_global_var_in_viminfo_spec.lua b/test/functional/legacy/074_global_var_in_viminfo_spec.lua index 49c4827613..2fc30c9d83 100644 --- a/test/functional/legacy/074_global_var_in_viminfo_spec.lua +++ b/test/functional/legacy/074_global_var_in_viminfo_spec.lua @@ -1,6 +1,7 @@ -- Tests for storing global variables in the .shada file -local helpers, lfs = require('test.functional.helpers'), require('lfs') +local helpers = require('test.functional.helpers')(after_each) +local lfs = require('lfs') local clear, execute, eq, neq, eval, wait, spawn = helpers.clear, helpers.execute, helpers.eq, helpers.neq, helpers.eval, helpers.wait, helpers.spawn diff --git a/test/functional/legacy/075_maparg_spec.lua b/test/functional/legacy/075_maparg_spec.lua index 82965f5cb2..e9d2acdaf5 100644 --- a/test/functional/legacy/075_maparg_spec.lua +++ b/test/functional/legacy/075_maparg_spec.lua @@ -1,7 +1,7 @@ -- Tests for maparg(). -- Also test utf8 map with a 0x80 byte. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed = helpers.clear, helpers.feed local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/076_completefunc_spec.lua b/test/functional/legacy/076_completefunc_spec.lua index 8af3be003e..bf3f56eb84 100644 --- a/test/functional/legacy/076_completefunc_spec.lua +++ b/test/functional/legacy/076_completefunc_spec.lua @@ -1,6 +1,6 @@ -- Tests for completefunc/omnifunc. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source local clear, expect, execute = helpers.clear, helpers.expect, helpers.execute diff --git a/test/functional/legacy/077_mf_hash_grow_spec.lua b/test/functional/legacy/077_mf_hash_grow_spec.lua index 029fe98fe9..b43263300d 100644 --- a/test/functional/legacy/077_mf_hash_grow_spec.lua +++ b/test/functional/legacy/077_mf_hash_grow_spec.lua @@ -6,7 +6,7 @@ -- cksum is part of POSIX and so should be available on most Unixes. -- If it isn't available then the test will be skipped. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed = helpers.feed local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/078_swapfile_recover_spec.lua b/test/functional/legacy/078_swapfile_recover_spec.lua index e48fddaac1..4390ba2ca8 100644 --- a/test/functional/legacy/078_swapfile_recover_spec.lua +++ b/test/functional/legacy/078_swapfile_recover_spec.lua @@ -3,7 +3,7 @@ -- restored. We need about 10000 lines of 100 characters to get two levels of -- pointer blocks. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, expect, source = helpers.clear, helpers.expect, helpers.source describe('78', function() diff --git a/test/functional/legacy/080_substitute_spec.lua b/test/functional/legacy/080_substitute_spec.lua index 96082364e0..1bdae9be59 100644 --- a/test/functional/legacy/080_substitute_spec.lua +++ b/test/functional/legacy/080_substitute_spec.lua @@ -2,7 +2,7 @@ -- Test for submatch() on substitue(). -- Test for *:s%* on :substitute. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect local eq, eval = helpers.eq, helpers.eval diff --git a/test/functional/legacy/081_coptions_movement_spec.lua b/test/functional/legacy/081_coptions_movement_spec.lua index f27667b976..2ac1332687 100644 --- a/test/functional/legacy/081_coptions_movement_spec.lua +++ b/test/functional/legacy/081_coptions_movement_spec.lua @@ -1,6 +1,6 @@ -- Test for t movement command and 'cpo-;' setting -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/082_string_comparison_spec.lua b/test/functional/legacy/082_string_comparison_spec.lua index 933c6c8fa3..d6f3c45e1f 100644 --- a/test/functional/legacy/082_string_comparison_spec.lua +++ b/test/functional/legacy/082_string_comparison_spec.lua @@ -1,7 +1,7 @@ -- Tests for case-insensitive UTF-8 comparisons (utf_strnicmp() in mbyte.c) -- Also test "g~ap". -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, source = helpers.feed, helpers.source local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua b/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua index 6b5ee60568..e94b46ca66 100644 --- a/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua +++ b/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua @@ -1,6 +1,6 @@ -- Tests for tag search with !_TAG_FILE_ENCODING. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert, source, clear, expect, write_file = helpers.insert, helpers.source, helpers.clear, helpers.expect, helpers.write_file diff --git a/test/functional/legacy/084_curswant_spec.lua b/test/functional/legacy/084_curswant_spec.lua index 946dd5e501..818914eeb9 100644 --- a/test/functional/legacy/084_curswant_spec.lua +++ b/test/functional/legacy/084_curswant_spec.lua @@ -1,6 +1,6 @@ -- Tests for curswant not changing when setting an option. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert, source = helpers.insert, helpers.source local clear, expect = helpers.clear, helpers.expect diff --git a/test/functional/legacy/088_conceal_tabs_spec.lua b/test/functional/legacy/088_conceal_tabs_spec.lua index c78f4e5c3e..00e7312bf8 100644 --- a/test/functional/legacy/088_conceal_tabs_spec.lua +++ b/test/functional/legacy/088_conceal_tabs_spec.lua @@ -1,7 +1,7 @@ -- Tests for correct display (cursor column position) with +conceal and -- tabulators. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, clear, execute = helpers.feed, helpers.insert, helpers.clear, helpers.execute diff --git a/test/functional/legacy/089_number_relnumber_findfile_spec.lua b/test/functional/legacy/089_number_relnumber_findfile_spec.lua index f72ebf3f72..7a87fc8603 100644 --- a/test/functional/legacy/089_number_relnumber_findfile_spec.lua +++ b/test/functional/legacy/089_number_relnumber_findfile_spec.lua @@ -2,7 +2,7 @@ -- This is not all that useful now that the options are no longer reset when -- setting the other. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed = helpers.feed local clear, expect, source = helpers.clear, helpers.expect, helpers.source diff --git a/test/functional/legacy/090_sha256_spec.lua b/test/functional/legacy/090_sha256_spec.lua index 95e50063a1..e364af9400 100644 --- a/test/functional/legacy/090_sha256_spec.lua +++ b/test/functional/legacy/090_sha256_spec.lua @@ -1,6 +1,6 @@ -- Tests for sha256() function. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert, source = helpers.insert, helpers.source local clear, expect = helpers.clear, helpers.expect diff --git a/test/functional/legacy/091_context_variables_spec.lua b/test/functional/legacy/091_context_variables_spec.lua index 2c46ef643c..edf497d397 100644 --- a/test/functional/legacy/091_context_variables_spec.lua +++ b/test/functional/legacy/091_context_variables_spec.lua @@ -1,6 +1,6 @@ -- Tests for getbufvar(), getwinvar(), gettabvar() and gettabwinvar(). -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert, source = helpers.insert, helpers.source local clear, expect = helpers.clear, helpers.expect diff --git a/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua b/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua index f76ba25d7a..f8564384e9 100644 --- a/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua +++ b/test/functional/legacy/092_mksession_cursor_cols_utf8_spec.lua @@ -3,7 +3,7 @@ -- -- Same as legacy test 93 but using UTF-8 file encoding. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua b/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua index bf3af1a827..719ce25099 100644 --- a/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua +++ b/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua @@ -3,7 +3,7 @@ -- -- Same as legacy test 92 but using Latin-1 file encoding. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/094_visual_mode_operators_spec.lua b/test/functional/legacy/094_visual_mode_operators_spec.lua index 4dce39b8d2..a52fa00672 100644 --- a/test/functional/legacy/094_visual_mode_operators_spec.lua +++ b/test/functional/legacy/094_visual_mode_operators_spec.lua @@ -4,7 +4,7 @@ -- followed by an operator and those executed via Operator-pending mode. Also -- part of the test are mappings, counts, and repetition with the . command. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/095_regexp_multibyte_spec.lua b/test/functional/legacy/095_regexp_multibyte_spec.lua index a80a247612..845ebaaad7 100644 --- a/test/functional/legacy/095_regexp_multibyte_spec.lua +++ b/test/functional/legacy/095_regexp_multibyte_spec.lua @@ -3,7 +3,7 @@ -- A pattern that gives the expected result produces OK, so that we know it was -- actually tried. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert, source = helpers.insert, helpers.source local clear, expect = helpers.clear, helpers.expect diff --git a/test/functional/legacy/096_location_list_spec.lua b/test/functional/legacy/096_location_list_spec.lua index 6e2f22ea33..eac8d6356d 100644 --- a/test/functional/legacy/096_location_list_spec.lua +++ b/test/functional/legacy/096_location_list_spec.lua @@ -6,7 +6,7 @@ -- C. make sure that the location list window is not reused instead of the window -- it belongs to. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local source = helpers.source local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/097_glob_path_spec.lua b/test/functional/legacy/097_glob_path_spec.lua index 5c467fbb20..a6c146891a 100644 --- a/test/functional/legacy/097_glob_path_spec.lua +++ b/test/functional/legacy/097_glob_path_spec.lua @@ -2,7 +2,7 @@ -- Test whether glob()/globpath() return correct results with certain escaped -- characters. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/098_scrollbind_spec.lua b/test/functional/legacy/098_scrollbind_spec.lua index 6850e373ab..d22aefdcbc 100644 --- a/test/functional/legacy/098_scrollbind_spec.lua +++ b/test/functional/legacy/098_scrollbind_spec.lua @@ -1,6 +1,6 @@ -- Test for 'scrollbind' causing an unexpected scroll of one of the windows. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local source = helpers.source local clear, expect = helpers.clear, helpers.expect diff --git a/test/functional/legacy/101_hlsearch_spec.lua b/test/functional/legacy/101_hlsearch_spec.lua index 335d275c2a..0d88e99278 100644 --- a/test/functional/legacy/101_hlsearch_spec.lua +++ b/test/functional/legacy/101_hlsearch_spec.lua @@ -1,6 +1,6 @@ -- Test for v:hlsearch -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed = helpers.clear, helpers.feed local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/102_fnameescape_spec.lua b/test/functional/legacy/102_fnameescape_spec.lua index a3b0313d7a..c1a6c57956 100644 --- a/test/functional/legacy/102_fnameescape_spec.lua +++ b/test/functional/legacy/102_fnameescape_spec.lua @@ -1,6 +1,6 @@ -- Test if fnameescape is correct for special chars like! -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/103_visual_mode_reset_spec.lua b/test/functional/legacy/103_visual_mode_reset_spec.lua index c1407ef10a..d05b47fa32 100644 --- a/test/functional/legacy/103_visual_mode_reset_spec.lua +++ b/test/functional/legacy/103_visual_mode_reset_spec.lua @@ -1,6 +1,6 @@ -- Test for visual mode not being reset causing E315 error. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, source = helpers.feed, helpers.source local clear, expect = helpers.clear, helpers.expect diff --git a/test/functional/legacy/104_let_assignment_spec.lua b/test/functional/legacy/104_let_assignment_spec.lua index a2431da835..27c3715231 100644 --- a/test/functional/legacy/104_let_assignment_spec.lua +++ b/test/functional/legacy/104_let_assignment_spec.lua @@ -1,6 +1,6 @@ -- Tests for :let. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, source = helpers.clear, helpers.source local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/106_errorformat_spec.lua b/test/functional/legacy/106_errorformat_spec.lua index 5958f1aa7b..2b17d63378 100644 --- a/test/functional/legacy/106_errorformat_spec.lua +++ b/test/functional/legacy/106_errorformat_spec.lua @@ -1,6 +1,6 @@ -- Tests for errorformat. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/107_adjust_window_and_contents_spec.lua b/test/functional/legacy/107_adjust_window_and_contents_spec.lua index 7a6de3d748..ce8d967e00 100644 --- a/test/functional/legacy/107_adjust_window_and_contents_spec.lua +++ b/test/functional/legacy/107_adjust_window_and_contents_spec.lua @@ -1,6 +1,6 @@ -- Tests for adjusting window and contents -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local insert = helpers.insert local clear, execute = helpers.clear, helpers.execute diff --git a/test/functional/legacy/108_backtrace_debug_commands_spec.lua b/test/functional/legacy/108_backtrace_debug_commands_spec.lua new file mode 100644 index 0000000000..a03092e446 --- /dev/null +++ b/test/functional/legacy/108_backtrace_debug_commands_spec.lua @@ -0,0 +1,177 @@ +-- Tests for backtrace debug commands. + +local helpers = require('test.functional.helpers')(after_each) +local feed, clear = helpers.feed, helpers.clear +local execute, expect = helpers.execute, helpers.expect + +describe('108', function() + before_each(clear) + + it('is working', function() + execute('lang mess C') + execute('function! Foo()') + execute(' let var1 = 1') + execute(' let var2 = Bar(var1) + 9') + execute(' return var2') + execute('endfunction') + execute('function! Bar(var)') + execute(' let var1 = 2 + a:var') + execute(' let var2 = Bazz(var1) + 4') + execute(' return var2') + execute('endfunction') + execute('function! Bazz(var)') + execute(' let var1 = 3 + a:var') + execute(' let var3 = "another var"') + execute(' return var1') + execute('endfunction') + execute('new') + execute('debuggreedy') + execute('redir => out') + execute('debug echo Foo()') + feed('step<cr>') + feed('step<cr>') + feed('step<cr>') + feed('step<cr>') + feed('step<cr>') + feed('step<cr>') + feed([[echo "- show backtrace:\n"<cr>]]) + feed('backtrace<cr>') + feed([[echo "\nshow variables on different levels:\n"<cr>]]) + feed('echo var1<cr>') + feed('up<cr>') + feed('back<cr>') + feed('echo var1<cr>') + feed('u<cr>') + feed('bt<cr>') + feed('echo var1<cr>') + feed([[echo "\n- undefined vars:\n"<cr>]]) + feed('step<cr>') + feed('frame 2<cr>') + feed('echo "undefined var3 on former level:"<cr>') + feed('echo var3<cr>') + feed('fr 0<cr>') + feed([[echo "here var3 is defined with \"another var\":"<cr>]]) + feed('echo var3<cr>') + feed('step<cr>') + feed('step<cr>') + feed('step<cr>') + feed('up<cr>') + feed([[echo "\nundefined var2 on former level"<cr>]]) + feed('echo var2<cr>') + feed('down<cr>') + feed('echo "here var2 is defined with 10:"<cr>') + feed('echo var2<cr>') + feed([[echo "\n- backtrace movements:\n"<cr>]]) + feed('b<cr>') + feed([[echo "\nnext command cannot go down, we are on bottom\n"<cr>]]) + feed('down<cr>') + feed('up<cr>') + feed([[echo "\nnext command cannot go up, we are on top\n"<cr>]]) + feed('up<cr>') + feed('b<cr>') + feed('echo "fil is not frame or finish, it is file"<cr>') + feed('fil<cr>') + feed([[echo "\n- relative backtrace movement\n"<cr>]]) + feed('fr -1<cr>') + feed('frame<cr>') + feed('fra +1<cr>') + feed('fram<cr>') + feed([[echo "\n- go beyond limits does not crash\n"<cr>]]) + feed('fr 100<cr>') + feed('fra<cr>') + feed('frame -40<cr>') + feed('fram<cr>') + feed([[echo "\n- final result 19:"<cr>]]) + feed('cont<cr>') + execute('0debuggreedy') + execute('redir END') + execute('$put =out') + + -- Assert buffer contents. + expect([=[ + + + + - show backtrace: + + 2 function Foo[2] + 1 Bar[2] + ->0 Bazz + line 2: let var3 = "another var" + + show variables on different levels: + + 6 + 2 function Foo[2] + ->1 Bar[2] + 0 Bazz + line 2: let var3 = "another var" + 3 + ->2 function Foo[2] + 1 Bar[2] + 0 Bazz + line 2: let var3 = "another var" + 1 + + - undefined vars: + + undefined var3 on former level: + Error detected while processing function Foo[2]..Bar[2]..Bazz: + line 3: + E121: Undefined variable: var3 + E15: Invalid expression: var3 + here var3 is defined with "another var": + another var + + undefined var2 on former level + Error detected while processing function Foo[2]..Bar: + line 3: + E121: Undefined variable: var2 + E15: Invalid expression: var2 + here var2 is defined with 10: + 10 + + - backtrace movements: + + 1 function Foo[2] + ->0 Bar + line 3: End of function + + next command cannot go down, we are on bottom + + frame is zero + + next command cannot go up, we are on top + + frame at highest level: 1 + ->1 function Foo[2] + 0 Bar + line 3: End of function + fil is not frame or finish, it is file + "[No Name]" --No lines in buffer-- + + - relative backtrace movement + + 1 function Foo[2] + ->0 Bar + line 3: End of function + ->1 function Foo[2] + 0 Bar + line 3: End of function + + - go beyond limits does not crash + + frame at highest level: 1 + ->1 function Foo[2] + 0 Bar + line 3: End of function + frame is zero + 1 function Foo[2] + ->0 Bar + line 3: End of function + + - final result 19: + 19 + ]=]) + end) +end) diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua new file mode 100644 index 0000000000..c128aaf115 --- /dev/null +++ b/test/functional/legacy/arglist_spec.lua @@ -0,0 +1,268 @@ +-- Test argument list commands + +local helpers = require('test.functional.helpers')(after_each) +local clear, execute, eq = helpers.clear, helpers.execute, helpers.eq +local eval, exc_exec, neq = helpers.eval, helpers.exc_exec, helpers.neq + +describe('argument list commands', function() + before_each(clear) + + local function init_abc() + execute('args a b c') + execute('next') + end + + local function reset_arglist() + execute('arga a | %argd') + end + + local function assert_fails(cmd, err) + neq(exc_exec(cmd):find(err), nil) + end + + it('test that argidx() works', function() + execute('args a b c') + execute('last') + eq(2, eval('argidx()')) + execute('%argdelete') + eq(0, eval('argidx()')) + + execute('args a b c') + eq(0, eval('argidx()')) + execute('next') + eq(1, eval('argidx()')) + execute('next') + eq(2, eval('argidx()')) + execute('1argdelete') + eq(1, eval('argidx()')) + execute('1argdelete') + eq(0, eval('argidx()')) + execute('1argdelete') + eq(0, eval('argidx()')) + end) + + it('test that argadd() works', function() + execute('%argdelete') + execute('argadd a b c') + eq(0, eval('argidx()')) + + execute('%argdelete') + execute('argadd a') + eq(0, eval('argidx()')) + execute('argadd b c d') + eq(0, eval('argidx()')) + + init_abc() + execute('argadd x') + eq({'a', 'b', 'x', 'c'}, eval('argv()')) + eq(1, eval('argidx()')) + + init_abc() + execute('0argadd x') + eq({'x', 'a', 'b', 'c'}, eval('argv()')) + eq(2, eval('argidx()')) + + init_abc() + execute('1argadd x') + eq({'a', 'x', 'b', 'c'}, eval('argv()')) + eq(2, eval('argidx()')) + + init_abc() + execute('$argadd x') + eq({'a', 'b', 'c', 'x'}, eval('argv()')) + eq(1, eval('argidx()')) + + init_abc() + execute('$argadd x') + execute('+2argadd y') + eq({'a', 'b', 'c', 'x', 'y'}, eval('argv()')) + eq(1, eval('argidx()')) + + execute('%argd') + execute('edit d') + execute('arga') + eq(1, eval('len(argv())')) + eq('d', eval('get(argv(), 0, "")')) + + execute('%argd') + execute('new') + execute('arga') + eq(0, eval('len(argv())')) + end) + + it('test for [count]argument and [count]argdelete commands', function() + reset_arglist() + execute('let save_hidden = &hidden') + execute('set hidden') + execute('let g:buffers = []') + execute('augroup TEST') + execute([[au BufEnter * call add(buffers, expand('%:t'))]]) + execute('augroup END') + + execute('argadd a b c d') + execute('$argu') + execute('$-argu') + execute('-argu') + execute('1argu') + execute('+2argu') + + execute('augroup TEST') + execute('au!') + execute('augroup END') + + eq({'d', 'c', 'b', 'a', 'c'}, eval('g:buffers')) + + execute('redir => result') + execute('ar') + execute('redir END') + eq(1, eval([[result =~# 'a b \[c] d']])) + + execute('.argd') + eq({'a', 'b', 'd'}, eval('argv()')) + + execute('-argd') + eq({'a', 'd'}, eval('argv()')) + + execute('$argd') + eq({'a'}, eval('argv()')) + + execute('1arga c') + execute('1arga b') + execute('$argu') + execute('$arga x') + eq({'a', 'b', 'c', 'x'}, eval('argv()')) + + execute('0arga Y') + eq({'Y', 'a', 'b', 'c', 'x'}, eval('argv()')) + + execute('%argd') + eq({}, eval('argv()')) + + execute('arga a b c d e f') + execute('2,$-argd') + eq({'a', 'f'}, eval('argv()')) + + execute('let &hidden = save_hidden') + + -- Setting the argument list should fail when the current buffer has + -- unsaved changes + execute('%argd') + execute('enew!') + execute('set modified') + assert_fails('args x y z', 'E37:') + execute('args! x y z') + eq({'x', 'y', 'z'}, eval('argv()')) + eq('x', eval('expand("%:t")')) + + execute('%argdelete') + assert_fails('argument', 'E163:') + end) + + it('test for 0argadd and 0argedit', function() + reset_arglist() + + execute('arga a b c d') + execute('2argu') + execute('0arga added') + eq({'added', 'a', 'b', 'c', 'd'}, eval('argv()')) + + execute('%argd') + execute('arga a b c d') + execute('2argu') + execute('0arge edited') + eq({'edited', 'a', 'b', 'c', 'd'}, eval('argv()')) + + execute('2argu') + execute('arga third') + eq({'edited', 'a', 'third', 'b', 'c', 'd'}, eval('argv()')) + end) + + it('test for argc()', function() + reset_arglist() + eq(0, eval('argc()')) + execute('argadd a b') + eq(2, eval('argc()')) + end) + + it('test for arglistid()', function() + reset_arglist() + execute('arga a b') + eq(0, eval('arglistid()')) + execute('split') + execute('arglocal') + eq(1, eval('arglistid()')) + execute('tabnew | tabfirst') + eq(0, eval('arglistid(2)')) + eq(1, eval('arglistid(1, 1)')) + eq(0, eval('arglistid(2, 1)')) + eq(1, eval('arglistid(1, 2)')) + execute('tabonly | only | enew!') + execute('argglobal') + eq(0, eval('arglistid()')) + end) + + it('test for argv()', function() + reset_arglist() + eq({}, eval('argv()')) + eq('', eval('argv(2)')) + execute('argadd a b c d') + eq('c', eval('argv(2)')) + end) + + it('test for :argedit command', function() + reset_arglist() + execute('argedit a') + eq({'a'}, eval('argv()')) + eq('a', eval('expand("%:t")')) + execute('argedit b') + eq({'a', 'b'}, eval('argv()')) + eq('b', eval('expand("%:t")')) + execute('argedit a') + eq({'a', 'b'}, eval('argv()')) + eq('a', eval('expand("%:t")')) + assert_fails('argedit a b', 'E172:') + execute('argedit c') + eq({'a', 'c', 'b'}, eval('argv()')) + execute('0argedit x') + eq({'x', 'a', 'c', 'b'}, eval('argv()')) + execute('enew! | set modified') + assert_fails('argedit y', 'E37:') + execute('argedit! y') + eq({'x', 'y', 'a', 'c', 'b'}, eval('argv()')) + execute('%argd') + end) + + it('test for :argdelete command', function() + reset_arglist() + execute('args aa a aaa b bb') + execute('argdelete a*') + eq({'b', 'bb'}, eval('argv()')) + eq('aa', eval('expand("%:t")')) + execute('last') + execute('argdelete %') + eq({'b'}, eval('argv()')) + assert_fails('argdelete', 'E471:') + assert_fails('1,100argdelete', 'E16:') + execute('%argd') + end) + + it('test for the :next, :prev, :first, :last, :rewind commands', function() + reset_arglist() + execute('args a b c d') + execute('last') + eq(3, eval('argidx()')) + assert_fails('next', 'E165:') + execute('prev') + eq(2, eval('argidx()')) + execute('Next') + eq(1, eval('argidx()')) + execute('first') + eq(0, eval('argidx()')) + assert_fails('prev', 'E164:') + execute('3next') + eq(3, eval('argidx()')) + execute('rewind') + eq(0, eval('argidx()')) + execute('%argd') + end) +end) diff --git a/test/functional/legacy/argument_0count_spec.lua b/test/functional/legacy/argument_0count_spec.lua deleted file mode 100644 index 6e8b60547b..0000000000 --- a/test/functional/legacy/argument_0count_spec.lua +++ /dev/null @@ -1,28 +0,0 @@ --- Tests for :0argadd and :0argedit - -local helpers = require('test.functional.helpers') -local eq, eval, clear, execute = - helpers.eq, helpers.eval, helpers.clear, helpers.execute - -describe('argument_0count', function() - setup(clear) - - it('is working', function() - execute('arga a b c d') - eq({'a', 'b', 'c', 'd'}, eval('argv()')) - execute('2argu') - execute('0arga added') - eq({'added', 'a', 'b', 'c', 'd'}, eval('argv()')) - execute('2argu') - execute('arga third') - eq({'added', 'a', 'third', 'b', 'c', 'd'}, eval('argv()')) - execute('%argd') - execute('arga a b c d') - execute('2argu') - execute('0arge edited') - eq({'edited', 'a', 'b', 'c', 'd'}, eval('argv()')) - execute('2argu') - execute('arga third') - eq({'edited', 'a', 'third', 'b', 'c', 'd'}, eval('argv()')) - end) -end) diff --git a/test/functional/legacy/argument_count_spec.lua b/test/functional/legacy/argument_count_spec.lua deleted file mode 100644 index 182cce9475..0000000000 --- a/test/functional/legacy/argument_count_spec.lua +++ /dev/null @@ -1,47 +0,0 @@ --- Tests for :[count]argument! and :[count]argdelete - -local helpers = require('test.functional.helpers') -local clear, execute, eq, eval = - helpers.clear, helpers.execute, helpers.eq, helpers.eval - -describe('argument_count', function() - setup(clear) - - it('is working', function() - execute('%argd') - execute('argadd a b c d') - eq({'a', 'b', 'c', 'd'}, eval('argv()')) - execute('set hidden') - execute('let buffers = []') - execute('augroup TEST') - execute([[au BufEnter * call add(buffers, expand('%:t'))]]) - execute('augroup END') - execute('$argu') - execute('$-argu') - execute('-argu') - execute('1argu') - execute('+2argu') - execute('augroup TEST') - execute('au!') - execute('augroup END') - eq({'d', 'c', 'b', 'a', 'c'}, eval('buffers')) - execute('.argd') - eq({'a', 'b', 'd'}, eval('argv()')) - execute('-argd') - eq({'a', 'd'}, eval('argv()')) - execute('$argd') - eq({'a'}, eval('argv()')) - execute('1arga c') - execute('1arga b') - execute('$argu') - execute('$arga x') - eq({'a', 'b', 'c', 'x'}, eval('argv()')) - execute('0arga Y') - eq({'Y', 'a', 'b', 'c', 'x'}, eval('argv()')) - execute('%argd') - eq({}, eval('argv()')) - execute('arga a b c d e f') - execute('2,$-argd') - eq({'a', 'f'}, eval('argv()')) - end) -end) diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua index 1ce665360d..cfa368c361 100644 --- a/test/functional/legacy/assert_spec.lua +++ b/test/functional/legacy/assert_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim, call = helpers.meths, helpers.call local clear, eq = helpers.clear, helpers.eq local source, execute = helpers.source, helpers.execute @@ -141,5 +141,35 @@ describe('assert function:', function() tmpname_two .. " line 1: 'file two'", }) end) + + it('is reset to a list by assert functions', function() + source([[ + let save_verrors = v:errors + let v:['errors'] = {'foo': 3} + call assert_equal('yes', 'no') + let verrors = v:errors + let v:errors = save_verrors + call assert_equal(type([]), type(verrors)) + ]]) + expected_empty() + end) + end) + + -- assert_fails({cmd}, [, {error}]) + describe('assert_fails', function() + it('should change v:errors when error does not match v:errmsg', function() + execute([[call assert_fails('xxx', {})]]) + expected_errors({"Expected {} but got 'E731: using Dictionary as a String'"}) + end) + + it('should not change v:errors when cmd errors', function() + call('assert_fails', 'NonexistentCmd') + expected_empty() + end) + + it('should change v:errors when cmd succeeds', function() + call('assert_fails', 'call empty("")') + expected_errors({'command did not fail: call empty("")'}) + end) end) end) diff --git a/test/functional/legacy/autocmd_option_spec.lua b/test/functional/legacy/autocmd_option_spec.lua index 6349371808..28037e17c5 100644 --- a/test/functional/legacy/autocmd_option_spec.lua +++ b/test/functional/legacy/autocmd_option_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim = helpers.meths local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq local curbuf, buf = helpers.curbuf, helpers.bufmeths diff --git a/test/functional/legacy/autoformat_join_spec.lua b/test/functional/legacy/autoformat_join_spec.lua index a99cabca24..4110d66f5b 100644 --- a/test/functional/legacy/autoformat_join_spec.lua +++ b/test/functional/legacy/autoformat_join_spec.lua @@ -1,7 +1,7 @@ -- vim: set foldmethod=marker foldmarker=[[,]] : -- Tests for setting the '[,'] marks when joining lines. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/backspace_opt_spec.lua b/test/functional/legacy/backspace_opt_spec.lua index b40019a410..90bc6f74f0 100644 --- a/test/functional/legacy/backspace_opt_spec.lua +++ b/test/functional/legacy/backspace_opt_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local call, clear = helpers.call, helpers.clear local source, eq, nvim = helpers.source, helpers.eq, helpers.meths diff --git a/test/functional/legacy/breakindent_spec.lua b/test/functional/legacy/breakindent_spec.lua new file mode 100644 index 0000000000..2504fe8e51 --- /dev/null +++ b/test/functional/legacy/breakindent_spec.lua @@ -0,0 +1,211 @@ +-- Test for breakindent + +local helpers = require('test.functional.helpers')(after_each) +local feed, insert = helpers.feed, helpers.insert +local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect + +describe('breakindent', function() + setup(clear) + + it('is working', function() + insert('dummy text') + + execute('set wildchar=^E') + execute('10new') + execute('vsp') + execute('vert resize 20') + execute([[put =\"\tabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP\"]]) + execute('set ts=4 sw=4 sts=4 breakindent') + execute('fu! ScreenChar(line, width)') + execute(' let c=""') + execute(' for i in range(1,a:width)') + execute(' let c.=nr2char(screenchar(a:line, i))') + execute(' endfor') + execute([[ let c.="\n"]]) + execute(' for i in range(1,a:width)') + execute(' let c.=nr2char(screenchar(a:line+1, i))') + execute(' endfor') + execute([[ let c.="\n"]]) + execute(' for i in range(1,a:width)') + execute(' let c.=nr2char(screenchar(a:line+2, i))') + execute(' endfor') + execute(' return c') + execute('endfu') + execute('fu DoRecordScreen()') + execute(' wincmd l') + execute([[ $put =printf(\"\n%s\", g:test)]]) + execute(' $put =g:line1') + execute(' wincmd p') + execute('endfu') + execute('set briopt=min:0') + execute('let g:test="Test 1: Simple breakindent"') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test="Test 2: Simple breakindent + sbr=>>"') + execute('set sbr=>>') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test ="Test 3: Simple breakindent + briopt:sbr"') + execute('set briopt=sbr,min:0 sbr=++') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test ="Test 4: Simple breakindent + min width: 18"') + execute('set sbr= briopt=min:18') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test =" Test 5: Simple breakindent + shift by 2"') + execute('set briopt=shift:2,min:0') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test=" Test 6: Simple breakindent + shift by -1"') + execute('set briopt=shift:-1,min:0') + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + execute('let g:test=" Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr"') + execute('set briopt=shift:1,sbr,min:0 nu sbr=? nuw=4') + execute('let line1=ScreenChar(line("."),10)') + execute('call DoRecordScreen()') + execute('let g:test=" Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr"') + execute('set briopt=shift:1,sbr,min:0 nu sbr=# list lcs&vi') + execute('let line1=ScreenChar(line("."),10)') + execute('call DoRecordScreen()') + execute([[let g:test=" Test 9: breakindent + shift by +1 + 'nu' + sbr=# list"]]) + execute('set briopt-=sbr') + execute('let line1=ScreenChar(line("."),10)') + execute('call DoRecordScreen()') + execute([[let g:test=" Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n"]]) + execute('set cpo+=n sbr=~ nu nuw=4 nolist briopt=sbr,min:0') + execute('let line1=ScreenChar(line("."),10)') + execute('call DoRecordScreen()') + execute('wincmd p') + execute([[let g:test="\n Test 11: strdisplaywidth when breakindent is on"]]) + execute('set cpo-=n sbr=>> nu nuw=4 nolist briopt= ts=4') + -- Skip leading tab when calculating text width. + execute('let text=getline(2)') + -- Text wraps 3 times. + execute('let width = strlen(text[1:])+indent(2)*4+strlen(&sbr)*3') + execute('$put =g:test') + execute([[$put =printf(\"strdisplaywidth: %d == calculated: %d\", strdisplaywidth(text), width)]]) + execute([[let g:str="\t\t\t\t\t{"]]) + execute('let g:test=" Test 12: breakindent + long indent"') + execute('wincmd p') + execute('set all& breakindent linebreak briopt=min:10 nu numberwidth=3 ts=4') + execute('$put =g:str') + feed('zt') + execute('let line1=ScreenChar(1,10)') + execute('wincmd p') + execute('call DoRecordScreen()') + + -- Test, that the string " a\tb\tc\td\te" is correctly displayed in a + -- 20 column wide window (see bug report + -- https://groups.google.com/d/msg/vim_dev/ZOdg2mc9c9Y/TT8EhFjEy0IJ ). + execute('only') + execute('vert 20new') + execute('set all& breakindent briopt=min:10') + execute([[call setline(1, [" a\tb\tc\td\te", " z y x w v"])]]) + execute([[/^\s*a]]) + feed('fbgjyl') + execute('let line1 = @0') + execute([[?^\s*z]]) + feed('fygjyl') + execute('let line2 = @0') + execute('quit!') + execute([[$put ='Test 13: breakindent with wrapping Tab']]) + execute('$put =line1') + execute('$put =line2') + + execute('let g:test="Test 14: breakindent + visual blockwise delete #1"') + execute('set all& breakindent shada+=nX-test-breakindent.shada') + execute('30vnew') + execute('normal! 3a1234567890') + execute('normal! a abcde') + execute([[exec "normal! 0\<C-V>tex"]]) + execute('let line1=ScreenChar(line("."),8)') + execute('call DoRecordScreen()') + + execute('let g:test="Test 15: breakindent + visual blockwise delete #2"') + execute('%d') + execute('normal! 4a1234567890') + execute([[exec "normal! >>\<C-V>3f0x"]]) + execute('let line1=ScreenChar(line("."),20)') + execute('call DoRecordScreen()') + execute('quit!') + + -- Assert buffer contents. + expect([[ + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP + + Test 1: Simple breakindent + abcd + qrst + GHIJ + + Test 2: Simple breakindent + sbr=>> + abcd + >>qr + >>EF + + Test 3: Simple breakindent + briopt:sbr + abcd + ++ qrst + ++ GHIJ + + Test 4: Simple breakindent + min width: 18 + abcd + qrstuv + IJKLMN + + Test 5: Simple breakindent + shift by 2 + abcd + qr + EF + + Test 6: Simple breakindent + shift by -1 + abcd + qrstu + HIJKL + + Test 7: breakindent + shift by +1 + nu + sbr=? briopt:sbr + 2 ab + ? m + ? x + + Test 8: breakindent + shift:1 + nu + sbr=# list briopt:sbr + 2 ^Iabcd + # opq + # BCD + + Test 9: breakindent + shift by +1 + 'nu' + sbr=# list + 2 ^Iabcd + #op + #AB + + Test 10: breakindent + shift by +1 + 'nu' + sbr=~ cpo+=n + 2 ab + ~ mn + ~ yz + + Test 11: strdisplaywidth when breakindent is on + strdisplaywidth: 46 == calculated: 64 + { + + Test 12: breakindent + long indent + 56 + + ~ + Test 13: breakindent with wrapping Tab + d + w + + Test 14: breakindent + visual blockwise delete #1 + e + ~ + ~ + + Test 15: breakindent + visual blockwise delete #2 + 1234567890 + ~ + ~ ]]) + end) +end) diff --git a/test/functional/legacy/cdo_spec.lua b/test/functional/legacy/cdo_spec.lua index 4b313ede3f..5e46431cc1 100644 --- a/test/functional/legacy/cdo_spec.lua +++ b/test/functional/legacy/cdo_spec.lua @@ -1,6 +1,6 @@ -- Tests for the :cdo, :cfdo, :ldo and :lfdo commands -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim, clear = helpers.meths, helpers.clear local call, feed = helpers.call, helpers.feed local source, eq = helpers.source, helpers.eq diff --git a/test/functional/legacy/changelist_spec.lua b/test/functional/legacy/changelist_spec.lua index 7c696369d4..c718da3736 100644 --- a/test/functional/legacy/changelist_spec.lua +++ b/test/functional/legacy/changelist_spec.lua @@ -1,7 +1,7 @@ -- Test changelist position after splitting window -- Set 'undolevels' to make changelist for sourced file -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/charsearch_spec.lua b/test/functional/legacy/charsearch_spec.lua index 4a83801cfc..ef3369728d 100644 --- a/test/functional/legacy/charsearch_spec.lua +++ b/test/functional/legacy/charsearch_spec.lua @@ -1,6 +1,6 @@ -- Test for character searches -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert = helpers.feed, helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/close_count_spec.lua b/test/functional/legacy/close_count_spec.lua new file mode 100644 index 0000000000..ad1812f22e --- /dev/null +++ b/test/functional/legacy/close_count_spec.lua @@ -0,0 +1,133 @@ +-- Tests for :[count]close! and :[count]hide + +local helpers = require('test.functional.helpers')(after_each) +local feed, eval, eq, clear, execute = + helpers.feed, helpers.eval, helpers.eq, helpers.clear, helpers.execute + +describe('close_count', function() + setup(clear) + + it('is working', function() + execute('let tests = []') + execute('for i in range(5)') + execute('new') + execute('endfor') + execute('4wincmd w') + execute('close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({6, 5, 4, 2, 1}, eval('buffers')) + execute('1close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({5, 4, 2, 1}, eval('buffers')) + execute('$close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({5, 4, 2}, eval('buffers')) + execute('1wincmd w') + execute('2close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({5, 2}, eval('buffers')) + execute('1wincmd w') + execute('new') + execute('new') + execute('2wincmd w') + execute('-1close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({7, 5, 2}, eval('buffers')) + execute('2wincmd w') + execute('+1close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({7, 5}, eval('buffers')) + execute('only!') + execute('b1') + execute('let tests = []') + execute('for i in range(5)') + execute('new') + execute('endfor') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({13, 12, 11, 10, 9, 1}, eval('buffers')) + execute('4wincmd w') + execute('.hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({13, 12, 11, 9, 1}, eval('buffers')) + execute('1hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({12, 11, 9, 1}, eval('buffers')) + execute('$hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({12, 11, 9}, eval('buffers')) + execute('1wincmd w') + execute('2hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({12, 9}, eval('buffers')) + execute('1wincmd w') + execute('new') + execute('new') + execute('3wincmd w') + execute('-hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({15, 12, 9}, eval('buffers')) + execute('2wincmd w') + execute('+hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({15, 12}, eval('buffers')) + execute('only!') + execute('b1') + execute('let tests = []') + execute('set hidden') + execute('for i in range(5)') + execute('new') + execute('endfor') + execute('1wincmd w') + execute('$ hide') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({20, 19, 18, 17, 16}, eval('buffers')) + execute('$-1 close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({20, 19, 18, 16}, eval('buffers')) + execute('1wincmd w') + execute('.+close!') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({20, 18, 16}, eval('buffers')) + execute('only!') + execute('b1') + execute('let tests = []') + execute('set hidden') + execute('for i in range(5)') + execute('new') + execute('endfor') + execute('4wincmd w') + feed('<C-W>c<cr>') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({25, 24, 23, 21, 1}, eval('buffers')) + feed('1<C-W>c<cr>') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({24, 23, 21, 1}, eval('buffers')) + feed('9<C-W>c<cr>') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({24, 23, 21}, eval('buffers')) + execute('1wincmd w') + feed('2<C-W>c<cr>') + execute('let buffers = []') + execute('windo call add(buffers, bufnr("%"))') + eq({24, 21}, eval('buffers')) + end) +end) diff --git a/test/functional/legacy/command_count_spec.lua b/test/functional/legacy/command_count_spec.lua index d9b4f09263..c463ada968 100644 --- a/test/functional/legacy/command_count_spec.lua +++ b/test/functional/legacy/command_count_spec.lua @@ -1,25 +1,20 @@ -- Test for user command counts -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, source, expect = helpers.clear, helpers.source, helpers.expect -local execute, spawn = helpers.execute, helpers.spawn -local nvim_prog = helpers.nvim_prog +local execute = helpers.execute describe('command_count', function() - setup(clear) - teardown(function() - os.remove('test.out') - end) - it('is working', function() -- It is relevant for the test to load a file initially. If this is -- emulated with :arg the buffer count is wrong as nvim creates an empty -- buffer if it was started without a filename. - local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed', - 'test_command_count.in'}) - helpers.set_session(nvim2) + clear('test_command_count.in') source([[ + let g:tmpname = tempname() + call mkdir(g:tmpname) + execute "cd ".g:tmpname lang C let g:lines = [] com -range=% RangeLines @@ -239,5 +234,10 @@ describe('command_count', function() bufdo: 2 3 4 5 6 7 8 9 10 15 bufdo: 4 5 6 7 tabdo: 2 3 4]]) + + source([[ + cd .. + call delete(g:tmpname, 'rf') + ]]) end) end) diff --git a/test/functional/legacy/comparators_spec.lua b/test/functional/legacy/comparators_spec.lua index e3fa3eea23..27879b0f65 100644 --- a/test/functional/legacy/comparators_spec.lua +++ b/test/functional/legacy/comparators_spec.lua @@ -1,6 +1,6 @@ -- " Test for expression comparators. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, eq = helpers.clear, helpers.eq local eval, execute = helpers.eval, helpers.execute diff --git a/test/functional/legacy/delete_spec.lua b/test/functional/legacy/delete_spec.lua index cd18a8f750..42238b3a9e 100644 --- a/test/functional/legacy/delete_spec.lua +++ b/test/functional/legacy/delete_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, source = helpers.clear, helpers.source local eq, eval, execute = helpers.eq, helpers.eval, helpers.execute diff --git a/test/functional/legacy/erasebackword_spec.lua b/test/functional/legacy/erasebackword_spec.lua index cb3967b763..33b7704b65 100644 --- a/test/functional/legacy/erasebackword_spec.lua +++ b/test/functional/legacy/erasebackword_spec.lua @@ -1,6 +1,6 @@ -- Test for CTRL-W in Insert mode -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, expect = helpers.clear, helpers.feed, helpers.expect describe('CTRL-W in Insert mode', function() diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua index 3ff1092a4b..3684fe714d 100644 --- a/test/functional/legacy/eval_spec.lua +++ b/test/functional/legacy/eval_spec.lua @@ -1,15 +1,10 @@ -- Test for various eval features. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect local eq, eval, write_file = helpers.eq, helpers.eval, helpers.write_file -local function has_clipboard() - clear() - return 1 == eval("has('clipboard')") -end - describe('eval', function() setup(function() write_file('test_eval_setup.vim', [[ @@ -539,8 +534,13 @@ describe('eval', function() =: type v; value: abc/]].."\000 (['abc/\000"..[[']), expr: "abc/]]..'\000'..[[" (['"abc/]]..'\000'..[["'])]]) end) - if has_clipboard() then - it('system clipboard', function() + describe('system clipboard', function() + before_each(function() + execute('let &runtimepath = "test/functional/fixtures,".&runtimepath') + execute('call getreg("*")') -- force load of provider + end) + + it('works', function() insert([[ Some first line (this text was at the top of the old test_eval.in). @@ -570,9 +570,7 @@ describe('eval', function() *: type V; value: clipboard contents]]..'\00'..[[ (['clipboard contents']), expr: clipboard contents]]..'\00'..[[ (['clipboard contents']) *: type V; value: something else]]..'\00'..[[ (['something else']), expr: something else]]..'\00'..[[ (['something else'])]]) end) - else - pending('system clipboard not available', function() end) - end + end) it('errors', function() source([[ diff --git a/test/functional/legacy/expand_spec.lua b/test/functional/legacy/expand_spec.lua new file mode 100644 index 0000000000..5a2d46706a --- /dev/null +++ b/test/functional/legacy/expand_spec.lua @@ -0,0 +1,72 @@ +-- Test for expanding file names + +local helpers = require('test.functional.helpers')(after_each) +local eq = helpers.eq +local call = helpers.call +local nvim = helpers.meths +local clear = helpers.clear +local source = helpers.source + +local function expected_empty() + eq({}, nvim.get_vvar('errors')) +end + +describe('expand file name', function() + after_each(function() + helpers.rmdir('Xdir1') + helpers.rmdir('Xdir2') + helpers.rmdir('Xdir3') + helpers.rmdir('Xdir4') + end) + + before_each(function() + clear() + + source([[ + func Test_with_directories() + call mkdir('Xdir1') + call mkdir('Xdir2') + call mkdir('Xdir3') + cd Xdir3 + call mkdir('Xdir4') + cd .. + + split Xdir1/file + call setline(1, ['a', 'b']) + w + w Xdir3/Xdir4/file + close + + next Xdir?/*/file + call assert_equal('Xdir3/Xdir4/file', expand('%')) + next! Xdir?/*/nofile + call assert_equal('Xdir?/*/nofile', expand('%')) + + call delete('Xdir1', 'rf') + call delete('Xdir2', 'rf') + call delete('Xdir3', 'rf') + endfunc + + func Test_with_tilde() + let dir = getcwd() + call mkdir('Xdir ~ dir') + call assert_true(isdirectory('Xdir ~ dir')) + cd Xdir\ ~\ dir + call assert_true(getcwd() =~ 'Xdir \~ dir') + exe 'cd ' . fnameescape(dir) + call delete('Xdir ~ dir', 'd') + call assert_false(isdirectory('Xdir ~ dir')) + endfunc + ]]) + end) + + it('works with directories', function() + call('Test_with_directories') + expected_empty() + end) + + it('works with tilde', function() + call('Test_with_tilde') + expected_empty() + end) +end) diff --git a/test/functional/legacy/file_perm_spec.lua b/test/functional/legacy/file_perm_spec.lua new file mode 100644 index 0000000000..98bdf630dd --- /dev/null +++ b/test/functional/legacy/file_perm_spec.lua @@ -0,0 +1,42 @@ +-- Test getting and setting file permissions. +require('os') + +local helpers = require('test.functional.helpers')(after_each) +local clear, call, eq = helpers.clear, helpers.call, helpers.eq +local neq, exc_exec = helpers.neq, helpers.exc_exec + +describe('Test getting and setting file permissions', function() + local tempfile = os.tmpname() + + before_each(function() + os.remove(tempfile) + clear() + end) + + it('file permissions', function() + eq('', call('getfperm', tempfile)) + eq(0, call('setfperm', tempfile, 'r------')) + + call('writefile', {'one'}, tempfile) + eq(9, call('len', call('getfperm', tempfile))) + + eq(1, call('setfperm', tempfile, 'rwx------')) + if helpers.os_name == 'windows' then + eq('rw-rw-rw-', call('getfperm', tempfile)) + else + eq('rwx------', call('getfperm', tempfile)) + end + + eq(1, call('setfperm', tempfile, 'r--r--r--')) + eq('r--r--r--', call('getfperm', tempfile)) + + local err = exc_exec(('call setfperm("%s", "---")'):format(tempfile)) + neq(err:find('E475:'), nil) + + eq(1, call('setfperm', tempfile, 'rwx------')) + end) + + after_each(function() + os.remove(tempfile) + end) +end) diff --git a/test/functional/legacy/fixeol_spec.lua b/test/functional/legacy/fixeol_spec.lua index 2d1824c8cd..bba1415535 100644 --- a/test/functional/legacy/fixeol_spec.lua +++ b/test/functional/legacy/fixeol_spec.lua @@ -1,6 +1,6 @@ -- Tests for 'fixeol' -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed = helpers.feed local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/fnamemodify_spec.lua b/test/functional/legacy/fnamemodify_spec.lua index 2a32aea127..f614b07b36 100644 --- a/test/functional/legacy/fnamemodify_spec.lua +++ b/test/functional/legacy/fnamemodify_spec.lua @@ -1,6 +1,6 @@ -- Test filename modifiers. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, source = helpers.clear, helpers.source local call, eq, nvim = helpers.call, helpers.eq, helpers.meths diff --git a/test/functional/legacy/function_sort_spec.lua b/test/functional/legacy/function_sort_spec.lua index 9083911021..1b65f1ce95 100644 --- a/test/functional/legacy/function_sort_spec.lua +++ b/test/functional/legacy/function_sort_spec.lua @@ -1,7 +1,10 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq local eval = helpers.eval +local execute = helpers.execute +local exc_exec = helpers.exc_exec +local neq = helpers.neq describe('sort', function() before_each(clear) @@ -26,4 +29,25 @@ describe('sort', function() it('numbers compared as float', function() eq({0.28, 3, 13.5}, eval("sort([13.5, 0.28, 3], 'f')")) end) + + it('ability to call sort() from a compare function', function() + execute('func Compare1(a, b) abort') + execute([[call sort(range(3), 'Compare2')]]) + execute('return a:a - a:b') + execute('endfunc') + + execute('func Compare2(a, b) abort') + execute('return a:a - a:b') + execute('endfunc') + eq({1, 3, 5}, eval("sort([3, 1, 5], 'Compare1')")) + end) + + it('default sort', function() + -- docs say omitted, empty or zero argument sorts on string representation + eq({'2', 'A', 'AA', 'a', 1, 3.3}, eval('sort([3.3, 1, "2", "A", "a", "AA"])')) + eq({'2', 'A', 'AA', 'a', 1, 3.3}, eval([[sort([3.3, 1, "2", "A", "a", "AA"], '')]])) + eq({'2', 'A', 'AA', 'a', 1, 3.3}, eval('sort([3.3, 1, "2", "A", "a", "AA"], 0)')) + eq({'2', 'A', 'a', 'AA', 1, 3.3}, eval('sort([3.3, 1, "2", "A", "a", "AA"], 1)')) + neq(exc_exec('call sort([3.3, 1, "2"], 3)'):find('E474:'), nil) + end) end) diff --git a/test/functional/legacy/getcwd_spec.lua b/test/functional/legacy/getcwd_spec.lua new file mode 100644 index 0000000000..3bb9930b74 --- /dev/null +++ b/test/functional/legacy/getcwd_spec.lua @@ -0,0 +1,86 @@ +-- Tests for getcwd(), haslocaldir(), and :lcd + +local helpers = require('test.functional.helpers')(after_each) +local eq, eval, source = helpers.eq, helpers.eval, helpers.source +local call, clear, execute = helpers.call, helpers.clear, helpers.execute + +describe('getcwd', function() + before_each(clear) + + after_each(function() + helpers.rmdir('Xtopdir') + end) + + it('is working', function() + source([[ + function! GetCwdInfo(win, tab) + let tab_changed = 0 + let mod = ":t" + if a:tab > 0 && a:tab != tabpagenr() + let tab_changed = 1 + exec "tabnext " . a:tab + endif + let bufname = fnamemodify(bufname(winbufnr(a:win)), mod) + if tab_changed + tabprevious + endif + if a:win == 0 && a:tab == 0 + let dirname = fnamemodify(getcwd(), mod) + let lflag = haslocaldir() + elseif a:tab == 0 + let dirname = fnamemodify(getcwd(a:win), mod) + let lflag = haslocaldir(a:win) + else + let dirname = fnamemodify(getcwd(a:win, a:tab), mod) + let lflag = haslocaldir(a:win, a:tab) + endif + return bufname . ' ' . dirname . ' ' . lflag + endfunction + ]]) + execute('new') + execute('let cwd=getcwd()') + call('mkdir', 'Xtopdir') + execute('silent cd Xtopdir') + call('mkdir', 'Xdir1') + call('mkdir', 'Xdir2') + call('mkdir', 'Xdir3') + execute('new a') + execute('new b') + execute('new c') + execute('3wincmd w') + execute('silent lcd Xdir1') + eq('a Xdir1 1', eval('GetCwdInfo(0, 0)')) + execute('wincmd W') + eq('b Xtopdir 0', eval('GetCwdInfo(0, 0)')) + execute('wincmd W') + execute('silent lcd Xdir3') + eq('c Xdir3 1', eval('GetCwdInfo(0, 0)')) + eq('a Xdir1 1', eval('GetCwdInfo(bufwinnr("a"), 0)')) + eq('b Xtopdir 0', eval('GetCwdInfo(bufwinnr("b"), 0)')) + eq('c Xdir3 1', eval('GetCwdInfo(bufwinnr("c"), 0)')) + execute('wincmd W') + eq('a Xdir1 1', eval('GetCwdInfo(bufwinnr("a"), tabpagenr())')) + eq('b Xtopdir 0', eval('GetCwdInfo(bufwinnr("b"), tabpagenr())')) + eq('c Xdir3 1', eval('GetCwdInfo(bufwinnr("c"), tabpagenr())')) + + execute('tabnew x') + execute('new y') + execute('new z') + execute('3wincmd w') + eq('x Xtopdir 0', eval('GetCwdInfo(0, 0)')) + execute('wincmd W') + execute('silent lcd Xdir2') + eq('y Xdir2 1', eval('GetCwdInfo(0, 0)')) + execute('wincmd W') + execute('silent lcd Xdir3') + eq('z Xdir3 1', eval('GetCwdInfo(0, 0)')) + eq('x Xtopdir 0', eval('GetCwdInfo(bufwinnr("x"), 0)')) + eq('y Xdir2 1', eval('GetCwdInfo(bufwinnr("y"), 0)')) + eq('z Xdir3 1', eval('GetCwdInfo(bufwinnr("z"), 0)')) + execute('let tp_nr = tabpagenr()') + execute('tabrewind') + eq('x Xtopdir 0', eval('GetCwdInfo(3, tp_nr)')) + eq('y Xdir2 1', eval('GetCwdInfo(2, tp_nr)')) + eq('z Xdir3 1', eval('GetCwdInfo(1, tp_nr)')) + end) +end) diff --git a/test/functional/legacy/glob2regpat_spec.lua b/test/functional/legacy/glob2regpat_spec.lua index 0492143616..82e7e3010f 100644 --- a/test/functional/legacy/glob2regpat_spec.lua +++ b/test/functional/legacy/glob2regpat_spec.lua @@ -1,6 +1,6 @@ -- Tests for signs -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute = helpers.clear, helpers.execute local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval diff --git a/test/functional/legacy/increment_spec.lua b/test/functional/legacy/increment_spec.lua index 4aa24c0d53..0483edc934 100644 --- a/test/functional/legacy/increment_spec.lua +++ b/test/functional/legacy/increment_spec.lua @@ -1,6 +1,6 @@ -- Tests for using Ctrl-A/Ctrl-X on visual selections -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local source, execute = helpers.source, helpers.execute local call, clear = helpers.call, helpers.clear local eq, nvim = helpers.eq, helpers.meths diff --git a/test/functional/legacy/insertcount_spec.lua b/test/functional/legacy/insertcount_spec.lua index 01236e1afe..3142f040b3 100644 --- a/test/functional/legacy/insertcount_spec.lua +++ b/test/functional/legacy/insertcount_spec.lua @@ -1,6 +1,6 @@ -- Tests for repeating insert and replace. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect diff --git a/test/functional/legacy/join_spec.lua b/test/functional/legacy/join_spec.lua new file mode 100644 index 0000000000..3c4da8119c --- /dev/null +++ b/test/functional/legacy/join_spec.lua @@ -0,0 +1,20 @@ +-- Test for joining lines + +local helpers = require('test.functional.helpers')(after_each) +local clear, eq = helpers.clear, helpers.eq +local eval, execute = helpers.eval, helpers.execute + +describe('joining lines', function() + before_each(clear) + + it('is working', function() + execute('new') + execute([[call setline(1, ['one', 'two', 'three', 'four'])]]) + execute('normal J') + eq('one two', eval('getline(1)')) + execute('%del') + execute([[call setline(1, ['one', 'two', 'three', 'four'])]]) + execute('normal 10J') + eq('one two three four', eval('getline(1)')) + end) +end) diff --git a/test/functional/legacy/lispwords_spec.lua b/test/functional/legacy/lispwords_spec.lua index 48df4de55e..2ec51dca1b 100644 --- a/test/functional/legacy/lispwords_spec.lua +++ b/test/functional/legacy/lispwords_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq local eval = helpers.eval diff --git a/test/functional/legacy/listchars_spec.lua b/test/functional/legacy/listchars_spec.lua index 89ed90178b..d2838cddb6 100644 --- a/test/functional/legacy/listchars_spec.lua +++ b/test/functional/legacy/listchars_spec.lua @@ -1,6 +1,6 @@ -- Tests for 'listchars' display with 'list' and :list. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/listlbr_spec.lua b/test/functional/legacy/listlbr_spec.lua new file mode 100644 index 0000000000..eb979edc69 --- /dev/null +++ b/test/functional/legacy/listlbr_spec.lua @@ -0,0 +1,195 @@ +-- Test for linebreak and list option (non-utf8) + +local helpers = require('test.functional.helpers')(after_each) +local feed, insert, source = helpers.feed, helpers.insert, helpers.source +local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect + +describe('listlbr', function() + setup(clear) + + it('is working', function() + insert([[ + dummy text]]) + + execute('set wildchar=^E') + execute('10new') + execute('vsp') + execute('vert resize 20') + execute([[put =\"\tabcdef hijklmn\tpqrstuvwxyz_1060ABCDEFGHIJKLMNOP \"]]) + execute('norm! zt') + execute('set ts=4 sw=4 sts=4 linebreak sbr=+ wrap') + source([[ + fu! ScreenChar(width) + let c='' + for j in range(1,4) + for i in range(1,a:width) + let c.=nr2char(screenchar(j, i)) + endfor + let c.="\n" + endfor + return c + endfu + fu! DoRecordScreen() + wincmd l + $put =printf(\"\n%s\", g:test) + $put =g:line + wincmd p + endfu + ]]) + execute('let g:test="Test 1: set linebreak"') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + + execute('let g:test="Test 2: set linebreak + set list"') + execute('set linebreak list listchars=') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + + execute('let g:test ="Test 3: set linebreak nolist"') + execute('set nolist linebreak') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + + execute('let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!"') + execute('set nolist linebreak ts=8') + execute([[let line="1\t".repeat('a', winwidth(0)-2)]]) + execute('$put =line') + execute('$') + execute('norm! zt') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + execute([[let line="_S_\t bla"]]) + execute('$put =line') + execute('$') + execute('norm! zt') + + execute('let g:test ="Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)"') + execute('set cpo&vim list linebreak conceallevel=2 concealcursor=nv listchars=tab:ab') + execute('syn match ConcealVar contained /_/ conceal') + execute('syn match All /.*/ contains=ConcealVar') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + execute('set cpo&vim linebreak') + + execute('let g:test ="Test 6: set linebreak with visual block mode"') + execute('let line="REMOVE: this not"') + execute('$put =g:test') + execute('$put =line') + execute('let line="REMOVE: aaaaaaaaaaaaa"') + execute('$put =line') + execute('1/^REMOVE:') + feed('0<C-V>jf x') + execute('$put') + execute('set cpo&vim linebreak') + + execute('let g:test ="Test 7: set linebreak with visual block mode and v_b_A"') + execute('$put =g:test') + feed('Golong line: <esc>40afoobar <esc>aTARGET at end<esc>') + execute([[exe "norm! $3B\<C-v>eAx\<Esc>"]]) + execute('set cpo&vim linebreak sbr=') + + execute('let g:test ="Test 8: set linebreak with visual char mode and changing block"') + execute('$put =g:test') + feed('Go1111-1111-1111-11-1111-1111-1111<esc>0f-lv3lc2222<esc>bgj.') + + execute('let g:test ="Test 9: using redo after block visual mode"') + execute('$put =g:test') + feed('Go<CR>') + feed('aaa<CR>') + feed('aaa<CR>') + feed('a<ESC>2k<C-V>2j~e.<CR>') + + execute('let g:test ="Test 10: using normal commands after block-visual"') + execute('$put =g:test') + execute('set linebreak') + feed('Go<cr>') + feed('abcd{ef<cr>') + feed('ghijklm<cr>') + feed('no}pqrs<esc>2k0f{<C-V><C-V>c%<esc>') + + execute('let g:test ="Test 11: using block replace mode after wrapping"') + execute('$put =g:test') + execute('set linebreak wrap') + feed('Go<esc>150aa<esc>yypk147|<C-V>jr0<cr>') + + execute('let g:test ="Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$"') + execute('set list listchars=space:_,trail:-,tab:>-,eol:$') + execute('$put =g:test') + execute([[let line="a aaaaaaaaaaaaaaaaaaaaaa\ta "]]) + execute('$put =line') + execute('$') + execute('norm! zt') + execute('redraw!') + execute('let line=ScreenChar(winwidth(0))') + execute('call DoRecordScreen()') + + -- Assert buffer contents. + expect([[ + + abcdef hijklmn pqrstuvwxyz_1060ABCDEFGHIJKLMNOP + + Test 1: set linebreak + abcdef + +hijklmn + +pqrstuvwxyz_1060ABC + +DEFGHIJKLMNOP + + Test 2: set linebreak + set list + ^Iabcdef hijklmn^I + +pqrstuvwxyz_1060ABC + +DEFGHIJKLMNOP + + + Test 3: set linebreak nolist + abcdef + +hijklmn + +pqrstuvwxyz_1060ABC + +DEFGHIJKLMNOP + 1 aaaaaaaaaaaaaaaaaa + + Test 4: set linebreak with tab and 1 line as long as screen: should break! + 1 + +aaaaaaaaaaaaaaaaaa + ~ + ~ + _S_ bla + + Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated) + Sabbbbbb bla + ~ + ~ + ~ + Test 6: set linebreak with visual block mode + this not + aaaaaaaaaaaaa + REMOVE: + REMOVE: + Test 7: set linebreak with visual block mode and v_b_A + long line: foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar foobar TARGETx at end + Test 8: set linebreak with visual char mode and changing block + 1111-2222-1111-11-1111-2222-1111 + Test 9: using redo after block visual mode + + AaA + AaA + A + Test 10: using normal commands after block-visual + + abcdpqrs + Test 11: using block replace mode after wrapping + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0aaa + Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$ + a aaaaaaaaaaaaaaaaaaaaaa a + + Test 12: set linebreak list listchars=space:_,tab:>-,tail:-,eol:$ + a_ + aaaaaaaaaaaaaaaaaaaa + aa>-----a-$ + ~ ]]) + end) +end) diff --git a/test/functional/legacy/listlbr_utf8_spec.lua b/test/functional/legacy/listlbr_utf8_spec.lua index df0e817533..f06bca72ba 100644 --- a/test/functional/legacy/listlbr_utf8_spec.lua +++ b/test/functional/legacy/listlbr_utf8_spec.lua @@ -1,6 +1,6 @@ -- Test for linebreak and list option in utf-8 mode -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local source = helpers.source local feed = helpers.feed local clear, expect = helpers.clear, helpers.expect diff --git a/test/functional/legacy/mapping_spec.lua b/test/functional/legacy/mapping_spec.lua index a0d19926cb..1712219d04 100644 --- a/test/functional/legacy/mapping_spec.lua +++ b/test/functional/legacy/mapping_spec.lua @@ -1,6 +1,6 @@ -- Test for mappings and abbreviations -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect, wait = helpers.execute, helpers.expect, helpers.wait diff --git a/test/functional/legacy/marks_spec.lua b/test/functional/legacy/marks_spec.lua index 8e9ceb1653..6ecba70f08 100644 --- a/test/functional/legacy/marks_spec.lua +++ b/test/functional/legacy/marks_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/match_conceal_spec.lua b/test/functional/legacy/match_conceal_spec.lua index 0ffa3cae7a..d95b07d695 100644 --- a/test/functional/legacy/match_conceal_spec.lua +++ b/test/functional/legacy/match_conceal_spec.lua @@ -1,6 +1,6 @@ -- Test for matchadd() and conceal feature -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local expect = helpers.expect local source = helpers.source diff --git a/test/functional/legacy/nested_function_spec.lua b/test/functional/legacy/nested_function_spec.lua index fac3b03191..be9b66ee38 100644 --- a/test/functional/legacy/nested_function_spec.lua +++ b/test/functional/legacy/nested_function_spec.lua @@ -1,6 +1,6 @@ -- Tests for nested function. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, insert = helpers.clear, helpers.insert local execute, expect, source = helpers.execute, helpers.expect, helpers.source diff --git a/test/functional/legacy/options_spec.lua b/test/functional/legacy/options_spec.lua index 21e99c4aa1..4f4d4ceaf9 100644 --- a/test/functional/legacy/options_spec.lua +++ b/test/functional/legacy/options_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local command, clear = helpers.command, helpers.clear local source, expect = helpers.source, helpers.expect diff --git a/test/functional/legacy/qf_title_spec.lua b/test/functional/legacy/qf_title_spec.lua index 01c781cc05..9f97eb27b2 100644 --- a/test/functional/legacy/qf_title_spec.lua +++ b/test/functional/legacy/qf_title_spec.lua @@ -1,6 +1,6 @@ -- Tests for quickfix window's title -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert, source = helpers.insert, helpers.source local clear, expect = helpers.clear, helpers.expect diff --git a/test/functional/legacy/quickfix_spec.lua b/test/functional/legacy/quickfix_spec.lua index 88f86815b3..df8f2625db 100644 --- a/test/functional/legacy/quickfix_spec.lua +++ b/test/functional/legacy/quickfix_spec.lua @@ -1,12 +1,286 @@ -- Test for the quickfix commands. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local source, clear = helpers.source, helpers.clear +local eq, nvim, call = helpers.eq, helpers.meths, helpers.call +local eval = helpers.eval +local execute = helpers.execute + +local function expected_empty() + eq({}, nvim.get_vvar('errors')) +end describe('helpgrep', function() - before_each(clear) + before_each(function() + clear() - it('works', function() + source([[ + " Tests for the :clist and :llist commands + function XlistTests(cchar) + let Xlist = a:cchar . 'list' + let Xgetexpr = a:cchar . 'getexpr' + + " With an empty list, command should return error + exe Xgetexpr . ' []' + exe 'silent! ' . Xlist + call assert_true(v:errmsg ==# 'E42: No Errors') + + " Populate the list and then try + exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1', + \ 'non-error 2', 'Xtestfile2:2:2:Line2', + \ 'non-error 3', 'Xtestfile3:3:1:Line3']" + + " List only valid entries + redir => result + exe 'silent ' . Xlist + redir END + let l = split(result, "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1', + \ ' 4 Xtestfile2:2 col 2: Line2', + \ ' 6 Xtestfile3:3 col 1: Line3'], l) + + " List all the entries + redir => result + exe 'silent ' . Xlist . "!" + redir END + let l = split(result, "\n") + call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1', + \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2', + \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l) + + " List a range of errors + redir => result + exe 'silent '. Xlist . " 3,6" + redir END + let l = split(result, "\n") + call assert_equal([' 4 Xtestfile2:2 col 2: Line2', + \ ' 6 Xtestfile3:3 col 1: Line3'], l) + + redir => result + exe 'silent ' . Xlist . "! 3,4" + redir END + let l = split(result, "\n") + call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) + + redir => result + exe 'silent ' . Xlist . " -6,-4" + redir END + let l = split(result, "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l) + + redir => result + exe 'silent ' . Xlist . "! -5,-3" + redir END + let l = split(result, "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1', + \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) + endfunction + + " Tests for the :colder, :cnewer, :lolder and :lnewer commands + " Note that this test assumes that a quickfix/location list is + " already set by the caller + function XageTests(cchar) + let Xolder = a:cchar . 'older' + let Xnewer = a:cchar . 'newer' + let Xgetexpr = a:cchar . 'getexpr' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + + " Jumping to a non existent list should return error + exe 'silent! ' . Xolder . ' 99' + call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack') + + exe 'silent! ' . Xnewer . ' 99' + call assert_true(v:errmsg ==# 'E381: At top of quickfix stack') + + " Add three quickfix/location lists + exe Xgetexpr . " ['Xtestfile1:1:3:Line1']" + exe Xgetexpr . " ['Xtestfile2:2:2:Line2']" + exe Xgetexpr . " ['Xtestfile3:3:1:Line3']" + + " Go back two lists + exe Xolder + exe 'let l = ' . Xgetlist + call assert_equal('Line2', l[0].text) + + " Go forward two lists + exe Xnewer + exe 'let l = ' . Xgetlist + call assert_equal('Line3', l[0].text) + + " Test for the optional count argument + exe Xolder . ' 2' + exe 'let l = ' . Xgetlist + call assert_equal('Line1', l[0].text) + + exe Xnewer . ' 2' + exe 'let l = ' . Xgetlist + call assert_equal('Line3', l[0].text) + endfunction + + " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen + " commands + function XwindowTests(cchar) + let Xwindow = a:cchar . 'window' + let Xclose = a:cchar . 'close' + let Xopen = a:cchar . 'open' + let Xgetexpr = a:cchar . 'getexpr' + + " Create a list with no valid entries + exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']" + + " Quickfix/Location window should not open with no valid errors + exe Xwindow + call assert_true(winnr('$') == 1) + + " Create a list with valid entries + exe Xgetexpr . " ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2', + \ 'Xtestfile3:3:1:Line3']" + + " Open the window + exe Xwindow + call assert_true(winnr('$') == 2 && winnr() == 2 && + \ getline('.') ==# 'Xtestfile1|1 col 3| Line1') + + " Close the window + exe Xclose + call assert_true(winnr('$') == 1) + + " Create a list with no valid entries + exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']" + + " Open the window + exe Xopen . ' 5' + call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1' + \ && winheight('.') == 5) + + " Opening the window again, should move the cursor to that window + wincmd t + exe Xopen . ' 7' + call assert_true(winnr('$') == 2 && winnr() == 2 && + \ winheight('.') == 7 && + \ getline('.') ==# '|| non-error 1') + + + " Calling cwindow should close the quickfix window with no valid errors + exe Xwindow + call assert_true(winnr('$') == 1) + endfunction + + " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile + " commands. + function XfileTests(cchar) + let Xfile = a:cchar . 'file' + let Xgetfile = a:cchar . 'getfile' + let Xaddfile = a:cchar . 'addfile' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + + call writefile(['Xtestfile1:700:10:Line 700', + \ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1') + + enew! + exe Xfile . ' Xqftestfile1' + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && + \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') + + " Run cfile/lfile from a modified buffer + enew! + silent! put ='Quickfix' + exe 'silent! ' . Xfile . ' Xqftestfile1' + call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)') + + call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1') + exe Xaddfile . ' Xqftestfile1' + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 3 && + \ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900') + + call writefile(['Xtestfile1:222:77:Line 222', + \ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1') + + enew! + exe Xgetfile . ' Xqftestfile1' + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' && + \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333') + + call delete('Xqftestfile1') + endfunction + + " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and + " :lgetbuffer commands. + function XbufferTests(cchar) + let Xbuffer = a:cchar . 'buffer' + let Xgetbuffer = a:cchar . 'getbuffer' + let Xaddbuffer = a:cchar . 'addbuffer' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + + enew! + silent! call setline(1, ['Xtestfile7:700:10:Line 700', + \ 'Xtestfile8:800:15:Line 800']) + exe Xbuffer . "!" + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && + \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') + + enew! + silent! call setline(1, ['Xtestfile9:900:55:Line 900', + \ 'Xtestfile10:950:66:Line 950']) + exe Xgetbuffer + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' && + \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950') + + enew! + silent! call setline(1, ['Xtestfile11:700:20:Line 700', + \ 'Xtestfile12:750:25:Line 750']) + exe Xaddbuffer + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 4 && + \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' && + \ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' && + \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750') + + endfunction + + function Test_locationlist_curwin_was_closed() + augroup testgroup + au! + autocmd BufReadCmd t call R(expand("<amatch>")) + augroup END + + function R(n) + quit + endfunc + + new + let q = [] + call add(q, {'filename': 't' }) + call setloclist(0, q) + call assert_fails('lrewind', 'E924:') + + augroup! testgroup + endfunction + ]]) + end) + + it('copen/cclose work', function() source([[ helpgrep quickfix copen @@ -14,4 +288,55 @@ describe('helpgrep', function() cclose ]]) end) + + it('clist/llist work', function() + call('XlistTests', 'c') + expected_empty() + call('XlistTests', 'l') + expected_empty() + end) + + it('colder/cnewer and lolder/lnewer work', function() + local list = {{bufnr = 1, lnum = 1}} + call('setqflist', list) + call('XageTests', 'c') + expected_empty() + + call('setloclist', 0, list) + call('XageTests', 'l') + expected_empty() + end) + + it('quickfix/location list window commands work', function() + call('XwindowTests', 'c') + expected_empty() + call('XwindowTests', 'l') + expected_empty() + end) + + it('quickfix/location list file commands work', function() + call('XfileTests', 'c') + expected_empty() + call('XfileTests', 'l') + expected_empty() + end) + + it('quickfix/location list buffer commands work', function() + call('XbufferTests', 'c') + expected_empty() + call('XbufferTests', 'l') + expected_empty() + end) + + it('autocommands triggered by quickfix can get title', function() + execute('au FileType qf let g:foo = get(w:, "quickfix_title", "NONE")') + execute('call setqflist([])') + execute('copen') + eq(':setqflist()', eval('g:foo')) + end) + + it('errors when an autocommand closes the location list\'s window', function() + call('Test_locationlist_curwin_was_closed') + expected_empty() + end) end) diff --git a/test/functional/legacy/search_mbyte_spec.lua b/test/functional/legacy/search_mbyte_spec.lua index 075b24b897..a5a5822a45 100644 --- a/test/functional/legacy/search_mbyte_spec.lua +++ b/test/functional/legacy/search_mbyte_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local insert = helpers.insert local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect diff --git a/test/functional/legacy/searchpos_spec.lua b/test/functional/legacy/searchpos_spec.lua index 1c9b1ccee6..7d4b7a3734 100644 --- a/test/functional/legacy/searchpos_spec.lua +++ b/test/functional/legacy/searchpos_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local call = helpers.call local clear = helpers.clear local execute = helpers.execute diff --git a/test/functional/legacy/set_spec.lua b/test/functional/legacy/set_spec.lua index f81fcd3700..11f371569d 100644 --- a/test/functional/legacy/set_spec.lua +++ b/test/functional/legacy/set_spec.lua @@ -1,12 +1,27 @@ -- Tests for :set -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, eval, eq = helpers.clear, helpers.execute, helpers.eval, helpers.eq describe(':set', function() before_each(clear) + it('handles backslash properly', function() + execute('set iskeyword=a,b,c') + execute('set iskeyword+=d') + eq('a,b,c,d', eval('&iskeyword')) + + execute([[set iskeyword+=\\,e]]) + eq([[a,b,c,d,\,e]], eval('&iskeyword')) + + execute('set iskeyword-=e') + eq([[a,b,c,d,\]], eval('&iskeyword')) + + execute([[set iskeyword-=\]]) + eq('a,b,c,d', eval('&iskeyword')) + end) + it('recognizes a trailing comma with +=', function() execute('set wildignore=*.png,') execute('set wildignore+=*.jpg') diff --git a/test/functional/legacy/signs_spec.lua b/test/functional/legacy/signs_spec.lua index 5a834c39e3..e80a32455a 100644 --- a/test/functional/legacy/signs_spec.lua +++ b/test/functional/legacy/signs_spec.lua @@ -1,6 +1,6 @@ -- Tests for signs -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect describe('signs', function() diff --git a/test/functional/legacy/tagcase_spec.lua b/test/functional/legacy/tagcase_spec.lua index 9a8c6fbe42..ed2876a375 100644 --- a/test/functional/legacy/tagcase_spec.lua +++ b/test/functional/legacy/tagcase_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq local eval = helpers.eval diff --git a/test/functional/legacy/textobjects_spec.lua b/test/functional/legacy/textobjects_spec.lua index 1e8e0b0bcb..15a93e3819 100644 --- a/test/functional/legacy/textobjects_spec.lua +++ b/test/functional/legacy/textobjects_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local call = helpers.call local clear = helpers.clear local execute = helpers.execute diff --git a/test/functional/legacy/undolevels_spec.lua b/test/functional/legacy/undolevels_spec.lua index 41274b3a04..9902b101f6 100644 --- a/test/functional/legacy/undolevels_spec.lua +++ b/test/functional/legacy/undolevels_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local source, clear = helpers.source, helpers.clear local eq, nvim = helpers.eq, helpers.meths diff --git a/test/functional/legacy/utf8_spec.lua b/test/functional/legacy/utf8_spec.lua index d33ba6b5fd..4d4f55b9eb 100644 --- a/test/functional/legacy/utf8_spec.lua +++ b/test/functional/legacy/utf8_spec.lua @@ -1,6 +1,6 @@ -- Tests for Unicode manipulations -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, expect = helpers.execute, helpers.expect local eq, eval = helpers.eq, helpers.eval diff --git a/test/functional/legacy/wordcount_spec.lua b/test/functional/legacy/wordcount_spec.lua index ba7be8f21b..300a777772 100644 --- a/test/functional/legacy/wordcount_spec.lua +++ b/test/functional/legacy/wordcount_spec.lua @@ -1,6 +1,6 @@ -- Test for wordcount() function -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, insert, source = helpers.feed, helpers.insert, helpers.source local clear, execute = helpers.clear, helpers.execute local eq, eval = helpers.eq, helpers.eval diff --git a/test/functional/legacy/writefile_spec.lua b/test/functional/legacy/writefile_spec.lua index efdfc1d09f..f096aa23b9 100644 --- a/test/functional/legacy/writefile_spec.lua +++ b/test/functional/legacy/writefile_spec.lua @@ -1,6 +1,6 @@ -- Tests for writefile() -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, expect = helpers.clear, helpers.execute, helpers.expect describe('writefile', function() diff --git a/test/functional/normal/K_spec.lua b/test/functional/normal/K_spec.lua index df6b429f50..af0f82ef9a 100644 --- a/test/functional/normal/K_spec.lua +++ b/test/functional/normal/K_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eq, clear, eval, feed = helpers.eq, helpers.clear, helpers.eval, helpers.feed diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index d4c3267997..ed978cd17e 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq local execute = helpers.execute diff --git a/test/functional/options/shortmess_spec.lua b/test/functional/options/shortmess_spec.lua index 4455ef663f..d531e47e28 100644 --- a/test/functional/options/shortmess_spec.lua +++ b/test/functional/options/shortmess_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, execute = helpers.clear, helpers.execute diff --git a/test/functional/plugin/helpers.lua b/test/functional/plugin/helpers.lua index 5b6ea88c34..7580670149 100644 --- a/test/functional/plugin/helpers.lua +++ b/test/functional/plugin/helpers.lua @@ -1,6 +1,6 @@ local paths = require('test.config.paths') -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(nil) local spawn, set_session, nvim_prog, merge_args = helpers.spawn, helpers.set_session, helpers.nvim_prog, helpers.merge_args diff --git a/test/functional/plugin/matchparen_spec.lua b/test/functional/plugin/matchparen_spec.lua index d8c1f2d392..4181f69263 100644 --- a/test/functional/plugin/matchparen_spec.lua +++ b/test/functional/plugin/matchparen_spec.lua @@ -1,20 +1,27 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) +local plugin_helpers = require('test.functional.plugin.helpers') local Screen = require('test.functional.ui.screen') -local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute + +local execute = helpers.execute +local meths = helpers.meths +local feed = helpers.feed +local eq = helpers.eq + +local reset = plugin_helpers.reset describe('matchparen', function() local screen before_each(function() - clear() + reset() screen = Screen.new(20,5) screen:attach() screen:set_default_attr_ignore( {{bold=true, foreground=Screen.colors.Blue}} ) end) it('uses correct column after i_<Up>. Vim patch 7.4.1296', function() - execute('set noai nosi nocin') - execute('runtime plugin/matchparen.vim') + execute('set noautoindent nosmartindent nocindent laststatus=0') + eq(1, meths.get_var('loaded_matchparen')) feed('ivoid f_test()<cr>') feed('{<cr>') feed('}') diff --git a/test/functional/plugin/msgpack_spec.lua b/test/functional/plugin/msgpack_spec.lua index 60ba88e55b..c8da8e8f6c 100644 --- a/test/functional/plugin/msgpack_spec.lua +++ b/test/functional/plugin/msgpack_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local meths = helpers.meths local eq, nvim_eval, nvim_command, exc_exec = helpers.eq, helpers.eval, helpers.command, helpers.exc_exec diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua index aad0e366bf..e18e9ef428 100644 --- a/test/functional/plugin/shada_spec.lua +++ b/test/functional/plugin/shada_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eq, nvim_eval, nvim_command, nvim, exc_exec, funcs, nvim_feed, curbuf = helpers.eq, helpers.eval, helpers.command, helpers.nvim, helpers.exc_exec, helpers.funcs, helpers.feed, helpers.curbuf diff --git a/test/functional/preload.lua b/test/functional/preload.lua index 1971ef77cc..1107b45d54 100644 --- a/test/functional/preload.lua +++ b/test/functional/preload.lua @@ -1,4 +1,4 @@ -- Modules loaded here will not be cleared and reloaded by Busted. -- Busted started doing this to help provide more isolation. See issue #62 -- for more information about this. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(nil) diff --git a/test/functional/provider/define_spec.lua b/test/functional/provider/define_spec.lua index c30ad6d8c2..b0363eb435 100644 --- a/test/functional/provider/define_spec.lua +++ b/test/functional/provider/define_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eval, command, nvim = helpers.eval, helpers.command, helpers.nvim local eq, run, stop = helpers.eq, helpers.run, helpers.stop local clear = helpers.clear diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua index a94880d4a2..a4e9a49c8a 100644 --- a/test/functional/provider/python3_spec.lua +++ b/test/functional/provider/python3_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eval, command, feed = helpers.eval, helpers.command, helpers.feed local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert local expect, write_file = helpers.expect, helpers.write_file diff --git a/test/functional/provider/python_spec.lua b/test/functional/provider/python_spec.lua index da45d6aa00..94dfa90ea8 100644 --- a/test/functional/provider/python_spec.lua +++ b/test/functional/provider/python_spec.lua @@ -1,12 +1,22 @@ -local helpers = require('test.functional.helpers') -local eval, command, feed = helpers.eval, helpers.command, helpers.feed -local eq, clear, insert = helpers.eq, helpers.clear, helpers.insert -local expect, write_file = helpers.expect, helpers.write_file +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +local neq = helpers.neq +local feed = helpers.feed +local clear = helpers.clear +local funcs = helpers.funcs +local meths = helpers.meths +local insert = helpers.insert +local expect = helpers.expect +local command = helpers.command +local exc_exec = helpers.exc_exec +local write_file = helpers.write_file +local curbufmeths = helpers.curbufmeths do clear() command('let [g:interp, g:errors] = provider#pythonx#Detect(2)') - local errors = eval('g:errors') + local errors = meths.get_var('errors') if errors ~= '' then pending( 'Python 2 (or the Python 2 neovim module) is broken or missing:\n' .. errors, @@ -15,49 +25,58 @@ do end end -describe('python commands and functions', function() - before_each(function() - clear() - command('python import vim') - end) +before_each(function() + clear() + command('python import vim') +end) - it('feature test', function() - eq(1, eval('has("python")')) +describe('python feature test', function() + it('works', function() + eq(1, funcs.has('python')) end) +end) - it('python_execute', function() +describe(':python command', function() + it('works with a line', function() command('python vim.vars["set_by_python"] = [100, 0]') - eq({100, 0}, eval('g:set_by_python')) + eq({100, 0}, meths.get_var('set_by_python')) end) - it('python_execute with nested commands', function() + -- TODO(ZyX-I): works with << EOF + -- TODO(ZyX-I): works with execute 'python' line1."\n".line2."\n"… + + it('supports nesting', function() command([[python vim.command('python vim.command("python vim.command(\'let set_by_nested_python = 555\')")')]]) - eq(555, eval('g:set_by_nested_python')) + eq(555, meths.get_var('set_by_nested_python')) end) - it('python_execute with range', function() + it('supports range', function() insert([[ line1 line2 line3 line4]]) feed('ggjvj:python vim.vars["range"] = vim.current.range[:]<CR>') - eq({'line2', 'line3'}, eval('g:range')) + eq({'line2', 'line3'}, meths.get_var('range')) end) +end) - it('pyfile', function() +describe(':pyfile command', function() + it('works', function() local fname = 'pyfile.py' write_file(fname, 'vim.command("let set_by_pyfile = 123")') command('pyfile pyfile.py') - eq(123, eval('g:set_by_pyfile')) + eq(123, meths.get_var('set_by_pyfile')) os.remove(fname) end) +end) - it('pydo', function() +describe(':pydo command', function() + it('works', function() -- :pydo 42 returns None for all lines, -- the buffer should not be changed command('normal :pydo 42') - eq(0, eval('&mod')) + eq(false, curbufmeths.get_option('modified')) -- insert some text insert('abc\ndef\nghi') expect([[ @@ -71,8 +90,25 @@ describe('python commands and functions', function() 2 ghi]]) end) +end) + +describe('pyeval()', function() + it('works', function() + eq({1, 2, {['key'] = 'val'}}, funcs.pyeval('[1, 2, {"key": "val"}]')) + end) + + it('errors out when given non-string', function() + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(10)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_dict)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:_null_list)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(0.0)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(function("tr"))')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:true)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:false)')) + eq('Vim(call):E474: Invalid argument', exc_exec('call pyeval(v:null)')) + end) - it('pyeval', function() - eq({1, 2, {['key'] = 'val'}}, eval([[pyeval('[1, 2, {"key": "val"}]')]])) + it('accepts NULL string', function() + neq(0, exc_exec('call pyeval($XXX_NONEXISTENT_VAR_XXX)')) end) end) diff --git a/test/functional/shada/buffers_spec.lua b/test/functional/shada/buffers_spec.lua index fd4809e01a..e4d02c268b 100644 --- a/test/functional/shada/buffers_spec.lua +++ b/test/functional/shada/buffers_spec.lua @@ -1,5 +1,5 @@ -- ShaDa buffer list saving/reading support -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim_command, funcs, eq, curbufmeths = helpers.command, helpers.funcs, helpers.eq, helpers.curbufmeths diff --git a/test/functional/shada/compatibility_spec.lua b/test/functional/shada/compatibility_spec.lua index 1fa88c58e5..1287ac010c 100644 --- a/test/functional/shada/compatibility_spec.lua +++ b/test/functional/shada/compatibility_spec.lua @@ -1,5 +1,5 @@ -- ShaDa compatibility support -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim_command, funcs, eq = helpers.command, helpers.funcs, helpers.eq local exc_exec = helpers.exc_exec diff --git a/test/functional/shada/errors_spec.lua b/test/functional/shada/errors_spec.lua index e7951ee74c..98ead6cc3d 100644 --- a/test/functional/shada/errors_spec.lua +++ b/test/functional/shada/errors_spec.lua @@ -1,5 +1,5 @@ -- ShaDa errors handling support -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim_command, eq, exc_exec, redir_exec = helpers.command, helpers.eq, helpers.exc_exec, helpers.redir_exec diff --git a/test/functional/shada/helpers.lua b/test/functional/shada/helpers.lua index d4eb7f57bd..bb2919d4fb 100644 --- a/test/functional/shada/helpers.lua +++ b/test/functional/shada/helpers.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(nil) local spawn, set_session, meths, nvim_prog = helpers.spawn, helpers.set_session, helpers.meths, helpers.nvim_prog local write_file, merge_args = helpers.write_file, helpers.merge_args diff --git a/test/functional/shada/history_spec.lua b/test/functional/shada/history_spec.lua index 94513945d0..22e653b1d6 100644 --- a/test/functional/shada/history_spec.lua +++ b/test/functional/shada/history_spec.lua @@ -1,5 +1,5 @@ -- ShaDa history saving/reading support -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim_command, funcs, meths, nvim_feed, eq = helpers.command, helpers.funcs, helpers.meths, helpers.feed, helpers.eq diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua index 955a6f382b..ace3c74a62 100644 --- a/test/functional/shada/marks_spec.lua +++ b/test/functional/shada/marks_spec.lua @@ -1,5 +1,5 @@ -- ShaDa marks saving/reading support -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local meths, curwinmeths, curbufmeths, nvim_command, funcs, eq = helpers.meths, helpers.curwinmeths, helpers.curbufmeths, helpers.command, helpers.funcs, helpers.eq diff --git a/test/functional/shada/merging_spec.lua b/test/functional/shada/merging_spec.lua index 221f989409..25c73b99eb 100644 --- a/test/functional/shada/merging_spec.lua +++ b/test/functional/shada/merging_spec.lua @@ -1,5 +1,5 @@ -- ShaDa merging data support -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim_command, funcs, curbufmeths, eq = helpers.command, helpers.funcs, helpers.curbufmeths, helpers.eq diff --git a/test/functional/shada/registers_spec.lua b/test/functional/shada/registers_spec.lua index 4043d94a69..f1c587c640 100644 --- a/test/functional/shada/registers_spec.lua +++ b/test/functional/shada/registers_spec.lua @@ -1,5 +1,5 @@ -- ShaDa registers saving/reading support -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local nvim_command, funcs, eq = helpers.command, helpers.funcs, helpers.eq local shada_helpers = require('test.functional.shada.helpers') diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua index 683d520627..32e7b16fc5 100644 --- a/test/functional/shada/shada_spec.lua +++ b/test/functional/shada/shada_spec.lua @@ -1,5 +1,5 @@ -- Other ShaDa tests -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local meths, nvim_command, funcs, eq = helpers.meths, helpers.command, helpers.funcs, helpers.eq local write_file, spawn, set_session, nvim_prog, exc_exec = diff --git a/test/functional/shada/variables_spec.lua b/test/functional/shada/variables_spec.lua index 7ceeafdc71..40101baf8f 100644 --- a/test/functional/shada/variables_spec.lua +++ b/test/functional/shada/variables_spec.lua @@ -1,5 +1,5 @@ -- ShaDa variables saving/reading support -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local meths, funcs, nvim_command, eq, exc_exec = helpers.meths, helpers.funcs, helpers.command, helpers.eq, helpers.exc_exec diff --git a/test/functional/shell/bang_filter_spec.lua b/test/functional/shell/bang_filter_spec.lua index 964dbd1029..cd5325c4e1 100644 --- a/test/functional/shell/bang_filter_spec.lua +++ b/test/functional/shell/bang_filter_spec.lua @@ -1,6 +1,6 @@ -- Specs for bang/filter commands -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, execute, clear = helpers.feed, helpers.execute, helpers.clear local mkdir, write_file, rmdir = helpers.mkdir, helpers.write_file, helpers.rmdir diff --git a/test/functional/shell/viml_system_spec.lua b/test/functional/shell/viml_system_spec.lua index 00b16e9158..3de022cbd9 100644 --- a/test/functional/shell/viml_system_spec.lua +++ b/test/functional/shell/viml_system_spec.lua @@ -2,7 +2,7 @@ -- - `system()` -- - `systemlist()` -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local eq, clear, eval, feed, nvim = helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.nvim @@ -151,8 +151,8 @@ describe('system()', function() describe('with output containing NULs', function() local fname = 'Xtest' - setup(create_file_with_nuls(fname)) - teardown(delete_file(fname)) + before_each(create_file_with_nuls(fname)) + after_each(delete_file(fname)) it('replaces NULs by SOH characters', function() eq('part1\001part2\001part3\n', eval('system("cat '..fname..'")')) @@ -310,8 +310,8 @@ describe('systemlist()', function() describe('with output containing NULs', function() local fname = 'Xtest' - setup(create_file_with_nuls(fname)) - teardown(delete_file(fname)) + before_each(create_file_with_nuls(fname)) + after_each(delete_file(fname)) it('replaces NULs by newline characters', function() eq({'part1\npart2\npart3'}, eval('systemlist("cat '..fname..'")')) diff --git a/test/functional/terminal/altscreen_spec.lua b/test/functional/terminal/altscreen_spec.lua index d9d96b25f9..e1760c8ad8 100644 --- a/test/functional/terminal/altscreen_spec.lua +++ b/test/functional/terminal/altscreen_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf local feed = helpers.feed diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index 55ef254a63..8a535d6864 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim local wait = helpers.wait @@ -158,8 +158,7 @@ describe('terminal buffer', function() end) it('handles loss of focus gracefully', function() - -- Temporarily change the statusline to avoid printing the file name, which - -- varies be where the test is run. + -- Change the statusline to avoid printing the file name, which varies. nvim('set_option', 'statusline', '==========') execute('set laststatus=0') @@ -195,5 +194,15 @@ describe('terminal buffer', function() execute('set laststatus=1') -- Restore laststatus to the default. end) + + it('term_close() use-after-free #4393', function() + if eval("executable('yes')") == 0 then + pending('missing "yes" command') + return + end + execute('terminal yes') + feed([[<C-\><C-n>]]) + execute('bdelete!') + end) end) diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua index c15da2f760..461ddd0ec7 100644 --- a/test/functional/terminal/cursor_spec.lua +++ b/test/functional/terminal/cursor_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local thelpers = require('test.functional.terminal.helpers') local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua index dcc4a54610..c98aef70b1 100644 --- a/test/functional/terminal/edit_spec.lua +++ b/test/functional/terminal/edit_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local screen = require('test.functional.ui.screen') local curbufmeths = helpers.curbufmeths diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua index 493539b4d3..458fa02fca 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_spec.lua @@ -1,15 +1,15 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, wait, nvim = helpers.clear, helpers.wait, helpers.nvim -local nvim_dir = helpers.nvim_dir -local execute = helpers.execute +local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq +local execute, eval = helpers.execute, helpers.eval describe(':terminal', function() local screen before_each(function() clear() - screen = Screen.new(50, 7) + screen = Screen.new(50, 4) screen:attach(false) nvim('set_option', 'shell', nvim_dir..'/shell-test') nvim('set_option', 'shellcmdflag', 'EXE') @@ -23,9 +23,6 @@ describe(':terminal', function() ready $ | [Process exited 0] | | - | - | - | -- TERMINAL -- | ]]) end) @@ -37,9 +34,6 @@ describe(':terminal', function() ready $ echo hi | | [Process exited 0] | - | - | - | -- TERMINAL -- | ]]) end) @@ -51,10 +45,15 @@ describe(':terminal', function() ready $ echo 'hello' \ "world" | | [Process exited 0] | - | - | - | -- TERMINAL -- | ]]) end) + + it('ex_terminal() double-free #4554', function() + source([[ + autocmd BufNew * set shell=foo + terminal]]) + -- Verify that BufNew actually fired (else the test is invalid). + eq('foo', eval('&shell')) + end) end) diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua index a32ae650d6..3d1530bd90 100644 --- a/test/functional/terminal/helpers.lua +++ b/test/functional/terminal/helpers.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(nil) local Screen = require('test.functional.ui.screen') local nvim_dir = helpers.nvim_dir local execute, nvim, wait = helpers.execute, helpers.nvim, helpers.wait diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua index 045f5aa42f..8d7c7451d3 100644 --- a/test/functional/terminal/highlight_spec.lua +++ b/test/functional/terminal/highlight_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local thelpers = require('test.functional.terminal.helpers') local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim @@ -25,7 +25,7 @@ describe('terminal window highlighting', function() [5] = {background = 11}, [6] = {foreground = 130}, [7] = {reverse = true}, - [8] = {background = 11} + [8] = {background = 11}, }) screen:attach(false) execute('enew | call termopen(["'..nvim_dir..'/tty-test"]) | startinsert') @@ -121,7 +121,7 @@ describe('terminal window highlighting with custom palette', function() clear() screen = Screen.new(50, 7) screen:set_default_attr_ids({ - [1] = {foreground = 1193046} + [1] = {foreground = 1193046, special = Screen.colors.Black} }) screen:set_default_attr_ignore({ [1] = {bold = true}, @@ -130,7 +130,7 @@ describe('terminal window highlighting with custom palette', function() [5] = {background = 11}, [6] = {foreground = 130}, [7] = {reverse = true}, - [8] = {background = 11} + [8] = {background = 11}, }) screen:attach(true) nvim('set_var', 'terminal_color_3', '#123456') @@ -165,24 +165,49 @@ end) describe('synIDattr()', function() local screen - before_each(function() clear() screen = Screen.new(50, 7) - execute('highlight Normal ctermfg=1 guifg=#ff0000') + execute('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black') + -- Salmon #fa8072 Maroon #800000 + execute('highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon') + end) + + it('returns cterm-color if RGB-capable UI is _not_ attached', function() + eq('252', eval('synIDattr(hlID("Normal"), "fg")')) + eq('252', eval('synIDattr(hlID("Normal"), "fg#")')) + eq('-1', eval('synIDattr(hlID("Normal"), "bg")')) + eq('-1', eval('synIDattr(hlID("Normal"), "bg#")')) + eq('79', eval('synIDattr(hlID("Keyword"), "fg")')) + eq('79', eval('synIDattr(hlID("Keyword"), "fg#")')) + eq('', eval('synIDattr(hlID("Keyword"), "sp")')) + eq('', eval('synIDattr(hlID("Keyword"), "sp#")')) end) - after_each(function() - screen:detach() + it('returns gui-color if "gui" arg is passed', function() + eq('Black', eval('synIDattr(hlID("Normal"), "bg", "gui")')) + eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp", "gui")')) + end) + + it('returns gui-color if RGB-capable UI is attached', function() + screen:attach(true) + eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg")')) + eq('Black', eval('synIDattr(hlID("Normal"), "bg")')) + eq('Salmon', eval('synIDattr(hlID("Keyword"), "fg")')) + eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp")')) end) - it('returns RGB number if GUI', function() + it('returns #RRGGBB value for fg#/bg#/sp#', function() screen:attach(true) - eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg")')) + eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg#")')) + eq('#000000', eval('synIDattr(hlID("Normal"), "bg#")')) + eq('#fa8072', eval('synIDattr(hlID("Keyword"), "fg#")')) + eq('#800000', eval('synIDattr(hlID("Keyword"), "sp#")')) end) it('returns color number if non-GUI', function() screen:attach(false) - eq('1', eval('synIDattr(hlID("Normal"), "fg")')) + eq('252', eval('synIDattr(hlID("Normal"), "fg")')) + eq('79', eval('synIDattr(hlID("Keyword"), "fg")')) end) end) diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua index c4bd3c2663..a86615184d 100644 --- a/test/functional/terminal/mouse_spec.lua +++ b/test/functional/terminal/mouse_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear = helpers.clear local feed, nvim = helpers.feed, helpers.nvim @@ -112,7 +112,7 @@ describe('terminal mouse', function() line28 |line28 | line29 |line29 | line30 |line30 | - rows: 5, cols: 24 |rows: 5, cols: 24 | + rows: 5, cols: 25 |rows: 5, cols: 25 | {2:^ } |{2: } | ========== ========== | | @@ -122,7 +122,7 @@ describe('terminal mouse', function() 1 ^ |line28 | ~ |line29 | ~ |line30 | - ~ |rows: 5, cols: 24 | + ~ |rows: 5, cols: 25 | ~ |{2: } | ========== ========== | :enew | set number | @@ -132,16 +132,16 @@ describe('terminal mouse', function() 27 line |line28 | 28 line |line29 | 29 line |line30 | - 30 line |rows: 5, cols: 24 | + 30 line |rows: 5, cols: 25 | 31 ^ |{2: } | ========== ========== | | ]]) feed('<c-w>li') screen:expect([[ - 27 line |line28 | - 28 line |line29 | - 29 line |line30 | + 27 line |line29 | + 28 line |line30 | + 29 line |rows: 5, cols: 25 | 30 line |rows: 5, cols: 24 | 31 |{1: } | ========== ========== | @@ -151,8 +151,8 @@ describe('terminal mouse', function() thelpers.enable_mouse() thelpers.feed_data('mouse enabled\n') screen:expect([[ - 27 line |line29 | - 28 line |line30 | + 27 line |line30 | + 28 line |rows: 5, cols: 25 | 29 line |rows: 5, cols: 24 | 30 line |mouse enabled | 31 |{1: } | @@ -164,8 +164,8 @@ describe('terminal mouse', function() it('wont lose focus if another window is scrolled', function() feed('<MouseDown><0,0><MouseDown><0,0>') screen:expect([[ - 21 line |line29 | - 22 line |line30 | + 21 line |line30 | + 22 line |rows: 5, cols: 25 | 23 line |rows: 5, cols: 24 | 24 line |mouse enabled | 25 line |{1: } | @@ -174,8 +174,8 @@ describe('terminal mouse', function() ]]) feed('<S-MouseUp><0,0>') screen:expect([[ - 26 line |line29 | - 27 line |line30 | + 26 line |line30 | + 27 line |rows: 5, cols: 25 | 28 line |rows: 5, cols: 24 | 29 line |mouse enabled | 30 line |{1: } | @@ -187,8 +187,8 @@ describe('terminal mouse', function() it('will lose focus if another window is clicked', function() feed('<LeftMouse><5,1>') screen:expect([[ - 27 line |line29 | - 28 l^ine |line30 | + 27 line |line30 | + 28 l^ine |rows: 5, cols: 25 | 29 line |rows: 5, cols: 24 | 30 line |mouse enabled | 31 |{2: } | diff --git a/test/functional/terminal/scrollback_spec.lua b/test/functional/terminal/scrollback_spec.lua index 4b56698520..7914e30a44 100644 --- a/test/functional/terminal/scrollback_spec.lua +++ b/test/functional/terminal/scrollback_spec.lua @@ -1,5 +1,5 @@ local Screen = require('test.functional.ui.screen') -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf local feed, nvim_dir, execute = helpers.feed, helpers.nvim_dir, helpers.execute diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index 364ca327a4..91789d6575 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -1,6 +1,6 @@ -- Some sanity checks for the TUI using the builtin terminal emulator -- as a simple way to send keys and assert screen state. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local feed = thelpers.feed_data local execute = helpers.execute diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua index 6c236ed868..eec8b53f4d 100644 --- a/test/functional/terminal/window_spec.lua +++ b/test/functional/terminal/window_spec.lua @@ -1,8 +1,8 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local feed, clear = helpers.feed, helpers.clear local wait = helpers.wait - +local execute = helpers.execute describe('terminal window', function() local screen @@ -12,6 +12,23 @@ describe('terminal window', function() screen = thelpers.screen_setup() end) + it('resets its size when entering terminal buffer', function() + feed('<c-\\><c-n>') + execute('set hidden') + execute('edit foo') + execute('doautoall SessionLoadPost') + execute('silent bnext') + screen:expect([[ + tty ready | + {2: } | + | + | + | + ^ | + :silent bnext | + ]]) + end) + describe('with colorcolumn set', function() before_each(function() feed('<c-\\><c-n>') diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua index 727eba2717..644060103a 100644 --- a/test/functional/terminal/window_split_tab_spec.lua +++ b/test/functional/terminal/window_split_tab_spec.lua @@ -1,7 +1,8 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local thelpers = require('test.functional.terminal.helpers') local clear = helpers.clear local feed, nvim = helpers.feed, helpers.nvim +local execute = helpers.execute describe('terminal', function() local screen @@ -21,6 +22,49 @@ describe('terminal', function() screen:detach() end) + it('resets its size when entering terminal window', function() + feed('<c-\\><c-n>') + execute('2split') + screen:expect([[ + tty ready | + ^rows: 2, cols: 50 | + ========== | + tty ready | + rows: 2, cols: 50 | + {2: } | + ~ | + ~ | + ========== | + | + ]]) + execute('wincmd p') + screen:expect([[ + tty ready | + rows: 2, cols: 50 | + ========== | + tty ready | + rows: 2, cols: 50 | + rows: 5, cols: 50 | + {2: } | + ^ | + ========== | + :wincmd p | + ]]) + execute('wincmd p') + screen:expect([[ + rows: 5, cols: 50 | + ^rows: 2, cols: 50 | + ========== | + rows: 5, cols: 50 | + rows: 2, cols: 50 | + {2: } | + ~ | + ~ | + ========== | + :wincmd p | + ]]) + end) + describe('when the screen is resized', function() it('will forward a resize request to the program', function() screen:try_resize(screen._width + 3, screen._height + 5) @@ -51,87 +95,4 @@ describe('terminal', function() ]]) end) end) - - describe('split horizontally', function() - before_each(function() - nvim('command', 'sp') - end) - - local function reduce_height() - screen:expect([[ - tty ready | - rows: 3, cols: 50 | - {1: } | - ~ | - ========== | - tty ready | - rows: 3, cols: 50 | - {2: } | - ========== | - -- TERMINAL -- | - ]]) - end - - it('uses the minimum height of all window displaying it', reduce_height) - - describe('and then vertically', function() - before_each(function() - reduce_height() - nvim('command', 'vsp') - end) - - local function reduce_width() - screen:expect([[ - rows: 3, cols: 50 |rows: 3, cols: 50 | - rows: 3, cols: 24 |rows: 3, cols: 24 | - {1: } |{2: } | - ~ |~ | - ========== ========== | - rows: 3, cols: 50 | - rows: 3, cols: 24 | - {2: } | - ========== | - -- TERMINAL -- | - ]]) - feed('<c-\\><c-n>gg') - screen:expect([[ - ^tty ready |rows: 3, cols: 50 | - rows: 3, cols: 50 |rows: 3, cols: 24 | - rows: 3, cols: 24 |{2: } | - {2: } |~ | - ========== ========== | - rows: 3, cols: 50 | - rows: 3, cols: 24 | - {2: } | - ========== | - | - ]]) - end - - it('uses the minimum width of all window displaying it', reduce_width) - - describe('and then closes one of the vertical splits with q:', function() - before_each(function() - reduce_width() - nvim('command', 'q') - feed('<c-w>ja') - end) - - it('will restore the width', function() - screen:expect([[ - rows: 3, cols: 24 | - rows: 3, cols: 50 | - {2: } | - ~ | - ========== | - rows: 3, cols: 24 | - rows: 3, cols: 50 | - {1: } | - ========== | - -- TERMINAL -- | - ]]) - end) - end) - end) - end) end) diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua index 58f5b11de0..f91aa8d402 100644 --- a/test/functional/ui/bufhl_spec.lua +++ b/test/functional/ui/bufhl_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, request, neq = helpers.execute, helpers.request, helpers.neq diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 06139277b2..6ef40fff62 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -1,7 +1,7 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local os = require('os') -local clear, feed = helpers.clear, helpers.feed +local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute, request, eq = helpers.execute, helpers.request, helpers.eq @@ -38,7 +38,6 @@ describe('manual syntax highlight', function() os.remove('Xtest-functional-ui-highlight.tmp.vim') end) - -- test with "set hidden" even if the bug did not occur this way it("works with buffer switch and 'hidden'", function() execute('e tmp1.vim') execute('e Xtest-functional-ui-highlight.tmp.vim') @@ -302,4 +301,353 @@ describe('Default highlight groups', function() {1:-- INSERT --} | ]], {[1] = {foreground = Screen.colors.Red, background = Screen.colors.Green}}) end) + it('can be cleared by assigning NONE', function() + execute('syn keyword TmpKeyword neovim') + execute('hi link TmpKeyword ErrorMsg') + insert('neovim') + screen:expect([[ + {1:neovi^m} | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + | + ]], { + [1] = {foreground = Screen.colors.White, background = Screen.colors.Red} + }) + execute("hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE" + .. " gui=NONE guifg=NONE guibg=NONE guisp=NONE") + screen:expect([[ + neovi^m | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + | + ]], {}) + end) +end) + +describe('guisp (special/undercurl)', function() + local screen + + before_each(function() + clear() + screen = Screen.new(25,10) + screen:attach() + screen:set_default_attr_ignore({ + [1] = {bold = true, foreground = Screen.colors.Blue}, + [2] = {bold = true} + }) + end) + + it('can be set and is applied like foreground or background', function() + execute('syntax on') + execute('syn keyword TmpKeyword neovim') + execute('syn keyword TmpKeyword1 special') + execute('syn keyword TmpKeyword2 specialwithbg') + execute('syn keyword TmpKeyword3 specialwithfg') + execute('hi! Awesome guifg=red guibg=yellow guisp=red') + execute('hi! Awesome1 guisp=red') + execute('hi! Awesome2 guibg=yellow guisp=red') + execute('hi! Awesome3 guifg=red guisp=red') + execute('hi link TmpKeyword Awesome') + execute('hi link TmpKeyword1 Awesome1') + execute('hi link TmpKeyword2 Awesome2') + execute('hi link TmpKeyword3 Awesome3') + insert([[ + neovim + awesome neovim + wordcontainingneovim + special + specialwithbg + specialwithfg + ]]) + feed('Go<tab>neovim tabbed') + screen:expect([[ + {1:neovim} | + awesome {1:neovim} | + wordcontainingneovim | + {2:special} | + {3:specialwithbg} | + {4:specialwithfg} | + | + {1:neovim} tabbed^ | + ~ | + -- INSERT -- | + ]],{ + [1] = {background = Screen.colors.Yellow, foreground = Screen.colors.Red, + special = Screen.colors.Red}, + [2] = {special = Screen.colors.Red}, + [3] = {special = Screen.colors.Red, background = Screen.colors.Yellow}, + [4] = {foreground = Screen.colors.Red, special = Screen.colors.Red}, + }) + + end) +end) + +describe("'cursorline' with 'listchars'", function() + local screen + + local hlgroup_colors = { + NonText = Screen.colors.Blue, + Cursorline = Screen.colors.Grey90, + SpecialKey = Screen.colors.Red, + Visual = Screen.colors.LightGrey, + } + + before_each(function() + clear() + screen = Screen.new(20,5) + screen:attach() + end) + + after_each(function() + screen:detach() + end) + + it("'cursorline' and 'cursorcolumn'", function() + screen:set_default_attr_ids({[1] = {background=hlgroup_colors.Cursorline}}) + screen:set_default_attr_ignore( {{bold=true, foreground=hlgroup_colors.NonText}} ) + execute('highlight clear ModeMsg') + execute('set cursorline') + feed('i') + screen:expect([[ + {1:^ }| + ~ | + ~ | + ~ | + -- INSERT -- | + ]]) + feed('abcdefg<cr>kkasdf') + screen:expect([[ + abcdefg | + {1:kkasdf^ }| + ~ | + ~ | + -- INSERT -- | + ]]) + feed('<esc>') + screen:expect([[ + abcdefg | + {1:kkasd^f }| + ~ | + ~ | + | + ]]) + execute('set nocursorline') + screen:expect([[ + abcdefg | + kkasd^f | + ~ | + ~ | + :set nocursorline | + ]]) + feed('k') + screen:expect([[ + abcde^fg | + kkasdf | + ~ | + ~ | + :set nocursorline | + ]]) + feed('jjji<cr><cr><cr><esc>') + screen:expect([[ + kkasd | + | + | + ^f | + | + ]]) + execute('set cursorline') + execute('set cursorcolumn') + feed('kkiabcdefghijk<esc>hh') + screen:expect([[ + kkasd {1: } | + {1:abcdefgh^ijk }| + {1: } | + f {1: } | + | + ]]) + feed('khh') + screen:expect([[ + {1:kk^asd }| + ab{1:c}defghijk | + {1: } | + f {1: } | + | + ]]) + end) + + it("'cursorline' and with 'listchar' option: space, eol, tab, and trail", function() + screen:set_default_attr_ids({ + [1] = {background=hlgroup_colors.Cursorline}, + [2] = { + foreground=hlgroup_colors.SpecialKey, + background=hlgroup_colors.Cursorline, + }, + [3] = { + background=hlgroup_colors.Cursorline, + foreground=hlgroup_colors.NonText, + bold=true, + }, + [4] = { + foreground=hlgroup_colors.NonText, + bold=true, + }, + [5] = { + foreground=hlgroup_colors.SpecialKey, + }, + }) + execute('highlight clear ModeMsg') + execute('highlight SpecialKey guifg=#FF0000') + execute('set cursorline') + execute('set tabstop=8') + execute('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list') + feed('i\t abcd <cr>\t abcd <cr><esc>k') + screen:expect([[ + {5:>-------.}abcd{5:*}{4:¬} | + {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }| + {4:¬} | + {4:~ }| + | + ]]) + feed('k') + screen:expect([[ + {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }| + {5:>-------.}abcd{5:*}{4:¬} | + {4:¬} | + {4:~ }| + | + ]]) + execute('set nocursorline') + screen:expect([[ + {5:^>-------.}abcd{5:*}{4:¬} | + {5:>-------.}abcd{5:*}{4:¬} | + {4:¬} | + {4:~ }| + :set nocursorline | + ]]) + execute('set nowrap') + feed('ALorem ipsum dolor sit amet<ESC>0') + screen:expect([[ + {5:^>-------.}abcd{5:.}Lorem{4:>}| + {5:>-------.}abcd{5:*}{4:¬} | + {4:¬} | + {4:~ }| + | + ]]) + execute('set cursorline') + screen:expect([[ + {2:^>-------.}{1:abcd}{2:.}{1:Lorem}{4:>}| + {5:>-------.}abcd{5:*}{4:¬} | + {4:¬} | + {4:~ }| + :set cursorline | + ]]) + feed('$') + screen:expect([[ + {4:<}{1:r}{2:.}{1:sit}{2:.}{1:ame^t}{3:¬}{1: }| + {4:<} | + {4:<} | + {4:~ }| + :set cursorline | + ]]) + feed('G') + screen:expect([[ + {5:>-------.}abcd{5:.}Lorem{4:>}| + {5:>-------.}abcd{5:*}{4:¬} | + {3:^¬}{1: }| + {4:~ }| + :set cursorline | + ]]) + end) + + it("'listchar' in visual mode", function() + screen:set_default_attr_ids({ + [1] = {background=hlgroup_colors.Cursorline}, + [2] = { + foreground=hlgroup_colors.SpecialKey, + background=hlgroup_colors.Cursorline, + }, + [3] = { + background=hlgroup_colors.Cursorline, + foreground=hlgroup_colors.NonText, + bold=true, + }, + [4] = { + foreground=hlgroup_colors.NonText, + bold=true, + }, + [5] = { + foreground=hlgroup_colors.SpecialKey, + }, + [6] = { + background=hlgroup_colors.Visual, + }, + [7] = { + background=hlgroup_colors.Visual, + foreground=hlgroup_colors.SpecialKey, + }, + [8] = { + background=hlgroup_colors.Visual, + foreground=hlgroup_colors.NonText, + bold=true, + }, + }) + execute('highlight clear ModeMsg') + execute('highlight SpecialKey guifg=#FF0000') + execute('set cursorline') + execute('set tabstop=8') + execute('set nowrap') + execute('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list') + feed('i\t abcd <cr>\t abcd Lorem ipsum dolor sit amet<cr><esc>kkk0') + screen:expect([[ + {2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }| + {5:>-------.}abcd{5:.}Lorem{4:>}| + {4:¬} | + {4:~ }| + | + ]]) + feed('lllvj') + screen:expect([[ + {5:>-------.}a{6:bcd}{7:*}{8:¬} | + {7:>-------.}{6:a}^bcd{5:.}Lorem{4:>}| + {4:¬} | + {4:~ }| + -- VISUAL -- | + ]]) + feed('<esc>V') + screen:expect([[ + {5:>-------.}abcd{5:*}{4:¬} | + {7:>-------.}{6:a}^b{6:cd}{7:.}{6:Lorem}{4:>}| + {4:¬} | + {4:~ }| + -- VISUAL LINE -- | + ]]) + feed('<esc>$') + screen:expect([[ + {4:<} | + {4:<}{1:r}{2:.}{1:sit}{2:.}{1:ame^t}{3:¬}{1: }| + {4:<} | + {4:~ }| + | + ]]) + end) end) diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua index 6f5cadaf81..407c576002 100644 --- a/test/functional/ui/input_spec.lua +++ b/test/functional/ui/input_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear, execute, nvim = helpers.clear, helpers.execute, helpers.nvim local feed, next_message, eq = helpers.feed, helpers.next_message, helpers.eq local expect = helpers.expect diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index d0d791308b..a433143266 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths local insert, execute = helpers.insert, helpers.execute @@ -23,7 +23,12 @@ describe('Mouse input', function() screen:attach() screen:set_default_attr_ids({ [1] = {background = hlgroup_colors.Visual}, - [2] = {bold = true} + [2] = {bold = true}, + [3] = { + foreground = hlgroup_colors.NonText, + background = hlgroup_colors.Visual, + bold = true, + }, }) screen:set_default_attr_ignore( {{bold=true, foreground=hlgroup_colors.NonText}} ) feed('itesting<cr>mouse<cr>support and selection<esc>') @@ -225,14 +230,14 @@ describe('Mouse input', function() feed('<LeftDrag><2,2>') screen:expect([[ testing | - mo{1:use } | + mo{1:use}{3: } | {1:su}^pport and selection | ~ | {2:-- VISUAL --} | ]]) feed('<LeftDrag><0,0>') screen:expect([[ - ^t{1:esting } | + ^t{1:esting}{3: } | {1:mou}se | support and selection | ~ | @@ -293,7 +298,7 @@ describe('Mouse input', function() screen:expect([[ testing | mouse | - {1:su}^p{1:port and selection } | + {1:su}^p{1:port and selection}{3: } | ~ | {2:-- VISUAL LINE --} | ]]) @@ -321,8 +326,8 @@ describe('Mouse input', function() ]]) feed('<RightMouse><2,2>') screen:expect([[ - {1:testing } | - {1:mouse } | + {1:testing}{3: } | + {1:mouse}{3: } | {1:su}^pport and selection | ~ | {2:-- VISUAL --} | diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index a11fab18a2..d7af2a4fce 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -105,7 +105,7 @@ -- To generate a text-only test without highlight checks, -- use `screen:snapshot_util({},true)` -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(nil) local request, run = helpers.request, helpers.run local dedent = helpers.dedent @@ -290,6 +290,10 @@ If everything else fails, use Screen:redraw_debug to help investigate what is end end +function Screen:sleep(ms) + pcall(function() self:wait(function() return "error" end, ms) end) +end + function Screen:_redraw(updates) for _, update in ipairs(updates) do -- print('--') @@ -425,6 +429,10 @@ function Screen:_handle_update_bg(bg) self._bg = bg end +function Screen:_handle_update_sp(sp) + self._sp = sp +end + function Screen:_handle_suspend() self.suspended = true end @@ -497,7 +505,7 @@ end function Screen:snapshot_util(attrs, ignore) -- util to generate screen test - pcall(function() self:wait(function() return "error" end, 250) end) + self:sleep(250) self:print_snapshot(attrs, ignore) end @@ -573,7 +581,7 @@ function Screen:_pprint_attrs(attrs) local items = {} for f, v in pairs(attrs) do local desc = tostring(v) - if f == "foreground" or f == "background" then + if f == "foreground" or f == "background" or f == "special" then if Screen.colornames[v] ~= nil then desc = "Screen.colors."..Screen.colornames[v] end @@ -614,7 +622,8 @@ function Screen:_equal_attrs(a, b) a.underline == b.underline and a.undercurl == b.undercurl and a.italic == b.italic and a.reverse == b.reverse and a.foreground == b.foreground and - a.background == b.background + a.background == b.background and + a.special == b.special end function Screen:_attr_index(attrs, attr) diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index a4545eeff0..9249be4aec 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local spawn, set_session, clear = helpers.spawn, helpers.set_session, helpers.clear local feed, execute = helpers.feed, helpers.execute diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua index e4217abcfe..894a75d355 100644 --- a/test/functional/ui/searchhl_spec.lua +++ b/test/functional/ui/searchhl_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local execute = helpers.execute diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index c32a7b9381..2b6e294627 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua index 66ea779011..c2ab0711c0 100644 --- a/test/functional/ui/syntax_conceal_spec.lua +++ b/test/functional/ui/syntax_conceal_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute local insert = helpers.insert diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index c57d4abcbf..2a55d27567 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed, execute = helpers.clear, helpers.feed, helpers.execute local funcs = helpers.funcs diff --git a/test/functional/viml/completion_spec.lua b/test/functional/viml/completion_spec.lua index 2b3844bf6d..33f481bae2 100644 --- a/test/functional/viml/completion_spec.lua +++ b/test/functional/viml/completion_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local Screen = require('test.functional.ui.screen') local clear, feed = helpers.clear, helpers.feed local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq diff --git a/test/functional/viml/errorlist_spec.lua b/test/functional/viml/errorlist_spec.lua index 30cb86f8d1..56d08771b7 100644 --- a/test/functional/viml/errorlist_spec.lua +++ b/test/functional/viml/errorlist_spec.lua @@ -1,4 +1,4 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local command = helpers.command diff --git a/test/functional/viml/function_spec.lua b/test/functional/viml/function_spec.lua index 665f5d4467..f0a4406593 100644 --- a/test/functional/viml/function_spec.lua +++ b/test/functional/viml/function_spec.lua @@ -1,7 +1,8 @@ -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq +local eval = helpers.eval local exc_exec = helpers.exc_exec describe('Up to MAX_FUNC_ARGS arguments are handled by', function() @@ -27,3 +28,11 @@ describe('Up to MAX_FUNC_ARGS arguments are handled by', function() eq('Vim(call):E740: Too many arguments for function rpcnotify', ret) end) end) + +describe('api_info()', function() + before_each(clear) + it('has the right keys', function() + local api_keys = eval("sort(keys(api_info()))") + eq({'error_types', 'functions', 'types'}, api_keys) + end) +end) diff --git a/test/helpers.lua b/test/helpers.lua new file mode 100644 index 0000000000..4c50c7644f --- /dev/null +++ b/test/helpers.lua @@ -0,0 +1,60 @@ +local assert = require('luassert') +local lfs = require('lfs') + +local check_logs_useless_lines = { + ['Warning: noted but unhandled ioctl']=1, + ['could cause spurious value errors to appear']=2, + ['See README_MISSING_SYSCALL_OR_IOCTL for guidance']=3, +} + +local eq = function(exp, act) + return assert.are.same(exp, act) +end +local neq = function(exp, act) + return assert.are_not.same(exp, act) +end +local ok = function(res) + return assert.is_true(res) +end + +local function check_logs() + local log_dir = os.getenv('LOG_DIR') + local runtime_errors = 0 + if log_dir and lfs.attributes(log_dir, 'mode') == 'directory' then + for tail in lfs.dir(log_dir) do + if tail:sub(1, 30) == 'valgrind-' or tail:find('san%.') then + local file = log_dir .. '/' .. tail + local fd = io.open(file) + local start_msg = ('='):rep(20) .. ' File ' .. file .. ' ' .. ('='):rep(20) + local lines = {} + local warning_line = 0 + for line in fd:lines() do + local cur_warning_line = check_logs_useless_lines[line] + if cur_warning_line == warning_line + 1 then + warning_line = cur_warning_line + else + lines[#lines + 1] = line + end + end + fd:close() + os.remove(file) + if #lines > 0 then + -- local out = os.getenv('TRAVIS_CI_BUILD') and io.stdout or io.stderr + local out = io.stdout + out:write(start_msg .. '\n') + out:write('= ' .. table.concat(lines, '\n= ') .. '\n') + out:write(select(1, start_msg:gsub('.', '=')) .. '\n') + runtime_errors = runtime_errors + 1 + end + end + end + end + assert(0 == runtime_errors) +end + +return { + eq = eq, + neq = neq, + ok = ok, + check_logs = check_logs, +} diff --git a/test/unit/api/helpers.lua b/test/unit/api/helpers.lua new file mode 100644 index 0000000000..883e1c6c19 --- /dev/null +++ b/test/unit/api/helpers.lua @@ -0,0 +1,156 @@ +local helpers = require('test.unit.helpers') +local eval_helpers = require('test.unit.eval.helpers') + +local cimport = helpers.cimport +local to_cstr = helpers.to_cstr +local ffi = helpers.ffi + +local list_type = eval_helpers.list_type +local dict_type = eval_helpers.dict_type +local func_type = eval_helpers.func_type +local nil_value = eval_helpers.nil_value +local int_type = eval_helpers.int_type +local flt_type = eval_helpers.flt_type +local type_key = eval_helpers.type_key + +local api = cimport('./src/nvim/api/private/defs.h', + './src/nvim/api/private/helpers.h', + './src/nvim/memory.h') + +local obj2lua + +local obj2lua_tab = { + [tonumber(api.kObjectTypeArray)] = function(obj) + local ret = {[type_key]=list_type} + for i = 1,tonumber(obj.data.array.size) do + ret[i] = obj2lua(obj.data.array.items[i - 1]) + end + if ret[1] then + ret[type_key] = nil + end + return ret + end, + [tonumber(api.kObjectTypeDictionary)] = function(obj) + local ret = {} + for i = 1,tonumber(obj.data.dictionary.size) do + local kv_pair = obj.data.dictionary.items[i - 1] + ret[ffi.string(kv_pair.key.data, kv_pair.key.size)] = obj2lua(kv_pair.value) + end + return ret + end, + [tonumber(api.kObjectTypeBoolean)] = function(obj) + if obj.data.boolean == false then + return false + else + return true + end + end, + [tonumber(api.kObjectTypeNil)] = function(_) + return nil_value + end, + [tonumber(api.kObjectTypeFloat)] = function(obj) + return tonumber(obj.data.floating) + end, + [tonumber(api.kObjectTypeInteger)] = function(obj) + return {[type_key]=int_type, value=tonumber(obj.data.integer)} + end, + [tonumber(api.kObjectTypeString)] = function(obj) + return ffi.string(obj.data.string.data, obj.data.string.size) + end, +} + +obj2lua = function(obj) + return ((obj2lua_tab[tonumber(obj['type'])] or function(obj_inner) + assert(false, 'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet') + end)(obj)) +end + +local obj = function(typ, data) + return ffi.gc(ffi.new('Object', {['type']=typ, data=data}), + api.api_free_object) +end + +local lua2obj + +local lua2obj_type_tab = { + [int_type] = function(l) + return obj(api.kObjectTypeInteger, {integer=l.value}) + end, + [flt_type] = function(l) + return obj(api.kObjectTypeFloat, {floating=l}) + end, + [list_type] = function(l) + local len = #l + local arr = obj(api.kObjectTypeArray, {array={ + size=len, + capacity=len, + items=ffi.cast('Object *', api.xmalloc(len * ffi.sizeof('Object'))), + }}) + for i = 1, len do + arr.data.array.items[i - 1] = ffi.gc(lua2obj(l[i]), nil) + end + return arr + end, + [dict_type] = function(l) + local kvs = {} + for k, v in pairs(l) do + if type(k) == 'string' then + kvs[#kvs + 1] = {k, v} + end + end + local len = #kvs + local dct = obj(api.kObjectTypeDictionary, {dictionary={ + size=len, + capacity=len, + items=ffi.cast('KeyValuePair *', + api.xmalloc(len * ffi.sizeof('KeyValuePair'))), + }}) + for i = 1, len do + local key, val = table.unpack(kvs[i]) + dct.data.dictionary.items[i - 1] = ffi.new( + 'KeyValuePair', {key=ffi.gc(lua2obj(key), nil).data.string, + value=ffi.gc(lua2obj(val), nil)}) + end + return dct + end, +} + +lua2obj = function(l) + if type(l) == 'table' then + if l[type_key] then + return lua2obj_type_tab[l[type_key]](l) + else + if l[1] then + return lua2obj_type_tab[list_type](l) + else + return lua2obj_type_tab[dict_type](l) + end + end + elseif type(l) == 'number' then + return lua2obj_type_tab[flt_type](l) + elseif type(l) == 'boolean' then + return obj(api.kObjectTypeBoolean, {boolean=l}) + elseif type(l) == 'string' then + return obj(api.kObjectTypeString, {string={ + size=#l, + data=api.xmemdupz(to_cstr(l), #l), + }}) + elseif l == nil or l == nil_value then + return obj(api.kObjectTypeNil, {integer=0}) + end +end + +return { + list_type=list_type, + dict_type=dict_type, + func_type=func_type, + int_type=int_type, + flt_type=flt_type, + + nil_value=nil_value, + + type_key=type_key, + + obj2lua=obj2lua, + lua2obj=lua2obj, +} diff --git a/test/unit/api/private_helpers_spec.lua b/test/unit/api/private_helpers_spec.lua new file mode 100644 index 0000000000..1d7c03787b --- /dev/null +++ b/test/unit/api/private_helpers_spec.lua @@ -0,0 +1,88 @@ +local helpers = require('test.unit.helpers') +local eval_helpers = require('test.unit.eval.helpers') +local api_helpers = require('test.unit.api.helpers') + +local cimport = helpers.cimport +local NULL = helpers.NULL +local eq = helpers.eq + +local lua2typvalt = eval_helpers.lua2typvalt +local typvalt = eval_helpers.typvalt + +local nil_value = api_helpers.nil_value +local list_type = api_helpers.list_type +local int_type = api_helpers.int_type +local type_key = api_helpers.type_key +local obj2lua = api_helpers.obj2lua + +local api = cimport('./src/nvim/api/private/helpers.h') + +describe('vim_to_object', function() + local vim_to_object = function(l) + return obj2lua(api.vim_to_object(lua2typvalt(l))) + end + + local different_output_test = function(name, input, output) + it(name, function() + eq(output, vim_to_object(input)) + end) + end + + local simple_test = function(name, l) + different_output_test(name, l, l) + end + + simple_test('converts true', true) + simple_test('converts false', false) + simple_test('converts nil', nil_value) + simple_test('converts 1', 1) + simple_test('converts -1.5', -1.5) + simple_test('converts empty string', '') + simple_test('converts non-empty string', 'foobar') + simple_test('converts integer 10', {[type_key]=int_type, value=10}) + simple_test('converts empty dictionary', {}) + simple_test('converts dictionary with scalar values', {test=10, test2=true, test3='test'}) + simple_test('converts dictionary with containers inside', {test={}, test2={1, 2}}) + simple_test('converts empty list', {[type_key]=list_type}) + simple_test('converts list with scalar values', {1, 2, 'test', 'foo'}) + simple_test('converts list with containers inside', {{}, {test={}, test3={test4=true}}}) + + local dct = {} + dct.dct = dct + different_output_test('outputs nil for nested dictionaries (1 level)', dct, {dct=nil_value}) + + local lst = {} + lst[1] = lst + different_output_test('outputs nil for nested lists (1 level)', lst, {nil_value}) + + local dct2 = {test=true, dict=nil_value} + dct2.dct = {dct2} + different_output_test('outputs nil for nested dictionaries (2 level, in list)', + dct2, {dct={nil_value}, test=true, dict=nil_value}) + + local dct3 = {test=true, dict=nil_value} + dct3.dct = {dctin=dct3} + different_output_test('outputs nil for nested dictionaries (2 level, in dict)', + dct3, {dct={dctin=nil_value}, test=true, dict=nil_value}) + + local lst2 = {} + lst2[1] = {lst2} + different_output_test('outputs nil for nested lists (2 level, in list)', lst2, {{nil_value}}) + + local lst3 = {nil, true, false, 'ttest'} + lst3[1] = {lst=lst3} + different_output_test('outputs nil for nested lists (2 level, in dict)', + lst3, {{lst=nil_value}, true, false, 'ttest'}) + + it('outputs empty list for NULL list', function() + local tt = typvalt('VAR_LIST', {v_list=NULL}) + eq(nil, tt.vval.v_list) + eq({[type_key]=list_type}, obj2lua(api.vim_to_object(tt))) + end) + + it('outputs empty dict for NULL dict', function() + local tt = typvalt('VAR_DICT', {v_dict=NULL}) + eq(nil, tt.vval.v_dict) + eq({}, obj2lua(api.vim_to_object(tt))) + end) +end) diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua index b7f82064d7..317c9be6e7 100644 --- a/test/unit/buffer_spec.lua +++ b/test/unit/buffer_spec.lua @@ -1,10 +1,9 @@ -local assert = require("luassert") local helpers = require("test.unit.helpers") local to_cstr = helpers.to_cstr +local get_str = helpers.ffi.string local eq = helpers.eq -local neq = helpers.neq local NULL = helpers.NULL local globals = helpers.cimport("./src/nvim/globals.h") @@ -211,93 +210,246 @@ describe('buffer functions', function() end) describe('build_stl_str_hl', function() + local buffer_byte_size = 100 + local STL_MAX_ITEM = 80 + local output_buffer = '' + + -- This function builds the statusline + -- + -- @param arg Optional arguments are: + -- .pat The statusline format string + -- .fillchar The fill character used in the statusline + -- .maximum_cell_count The number of cells available in the statusline + local function build_stl_str_hl(arg) + output_buffer = to_cstr(string.rep(" ", buffer_byte_size)) + + local pat = arg.pat or '' + local fillchar = arg.fillchar or (' '):byte() + local maximum_cell_count = arg.maximum_cell_count or buffer_byte_size - local output_buffer = to_cstr(string.rep(" ", 100)) - - local build_stl_str_hl = function(pat) return buffer.build_stl_str_hl(globals.curwin, output_buffer, - 100, + buffer_byte_size, to_cstr(pat), false, - 32, - 80, + fillchar, + maximum_cell_count, NULL, NULL) end - it('should copy plain text', function() - local width = build_stl_str_hl("this is a test") - - eq(14, width) - eq("this is a test", helpers.ffi.string(output_buffer, width)) - - end) - - it('should print no file name', function() - local width = build_stl_str_hl("%f") - - eq(9, width) - eq("[No Name]", helpers.ffi.string(output_buffer, width)) - - end) - - it('should print the relative file name', function() - buffer.setfname(globals.curbuf, to_cstr("Makefile"), NULL, 1) - local width = build_stl_str_hl("%f") - - eq(8, width) - eq("Makefile", helpers.ffi.string(output_buffer, width)) - - end) - - it('should print the full file name', function() - buffer.setfname(globals.curbuf, to_cstr("Makefile"), NULL, 1) - - local width = build_stl_str_hl("%F") - - assert.is_true(8 < width) - neq(NULL, string.find(helpers.ffi.string(output_buffer, width), "Makefile")) - - end) - - it('should print the tail file name', function() - buffer.setfname(globals.curbuf, to_cstr("src/nvim/buffer.c"), NULL, 1) - - local width = build_stl_str_hl("%t") - - eq(8, width) - eq("buffer.c", helpers.ffi.string(output_buffer, width)) - - end) - - it('should print the buffer number', function() - buffer.setfname(globals.curbuf, to_cstr("src/nvim/buffer.c"), NULL, 1) - - local width = build_stl_str_hl("%n") - - eq(1, width) - eq("1", helpers.ffi.string(output_buffer, width)) - end) - - it('should print the current line number in the buffer', function() - buffer.setfname(globals.curbuf, to_cstr("test/unit/buffer_spec.lua"), NULL, 1) - - local width = build_stl_str_hl("%l") - - eq(1, width) - eq("0", helpers.ffi.string(output_buffer, width)) - - end) - - it('should print the number of lines in the buffer', function() - buffer.setfname(globals.curbuf, to_cstr("test/unit/buffer_spec.lua"), NULL, 1) - - local width = build_stl_str_hl("%L") + -- Use this function to simplify testing the comparison between + -- the format string and the resulting statusline. + -- + -- @param description The description of what the test should be doing + -- @param statusline_cell_count The number of cells available in the statusline + -- @param input_stl The format string for the statusline + -- @param expected_stl The expected result string for the statusline + -- + -- @param arg Options can be placed in an optional dictionary as the last parameter + -- .expected_cell_count The expected number of cells build_stl_str_hl will return + -- .expected_byte_length The expected byte length of the string + -- .file_name The name of the file to be tested (useful in %f type tests) + -- .fillchar The character that will be used to fill any 'extra' space in the stl + local function statusline_test (description, + statusline_cell_count, + input_stl, + expected_stl, + arg) + + -- arg is the optional parameter + -- so we either fill in option with arg or an empty dictionary + local option = arg or {} + + local fillchar = option.fillchar or (' '):byte() + local expected_cell_count = option.expected_cell_count or statusline_cell_count + local expected_byte_length = option.expected_byte_length or expected_cell_count + + it(description, function() + if option.file_name then + buffer.setfname(globals.curbuf, to_cstr(option.file_name), NULL, 1) + else + buffer.setfname(globals.curbuf, nil, NULL, 1) + end + + local result_cell_count = build_stl_str_hl{pat=input_stl, + maximum_cell_count=statusline_cell_count, + fillchar=fillchar} + + eq(expected_stl, get_str(output_buffer, expected_byte_length)) + eq(expected_cell_count, result_cell_count) + end) + end - eq(1, width) - eq("1", helpers.ffi.string(output_buffer, width)) + -- file name testing + statusline_test('should print no file name', 10, + '%f', '[No Name]', + {expected_cell_count=9}) + statusline_test('should print the relative file name', 30, + '%f', 'test/unit/buffer_spec.lua', + {file_name='test/unit/buffer_spec.lua', expected_cell_count=25}) + statusline_test('should print the full file name', 40, + '%F', '/test/unit/buffer_spec.lua', + {file_name='/test/unit/buffer_spec.lua', expected_cell_count=26}) + + -- fillchar testing + statusline_test('should handle `!` as a fillchar', 10, + 'abcde%=', 'abcde!!!!!', + {fillchar=('!'):byte()}) + statusline_test('should handle `~` as a fillchar', 10, + '%=abcde', '~~~~~abcde', + {fillchar=('~'):byte()}) + statusline_test('should put fillchar `!` in between text', 10, + 'abc%=def', 'abc!!!!def', + {fillchar=('!'):byte()}) + statusline_test('should put fillchar `~` in between text', 10, + 'abc%=def', 'abc~~~~def', + {fillchar=('~'):byte()}) + statusline_test('should print the tail file name', 80, + '%t', 'buffer_spec.lua', + {file_name='test/unit/buffer_spec.lua', expected_cell_count=15}) + + -- standard text testing + statusline_test('should copy plain text', 80, + 'this is a test', 'this is a test', + {expected_cell_count=14}) + + -- line number testing + statusline_test('should print the buffer number', 80, + '%n', '1', + {expected_cell_count=1}) + statusline_test('should print the current line number in the buffer', 80, + '%l', '0', + {expected_cell_count=1}) + statusline_test('should print the number of lines in the buffer', 80, + '%L', '1', + {expected_cell_count=1}) + + -- truncation testing + statusline_test('should truncate when standard text pattern is too long', 10, + '0123456789abcde', '<6789abcde') + statusline_test('should truncate when using =', 10, + 'abcdef%=ghijkl', 'abcdef<jkl') + statusline_test('should truncate centered text when using ==', 10, + 'abcde%=gone%=fghij', 'abcde<ghij') + statusline_test('should respect the `<` marker', 10, + 'abc%<defghijkl', 'abc<ghijkl') + statusline_test('should truncate at `<` with one `=`, test 1', 10, + 'abc%<def%=ghijklmno', 'abc<jklmno') + statusline_test('should truncate at `<` with one `=`, test 2', 10, + 'abcdef%=ghijkl%<mno', 'abcdefghi>') + statusline_test('should truncate at `<` with one `=`, test 3', 10, + 'abc%<def%=ghijklmno', 'abc<jklmno') + statusline_test('should truncate at `<` with one `=`, test 4', 10, + 'abc%<def%=ghij', 'abcdefghij') + statusline_test('should truncate at `<` with one `=`, test 4', 10, + 'abc%<def%=ghijk', 'abc<fghijk') + + statusline_test('should truncate at `<` with many `=`, test 4', 10, + 'ab%<cdef%=g%=h%=ijk', 'ab<efghijk') + + statusline_test('should truncate at the first `<`', 10, + 'abc%<def%<ghijklm', 'abc<hijklm') + + -- alignment testing + statusline_test('should right align when using =', 20, + 'neo%=vim', 'neo vim') + statusline_test('should, when possible, center text when using %=text%=', 20, + 'abc%=neovim%=def', 'abc neovim def') + statusline_test('should handle uneven spacing in the buffer when using %=text%=', 20, + 'abc%=neo_vim%=def', 'abc neo_vim def') + statusline_test('should have equal spaces even with non-equal sides when using =', 20, + 'foobar%=test%=baz', 'foobar test baz') + statusline_test('should have equal spaces even with longer right side when using =', 20, + 'a%=test%=longtext', 'a test longtext') + statusline_test('should handle an empty left side when using ==', 20, + '%=test%=baz', ' test baz') + statusline_test('should handle an empty right side when using ==', 20, + 'foobar%=test%=', 'foobar test ') + statusline_test('should handle consecutive empty ==', 20, + '%=%=test%=', ' test ') + statusline_test('should handle an = alone', 20, + '%=', ' ') + statusline_test('should right align text when it is alone with =', 20, + '%=foo', ' foo') + statusline_test('should left align text when it is alone with =', 20, + 'foo%=', 'foo ') + + statusline_test('should approximately center text when using %=text%=', 21, + 'abc%=neovim%=def', 'abc neovim def') + statusline_test('should completely fill the buffer when using %=text%=', 21, + 'abc%=neo_vim%=def', 'abc neo_vim def') + statusline_test('should have equal spaces even with non-equal sides when using =', 21, + 'foobar%=test%=baz', 'foobar test baz') + statusline_test('should have equal spaces even with longer right side when using =', 21, + 'a%=test%=longtext', 'a test longtext') + statusline_test('should handle an empty left side when using ==', 21, + '%=test%=baz', ' test baz') + statusline_test('should handle an empty right side when using ==', 21, + 'foobar%=test%=', 'foobar test ') + + statusline_test('should quadrant the text when using 3 %=', 40, + 'abcd%=n%=eovim%=ef', 'abcd n eovim ef') + statusline_test('should work well with %t', 40, + '%t%=right_aligned', 'buffer_spec.lua right_aligned', + {file_name='test/unit/buffer_spec.lua'}) + statusline_test('should work well with %t and regular text', 40, + 'l%=m_l %t m_r%=r', 'l m_l buffer_spec.lua m_r r', + {file_name='test/unit/buffer_spec.lua'}) + statusline_test('should work well with %=, %t, %L, and %l', 40, + '%t %= %L %= %l', 'buffer_spec.lua 1 0', + {file_name='test/unit/buffer_spec.lua'}) + + statusline_test('should quadrant the text when using 3 %=', 41, + 'abcd%=n%=eovim%=ef', 'abcd n eovim ef') + statusline_test('should work well with %t', 41, + '%t%=right_aligned', 'buffer_spec.lua right_aligned', + {file_name='test/unit/buffer_spec.lua'}) + statusline_test('should work well with %t and regular text', 41, + 'l%=m_l %t m_r%=r', 'l m_l buffer_spec.lua m_r r', + {file_name='test/unit/buffer_spec.lua'}) + statusline_test('should work well with %=, %t, %L, and %l', 41, + '%t %= %L %= %l', 'buffer_spec.lua 1 0', + {file_name='test/unit/buffer_spec.lua'}) + + statusline_test('should work with 10 %=', 50, + 'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz', + 'aaaa b c d e fg hi jk lmnop qrstuv wxyz') + + -- maximum stl item testing + statusline_test('should handle a much larger amount of = than buffer locations', 20, + ('%='):rep(STL_MAX_ITEM - 1), + ' ') -- Should be fine, because within limit + statusline_test('should handle a much larger amount of = than stl max item', 20, + ('%='):rep(STL_MAX_ITEM + 1), + ' E541') -- Should show the VIM error + statusline_test('should handle many extra characters', 20, + 'a' .. ('a'):rep(STL_MAX_ITEM * 4), + '<aaaaaaaaaaaaaaaaaaa') -- Does not show the error because there are no items + statusline_test('should handle almost maximum of characters and flags', 20, + 'a' .. ('%=a'):rep(STL_MAX_ITEM - 1), + 'a<aaaaaaaaaaaaaaaaaa') -- Should not show the VIM error + statusline_test('should handle many extra characters and flags', 20, + 'a' .. ('%=a'):rep(STL_MAX_ITEM), + 'a<aaaaaaaaaaaaa E541') -- Should show the VIM error + statusline_test('should handle many extra characters and flags', 20, + 'a' .. ('%=a'):rep(STL_MAX_ITEM * 2), + 'a<aaaaaaaaaaaaa E541') -- Should show the VIM error + statusline_test('should handle many extra characters and flags with truncation', 20, + 'aaa%<' .. ('%=a'):rep(STL_MAX_ITEM), + 'aaa<aaaaaaaaaaa E541') -- Should show the VIM error + statusline_test('should handle many characters and flags before and after truncation', 20, + 'a%=a%=a%<' .. ('%=a'):rep(STL_MAX_ITEM), + 'aaa<aaaaaaaaaaa E541') -- Should show the VIM error + + + -- multi-byte testing + statusline_test('should handle multibyte characters', 10, + 'Ĉ%=x', 'Ĉ x', + {expected_byte_length=11}) + statusline_test('should handle multibyte characters and different fillchars', 10, + 'Ą%=mid%=end', 'Ą@mid@@end', + {fillchar=('@'):byte(), expected_byte_length=11}) - end) end) end) diff --git a/test/unit/eval/encode_spec.lua b/test/unit/eval/encode_spec.lua index f151a191fb..98fc8305e0 100644 --- a/test/unit/eval/encode_spec.lua +++ b/test/unit/eval/encode_spec.lua @@ -27,74 +27,74 @@ describe('encode_list_write()', function() it('writes ASCII string literal with printable characters', function() local l = list() eq(0, encode_list_write(l, 'abc')) - eq({[type_key]=list_type, 'abc'}, lst2tbl(l)) + eq({'abc'}, lst2tbl(l)) end) it('writes string starting with NL', function() local l = list() eq(0, encode_list_write(l, '\nabc')) - eq({[type_key]=list_type, null_string, 'abc'}, lst2tbl(l)) + eq({null_string, 'abc'}, lst2tbl(l)) end) it('writes string starting with NL twice', function() local l = list() eq(0, encode_list_write(l, '\nabc')) - eq({[type_key]=list_type, null_string, 'abc'}, lst2tbl(l)) + eq({null_string, 'abc'}, lst2tbl(l)) eq(0, encode_list_write(l, '\nabc')) - eq({[type_key]=list_type, null_string, 'abc', 'abc'}, lst2tbl(l)) + eq({null_string, 'abc', 'abc'}, lst2tbl(l)) end) it('writes string ending with NL', function() local l = list() eq(0, encode_list_write(l, 'abc\n')) - eq({[type_key]=list_type, 'abc', null_string}, lst2tbl(l)) + eq({'abc', null_string}, lst2tbl(l)) end) it('writes string ending with NL twice', function() local l = list() eq(0, encode_list_write(l, 'abc\n')) - eq({[type_key]=list_type, 'abc', null_string}, lst2tbl(l)) + eq({'abc', null_string}, lst2tbl(l)) eq(0, encode_list_write(l, 'abc\n')) - eq({[type_key]=list_type, 'abc', 'abc', null_string}, lst2tbl(l)) + eq({'abc', 'abc', null_string}, lst2tbl(l)) end) it('writes string starting, ending and containing NL twice', function() local l = list() eq(0, encode_list_write(l, '\na\nb\n')) - eq({[type_key]=list_type, null_string, 'a', 'b', null_string}, lst2tbl(l)) + eq({null_string, 'a', 'b', null_string}, lst2tbl(l)) eq(0, encode_list_write(l, '\na\nb\n')) - eq({[type_key]=list_type, null_string, 'a', 'b', null_string, 'a', 'b', null_string}, lst2tbl(l)) + eq({null_string, 'a', 'b', null_string, 'a', 'b', null_string}, lst2tbl(l)) end) it('writes string starting, ending and containing NUL with NL between twice', function() local l = list() eq(0, encode_list_write(l, '\0\n\0\n\0')) - eq({[type_key]=list_type, '\n', '\n', '\n'}, lst2tbl(l)) + eq({'\n', '\n', '\n'}, lst2tbl(l)) eq(0, encode_list_write(l, '\0\n\0\n\0')) - eq({[type_key]=list_type, '\n', '\n', '\n\n', '\n', '\n'}, lst2tbl(l)) + eq({'\n', '\n', '\n\n', '\n', '\n'}, lst2tbl(l)) end) it('writes string starting, ending and containing NL with NUL between twice', function() local l = list() eq(0, encode_list_write(l, '\n\0\n\0\n')) - eq({[type_key]=list_type, null_string, '\n', '\n', null_string}, lst2tbl(l)) + eq({null_string, '\n', '\n', null_string}, lst2tbl(l)) eq(0, encode_list_write(l, '\n\0\n\0\n')) - eq({[type_key]=list_type, null_string, '\n', '\n', null_string, '\n', '\n', null_string}, lst2tbl(l)) + eq({null_string, '\n', '\n', null_string, '\n', '\n', null_string}, lst2tbl(l)) end) it('writes string containing a single NL twice', function() local l = list() eq(0, encode_list_write(l, '\n')) - eq({[type_key]=list_type, null_string, null_string}, lst2tbl(l)) + eq({null_string, null_string}, lst2tbl(l)) eq(0, encode_list_write(l, '\n')) - eq({[type_key]=list_type, null_string, null_string, null_string}, lst2tbl(l)) + eq({null_string, null_string, null_string}, lst2tbl(l)) end) it('writes string containing a few NLs twice', function() local l = list() eq(0, encode_list_write(l, '\n\n\n')) - eq({[type_key]=list_type, null_string, null_string, null_string, null_string}, lst2tbl(l)) + eq({null_string, null_string, null_string, null_string}, lst2tbl(l)) eq(0, encode_list_write(l, '\n\n\n')) - eq({[type_key]=list_type, null_string, null_string, null_string, null_string, null_string, null_string, null_string}, lst2tbl(l)) + eq({null_string, null_string, null_string, null_string, null_string, null_string, null_string}, lst2tbl(l)) end) end) diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/helpers.lua index 2367f03e0d..45fbf8da5c 100644 --- a/test/unit/eval/helpers.lua +++ b/test/unit/eval/helpers.lua @@ -11,6 +11,12 @@ local null_string = {[true]='NULL string'} local null_list = {[true]='NULL list'} local type_key = {[true]='type key'} local list_type = {[true]='list type'} +local dict_type = {[true]='dict type'} +local func_type = {[true]='func type'} +local int_type = {[true]='int type'} +local flt_type = {[true]='flt type'} + +local nil_value = {[true]='nil'} local function list(...) local ret = ffi.gc(eval.list_alloc(), eval.list_unref) @@ -37,7 +43,53 @@ local function list(...) return ret end -local lst2tbl = function(l) +local special_tab = { + [eval.kSpecialVarFalse] = false, + [eval.kSpecialVarNull] = nil_value, + [eval.kSpecialVarTrue] = true, +} + +local lst2tbl +local dct2tbl + +local typvalt2lua_tab + +typvalt2lua_tab = { + [tonumber(eval.VAR_SPECIAL)] = function(t) + return special_tab[t.vval.v_special] + end, + [tonumber(eval.VAR_NUMBER)] = function(t) + return {[type_key]=int_type, value=tonumber(t.vval.v_number)} + end, + [tonumber(eval.VAR_FLOAT)] = function(t) + return tonumber(t.vval.v_float) + end, + [tonumber(eval.VAR_STRING)] = function(t) + local str = t.vval.v_string + if str == nil then + return null_string + else + return ffi.string(str) + end + end, + [tonumber(eval.VAR_LIST)] = function(t) + return lst2tbl(t.vval.v_list) + end, + [tonumber(eval.VAR_DICT)] = function(t) + return dct2tbl(t.vval.v_dict) + end, + [tonumber(eval.VAR_FUNC)] = function(t) + return {[type_key]=func_type, value=typvalt2lua_tab[eval.VAR_STRING](t)} + end, +} + +local typvalt2lua = function(t) + return ((typvalt2lua_tab[tonumber(t.v_type)] or function(t_inner) + assert(false, 'Converting ' .. tonumber(t_inner.v_type) .. ' was not implemented yet') + end)(t)) +end + +lst2tbl = function(l) local ret = {[type_key]=list_type} if l == nil then return ret @@ -45,28 +97,119 @@ local lst2tbl = function(l) local li = l.lv_first -- (listitem_T *) NULL is equal to nil, but yet it is not false. while li ~= nil do - local typ = li.li_tv.v_type - if typ == eval.VAR_STRING then - local str = li.li_tv.vval.v_string - if str == nil then - ret[#ret + 1] = null_string - else - ret[#ret + 1] = ffi.string(str) + ret[#ret + 1] = typvalt2lua(li.li_tv) + li = li.li_next + end + if ret[1] then + ret[type_key] = nil + end + return ret +end + +dct2tbl = function(d) + local ret = {d=d} + assert(false, 'Converting dictionaries is not implemented yet') + return ret +end + +local lua2typvalt + +local typvalt = function(typ, vval) + if type(typ) == 'string' then + typ = eval[typ] + end + return ffi.gc(ffi.new('typval_T', {v_type=typ, vval=vval}), eval.clear_tv) +end + +local lua2typvalt_type_tab = { + [int_type] = function(l, _) + return typvalt(eval.VAR_NUMBER, {v_number=l.value}) + end, + [flt_type] = function(l, processed) + return lua2typvalt(l.value, processed) + end, + [list_type] = function(l, processed) + if processed[l] then + processed[l].lv_refcount = processed[l].lv_refcount + 1 + return typvalt(eval.VAR_LIST, {v_list=processed[l]}) + end + local lst = eval.list_alloc() + lst.lv_refcount = 1 + processed[l] = lst + local ret = typvalt(eval.VAR_LIST, {v_list=lst}) + for i = 1, #l do + local item_tv = ffi.gc(lua2typvalt(l[i], processed), nil) + eval.list_append_tv(lst, item_tv) + eval.clear_tv(item_tv) + end + return ret + end, + [dict_type] = function(l, processed) + if processed[l] then + processed[l].dv_refcount = processed[l].dv_refcount + 1 + return typvalt(eval.VAR_DICT, {v_dict=processed[l]}) + end + local dct = eval.dict_alloc() + dct.dv_refcount = 1 + processed[l] = dct + local ret = typvalt(eval.VAR_DICT, {v_dict=dct}) + for k, v in pairs(l) do + if type(k) == 'string' then + local di = eval.dictitem_alloc(to_cstr(k)) + local val_tv = ffi.gc(lua2typvalt(v, processed), nil) + eval.copy_tv(val_tv, di.di_tv) + eval.clear_tv(val_tv) + eval.dict_add(dct, di) end + end + return ret + end, +} + +lua2typvalt = function(l, processed) + processed = processed or {} + if l == nil or l == nil_value then + return typvalt(eval.VAR_SPECIAL, {v_special=eval.kSpecialVarNull}) + elseif type(l) == 'table' then + if l[type_key] then + return lua2typvalt_type_tab[l[type_key]](l, processed) else - assert(false, 'Not implemented yet') + if l[1] then + return lua2typvalt_type_tab[list_type](l, processed) + else + return lua2typvalt_type_tab[dict_type](l, processed) + end end - li = li.li_next + elseif type(l) == 'number' then + return typvalt(eval.VAR_FLOAT, {v_float=l}) + elseif type(l) == 'boolean' then + return typvalt(eval.VAR_SPECIAL, { + v_special=(l and eval.kSpecialVarTrue or eval.kSpecialVarFalse) + }) + elseif type(l) == 'string' then + return typvalt(eval.VAR_STRING, {v_string=eval.xmemdupz(to_cstr(l), #l)}) end - return ret end return { null_string=null_string, null_list=null_list, list_type=list_type, + dict_type=dict_type, + func_type=func_type, + int_type=int_type, + flt_type=flt_type, + + nil_value=nil_value, + type_key=type_key, list=list, lst2tbl=lst2tbl, + dct2tbl=dct2tbl, + + lua2typvalt=lua2typvalt, + typvalt2lua=typvalt2lua, + + typvalt=typvalt, } diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua index 426ae2d9e0..91da459393 100644 --- a/test/unit/helpers.lua +++ b/test/unit/helpers.lua @@ -1,9 +1,13 @@ -local assert = require('luassert') local ffi = require('ffi') local formatc = require('test.unit.formatc') local Set = require('test.unit.set') local Preprocess = require('test.unit.preprocess') local Paths = require('test.config.paths') +local global_helpers = require('test.helpers') + +local neq = global_helpers.neq +local eq = global_helpers.eq +local ok = global_helpers.ok -- add some standard header locations for _, p in ipairs(Paths.include_paths) do @@ -31,7 +35,8 @@ local function filter_complex_blocks(body) if not (string.find(line, "(^)", 1, true) ~= nil or string.find(line, "_ISwupper", 1, true) or string.find(line, "msgpack_zone_push_finalizer") - or string.find(line, "msgpack_unpacker_reserve_buffer")) then + or string.find(line, "msgpack_unpacker_reserve_buffer") + or string.find(line, "inline _Bool")) then result[#result + 1] = line end end @@ -153,12 +158,9 @@ return { cimport = cimport, cppimport = cppimport, internalize = internalize, - eq = function(expected, actual) - return assert.are.same(expected, actual) - end, - neq = function(expected, actual) - return assert.are_not.same(expected, actual) - end, + ok = ok, + eq = eq, + neq = neq, ffi = ffi, lib = libnvim, cstr = cstr, diff --git a/test/unit/os/fileio_spec.lua b/test/unit/os/fileio_spec.lua new file mode 100644 index 0000000000..5358022422 --- /dev/null +++ b/test/unit/os/fileio_spec.lua @@ -0,0 +1,365 @@ +local lfs = require('lfs') + +local helpers = require('test.unit.helpers') + +local eq = helpers.eq +local ffi = helpers.ffi +local cimport = helpers.cimport + +local m = cimport('./src/nvim/os/fileio.h') + +local fcontents = '' +for i = 0, 255 do + fcontents = fcontents .. (i == 0 and '\0' or ('%c'):format(i)) +end +fcontents = fcontents:rep(16) + +local dir = 'Xtest-unit-file_spec.d' +local file1 = dir .. '/file1.dat' +local file2 = dir .. '/file2.dat' +local linkf = dir .. '/file.lnk' +local linkb = dir .. '/broken.lnk' +local filec = dir .. '/created-file.dat' + +before_each(function() + lfs.mkdir(dir); + + local f1 = io.open(file1, 'w') + f1:write(fcontents) + f1:close() + + local f2 = io.open(file2, 'w') + f2:write(fcontents) + f2:close() + + lfs.link('file1.dat', linkf, true) + lfs.link('broken.dat', linkb, true) +end) + +after_each(function() + os.remove(file1) + os.remove(file2) + os.remove(linkf) + os.remove(linkb) + os.remove(filec) + lfs.rmdir(dir) +end) + +local function file_open(fname, flags, mode) + local ret2 = ffi.new('FileDescriptor') + local ret1 = m.file_open(ret2, fname, flags, mode) + return ret1, ret2 +end + +local function file_open_new(fname, flags, mode) + local ret1 = ffi.new('int[?]', 1, {0}) + local ret2 = ffi.gc(m.file_open_new(ret1, fname, flags, mode), nil) + return ret1[0], ret2 +end + +local function file_write(fp, buf) + return m.file_write(fp, buf, #buf) +end + +local function file_read(fp, size) + local buf = nil + if size == nil then + size = 0 + else + -- For some reason if length of NUL-bytes-string is the same as `char[?]` + -- size luajit garbage collector crashes. But it does not do so in + -- os_read[v] tests in os/fs_spec.lua. + buf = ffi.new('char[?]', size + 1, ('\0'):rep(size)) + end + local ret1 = m.file_read(fp, buf, size) + local ret2 = '' + if buf ~= nil then + ret2 = ffi.string(buf, size) + end + return ret1, ret2 +end + +local function file_fsync(fp) + return m.file_fsync(fp) +end + +local function file_skip(fp, size) + return m.file_skip(fp, size) +end + +describe('file_open', function() + it('can create a rwx------ file with kFileCreate', function() + local err, fp = file_open(filec, m.kFileCreate, 448) + eq(0, err) + local attrs = lfs.attributes(filec) + eq('rwx------', attrs.permissions) + eq(0, m.file_close(fp)) + end) + + it('can create a rw------- file with kFileCreate', function() + local err, fp = file_open(filec, m.kFileCreate, 384) + eq(0, err) + local attrs = lfs.attributes(filec) + eq('rw-------', attrs.permissions) + eq(0, m.file_close(fp)) + end) + + it('can create a rwx------ file with kFileCreateOnly', function() + local err, fp = file_open(filec, m.kFileCreateOnly, 448) + eq(0, err) + local attrs = lfs.attributes(filec) + eq('rwx------', attrs.permissions) + eq(0, m.file_close(fp)) + end) + + it('can create a rw------- file with kFileCreateOnly', function() + local err, fp = file_open(filec, m.kFileCreateOnly, 384) + eq(0, err) + local attrs = lfs.attributes(filec) + eq('rw-------', attrs.permissions) + eq(0, m.file_close(fp)) + end) + + it('fails to open an existing file with kFileCreateOnly', function() + local err, _ = file_open(file1, m.kFileCreateOnly, 384) + eq(m.UV_EEXIST, err) + end) + + it('fails to open an symlink with kFileNoSymlink', function() + local err, _ = file_open(linkf, m.kFileNoSymlink, 384) + -- err is UV_EMLINK in FreeBSD, but if I use `ok(err == m.UV_ELOOP or err == + -- m.UV_EMLINK)`, then I loose the ability to see actual `err` value. + if err ~= m.UV_ELOOP then eq(m.UV_EMLINK, err) end + end) + + it('can open an existing file write-only with kFileCreate', function() + local err, fp = file_open(file1, m.kFileCreate, 384) + eq(0, err) + eq(true, fp.wr) + eq(0, m.file_close(fp)) + end) + + it('can open an existing file read-only with zero', function() + local err, fp = file_open(file1, 0, 384) + eq(0, err) + eq(false, fp.wr) + eq(0, m.file_close(fp)) + end) + + it('can open an existing file read-only with kFileReadOnly', function() + local err, fp = file_open(file1, m.kFileReadOnly, 384) + eq(0, err) + eq(false, fp.wr) + eq(0, m.file_close(fp)) + end) + + it('can open an existing file read-only with kFileNoSymlink', function() + local err, fp = file_open(file1, m.kFileNoSymlink, 384) + eq(0, err) + eq(false, fp.wr) + eq(0, m.file_close(fp)) + end) + + it('can truncate an existing file with kFileTruncate', function() + local err, fp = file_open(file1, m.kFileTruncate, 384) + eq(0, err) + eq(true, fp.wr) + eq(0, m.file_close(fp)) + local attrs = lfs.attributes(file1) + eq(0, attrs.size) + end) + + it('can open an existing file write-only with kFileWriteOnly', function() + local err, fp = file_open(file1, m.kFileWriteOnly, 384) + eq(0, err) + eq(true, fp.wr) + eq(0, m.file_close(fp)) + local attrs = lfs.attributes(file1) + eq(4096, attrs.size) + end) + + it('fails to create a file with just kFileWriteOnly', function() + local err, _ = file_open(filec, m.kFileWriteOnly, 384) + eq(m.UV_ENOENT, err) + local attrs = lfs.attributes(filec) + eq(nil, attrs) + end) + + it('can truncate an existing file with kFileTruncate when opening a symlink', + function() + local err, fp = file_open(linkf, m.kFileTruncate, 384) + eq(0, err) + eq(true, fp.wr) + eq(0, m.file_close(fp)) + local attrs = lfs.attributes(file1) + eq(0, attrs.size) + end) + + it('fails to open a directory write-only', function() + local err, _ = file_open(dir, m.kFileWriteOnly, 384) + eq(m.UV_EISDIR, err) + end) + + it('fails to open a broken symbolic link write-only', function() + local err, _ = file_open(linkb, m.kFileWriteOnly, 384) + eq(m.UV_ENOENT, err) + end) + + it('fails to open a broken symbolic link read-only', function() + local err, _ = file_open(linkb, m.kFileReadOnly, 384) + eq(m.UV_ENOENT, err) + end) +end) + +describe('file_open_new', function() + it('can open a file read-only', function() + local err, fp = file_open_new(file1, 0, 384) + eq(0, err) + eq(false, fp.wr) + eq(0, m.file_free(fp)) + end) + + it('fails to open an existing file with kFileCreateOnly', function() + local err, fp = file_open_new(file1, m.kFileCreateOnly, 384) + eq(m.UV_EEXIST, err) + eq(nil, fp) + end) +end) + +-- file_close is called above, so it is not tested directly + +describe('file_fsync', function() + it('can flush writes to disk', function() + local err, fp = file_open(filec, m.kFileCreateOnly, 384) + eq(0, file_fsync(fp)) + eq(0, err) + eq(0, lfs.attributes(filec).size) + local wsize = file_write(fp, 'test') + eq(4, wsize) + eq(0, lfs.attributes(filec).size) + eq(0, file_fsync(fp)) + eq(wsize, lfs.attributes(filec).size) + eq(0, m.file_close(fp)) + end) +end) + +describe('file_read', function() + it('can read small chunks of input until eof', function() + local err, fp = file_open(file1, 0, 384) + eq(0, err) + eq(false, fp.wr) + local shift = 0 + while shift < #fcontents do + local size = 3 + local exp_err = size + local exp_s = fcontents:sub(shift + 1, shift + size) + if shift + size >= #fcontents then + exp_err = #fcontents - shift + exp_s = (fcontents:sub(shift + 1, shift + size) + .. (('\0'):rep(size - exp_err))) + end + eq({exp_err, exp_s}, {file_read(fp, size)}) + shift = shift + size + end + eq(0, m.file_close(fp)) + end) + + it('can read the whole file at once', function() + local err, fp = file_open(file1, 0, 384) + eq(0, err) + eq(false, fp.wr) + eq({#fcontents, fcontents}, {file_read(fp, #fcontents)}) + eq({0, ('\0'):rep(#fcontents)}, {file_read(fp, #fcontents)}) + eq(0, m.file_close(fp)) + end) + + it('can read more then 1024 bytes after reading a small chunk', function() + local err, fp = file_open(file1, 0, 384) + eq(0, err) + eq(false, fp.wr) + eq({5, fcontents:sub(1, 5)}, {file_read(fp, 5)}) + eq({#fcontents - 5, fcontents:sub(6) .. (('\0'):rep(5))}, + {file_read(fp, #fcontents)}) + eq(0, m.file_close(fp)) + end) + + it('can read file by 768-byte-chunks', function() + local err, fp = file_open(file1, 0, 384) + eq(0, err) + eq(false, fp.wr) + local shift = 0 + while shift < #fcontents do + local size = 768 + local exp_err = size + local exp_s = fcontents:sub(shift + 1, shift + size) + if shift + size >= #fcontents then + exp_err = #fcontents - shift + exp_s = (fcontents:sub(shift + 1, shift + size) + .. (('\0'):rep(size - exp_err))) + end + eq({exp_err, exp_s}, {file_read(fp, size)}) + shift = shift + size + end + eq(0, m.file_close(fp)) + end) +end) + +describe('file_write', function() + it('can write the whole file at once', function() + local err, fp = file_open(filec, m.kFileCreateOnly, 384) + eq(0, err) + eq(true, fp.wr) + local wr = file_write(fp, fcontents) + eq(#fcontents, wr) + eq(0, m.file_close(fp)) + eq(wr, lfs.attributes(filec).size) + eq(fcontents, io.open(filec):read('*a')) + end) + + it('can write the whole file by small chunks', function() + local err, fp = file_open(filec, m.kFileCreateOnly, 384) + eq(0, err) + eq(true, fp.wr) + local shift = 0 + while shift < #fcontents do + local size = 3 + local s = fcontents:sub(shift + 1, shift + size) + local wr = file_write(fp, s) + eq(wr, #s) + shift = shift + size + end + eq(0, m.file_close(fp)) + eq(#fcontents, lfs.attributes(filec).size) + eq(fcontents, io.open(filec):read('*a')) + end) + + it('can write the whole file by 768-byte-chunks', function() + local err, fp = file_open(filec, m.kFileCreateOnly, 384) + eq(0, err) + eq(true, fp.wr) + local shift = 0 + while shift < #fcontents do + local size = 768 + local s = fcontents:sub(shift + 1, shift + size) + local wr = file_write(fp, s) + eq(wr, #s) + shift = shift + size + end + eq(0, m.file_close(fp)) + eq(#fcontents, lfs.attributes(filec).size) + eq(fcontents, io.open(filec):read('*a')) + end) +end) + +describe('file_skip', function() + it('can skip 3 bytes', function() + local err, fp = file_open(file1, 0, 384) + eq(0, err) + eq(false, fp.wr) + eq(3, file_skip(fp, 3)) + local rd, s = file_read(fp, 3) + eq(3, rd) + eq(fcontents:sub(4, 6), s) + eq(0, m.file_close(fp)) + end) +end) diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua index 71b5e7f576..cc10b0cfa4 100644 --- a/test/unit/os/fs_spec.lua +++ b/test/unit/os/fs_spec.lua @@ -6,6 +6,7 @@ local helpers = require('test.unit.helpers') local cimport = helpers.cimport local cppimport = helpers.cppimport local internalize = helpers.internalize +local ok = helpers.ok local eq = helpers.eq local neq = helpers.neq local ffi = helpers.ffi @@ -14,6 +15,8 @@ local to_cstr = helpers.to_cstr local OK = helpers.OK local FAIL = helpers.FAIL local NULL = helpers.NULL +local NODE_NORMAL = 0 +local NODE_WRITABLE = 1 cimport('unistd.h') cimport('./src/nvim/os/shell.h') @@ -25,6 +28,12 @@ cppimport('sys/stat.h') cppimport('fcntl.h') cppimport('uv-errno.h') +local s = '' +for i = 0, 255 do + s = s .. (i == 0 and '\0' or ('%c'):format(i)) +end +local fcontents = s:rep(16) + local buffer = "" local directory = nil local absolute_executable = nil @@ -148,11 +157,11 @@ describe('fs function', function() local function os_can_exe(name) local buf = ffi.new('char *[1]') buf[0] = NULL - local ok = fs.os_can_exe(to_cstr(name), buf, true) + local ce_ret = fs.os_can_exe(to_cstr(name), buf, true) -- When os_can_exe returns true, it must set the path. -- When it returns false, the path must be NULL. - if ok then + if ce_ret then neq(NULL, buf[0]) return internalize(buf[0]) else @@ -357,18 +366,60 @@ describe('fs function', function() local function os_file_exists(filename) return fs.os_file_exists((to_cstr(filename))) end - local function os_rename(path, new_path) return fs.os_rename((to_cstr(path)), (to_cstr(new_path))) end - local function os_remove(path) return fs.os_remove((to_cstr(path))) end - local function os_open(path, flags, mode) return fs.os_open((to_cstr(path)), flags, mode) end + local function os_close(fd) + return fs.os_close(fd) + end + -- For some reason if length of NUL-bytes-string is the same as `char[?]` + -- size luajit crashes. Though it does not do so in this test suite, better + -- be cautios and allocate more elements then needed. I only did this to + -- strings. + local function os_read(fd, size) + local buf = nil + if size == nil then + size = 0 + else + buf = ffi.new('char[?]', size + 1, ('\0'):rep(size)) + end + local eof = ffi.new('bool[?]', 1, {true}) + local ret2 = fs.os_read(fd, eof, buf, size) + local ret1 = eof[0] + local ret3 = '' + if buf ~= nil then + ret3 = ffi.string(buf, size) + end + return ret1, ret2, ret3 + end + local function os_readv(fd, sizes) + local bufs = {} + for i, size in ipairs(sizes) do + bufs[i] = { + iov_base=ffi.new('char[?]', size + 1, ('\0'):rep(size)), + iov_len=size, + } + end + local iov = ffi.new('struct iovec[?]', #sizes, bufs) + local eof = ffi.new('bool[?]', 1, {true}) + local ret2 = fs.os_readv(fd, eof, iov, #sizes) + local ret1 = eof[0] + local ret3 = {} + for i = 1,#sizes do + -- Warning: iov may not be used. + ret3[i] = ffi.string(bufs[i].iov_base, bufs[i].iov_len) + end + return ret1, ret2, ret3 + end + local function os_write(fd, data) + return fs.os_write(fd, data, data and #data or 0) + end describe('os_file_exists', function() it('returns false when given a non-existing file', function() @@ -433,30 +484,34 @@ describe('fs function', function() end) describe('os_open', function() + local new_file = 'test_new_file' + local existing_file = 'unit-test-directory/test_existing.file' + before_each(function() - io.open('unit-test-directory/test_existing.file', 'w').close() + (io.open(existing_file, 'w')):close() end) after_each(function() - os.remove('unit-test-directory/test_existing.file') - os.remove('test_new_file') + os.remove(existing_file) + os.remove(new_file) end) - local new_file = 'test_new_file' - local existing_file = 'unit-test-directory/test_existing.file' - it('returns UV_ENOENT for O_RDWR on a non-existing file', function() eq(ffi.C.UV_ENOENT, (os_open('non-existing-file', ffi.C.kO_RDWR, 0))) end) - it('returns non-negative for O_CREAT on a non-existing file', function() + it('returns non-negative for O_CREAT on a non-existing file which then can be closed', function() assert_file_does_not_exist(new_file) - assert.is_true(0 <= (os_open(new_file, ffi.C.kO_CREAT, 0))) + local fd = os_open(new_file, ffi.C.kO_CREAT, 0) + assert.is_true(0 <= fd) + eq(0, os_close(fd)) end) - it('returns non-negative for O_CREAT on a existing file', function() + it('returns non-negative for O_CREAT on a existing file which then can be closed', function() assert_file_exists(existing_file) - assert.is_true(0 <= (os_open(existing_file, ffi.C.kO_CREAT, 0))) + local fd = os_open(existing_file, ffi.C.kO_CREAT, 0) + assert.is_true(0 <= fd) + eq(0, os_close(fd)) end) it('returns UV_EEXIST for O_CREAT|O_EXCL on a existing file', function() @@ -464,24 +519,195 @@ describe('fs function', function() eq(ffi.C.kUV_EEXIST, (os_open(existing_file, (bit.bor(ffi.C.kO_CREAT, ffi.C.kO_EXCL)), 0))) end) - it('sets `rwx` permissions for O_CREAT 700', function() + it('sets `rwx` permissions for O_CREAT 700 which then can be closed', function() assert_file_does_not_exist(new_file) --create the file - os_open(new_file, ffi.C.kO_CREAT, tonumber("700", 8)) + local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber("700", 8)) --verify permissions eq('rwx------', lfs.attributes(new_file)['permissions']) + eq(0, os_close(fd)) end) - it('sets `rw` permissions for O_CREAT 600', function() + it('sets `rw` permissions for O_CREAT 600 which then can be closed', function() assert_file_does_not_exist(new_file) --create the file - os_open(new_file, ffi.C.kO_CREAT, tonumber("600", 8)) + local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber("600", 8)) --verify permissions eq('rw-------', lfs.attributes(new_file)['permissions']) + eq(0, os_close(fd)) + end) + + it('returns a non-negative file descriptor for an existing file which then can be closed', function() + local fd = os_open(existing_file, ffi.C.kO_RDWR, 0) + assert.is_true(0 <= fd) + eq(0, os_close(fd)) + end) + end) + + describe('os_close', function() + it('returns EBADF for negative file descriptors', function() + eq(ffi.C.UV_EBADF, os_close(-1)) + eq(ffi.C.UV_EBADF, os_close(-1000)) + end) + end) + + describe('os_read', function() + local file = 'test-unit-os-fs_spec-os_read.dat' + + before_each(function() + local f = io.open(file, 'w') + f:write(fcontents) + f:close() + end) + + after_each(function() + os.remove(file) + end) + + it('can read zero bytes from a file', function() + local fd = os_open(file, ffi.C.kO_RDONLY, 0) + ok(fd >= 0) + eq({false, 0, ''}, {os_read(fd, nil)}) + eq({false, 0, ''}, {os_read(fd, 0)}) + eq(0, os_close(fd)) + end) + + it('can read from a file multiple times', function() + local fd = os_open(file, ffi.C.kO_RDONLY, 0) + ok(fd >= 0) + eq({false, 2, '\000\001'}, {os_read(fd, 2)}) + eq({false, 2, '\002\003'}, {os_read(fd, 2)}) + eq(0, os_close(fd)) + end) + + it('can read the whole file at once and then report eof', function() + local fd = os_open(file, ffi.C.kO_RDONLY, 0) + ok(fd >= 0) + eq({false, #fcontents, fcontents}, {os_read(fd, #fcontents)}) + eq({true, 0, ('\0'):rep(#fcontents)}, {os_read(fd, #fcontents)}) + eq(0, os_close(fd)) + end) + + it('can read the whole file in two calls, one partially', function() + local fd = os_open(file, ffi.C.kO_RDONLY, 0) + ok(fd >= 0) + eq({false, #fcontents * 3/4, fcontents:sub(1, #fcontents * 3/4)}, + {os_read(fd, #fcontents * 3/4)}) + eq({true, + (#fcontents * 1/4), + fcontents:sub(#fcontents * 3/4 + 1) .. ('\0'):rep(#fcontents * 2/4)}, + {os_read(fd, #fcontents * 3/4)}) + eq(0, os_close(fd)) + end) + end) + + describe('os_readv', function() + -- Function may be absent + if not pcall(function() return fs.os_readv end) then + return + end + local file = 'test-unit-os-fs_spec-os_readv.dat' + + before_each(function() + local f = io.open(file, 'w') + f:write(fcontents) + f:close() + end) + + after_each(function() + os.remove(file) + end) + + it('can read zero bytes from a file', function() + local fd = os_open(file, ffi.C.kO_RDONLY, 0) + ok(fd >= 0) + eq({false, 0, {}}, {os_readv(fd, {})}) + eq({false, 0, {'', '', ''}}, {os_readv(fd, {0, 0, 0})}) + eq(0, os_close(fd)) + end) + + it('can read from a file multiple times to a differently-sized buffers', function() + local fd = os_open(file, ffi.C.kO_RDONLY, 0) + ok(fd >= 0) + eq({false, 2, {'\000\001'}}, {os_readv(fd, {2})}) + eq({false, 5, {'\002\003', '\004\005\006'}}, {os_readv(fd, {2, 3})}) + eq(0, os_close(fd)) + end) + + it('can read the whole file at once and then report eof', function() + local fd = os_open(file, ffi.C.kO_RDONLY, 0) + ok(fd >= 0) + eq({false, + #fcontents, + {fcontents:sub(1, #fcontents * 1/4), + fcontents:sub(#fcontents * 1/4 + 1, #fcontents * 3/4), + fcontents:sub(#fcontents * 3/4 + 1, #fcontents * 15/16), + fcontents:sub(#fcontents * 15/16 + 1, #fcontents)}}, + {os_readv(fd, {#fcontents * 1/4, + #fcontents * 2/4, + #fcontents * 3/16, + #fcontents * 1/16})}) + eq({true, 0, {'\0'}}, {os_readv(fd, {1})}) + eq(0, os_close(fd)) + end) + + it('can read the whole file in two calls, one partially', function() + local fd = os_open(file, ffi.C.kO_RDONLY, 0) + ok(fd >= 0) + eq({false, #fcontents * 3/4, {fcontents:sub(1, #fcontents * 3/4)}}, + {os_readv(fd, {#fcontents * 3/4})}) + eq({true, + (#fcontents * 1/4), + {fcontents:sub(#fcontents * 3/4 + 1) .. ('\0'):rep(#fcontents * 2/4)}}, + {os_readv(fd, {#fcontents * 3/4})}) + eq(0, os_close(fd)) + end) + end) + + describe('os_write', function() + -- Function may be absent + local file = 'test-unit-os-fs_spec-os_write.dat' + + before_each(function() + local f = io.open(file, 'w') + f:write(fcontents) + f:close() + end) + + after_each(function() + os.remove(file) + end) + + it('can write zero bytes to a file', function() + local fd = os_open(file, ffi.C.kO_WRONLY, 0) + ok(fd >= 0) + eq(0, os_write(fd, '')) + eq(0, os_write(fd, nil)) + eq(fcontents, io.open(file, 'r'):read('*a')) + eq(0, os_close(fd)) + end) + + it('can write some data to a file', function() + local fd = os_open(file, ffi.C.kO_WRONLY, 0) + ok(fd >= 0) + eq(3, os_write(fd, 'abc')) + eq(4, os_write(fd, ' def')) + eq('abc def' .. fcontents:sub(8), io.open(file, 'r'):read('*a')) + eq(0, os_close(fd)) + end) + end) + + describe('os_nodetype', function() + before_each(function() + os.remove('non-existing-file') + end) + + it('returns NODE_NORMAL for non-existing file', function() + eq(NODE_NORMAL, fs.os_nodetype(to_cstr('non-existing-file'))) end) - it('returns a non-negative file descriptor for an existing file', function() - assert.is_true(0 <= (os_open(existing_file, ffi.C.kO_RDWR, 0))) + it('returns NODE_WRITABLE for /dev/stderr', function() + eq(NODE_WRITABLE, fs.os_nodetype(to_cstr('/dev/stderr'))) end) end) end) diff --git a/test/unit/os/shell_spec.lua b/test/unit/os/shell_spec.lua index 93103e4e8c..906f950308 100644 --- a/test/unit/os/shell_spec.lua +++ b/test/unit/os/shell_spec.lua @@ -30,10 +30,6 @@ describe('shell functions', function() cimported.p_shcf = to_cstr('-c') end) - teardown(function() - cimported.event_teardown() - end) - local function shell_build_argv(cmd, extra_args) local res = cimported.shell_build_argv( cmd and to_cstr(cmd), diff --git a/test/unit/strings_spec.lua b/test/unit/strings_spec.lua index e935d2af6a..0034670ee8 100644 --- a/test/unit/strings_spec.lua +++ b/test/unit/strings_spec.lua @@ -8,6 +8,38 @@ local to_cstr = helpers.to_cstr local strings = cimport('stdlib.h', './src/nvim/strings.h', './src/nvim/memory.h') +describe('vim_strsave_escaped()', function() + local vim_strsave_escaped = function(s, chars) + local res = strings.vim_strsave_escaped(to_cstr(s), to_cstr(chars)) + local ret = ffi.string(res) + + -- Explicitly free memory so we are sure it is allocated: if it was not it + -- will crash. + strings.xfree(res) + return ret + end + + it('precedes by a backslash all chars from second argument', function() + eq([[\a\b\c\d]], vim_strsave_escaped('abcd','abcd')) + end) + + it('precedes by a backslash chars only from second argument', function() + eq([[\a\bcd]], vim_strsave_escaped('abcd','ab')) + end) + + it('returns a copy of passed string if second argument is empty', function() + eq('text \n text', vim_strsave_escaped('text \n text','')) + end) + + it('returns an empty string if first argument is empty string', function() + eq('', vim_strsave_escaped('','\r')) + end) + + it('returns a copy of passed string if it does not contain chars from 2nd argument', function() + eq('some text', vim_strsave_escaped('some text', 'a')) + end) +end) + describe('vim_strnsave_unquoted()', function() local vim_strnsave_unquoted = function(s, len) local res = strings.vim_strnsave_unquoted(to_cstr(s), len or #s) |