diff options
Diffstat (limited to 'test/functional/eval')
-rw-r--r-- | test/functional/eval/interrupt_spec.lua | 61 | ||||
-rw-r--r-- | test/functional/eval/match_functions_spec.lua | 94 | ||||
-rw-r--r-- | test/functional/eval/msgpack_functions_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/eval/null_spec.lua | 85 |
4 files changed, 203 insertions, 39 deletions
diff --git a/test/functional/eval/interrupt_spec.lua b/test/functional/eval/interrupt_spec.lua new file mode 100644 index 0000000000..7f4ca95317 --- /dev/null +++ b/test/functional/eval/interrupt_spec.lua @@ -0,0 +1,61 @@ +local helpers = require('test.functional.helpers')(after_each) + +local command = helpers.command +local meths = helpers.meths +local clear = helpers.clear +local sleep = helpers.sleep +local wait = helpers.wait +local feed = helpers.feed +local eq = helpers.eq + +local dur +local min_dur = 8 +local len = 131072 + +describe('List support code', function() + if not pending('does not actually allows interrupting with just got_int', function() end) then return end + -- The following tests are confirmed to work with os_breakcheck() just before + -- `if (got_int) {break;}` in tv_list_copy and list_join_inner() and not to + -- work without. + setup(function() + clear() + dur = 0 + while true do + command(([[ + let rt = reltime() + let bl = range(%u) + let dur = reltimestr(reltime(rt)) + ]]):format(len)) + dur = tonumber(meths.get_var('dur')) + if dur >= min_dur then + -- print(('Using len %u, dur %g'):format(len, dur)) + break + else + len = len * 2 + end + end + end) + it('allows interrupting copy', function() + feed(':let t_rt = reltime()<CR>:let t_bl = copy(bl)<CR>') + sleep(min_dur / 16 * 1000) + feed('<C-c>') + wait() + command('let t_dur = reltimestr(reltime(t_rt))') + local t_dur = tonumber(meths.get_var('t_dur')) + if t_dur >= dur / 8 then + eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8)) + end + end) + it('allows interrupting join', function() + feed(':let t_rt = reltime()<CR>:let t_j = join(bl)<CR>') + sleep(min_dur / 16 * 1000) + feed('<C-c>') + wait() + command('let t_dur = reltimestr(reltime(t_rt))') + local t_dur = tonumber(meths.get_var('t_dur')) + print(('t_dur: %g'):format(t_dur)) + if t_dur >= dur / 8 then + eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8)) + end + end) +end) diff --git a/test/functional/eval/match_functions_spec.lua b/test/functional/eval/match_functions_spec.lua index 3150d89f62..7989b22b5e 100644 --- a/test/functional/eval/match_functions_spec.lua +++ b/test/functional/eval/match_functions_spec.lua @@ -1,9 +1,11 @@ local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local eq = helpers.eq local clear = helpers.clear local funcs = helpers.funcs local command = helpers.command +local exc_exec = helpers.exc_exec before_each(clear) @@ -59,3 +61,95 @@ describe('matchadd()', function() }}, funcs.getmatches()) end) end) + +describe('matchaddpos()', function() + it('errors out on invalid input', function() + command('hi clear PreProc') + eq('Vim(let):E5030: Empty list at position 0', + exc_exec('let val = matchaddpos("PreProc", [[]])')) + eq('Vim(let):E5030: Empty list at position 1', + exc_exec('let val = matchaddpos("PreProc", [1, v:_null_list])')) + eq('Vim(let):E5031: List or number required at position 1', + exc_exec('let val = matchaddpos("PreProc", [1, v:_null_dict])')) + end) + it('works with 0 lnum', function() + command('hi clear PreProc') + eq(4, funcs.matchaddpos('PreProc', {1}, 3, 4)) + eq({{ + group='PreProc', + pos1 = {1}, + priority=3, + id=4, + }}, funcs.getmatches()) + funcs.matchdelete(4) + eq(4, funcs.matchaddpos('PreProc', {{0}, 1}, 3, 4)) + eq({{ + group='PreProc', + pos1 = {1}, + priority=3, + id=4, + }}, funcs.getmatches()) + funcs.matchdelete(4) + eq(4, funcs.matchaddpos('PreProc', {0, 1}, 3, 4)) + eq({{ + group='PreProc', + pos1 = {1}, + priority=3, + id=4, + }}, funcs.getmatches()) + end) + it('works with negative numbers', function() + command('hi clear PreProc') + eq(4, funcs.matchaddpos('PreProc', {-10, 1}, 3, 4)) + eq({{ + group='PreProc', + pos1 = {1}, + priority=3, + id=4, + }}, funcs.getmatches()) + funcs.matchdelete(4) + eq(4, funcs.matchaddpos('PreProc', {{-10}, 1}, 3, 4)) + eq({{ + group='PreProc', + pos1 = {1}, + priority=3, + id=4, + }}, funcs.getmatches()) + funcs.matchdelete(4) + eq(4, funcs.matchaddpos('PreProc', {{2, -1}, 1}, 3, 4)) + eq({{ + group='PreProc', + pos1 = {1}, + priority=3, + id=4, + }}, funcs.getmatches()) + funcs.matchdelete(4) + eq(4, funcs.matchaddpos('PreProc', {{2, 0, -1}, 1}, 3, 4)) + eq({{ + group='PreProc', + pos1 = {1}, + priority=3, + id=4, + }}, funcs.getmatches()) + end) + it('works with zero length', function() + local screen = Screen.new(40, 5) + screen:attach() + funcs.setline(1, 'abcdef') + command('hi PreProc guifg=Red') + eq(4, funcs.matchaddpos('PreProc', {{1, 2, 0}}, 3, 4)) + eq({{ + group='PreProc', + pos1 = {1, 2, 0}, + priority=3, + id=4, + }}, funcs.getmatches()) + screen:expect([[ + ^a{1:b}cdef | + {2:~ }| + {2:~ }| + {2:~ }| + | + ]], {[1] = {foreground = Screen.colors.Red}, [2] = {bold = true, foreground = Screen.colors.Blue1}}) + end) +end) diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/eval/msgpack_functions_spec.lua index b241635dfe..258d6ee059 100644 --- a/test/functional/eval/msgpack_functions_spec.lua +++ b/test/functional/eval/msgpack_functions_spec.lua @@ -628,7 +628,7 @@ describe('msgpackdump() function', function() it('fails to dump a recursive (key) map in a special dict', function() command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}') command('call add(todump._VAL, [todump, 0])') - eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 1', + eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0', exc_exec('call msgpackdump([todump])')) end) diff --git a/test/functional/eval/null_spec.lua b/test/functional/eval/null_spec.lua index b67158eb22..afe999e1fa 100644 --- a/test/functional/eval/null_spec.lua +++ b/test/functional/eval/null_spec.lua @@ -41,35 +41,9 @@ describe('NULL', function() end describe('list', function() -- Incorrect behaviour - - -- FIXME add() should not return 1 at all - null_expr_test('does not crash add()', 'add(L, 0)', 0, 1) - null_expr_test('does not crash extend()', 'extend(L, [1])', 'E742: Cannot change value of extend() argument', 0) - null_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, {1}) - -- FIXME should be accepted by inputlist() - null_expr_test('is accepted as an empty list by inputlist()', - '[feedkeys("\\n"), inputlist(L)]', 'E686: Argument of inputlist() must be a List', {0, 0}) - -- FIXME should be accepted by writefile(), return {0, {}} - null_expr_test('is accepted as an empty list by writefile()', - ('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname), - 'E484: Can\'t open file ' .. tmpfname, {0, {}}) - -- FIXME should give error message - null_expr_test('does not crash remove()', 'remove(L, 0)', 0, 0) - -- FIXME should return 0 - null_expr_test('is accepted by setqflist()', 'setqflist(L)', 0, -1) - -- FIXME should return 0 - null_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, -1) - -- FIXME should return 0 - null_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, -1) - -- FIXME should return empty list or error out - null_expr_test('is accepted by sort()', 'sort(L)', 0, 0) - -- FIXME Should return 1 - null_expr_test('is accepted by sort()', 'sort(L) is L', 0, 0) - -- FIXME should not error out - null_test('is accepted by :cexpr', 'cexpr L', 'Vim(cexpr):E777: String or List expected') - -- FIXME should not error out - null_test('is accepted by :lexpr', 'lexpr L', 'Vim(lexpr):E777: String or List expected') - null_test('is accepted by :for', 'for x in L|throw x|endfor', 0) + -- FIXME Should error out with different message + null_test('makes :unlet act as if it is not a list', ':unlet L[0]', + 'Vim(unlet):E689: Can only index a List or Dictionary') -- Subjectable behaviour @@ -77,20 +51,19 @@ describe('NULL', function() null_expr_test('is equal to empty list', 'L == []', 0, 0) -- FIXME Should return 1 null_expr_test('is equal to empty list (reverse order)', '[] == L', 0, 0) - -- FIXME Should return 1 - null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0) - - -- Crashes - - -- null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0) - -- null_expr_test('does not crash setline', 'setline(1, L)', 0, 0) - -- null_expr_test('does not crash system()', 'system("cat", L)', 0, '') - -- null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {}) -- Correct behaviour + null_expr_test('can be indexed with error message for empty list', 'L[0]', + 'E684: list index out of range: 0\nE15: Invalid expression: L[0]', nil) + null_expr_test('can be splice-indexed', 'L[:]', 0, {}) + null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0) + null_test('is accepted by :for', 'for x in L|throw x|endfor', 0) null_expr_test('does not crash append()', 'append(1, L)', 0, 0, function() eq({''}, curbufmeths.get_lines(0, -1, false)) end) + null_expr_test('does not crash setline()', 'setline(1, L)', 0, 0, function() + eq({''}, curbufmeths.get_lines(0, -1, false)) + end) null_expr_test('is identical to itself', 'L is L', 0, 1) null_expr_test('can be sliced', 'L[:]', 0, {}) null_expr_test('can be copied', 'copy(L)', 0, {}) @@ -122,6 +95,42 @@ describe('NULL', function() null_expr_test('counts correctly', 'count([L], L)', 0, 1) null_expr_test('makes map() return v:_null_list', 'map(L, "v:val") is# L', 0, 1) null_expr_test('makes filter() return v:_null_list', 'filter(L, "1") is# L', 0, 1) + null_test('is treated by :let as empty list', ':let [l] = L', 'Vim(let):E688: More targets than List items') + null_expr_test('is accepted as an empty list by inputlist()', '[feedkeys("\\n"), inputlist(L)]', + 'Type number and <Enter> or click with mouse (empty cancels): ', {0, 0}) + null_expr_test('is accepted as an empty list by writefile()', + ('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname), + 0, {0, {}}) + null_expr_test('makes add() error out', 'add(L, 0)', + 'E742: Cannot change value of add() argument', 1) + null_expr_test('makes insert() error out', 'insert(L, 1)', + 'E742: Cannot change value of insert() argument', 0) + null_expr_test('does not crash remove()', 'remove(L, 0)', + 'E742: Cannot change value of remove() argument', 0) + null_expr_test('makes reverse() error out', 'reverse(L)', + 'E742: Cannot change value of reverse() argument', 0) + null_expr_test('makes sort() error out', 'sort(L)', + 'E742: Cannot change value of sort() argument', 0) + null_expr_test('makes uniq() error out', 'uniq(L)', + 'E742: Cannot change value of uniq() argument', 0) + null_expr_test('does not crash extend()', 'extend(L, [1])', 'E742: Cannot change value of extend() argument', 0) + null_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, {1}) + null_expr_test('makes join() return empty string', 'join(L, "")', 0, '') + null_expr_test('makes msgpackdump() return empty list', 'msgpackdump(L)', 0, {}) + null_expr_test('does not crash system()', 'system("cat", L)', 0, '') + null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0) + null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {}) + null_test('does not make Neovim crash when v:oldfiles gets assigned to that', ':let v:oldfiles = L|oldfiles', 0) + null_expr_test('does not make complete() crash or error out', + 'execute(":normal i\\<C-r>=complete(1, L)[-1]\\n")', + '', '\n', function() + eq({''}, curbufmeths.get_lines(0, -1, false)) + end) + null_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, 0) + null_expr_test('is accepted by setqflist()', 'setqflist(L)', 0, 0) + null_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, 0) + null_test('is accepted by :cexpr', 'cexpr L', 0) + null_test('is accepted by :lexpr', 'lexpr L', 0) end) describe('dict', function() it('does not crash when indexing NULL dict', function() |