diff options
Diffstat (limited to 'test/functional')
-rw-r--r-- | test/functional/eval/json_functions_spec.lua | 6 | ||||
-rw-r--r-- | test/functional/eval/msgpack_functions_spec.lua | 19 | ||||
-rw-r--r-- | test/functional/eval/string_spec.lua | 92 | ||||
-rw-r--r-- | test/functional/ex_cmds/ctrl_c_spec.lua | 62 | ||||
-rw-r--r-- | test/functional/ex_cmds/global_spec.lua | 74 | ||||
-rw-r--r-- | test/functional/helpers.lua | 25 | ||||
-rw-r--r-- | test/functional/plugin/msgpack_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/plugin/shada_spec.lua | 37 | ||||
-rw-r--r-- | test/functional/ui/mouse_spec.lua | 14 |
9 files changed, 238 insertions, 93 deletions
diff --git a/test/functional/eval/json_functions_spec.lua b/test/functional/eval/json_functions_spec.lua index 4a6758019b..fc0a19bdfa 100644 --- a/test/functional/eval/json_functions_spec.lua +++ b/test/functional/eval/json_functions_spec.lua @@ -672,6 +672,12 @@ describe('json_encode() function', function() exc_exec('call json_encode(function("tr"))')) end) + it('fails to dump a partial', function() + execute('function T() dict\nendfunction') + eq('Vim(call):E474: Error while dumping encode_tv2json() argument, itself: attempt to dump function reference', + exc_exec('call json_encode(function("T", [1, 2], {}))')) + end) + it('fails to dump a function reference in a list', function() eq('Vim(call):E474: Error while dumping encode_tv2json() argument, index 0: attempt to dump function reference', exc_exec('call json_encode([function("tr")])')) diff --git a/test/functional/eval/msgpack_functions_spec.lua b/test/functional/eval/msgpack_functions_spec.lua index 3fb54c2ee7..44c01d2226 100644 --- a/test/functional/eval/msgpack_functions_spec.lua +++ b/test/functional/eval/msgpack_functions_spec.lua @@ -493,6 +493,12 @@ describe('msgpackparse() function', function() exc_exec('call msgpackparse(function("tr"))')) end) + it('fails to parse a partial', function() + execute('function T() dict\nendfunction') + eq('Vim(call):E686: Argument of msgpackparse() must be a List', + exc_exec('call msgpackparse(function("T", [1, 2], {}))')) + end) + it('fails to parse a float', function() eq('Vim(call):E686: Argument of msgpackparse() must be a List', exc_exec('call msgpackparse(0.0)')) @@ -570,6 +576,13 @@ describe('msgpackdump() function', function() exc_exec('call msgpackdump([Todump])')) end) + it('fails to dump a partial', function() + execute('function T() dict\nendfunction') + execute('let Todump = function("T", [1, 2], {})') + eq('Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference', + exc_exec('call msgpackdump([Todump])')) + end) + it('fails to dump a function reference in a list', function() execute('let todump = [function("tr")]') eq('Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, index 0: attempt to dump function reference', @@ -675,6 +688,12 @@ describe('msgpackdump() function', function() exc_exec('call msgpackdump(function("tr"))')) end) + it('fails to dump a partial', function() + execute('function T() dict\nendfunction') + eq('Vim(call):E686: Argument of msgpackdump() must be a List', + exc_exec('call msgpackdump(function("T", [1, 2], {}))')) + end) + it('fails to dump a float', function() eq('Vim(call):E686: Argument of msgpackdump() must be a List', exc_exec('call msgpackdump(0.0)')) diff --git a/test/functional/eval/string_spec.lua b/test/functional/eval/string_spec.lua index 9e2dc4e111..f6279e85e8 100644 --- a/test/functional/eval/string_spec.lua +++ b/test/functional/eval/string_spec.lua @@ -9,6 +9,8 @@ local redir_exec = helpers.redir_exec local funcs = helpers.funcs local write_file = helpers.write_file local NIL = helpers.NIL +local source = helpers.source +local dedent = helpers.dedent describe('string() function', function() before_each(clear) @@ -110,10 +112,10 @@ describe('string() function', function() function Test1() endfunction - function s:Test2() + function s:Test2() dict endfunction - function g:Test3() + function g:Test3() dict endfunction let g:Test2_f = function('s:Test2') @@ -137,6 +139,85 @@ describe('string() function', function() it('dumps references to script functions', function() eq('function(\'<SNR>1_Test2\')', eval('string(Test2_f)')) end) + + it('dumps partials with self referencing a partial', function() + source([[ + function TestDict() dict + endfunction + let d = {} + let TestDictRef = function('TestDict', d) + let d.tdr = TestDictRef + ]]) + eq("\nE724: unable to correctly dump variable with self-referencing container\nfunction('TestDict', {'tdr': function('TestDict', {E724@1})})", + redir_exec('echo string(d.tdr)')) + end) + + it('dumps automatically created partials', function() + eq('function(\'<SNR>1_Test2\', {\'f\': function(\'<SNR>1_Test2\')})', + eval('string({"f": Test2_f}.f)')) + eq('function(\'<SNR>1_Test2\', [1], {\'f\': function(\'<SNR>1_Test2\', [1])})', + eval('string({"f": function(Test2_f, [1])}.f)')) + end) + + it('dumps manually created partials', function() + eq('function(\'Test3\', [1, 2], {})', + eval('string(function("Test3", [1, 2], {}))')) + eq('function(\'Test3\', {})', + eval('string(function("Test3", {}))')) + eq('function(\'Test3\', [1, 2])', + eval('string(function("Test3", [1, 2]))')) + end) + + it('does not crash or halt when dumping partials with reference cycles in self', + function() + meths.set_var('d', {v=true}) + eq(dedent([[ + + E724: unable to correctly dump variable with self-referencing container + {'p': function('<SNR>1_Test2', {E724@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]]), + redir_exec('echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))')) + end) + + it('does not show errors when dumping partials referencing the same dictionary', + function() + command('let d = {}') + -- Regression for “eval/typval_encode: Dump empty dictionary before + -- checking for refcycle”, results in error. + eq('[function(\'tr\', {}), function(\'tr\', {})]', eval('string([function("tr", d), function("tr", d)])')) + -- Regression for “eval: Work with reference cycles in partials (self) + -- properly”, results in crash. + eval('extend(d, {"a": 1})') + eq('[function(\'tr\', {\'a\': 1}), function(\'tr\', {\'a\': 1})]', eval('string([function("tr", d), function("tr", d)])')) + end) + + it('does not crash or halt when dumping partials with reference cycles in arguments', + function() + meths.set_var('l', {}) + eval('add(l, l)') + -- Regression: the below line used to crash (add returns original list and + -- there was error in dumping partials). Tested explicitly in + -- test/unit/api/private_helpers_spec.lua. + eval('add(l, function("Test1", l))') + eq(dedent([=[ + + E724: unable to correctly dump variable with self-referencing container + function('Test1', [[{E724@2}, function('Test1', [{E724@2}])], function('Test1', [[{E724@4}, function('Test1', [{E724@4}])]])])]=]), + redir_exec('echo string(function("Test1", l))')) + end) + + it('does not crash or halt when dumping partials with reference cycles in self and arguments', + function() + meths.set_var('d', {v=true}) + meths.set_var('l', {}) + eval('add(l, l)') + eval('add(l, function("Test1", l))') + eval('add(l, function("Test1", d))') + eq(dedent([=[ + + E724: unable to correctly dump variable with self-referencing container + {'p': function('<SNR>1_Test2', [[{E724@3}, function('Test1', [{E724@3}]), function('Test1', {E724@0})], function('Test1', [[{E724@5}, function('Test1', [{E724@5}]), function('Test1', {E724@0})]]), function('Test1', {E724@0})], {E724@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]=]), + redir_exec('echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))')) + end) end) describe('used to represent lists', function() @@ -174,6 +255,13 @@ describe('string() function', function() eq('{}', eval('string({})')) end) + it('dumps list with two same empty dictionaries, also in partials', function() + command('let d = {}') + eq('[{}, {}]', eval('string([d, d])')) + eq('[function(\'tr\', {}), {}]', eval('string([function("tr", d), d])')) + eq('[{}, function(\'tr\', {})]', eval('string([d, function("tr", d)])')) + end) + it('dumps non-empty dictionary', function() eq('{\'t\'\'est\': 1}', funcs.string({['t\'est']=1})) end) diff --git a/test/functional/ex_cmds/ctrl_c_spec.lua b/test/functional/ex_cmds/ctrl_c_spec.lua new file mode 100644 index 0000000000..b0acb02000 --- /dev/null +++ b/test/functional/ex_cmds/ctrl_c_spec.lua @@ -0,0 +1,62 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local clear, feed, source = helpers.clear, helpers.feed, helpers.source +local execute = helpers.execute + +if helpers.pending_win32(pending) then return end + +describe("CTRL-C (mapped)", function() + before_each(function() + clear() + end) + + it("interrupts :global", function() + if helpers.skip_fragile(pending, + (os.getenv("TRAVIS") and os.getenv("CLANG_SANITIZER") == "ASAN_UBSAN")) + then + return + end + + source([[ + set nomore nohlsearch undolevels=-1 + nnoremap <C-C> <NOP> + ]]) + + execute("silent edit! test/functional/fixtures/bigfile.txt") + local screen = Screen.new(52, 6) + screen:attach() + screen:set_default_attr_ids({ + [0] = {foreground = Screen.colors.White, + background = Screen.colors.Red}, + [1] = {bold = true, + foreground = Screen.colors.SeaGreen} + }) + + screen:expect([[ + ^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; | + 0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; | + 0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; | + 0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; | + 0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSION;;;;| + | + ]]) + + local function test_ctrl_c(ms) + feed(":global/^/p<CR>") + helpers.sleep(ms) + feed("<C-C>") + screen:expect([[Interrupt]], nil, nil, nil, true) + end + + -- The test is time-sensitive. Try different sleep values. + local ms_values = {1, 10, 100} + for i, ms in ipairs(ms_values) do + if i < #ms_values then + local status, _ = pcall(test_ctrl_c, ms) + if status then break end + else -- Call the last attempt directly. + test_ctrl_c(ms) + end + end + end) +end) diff --git a/test/functional/ex_cmds/global_spec.lua b/test/functional/ex_cmds/global_spec.lua deleted file mode 100644 index 81a0ef3248..0000000000 --- a/test/functional/ex_cmds/global_spec.lua +++ /dev/null @@ -1,74 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) -local Screen = require('test.functional.ui.screen') -local clear, feed, source = helpers.clear, helpers.feed, helpers.source - -if helpers.pending_win32(pending) then return end - -describe(':global', function() - before_each(function() - clear() - end) - - it('is interrupted by mapped CTRL-C', function() - if os.getenv("TRAVIS") and os.getenv("CLANG_SANITIZER") == "ASAN_UBSAN" then - -- XXX: ASAN_UBSAN is too slow to react to the CTRL-C. - pending("", function() end) - return - end - - source([[ - set nomore - set undolevels=-1 - nnoremap <C-C> <NOP> - for i in range(0, 99999) - put ='XXX' - endfor - put ='ZZZ' - 1 - .delete - ]]) - - local screen = Screen.new(52, 6) - screen:attach() - screen:set_default_attr_ids({ - [0] = {foreground = Screen.colors.White, - background = Screen.colors.Red}, - [1] = {bold = true, - foreground = Screen.colors.SeaGreen} - }) - - screen:expect([[ - ^XXX | - XXX | - XXX | - XXX | - XXX | - | - ]]) - - local function test_ctrl_c(ms) - feed(":global/^/p<CR>") - helpers.sleep(ms) - feed("<C-C>") - screen:expect([[ - XXX | - XXX | - XXX | - XXX | - {0:Interrupted} | - Interrupt: {1:Press ENTER or type command to continue}^ | - ]]) - end - - -- The test is time-sensitive. Try with different sleep values. - local ms_values = {10, 50, 100} - for i, ms in ipairs(ms_values) do - if i < #ms_values then - local status, _ = pcall(test_ctrl_c, ms) - if status then break end - else -- Call the last attempt directly. - test_ctrl_c(ms) - end - end - end) -end) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index ed153182ca..5eec3afe65 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -492,12 +492,12 @@ local function create_callindex(func) end -- Helper to skip tests. Returns true in Windows systems. --- pending_func is pending() from busted -local function pending_win32(pending_func) +-- pending_fn is pending() from busted +local function pending_win32(pending_fn) clear() if uname() == 'Windows' then - if pending_func ~= nil then - pending_func('FIXME: Windows', function() end) + if pending_fn ~= nil then + pending_fn('FIXME: Windows', function() end) end return true else @@ -505,6 +505,22 @@ local function pending_win32(pending_func) end end +-- Calls pending() and returns `true` if the system is too slow to +-- run fragile or expensive tests. Else returns `false`. +local function skip_fragile(pending_fn, cond) + if pending_fn == nil or type(pending_fn) ~= type(function()end) then + error("invalid pending_fn") + end + if cond then + pending_fn("skipped (test is fragile on this system)", function() end) + return true + elseif os.getenv("TEST_SKIP_FRAGILE") then + pending_fn("skipped (TEST_SKIP_FRAGILE)", function() end) + return true + end + return false +end + local funcs = create_callindex(nvim_call) local meths = create_callindex(nvim) local uimeths = create_callindex(ui) @@ -573,6 +589,7 @@ return function(after_each) curwinmeths = curwinmeths, curtabmeths = curtabmeths, pending_win32 = pending_win32, + skip_fragile = skip_fragile, tmpname = tmpname, NIL = mpack.NIL, } diff --git a/test/functional/plugin/msgpack_spec.lua b/test/functional/plugin/msgpack_spec.lua index c8da8e8f6c..5ba19708cf 100644 --- a/test/functional/plugin/msgpack_spec.lua +++ b/test/functional/plugin/msgpack_spec.lua @@ -652,6 +652,8 @@ describe('In autoload/msgpack.vim', function() eval_eq('integer', ('a'):byte(), '\'a\'') eval_eq('integer', 0xAB, '\'«\'') + eval_eq('integer', 0, '\'\\0\'') + eval_eq('integer', 10246567, '\'\\10246567\'') end) it('correctly loads constants', function() diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua index b1209a22e9..b543037ae2 100644 --- a/test/functional/plugin/shada_spec.lua +++ b/test/functional/plugin/shada_spec.lua @@ -609,6 +609,18 @@ describe('In autoload/shada.vim', function() 'abc', -1, ]}] ]]):gsub('\n', '')) + -- Regression: NUL separator must be properly supported + sd2strings_eq({ + 'History entry with timestamp ' .. epoch .. ':', + ' @ Description_ Value', + ' - history type SEARCH', + ' - contents ""', + ' - separator \'\\0\'', + }, ([[ [{'type': 4, 'timestamp': 0, 'data': [ + 1, + '', + 0x0 + ]}] ]]):gsub('\n', '')) end) it('works with register items', function() @@ -837,7 +849,7 @@ describe('In autoload/shada.vim', function() sd2strings_eq({ 'Global mark with timestamp ' .. epoch .. ':', ' % Key Description Value', - ' + n name 20', + ' + n name \'\\20\'', ' + f file name "foo"', ' # Value is negative', ' + l line number -10', @@ -852,7 +864,18 @@ describe('In autoload/shada.vim', function() sd2strings_eq({ 'Global mark with timestamp ' .. epoch .. ':', ' % Key Description Value', - ' + n name 20', + ' + n name 128', + ' + f file name "foo"', + ' + l line number 1', + ' + c column 0', + }, ([[ [{'type': 7, 'timestamp': 0, 'data': { + 'n': 128, + 'f': 'foo', + }}] ]]):gsub('\n', '')) + sd2strings_eq({ + 'Global mark with timestamp ' .. epoch .. ':', + ' % Key Description Value', + ' + n name \'\\20\'', ' + f file name "foo"', ' # Expected integer', ' + l line number "FOO"', @@ -1123,7 +1146,7 @@ describe('In autoload/shada.vim', function() 'Local mark with timestamp ' .. epoch .. ':', ' % Key Description Value', ' + f file name "foo"', - ' + n name 20', + ' + n name \'\\20\'', ' # Value is negative', ' + l line number -10', ' # Value is negative', @@ -1138,7 +1161,7 @@ describe('In autoload/shada.vim', function() 'Local mark with timestamp ' .. epoch .. ':', ' % Key Description Value', ' + f file name "foo"', - ' + n name 20', + ' + n name \'\\20\'', ' # Expected integer', ' + l line number "FOO"', ' # Expected integer', @@ -1932,13 +1955,13 @@ describe('In autoload/shada.vim', function() 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', ' # Expected binary string', - ' + f file name 10', + ' + f file name \'\\10\'', ' + l line number 1', ' + c column 0', '', ' % Key Description Value', ' # Expected binary string', - ' + f file name 20', + ' + f file name \'\\20\'', ' + l line number 1', ' + c column 0', }) @@ -1948,7 +1971,7 @@ describe('In autoload/shada.vim', function() 'Buffer list with timestamp ' .. epoch .. ':', ' % Key Description Value', ' # Expected binary string', - ' + f file name 10', + ' + f file name \'\\10\'', ' + l line number 1', ' + c column 0', '', diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index b729b0db08..17d949825a 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -153,9 +153,10 @@ describe('Mouse input', function() end) it('in tabline to the left moves tab left', function() - if os.getenv("TRAVIS") and (helpers.os_name() == "osx" - or os.getenv("CLANG_SANITIZER") == "ASAN_UBSAN") then - pending("[Fails on Travis macOS, ASAN_UBSAN. #4874]", function() end) + if helpers.skip_fragile(pending, + os.getenv("TRAVIS") and (helpers.os_name() == "osx" + or os.getenv("CLANG_SANITIZER") == "ASAN_UBSAN")) -- #4874 + then return end @@ -257,9 +258,10 @@ describe('Mouse input', function() end) it('out of tabline to the left moves tab left', function() - if os.getenv("TRAVIS") and (helpers.os_name() == "osx" - or os.getenv("CLANG_SANITIZER") == "ASAN_UBSAN") then - pending("[Fails on Travis macOS, ASAN_UBSAN. #4874]", function() end) + if helpers.skip_fragile(pending, + os.getenv("TRAVIS") and (helpers.os_name() == "osx" + or os.getenv("CLANG_SANITIZER") == "ASAN_UBSAN")) -- #4874 + then return end |