diff options
Diffstat (limited to 'test')
234 files changed, 4617 insertions, 760 deletions
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..7044307399 100644 --- a/test/functional/autocmd/tabnewentered_spec.lua +++ b/test/functional/autocmd/tabnewentered_spec.lua @@ -1,22 +1,31 @@ -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() - describe('au TabNewEntered', function() - describe('with * as <afile>', function() - it('matches when entering any new tab', function() - clear() - nvim('command', 'au! TabNewEntered * echom "tabnewentered:".tabpagenr().":".bufnr("")') - eq("\ntabnewentered:2:2", nvim('command_output', 'tabnew')) - eq("\n\"test.x2\" [New File]\ntabnewentered:3:3", nvim('command_output', 'tabnew test.x2')) - end) - end) - describe('with FILE as <afile>', function() - it('matches when opening a new tab for FILE', function() - local tmp_path = nvim('eval', 'tempname()') - nvim('command', 'au! TabNewEntered '..tmp_path..' echom "tabnewentered:match"') - eq("\n\""..tmp_path.."\" [New File]\ntabnewentered:4:4\ntabnewentered:match", nvim('command_output', 'tabnew '..tmp_path)) - end) - end) + describe('au TabNewEntered', function() + describe('with * as <afile>', function() + it('matches when entering any new tab', function() + clear() + nvim('command', 'au! TabNewEntered * echom "tabnewentered:".tabpagenr().":".bufnr("")') + eq("\ntabnewentered:2:2", nvim('command_output', 'tabnew')) + eq("\n\"test.x2\" [New File]\ntabnewentered:3:3", nvim('command_output', 'tabnew test.x2')) + end) end) + describe('with FILE as <afile>', function() + it('matches when opening a new tab for FILE', function() + local tmp_path = nvim('eval', 'tempname()') + nvim('command', 'au! TabNewEntered '..tmp_path..' echom "tabnewentered:match"') + eq("\n\""..tmp_path.."\" [New File]\ntabnewentered:4:4\ntabnewentered:match", nvim('command_output', 'tabnew '..tmp_path)) + end) + end) + describe('with CTRL-W T', function() + it('works when opening a new tab with CTRL-W T', function() + clear() + nvim('command', 'au! TabNewEntered * echom "entered"') + nvim('command', 'tabnew test.x2') + nvim('command', 'split') + eq('\nentered', nvim('command_output', 'execute "normal \\<C-W>T"')) + end) + end) + end) end) 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..15977b9777 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 @@ -308,6 +308,7 @@ describe('clipboard usage', function() end) it('links the "+ and unnamed registers', function() + eq('+', eval('v:register')) insert("one two") feed('^"+dwdw"+P') expect('two') @@ -335,6 +336,7 @@ describe('clipboard usage', function() eq({{'really unnamed', ''}, 'V'}, eval("g:test_clip['*']")) -- unnamedplus takes predecence when pasting + eq('+', eval('v:register')) execute("let g:test_clip['+'] = ['the plus','']") execute("let g:test_clip['*'] = ['the star','']") feed("p") diff --git a/test/functional/job/job_spec.lua b/test/functional/core/job_spec.lua index d21b9051e2..61ecdd1835 100644 --- a/test/functional/job/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -1,11 +1,10 @@ - -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 +36,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) @@ -94,7 +119,7 @@ describe('jobs', function() {0, {'a', '', 'c', '', '', '', 'b', '', ''}}}, next_msg()) end) - it('can preserve nuls', function() + it('can preserve NULs', function() nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") nvim('command', 'call jobsend(j, ["\n123\n", "abc\\nxyz\n", ""])') eq({'notification', 'stdout', {0, {'\n123\n', 'abc\nxyz\n', ''}}}, @@ -118,7 +143,7 @@ describe('jobs', function() eq({'notification', 'exit', {0, 0}}, next_msg()) end) - it("won't allow jobsend with a job that closed stdin", function() + it("disallows jobsend on a job that closed stdin", function() nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") nvim('command', 'call jobclose(j, "stdin")') eq(false, pcall(function() @@ -126,12 +151,12 @@ describe('jobs', function() end)) end) - it('will not allow jobsend/stop on a non-existent job', function() + it('disallows jobsend/stop on a non-existent job', function() eq(false, pcall(eval, "jobsend(-1, 'lol')")) eq(false, pcall(eval, "jobstop(-1)")) end) - it('will not allow jobstop twice on the same job', function() + it('disallows jobstop twice on the same job', function() nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") neq(0, eval('j')) eq(true, pcall(eval, "jobstop(j)")) @@ -218,7 +243,7 @@ describe('jobs', function() eq({'notification', 'exit', {45, 10}}, next_msg()) end) - it('cant redefine callbacks being used by a job', function() + it('cannot redefine callbacks being used by a job', function() local screen = Screen.new() screen:attach() local script = [[ @@ -441,3 +466,41 @@ describe('jobs', function() end) end) end) + +describe("pty process teardown", function() + local screen + before_each(function() + clear() + screen = Screen.new(30, 6) + screen:attach() + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + ~ | + | + ]]) + end) + after_each(function() + screen:detach() + end) + + it("does not prevent/delay exit. #4798 #4900", function() + -- Use a nested nvim (in :term) to test without --headless. + execute(":terminal '"..helpers.nvim_prog + -- Use :term again in the _nested_ nvim to get a PTY process. + -- Use `sleep` to simulate a long-running child of the PTY. + .."' +terminal +'!(sleep 300 &)' +qa") + + -- Exiting should terminate all descendants (PTY, its children, ...). + screen:expect([[ + | + [Process exited 0] | + | + | + | + -- TERMINAL -- | + ]]) + end) +end) 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 index 611113f560..2f83edb9e4 100644 --- a/test/functional/eval/timer_spec.lua +++ b/test/functional/eval/timer_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 ok, feed, eq, eval = helpers.ok, helpers.feed, helpers.eq, helpers.eval local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run @@ -22,6 +22,14 @@ describe('timers', function() eq(1,eval("g:val")) end) + it('works one-shot when repeat=0', function() + execute("call timer_start(50, 'MyHandler', {'repeat': 0})") + 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")) @@ -37,6 +45,13 @@ describe('timers', function() eq(2,eval("g:val")) end) + it('works with zero timeout', function() + -- timer_start does still not invoke the callback immediately + eq(0,eval("[timer_start(0, 'MyHandler', {'repeat': 1000}), g:val][1]")) + run(nil, nil, nil, 300) + eq(1000,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 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/drop_spec.lua b/test/functional/ex_cmds/drop_spec.lua new file mode 100644 index 0000000000..16b194dd7d --- /dev/null +++ b/test/functional/ex_cmds/drop_spec.lua @@ -0,0 +1,80 @@ +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 + +describe(":drop", function() + local screen + + before_each(function() + clear() + screen = Screen.new(35, 10) + screen:attach() + screen:set_default_attr_ignore({{bold=true, foreground=Screen.colors.Blue}}) + screen:set_default_attr_ids({ + [1] = {bold = true, reverse = true}, + [2] = {reverse = true}, + [3] = {bold = true}, + }) + execute("set laststatus=2") + end) + + after_each(function() + screen:detach() + end) + + it("works like :e when called with only one window open", function() + execute("drop tmp1.vim") + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + ~ | + {1:tmp1.vim }| + "tmp1.vim" [New File] | + ]]) + end) + + it("switches to an open window showing the buffer", function() + execute("edit tmp1") + execute("vsplit") + execute("edit tmp2") + execute("drop tmp1") + screen:expect([[ + {2:|}^ | + ~ {2:|}~ | + ~ {2:|}~ | + ~ {2:|}~ | + ~ {2:|}~ | + ~ {2:|}~ | + ~ {2:|}~ | + ~ {2:|}~ | + {2:tmp2 }{1:tmp1 }| + :drop tmp1 | + ]]) + end) + + it("splits off a new window when a buffer can't be abandoned", function() + execute("edit tmp1") + execute("vsplit") + execute("edit tmp2") + feed("iABC<esc>") + execute("drop tmp3") + screen:expect([[ + ^ {2:|} | + ~ {2:|}~ | + ~ {2:|}~ | + ~ {2:|}~ | + {1:tmp3 }{2:|}~ | + ABC {2:|}~ | + ~ {2:|}~ | + ~ {2:|}~ | + {2:tmp2 [+] tmp1 }| + "tmp3" [New File] | + ]]) + 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/fixtures/autoload/provider/clipboard.vim b/test/functional/fixtures/autoload/provider/clipboard.vim index 0935ea45ff..411e095c71 100644 --- a/test/functional/fixtures/autoload/provider/clipboard.vim +++ b/test/functional/fixtures/autoload/provider/clipboard.vim @@ -9,13 +9,12 @@ function! s:methods.get(reg) if g:cliperror return 0 end - let reg = a:reg == '"' ? '+' : a:reg if g:cliplossy " behave like pure text clipboard - return g:test_clip[reg][0] + return g:test_clip[a:reg][0] else " behave like VIMENC clipboard - return g:test_clip[reg] + return g:test_clip[a:reg] end endfunction diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 37b7bf664c..02109d0889 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 @@ -308,14 +300,18 @@ local function curbuf(method, ...) end local function wait() + -- Execute 'vim_eval' (a deferred function) to block + -- until all pending input is processed. session:request('vim_eval', '1') end +-- sleeps the test runner (_not_ the nvim instance) +local function sleep(timeout) + run(nil, nil, nil, timeout) +end + local function curbuf_contents() - -- Before inspecting the buffer, execute 'vim_eval' to wait until all - -- previously sent keys are processed(vim_eval is a deferred function, and - -- only processed after all input) - wait() + wait() -- Before inspecting the buffer, process all input. return table.concat(curbuf('get_lines', 0, -1, true), '\n') end @@ -345,10 +341,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 +408,60 @@ 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, + sleep = sleep, + 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/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 b79b1903ba..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, source = helpers.feed, helpers.insert, helpers.source -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) 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 350a77b2c5..9bf69ccba1 100644 --- a/test/functional/legacy/061_undo_tree_spec.lua +++ b/test/functional/legacy/061_undo_tree_spec.lua @@ -1,9 +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 expect, feed, source = helpers.expect, helpers.feed, helpers.source -local eval, clear, execute = helpers.eval, helpers.clear, helpers.execute -local write_file, command, eq = helpers.write_file, helpers.command, helpers.eq +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 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 index cac8be77f3..e232e5073d 100644 --- a/test/functional/legacy/068_text_formatting_spec.lua +++ b/test/functional/legacy/068_text_formatting_spec.lua @@ -1,6 +1,10 @@ -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 insert = helpers.insert +local execute = helpers.execute +local expect = helpers.expect describe('text formatting', function() setup(clear) 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 index 6df645d255..a03092e446 100644 --- a/test/functional/legacy/108_backtrace_debug_commands_spec.lua +++ b/test/functional/legacy/108_backtrace_debug_commands_spec.lua @@ -1,6 +1,6 @@ -- Tests for backtrace debug commands. -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, clear = helpers.feed, helpers.clear local execute, expect = helpers.execute, helpers.expect 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 63699387c1..8da6ee45d7 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,6 +141,18 @@ 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}]) @@ -160,4 +172,34 @@ describe('assert function:', function() expected_errors({'command did not fail: call empty("")'}) end) end) + + -- assert_exception({cmd}, [, {error}]) + describe('assert_exception()', function() + it('should assert thrown exceptions properly', function() + source([[ + try + nocommand + catch + call assert_exception('E492') + endtry + ]]) + expected_empty() + end) + + it('should work properly when nested', function() + source([[ + try + nocommand + catch + try + " illegal argument, get NULL for error + call assert_exception([]) + catch + call assert_exception('E730') + endtry + endtry + ]]) + expected_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 index a12d4add10..2504fe8e51 100644 --- a/test/functional/legacy/breakindent_spec.lua +++ b/test/functional/legacy/breakindent_spec.lua @@ -1,6 +1,6 @@ -- Test for breakindent -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/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 index ee6b29c618..ad1812f22e 100644 --- a/test/functional/legacy/close_count_spec.lua +++ b/test/functional/legacy/close_count_spec.lua @@ -1,6 +1,6 @@ -- Tests for :[count]close! and :[count]hide -local helpers = require('test.functional.helpers') +local helpers = require('test.functional.helpers')(after_each) local feed, eval, eq, clear, execute = helpers.feed, helpers.eval, helpers.eq, helpers.clear, helpers.execute 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..7bf6fb67dc --- /dev/null +++ b/test/functional/legacy/expand_spec.lua @@ -0,0 +1,77 @@ +-- 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('%')) + if has('unix') + next! Xdir?/*/nofile + call assert_equal('Xdir?/*/nofile', expand('%')) + endif + " Edit another file, on MS-Windows the swap file would be in use and can't + " be deleted + edit foo + + call assert_equal(0, delete('Xdir1', 'rf')) + call assert_equal(0, delete('Xdir2', 'rf')) + call assert_equal(0, 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 index cabeecdc9c..98bdf630dd 100644 --- a/test/functional/legacy/file_perm_spec.lua +++ b/test/functional/legacy/file_perm_spec.lua @@ -1,7 +1,7 @@ -- Test getting and setting file permissions. require('os') -local helpers = require('test.functional.helpers') +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 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 index 17ff2e71ad..3c4da8119c 100644 --- a/test/functional/legacy/join_spec.lua +++ b/test/functional/legacy/join_spec.lua @@ -1,6 +1,6 @@ -- Test for joining lines -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/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 index 6601a922ef..eb979edc69 100644 --- a/test/functional/legacy/listlbr_spec.lua +++ b/test/functional/legacy/listlbr_spec.lua @@ -1,6 +1,6 @@ -- Test for linebreak and list option (non-utf8) -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_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/packadd_spec.lua b/test/functional/legacy/packadd_spec.lua new file mode 100644 index 0000000000..b2ed39f288 --- /dev/null +++ b/test/functional/legacy/packadd_spec.lua @@ -0,0 +1,350 @@ +-- Tests for 'packpath' and :packadd + +local helpers = require('test.functional.helpers')(after_each) +local clear, source, execute = helpers.clear, helpers.source, helpers.execute +local call, eq, nvim = helpers.call, helpers.eq, helpers.meths +local feed = helpers.feed + +local function expected_empty() + eq({}, nvim.get_vvar('errors')) +end + +describe('packadd', function() + before_each(function() + clear() + + source([=[ + func SetUp() + let s:topdir = expand('%:p:h') . '/Xdir' + exe 'set packpath=' . s:topdir + let s:plugdir = s:topdir . '/pack/mine/opt/mytest' + endfunc + + func TearDown() + call delete(s:topdir, 'rf') + endfunc + + func Test_packadd() + call mkdir(s:plugdir . '/plugin', 'p') + call mkdir(s:plugdir . '/ftdetect', 'p') + call mkdir(s:plugdir . '/after', 'p') + set rtp& + let rtp = &rtp + filetype on + + exe 'split ' . s:plugdir . '/plugin/test.vim' + call setline(1, 'let g:plugin_works = 42') + wq + + exe 'split ' . s:plugdir . '/ftdetect/test.vim' + call setline(1, 'let g:ftdetect_works = 17') + wq + + packadd mytest + + call assert_true(42, g:plugin_works) + call assert_true(17, g:ftdetect_works) + call assert_true(len(&rtp) > len(rtp)) + call assert_true(&rtp =~ (s:plugdir . '\($\|,\)')) + call assert_true(&rtp =~ (s:plugdir . '/after$')) + + " Check exception + call assert_fails("packadd directorynotfound", 'E919:') + call assert_fails("packadd", 'E471:') + endfunc + + func Test_packadd_noload() + call mkdir(s:plugdir . '/plugin', 'p') + call mkdir(s:plugdir . '/syntax', 'p') + set rtp& + let rtp = &rtp + + exe 'split ' . s:plugdir . '/plugin/test.vim' + call setline(1, 'let g:plugin_works = 42') + wq + let g:plugin_works = 0 + + packadd! mytest + + call assert_true(len(&rtp) > len(rtp)) + call assert_true(&rtp =~ (s:plugdir . '\($\|,\)')) + call assert_equal(0, g:plugin_works) + + " check the path is not added twice + let new_rtp = &rtp + packadd! mytest + call assert_equal(new_rtp, &rtp) + endfunc + + func Test_packloadall() + " plugin foo with an autoload directory + let fooplugindir = &packpath . '/pack/mine/start/foo/plugin' + call mkdir(fooplugindir, 'p') + call writefile(['let g:plugin_foo_number = 1234', + \ 'let g:plugin_foo_auto = bbb#value', + \ 'let g:plugin_extra_auto = extra#value'], fooplugindir . '/bar.vim') + let fooautodir = &packpath . '/pack/mine/start/foo/autoload' + call mkdir(fooautodir, 'p') + call writefile(['let bar#value = 77'], fooautodir . '/bar.vim') + + " plugin aaa with an autoload directory + let aaaplugindir = &packpath . '/pack/mine/start/aaa/plugin' + call mkdir(aaaplugindir, 'p') + call writefile(['let g:plugin_aaa_number = 333', + \ 'let g:plugin_aaa_auto = bar#value'], aaaplugindir . '/bbb.vim') + let aaaautodir = &packpath . '/pack/mine/start/aaa/autoload' + call mkdir(aaaautodir, 'p') + call writefile(['let bbb#value = 55'], aaaautodir . '/bbb.vim') + + " plugin extra with only an autoload directory + let extraautodir = &packpath . '/pack/mine/start/extra/autoload' + call mkdir(extraautodir, 'p') + call writefile(['let extra#value = 99'], extraautodir . '/extra.vim') + + packloadall + call assert_equal(1234, g:plugin_foo_number) + call assert_equal(55, g:plugin_foo_auto) + call assert_equal(99, g:plugin_extra_auto) + call assert_equal(333, g:plugin_aaa_number) + call assert_equal(77, g:plugin_aaa_auto) + + " only works once + call writefile(['let g:plugin_bar_number = 4321'], + \ fooplugindir . '/bar2.vim') + packloadall + call assert_false(exists('g:plugin_bar_number')) + + " works when ! used + packloadall! + call assert_equal(4321, g:plugin_bar_number) + endfunc + + func Test_helptags() + let docdir1 = &packpath . '/pack/mine/start/foo/doc' + let docdir2 = &packpath . '/pack/mine/start/bar/doc' + call mkdir(docdir1, 'p') + call mkdir(docdir2, 'p') + call writefile(['look here: *look-here*'], docdir1 . '/bar.txt') + call writefile(['look away: *look-away*'], docdir2 . '/foo.txt') + exe 'set rtp=' . &packpath . '/pack/mine/start/foo,' . &packpath . '/pack/mine/start/bar' + + helptags ALL + + let tags1 = readfile(docdir1 . '/tags') + call assert_true(tags1[0] =~ 'look-here') + let tags2 = readfile(docdir2 . '/tags') + call assert_true(tags2[0] =~ 'look-away') + endfunc + + func Test_colorscheme() + let colordirrun = &packpath . '/runtime/colors' + let colordirstart = &packpath . '/pack/mine/start/foo/colors' + let colordiropt = &packpath . '/pack/mine/opt/bar/colors' + call mkdir(colordirrun, 'p') + call mkdir(colordirstart, 'p') + call mkdir(colordiropt, 'p') + call writefile(['let g:found_one = 1'], colordirrun . '/one.vim') + call writefile(['let g:found_two = 1'], colordirstart . '/two.vim') + call writefile(['let g:found_three = 1'], colordiropt . '/three.vim') + exe 'set rtp=' . &packpath . '/runtime' + + colorscheme one + call assert_equal(1, g:found_one) + colorscheme two + call assert_equal(1, g:found_two) + colorscheme three + call assert_equal(1, g:found_three) + endfunc + + func Test_runtime() + let rundir = &packpath . '/runtime/extra' + let startdir = &packpath . '/pack/mine/start/foo/extra' + let optdir = &packpath . '/pack/mine/opt/bar/extra' + call mkdir(rundir, 'p') + call mkdir(startdir, 'p') + call mkdir(optdir, 'p') + call writefile(['let g:sequence .= "run"'], rundir . '/bar.vim') + call writefile(['let g:sequence .= "start"'], startdir . '/bar.vim') + call writefile(['let g:sequence .= "foostart"'], startdir . '/foo.vim') + call writefile(['let g:sequence .= "opt"'], optdir . '/bar.vim') + call writefile(['let g:sequence .= "xxxopt"'], optdir . '/xxx.vim') + exe 'set rtp=' . &packpath . '/runtime' + + let g:sequence = '' + runtime extra/bar.vim + call assert_equal('run', g:sequence) + let g:sequence = '' + runtime START extra/bar.vim + call assert_equal('start', g:sequence) + let g:sequence = '' + runtime OPT extra/bar.vim + call assert_equal('opt', g:sequence) + let g:sequence = '' + runtime PACK extra/bar.vim + call assert_equal('start', g:sequence) + let g:sequence = '' + runtime! PACK extra/bar.vim + call assert_equal('startopt', g:sequence) + let g:sequence = '' + runtime PACK extra/xxx.vim + call assert_equal('xxxopt', g:sequence) + + let g:sequence = '' + runtime ALL extra/bar.vim + call assert_equal('run', g:sequence) + let g:sequence = '' + runtime ALL extra/foo.vim + call assert_equal('foostart', g:sequence) + let g:sequence = '' + runtime! ALL extra/xxx.vim + call assert_equal('xxxopt', g:sequence) + let g:sequence = '' + runtime! ALL extra/bar.vim + call assert_equal('runstartopt', g:sequence) + endfunc + ]=]) + call('SetUp') + end) + + after_each(function() + call('TearDown') + end) + + it('is working', function() + call('Test_packadd') + expected_empty() + end) + + it('works with packadd!', function() + call('Test_packadd_noload') + expected_empty() + end) + + it('works with :packloadall', function() + call('Test_packloadall') + expected_empty() + end) + + it('works with helptags', function() + call('Test_helptags') + expected_empty() + end) + + it('works with colorschemes', function() + call('Test_colorscheme') + expected_empty() + end) + + it('works with :runtime [what]', function() + call('Test_runtime') + expected_empty() + end) + + describe('command line completion', function() + local Screen = require('test.functional.ui.screen') + local screen + + before_each(function() + screen = Screen.new(30, 5) + screen:attach() + screen:set_default_attr_ids({ + [1] = { + foreground = Screen.colors.Black, + background = Screen.colors.Yellow, + }, + [2] = {bold = true, reverse = true} + }) + local NonText = Screen.colors.Blue + screen:set_default_attr_ignore({{}, {bold=true, foreground=NonText}}) + + execute([[let optdir1 = &packpath . '/pack/mine/opt']]) + execute([[let optdir2 = &packpath . '/pack/candidate/opt']]) + execute([[call mkdir(optdir1 . '/pluginA', 'p')]]) + execute([[call mkdir(optdir1 . '/pluginC', 'p')]]) + execute([[call mkdir(optdir2 . '/pluginB', 'p')]]) + execute([[call mkdir(optdir2 . '/pluginC', 'p')]]) + end) + + it('works', function() + feed(':packadd <Tab>') + screen:expect([=[ + | + ~ | + ~ | + {1:pluginA}{2: pluginB pluginC }| + :packadd pluginA^ | + ]=]) + feed('<Tab>') + screen:expect([=[ + | + ~ | + ~ | + {2:pluginA }{1:pluginB}{2: pluginC }| + :packadd pluginB^ | + ]=]) + feed('<Tab>') + screen:expect([=[ + | + ~ | + ~ | + {2:pluginA pluginB }{1:pluginC}{2: }| + :packadd pluginC^ | + ]=]) + feed('<Tab>') + screen:expect([=[ + | + ~ | + ~ | + {2:pluginA pluginB pluginC }| + :packadd ^ | + ]=]) + end) + + it('works for colorschemes', function() + source([[ + let colordirrun = &packpath . '/runtime/colors' + let colordirstart = &packpath . '/pack/mine/start/foo/colors' + let colordiropt = &packpath . '/pack/mine/opt/bar/colors' + call mkdir(colordirrun, 'p') + call mkdir(colordirstart, 'p') + call mkdir(colordiropt, 'p') + call writefile(['let g:found_one = 1'], colordirrun . '/one.vim') + call writefile(['let g:found_two = 1'], colordirstart . '/two.vim') + call writefile(['let g:found_three = 1'], colordiropt . '/three.vim') + exe 'set rtp=' . &packpath . '/runtime']]) + + feed(':colorscheme <Tab>') + screen:expect([=[ + | + ~ | + ~ | + {1:one}{2: three two }| + :colorscheme one^ | + ]=]) + feed('<Tab>') + screen:expect([=[ + | + ~ | + ~ | + {2:one }{1:three}{2: two }| + :colorscheme three^ | + ]=]) + feed('<Tab>') + screen:expect([=[ + | + ~ | + ~ | + {2:one three }{1:two}{2: }| + :colorscheme two^ | + ]=]) + feed('<Tab>') + screen:expect([=[ + | + ~ | + ~ | + {2:one three two }| + :colorscheme ^ | + ]=]) + end) + end) +end) 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 315b8ca682..df8f2625db 100644 --- a/test/functional/legacy/quickfix_spec.lua +++ b/test/functional/legacy/quickfix_spec.lua @@ -1,8 +1,10 @@ -- 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')) @@ -256,6 +258,25 @@ describe('helpgrep', function() \ 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) @@ -306,4 +327,16 @@ describe('helpgrep', function() 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 f2c907084e..11f371569d 100644 --- a/test/functional/legacy/set_spec.lua +++ b/test/functional/legacy/set_spec.lua @@ -1,6 +1,6 @@ -- 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 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/autochdir_spec.lua b/test/functional/options/autochdir_spec.lua new file mode 100644 index 0000000000..0e293761ad --- /dev/null +++ b/test/functional/options/autochdir_spec.lua @@ -0,0 +1,18 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear = helpers.clear +local eq = helpers.eq +local getcwd = helpers.funcs.getcwd + +describe("'autochdir'", function() + it('given on the shell gets processed properly', function() + local targetdir = 'test/functional/fixtures' + + -- By default 'autochdir' is off, thus getcwd() returns the repo root. + clear(targetdir..'/tty-test.c') + local rootdir = getcwd() + + -- With 'autochdir' on, we should get the directory of tty-test.c. + clear('--cmd', 'set autochdir', targetdir..'/tty-test.c') + eq(rootdir..'/'..targetdir, getcwd()) + end) +end) diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index d4c3267997..a36939b0bd 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -1,6 +1,6 @@ -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 eval, eq = helpers.eval, helpers.eq local execute = helpers.execute local function init_session(...) @@ -15,10 +15,6 @@ local function init_session(...) end describe('startup defaults', function() - before_each(function() - clear() - end) - describe(':filetype', function() local function expect_filetype(expected) local screen = Screen.new(48, 4) 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 06fdbef669..94dfa90ea8 100644 --- a/test/functional/provider/python_spec.lua +++ b/test/functional/provider/python_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 neq = helpers.neq diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua new file mode 100644 index 0000000000..7b0e17688d --- /dev/null +++ b/test/functional/provider/ruby_spec.lua @@ -0,0 +1,96 @@ +local helpers = require('test.functional.helpers')(after_each) + +local eq = helpers.eq +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 write_file = helpers.write_file +local curbufmeths = helpers.curbufmeths + +do + clear() + command('let g:prog = provider#ruby#Detect()') + local prog = meths.get_var('prog') + + if prog == '' then + pending( + "Cannot find the neovim RubyGem. Try :CheckHealth", + function() end) + return + end +end + +before_each(function() + clear() +end) + +describe('ruby feature test', function() + it('works', function() + eq(1, funcs.has('ruby')) + end) +end) + +describe(':ruby command', function() + it('evaluates ruby', function() + command('ruby VIM.command("let g:set_by_ruby = [100, 0]")') + eq({100, 0}, meths.get_var('set_by_ruby')) + end) + + it('supports nesting', function() + command([[ruby VIM.command('ruby VIM.command("let set_by_nested_ruby = 555")')]]) + eq(555, meths.get_var('set_by_nested_ruby')) + end) +end) + +describe(':rubyfile command', function() + it('evaluates a ruby file', function() + local fname = 'rubyfile.rb' + write_file(fname, 'VIM.command("let set_by_rubyfile = 123")') + command('rubyfile rubyfile.rb') + eq(123, meths.get_var('set_by_rubyfile')) + os.remove(fname) + end) +end) + +describe(':rubydo command', function() + it('exposes the $_ variable for modifying lines', function() + insert('abc\ndef\nghi\njkl') + expect([[ + abc + def + ghi + jkl]]) + + feed('ggjvj:rubydo $_.upcase!<CR>') + expect([[ + abc + DEF + GHI + jkl]]) + end) + + it('operates on all lines when not given a range', function() + insert('abc\ndef\nghi\njkl') + expect([[ + abc + def + ghi + jkl]]) + + feed(':rubydo $_.upcase!<CR>') + expect([[ + ABC + DEF + GHI + JKL]]) + end) + + it('does not modify the buffer if no changes are made', function() + command('normal :rubydo 42') + eq(false, curbufmeths.get_option('modified')) + 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 cefb603a7e..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 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 d89092ff27..458fa02fca 100644 --- a/test/functional/terminal/ex_terminal_spec.lua +++ b/test/functional/terminal/ex_terminal_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, wait, nvim = helpers.clear, helpers.wait, helpers.nvim local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq 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 97875c5147..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 @@ -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..e6586c7892 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 @@ -301,3 +301,72 @@ describe('tui focus event handling', function() ]]) end) end) + +-- These tests require `thelpers` because --headless/--embed +-- does not initialize the TUI. +describe("tui 't_Co' (terminal colors)", function() + local screen + local is_linux = (helpers.eval("system('uname') =~? 'linux'") == 1) + + local function assert_term_colors(term, colorterm, maxcolors) + helpers.clear({env={TERM=term}, args={}}) + -- This is ugly because :term/termopen() forces TERM=xterm-256color. + -- TODO: Revisit this after jobstart/termopen accept `env` dict. + screen = thelpers.screen_setup(0, string.format( + [=[['sh', '-c', 'TERM=%s %s %s -u NONE -i NONE --cmd "silent set noswapfile"']]=], + term, + (colorterm ~= nil and "COLORTERM="..colorterm or ""), + helpers.nvim_prog)) + + thelpers.feed_data(":echo &t_Co\n") + screen:expect(string.format([[ + {1: } | + ~ | + ~ | + ~ | + [No Name] | + %-3s | + -- TERMINAL -- | + ]], tostring(maxcolors and maxcolors or ""))) + end + + it("unknown TERM sets empty 't_Co'", function() + assert_term_colors("yet-another-term", nil, nil) + end) + + it("unknown TERM with COLORTERM=screen-256color uses 256 colors", function() + assert_term_colors("yet-another-term", "screen-256color", 256) + end) + + it("TERM=linux uses 8 colors", function() + if is_linux then + assert_term_colors("linux", nil, 8) + else + pending() + end + end) + + it("TERM=screen uses 8 colors", function() + if is_linux then + assert_term_colors("screen", nil, 8) + else + pending() + end + end) + + it("TERM=screen COLORTERM=screen-256color uses 256 colors", function() + assert_term_colors("screen", "screen-256color", 256) + end) + + it("TERM=yet-another-term COLORTERM=screen-256color uses 256 colors", function() + assert_term_colors("screen", "screen-256color", 256) + end) + + it("TERM=xterm uses 256 colors", function() + assert_term_colors("xterm", nil, 256) + end) + + it("TERM=xterm-256color uses 256 colors", function() + assert_term_colors("xterm-256color", nil, 256) + end) +end) 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 85fca4d7ca..6ef40fff62 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/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 os = require('os') local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert @@ -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') 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 993bbd5b0e..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 diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua new file mode 100644 index 0000000000..c7c8986527 --- /dev/null +++ b/test/functional/ui/output_spec.lua @@ -0,0 +1,39 @@ +local session = require('test.functional.helpers')(after_each) +local child_session = require('test.functional.terminal.helpers') + +describe("shell command :!", function() + local screen + before_each(function() + session.clear() + screen = child_session.screen_setup(0, '["'..session.nvim_prog.. + '", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]') + screen:expect([[ + {1: } | + ~ | + ~ | + ~ | + [No Name] | + | + -- TERMINAL -- | + ]]) + end) + + after_each(function() + screen:detach() + end) + + it("displays output even without LF/EOF. #4646 #4569 #3772", function() + -- NOTE: We use a child nvim (within a :term buffer) + -- to avoid triggering a UI flush. + child_session.feed_data(":!printf foo; sleep 200\n") + screen:expect([[ + ~ | + ~ | + [No Name] | + :!printf foo; sleep 200 | + | + foo | + -- TERMINAL -- | + ]]) + end) +end) diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 99b85caf10..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 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/functional/viml/lang_spec.lua b/test/functional/viml/lang_spec.lua new file mode 100644 index 0000000000..a27e18f695 --- /dev/null +++ b/test/functional/viml/lang_spec.lua @@ -0,0 +1,22 @@ +local helpers = require('test.functional.helpers')(after_each) +local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq +local execute, source = helpers.execute, helpers.source + +describe('viml', function() + before_each(clear) + + it('parses `<SID>` with turkish locale', function() + execute('lang ctype tr_TR.UTF-8') + if string.find(eval('v:errmsg'), '^E197: ') then + pending("Locale tr_TR.UTF-8 not supported") + return + end + source([[ + func! <sid>_dummy_function() + echo 1 + endfunc + au VimEnter * call <sid>_dummy_function() + ]]) + eq(nil, string.find(eval('v:errmsg'), '^E129')) + 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 857a5001f1..7e7eddb6fc 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 @@ -27,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 @@ -68,6 +75,8 @@ describe('fs function', function() io.open('unit-test-directory/test_2.file', 'w').close() lfs.link('test.file', 'unit-test-directory/test_link.file', true) + + lfs.link('non_existing_file.file', 'unit-test-directory/test_broken_link.file', true) -- Since the tests are executed, they are called by an executable. We use -- that executable for several asserts. absolute_executable = arg[0] @@ -81,6 +90,7 @@ describe('fs function', function() os.remove('unit-test-directory/test_2.file') os.remove('unit-test-directory/test_link.file') os.remove('unit-test-directory/test_hlink.file') + os.remove('unit-test-directory/test_broken_link.file') lfs.rmdir('unit-test-directory') end) @@ -150,11 +160,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 @@ -356,8 +366,8 @@ describe('fs function', function() end) describe('file operations', function() - local function os_file_exists(filename) - return fs.os_file_exists((to_cstr(filename))) + local function os_path_exists(filename) + return fs.os_path_exists((to_cstr(filename))) end local function os_rename(path, new_path) return fs.os_rename((to_cstr(path)), (to_cstr(new_path))) @@ -368,14 +378,67 @@ describe('fs function', function() 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() + describe('os_path_exists', function() it('returns false when given a non-existing file', function() - eq(false, (os_file_exists('non-existing-file'))) + eq(false, (os_path_exists('non-existing-file'))) end) it('returns true when given an existing file', function() - eq(true, (os_file_exists('unit-test-directory/test.file'))) + eq(true, (os_path_exists('unit-test-directory/test.file'))) + end) + + it('returns false when given a broken symlink', function() + eq(false, (os_path_exists('unit-test-directory/test_broken_link.file'))) + end) + + it('returns true when given a directory', function() + eq(true, (os_path_exists('unit-test-directory'))) end) end) @@ -385,8 +448,8 @@ describe('fs function', function() it('can rename file if destination file does not exist', function() eq(OK, (os_rename(test, not_exist))) - eq(false, (os_file_exists(test))) - eq(true, (os_file_exists(not_exist))) + eq(false, (os_path_exists(test))) + eq(true, (os_path_exists(not_exist))) eq(OK, (os_rename(not_exist, test))) -- restore test file end) @@ -402,8 +465,8 @@ describe('fs function', function() file:close() eq(OK, (os_rename(other, test))) - eq(false, (os_file_exists(other))) - eq(true, (os_file_exists(test))) + eq(false, (os_path_exists(other))) + eq(true, (os_path_exists(test))) file = io.open(test, 'r') eq('other', (file:read('*all'))) file:close() @@ -432,30 +495,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() @@ -463,24 +530,181 @@ 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('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('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) 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) diff --git a/test/unit/tempfile_spec.lua b/test/unit/tempfile_spec.lua index 7975d11aed..cf0d78b7a7 100644 --- a/test/unit/tempfile_spec.lua +++ b/test/unit/tempfile_spec.lua @@ -43,7 +43,7 @@ describe('tempfile related functions', function() it('generate name of non-existing file', function() local file = vim_tempname() assert.truthy(file) - assert.False(os.os_file_exists(file)) + assert.False(os.os_path_exists(file)) end) it('generate different names on each call', function() |