diff options
Diffstat (limited to 'test/functional/ex_cmds/echo_spec.lua')
-rw-r--r-- | test/functional/ex_cmds/echo_spec.lua | 224 |
1 files changed, 120 insertions, 104 deletions
diff --git a/test/functional/ex_cmds/echo_spec.lua b/test/functional/ex_cmds/echo_spec.lua index a6be04138b..e9176a6204 100644 --- a/test/functional/ex_cmds/echo_spec.lua +++ b/test/functional/ex_cmds/echo_spec.lua @@ -1,11 +1,11 @@ local helpers = require('test.functional.helpers')(after_each) local eq = helpers.eq -local NIL = helpers.NIL +local NIL = vim.NIL local eval = helpers.eval local clear = helpers.clear -local meths = helpers.meths -local funcs = helpers.funcs +local api = helpers.api +local fn = helpers.fn local source = helpers.source local dedent = helpers.dedent local command = helpers.command @@ -14,15 +14,15 @@ local exec_capture = helpers.exec_capture local matches = helpers.matches describe(':echo :echon :echomsg :echoerr', function() - local fn_tbl = {'String', 'StringN', 'StringMsg', 'StringErr'} + local fn_tbl = { 'String', 'StringN', 'StringMsg', 'StringErr' } local function assert_same_echo_dump(expected, input, use_eval) - for _,v in pairs(fn_tbl) do - eq(expected, use_eval and eval(v..'('..input..')') or funcs[v](input)) + for _, v in pairs(fn_tbl) do + eq(expected, use_eval and eval(v .. '(' .. input .. ')') or fn[v](input)) end end local function assert_matches_echo_dump(expected, input, use_eval) - for _,v in pairs(fn_tbl) do - matches(expected, use_eval and eval(v..'('..input..')') or funcs[v](input)) + for _, v in pairs(fn_tbl) do + matches(expected, use_eval and eval(v .. '(' .. input .. ')') or fn[v](input)) end end @@ -68,31 +68,29 @@ describe(':echo :echon :echomsg :echoerr', function() eq('v:true', eval('String(v:true)')) eq('v:false', eval('String(v:false)')) eq('v:null', eval('String(v:null)')) - eq('v:true', funcs.String(true)) - eq('v:false', funcs.String(false)) - eq('v:null', funcs.String(NIL)) + eq('v:true', fn.String(true)) + eq('v:false', fn.String(false)) + eq('v:null', fn.String(NIL)) eq('v:true', eval('StringMsg(v:true)')) eq('v:false', eval('StringMsg(v:false)')) eq('v:null', eval('StringMsg(v:null)')) - eq('v:true', funcs.StringMsg(true)) - eq('v:false', funcs.StringMsg(false)) - eq('v:null', funcs.StringMsg(NIL)) + eq('v:true', fn.StringMsg(true)) + eq('v:false', fn.StringMsg(false)) + eq('v:null', fn.StringMsg(NIL)) eq('v:true', eval('StringErr(v:true)')) eq('v:false', eval('StringErr(v:false)')) eq('v:null', eval('StringErr(v:null)')) - eq('v:true', funcs.StringErr(true)) - eq('v:false', funcs.StringErr(false)) - eq('v:null', funcs.StringErr(NIL)) + eq('v:true', fn.StringErr(true)) + eq('v:false', fn.StringErr(false)) + eq('v:null', fn.StringErr(NIL)) end) - it('dumps values with at most six digits after the decimal point', - function() + it('dumps values with at most six digits after the decimal point', function() assert_same_echo_dump('1.234568e-20', 1.23456789123456789123456789e-020) assert_same_echo_dump('1.234568', 1.23456789123456789123456789) end) - it('dumps values with at most seven digits before the decimal point', - function() + it('dumps values with at most seven digits before the decimal point', function() assert_same_echo_dump('1234567.891235', 1234567.89123456789123456789) assert_same_echo_dump('1.234568e7', 12345678.9123456789123456789) end) @@ -115,8 +113,8 @@ describe(':echo :echon :echomsg :echoerr', function() end) it('dumps large values', function() - assert_same_echo_dump('2147483647', 2^31-1) - assert_same_echo_dump('-2147483648', -2^31) + assert_same_echo_dump('2147483647', 2 ^ 31 - 1) + assert_same_echo_dump('-2147483648', -2 ^ 31) end) end) @@ -198,75 +196,95 @@ describe(':echo :echon :echomsg :echoerr', function() let TestDictRef = function('TestDict', d) let d.tdr = TestDictRef ]]) - eq(dedent([[ + eq( + dedent([[ function('TestDict', {'tdr': function('TestDict', {...@1})})]]), - exec_capture('echo String(d.tdr)')) + exec_capture('echo String(d.tdr)') + ) end) it('dumps automatically created partials', function() assert_same_echo_dump( "function('<SNR>1_Test2', {'f': function('<SNR>1_Test2')})", '{"f": Test2_f}.f', - true) + true + ) assert_same_echo_dump( "function('<SNR>1_Test2', [1], {'f': function('<SNR>1_Test2', [1])})", '{"f": function(Test2_f, [1])}.f', - true) + true + ) end) it('dumps manually created partials', function() - assert_same_echo_dump("function('Test3', [1, 2], {})", - "function('Test3', [1, 2], {})", true) - assert_same_echo_dump("function('Test3', [1, 2])", - "function('Test3', [1, 2])", true) - assert_same_echo_dump("function('Test3', {})", - "function('Test3', {})", true) + assert_same_echo_dump("function('Test3', [1, 2], {})", "function('Test3', [1, 2], {})", true) + assert_same_echo_dump("function('Test3', [1, 2])", "function('Test3', [1, 2])", true) + assert_same_echo_dump("function('Test3', {})", "function('Test3', {})", true) end) - it('does not crash or halt when dumping partials with reference cycles in self', - function() - meths.set_var('d', {v=true}) - eq(dedent([[ - {'p': function('<SNR>1_Test2', {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]]), - exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))')) + it('does not crash or halt when dumping partials with reference cycles in self', function() + api.nvim_set_var('d', { v = true }) + eq( + dedent( + [[ + {'p': function('<SNR>1_Test2', {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]] + ), + exec_capture('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() + 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)])')) + 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)])')) + 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', {}) + it('does not crash or halt when dumping partials with reference cycles in arguments', function() + api.nvim_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([=[ - function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=]), - exec_capture('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([=[ - {'p': function('<SNR>1_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]=]), - exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))')) - end) + eq( + dedent( + [=[ + function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=] + ), + exec_capture('echo String(function("Test1", l))') + ) + end) + + it( + 'does not crash or halt when dumping partials with reference cycles in self and arguments', + function() + api.nvim_set_var('d', { v = true }) + api.nvim_set_var('l', {}) + eval('add(l, l)') + eval('add(l, function("Test1", l))') + eval('add(l, function("Test1", d))') + eq( + dedent( + [=[ + {'p': function('<SNR>1_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]=] + ), + exec_capture( + 'echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))' + ) + ) + end + ) end) describe('used to represent lists', function() @@ -275,25 +293,25 @@ describe(':echo :echon :echomsg :echoerr', function() end) it('dumps non-empty list', function() - assert_same_echo_dump('[1, 2]', {1,2}) + assert_same_echo_dump('[1, 2]', { 1, 2 }) end) it('dumps nested lists', function() - assert_same_echo_dump('[[[[[]]]]]', {{{{{}}}}}) + assert_same_echo_dump('[[[[[]]]]]', { { { { {} } } } }) end) it('dumps nested non-empty lists', function() - assert_same_echo_dump('[1, [[3, [[5], 4]], 2]]', {1, {{3, {{5}, 4}}, 2}}) + assert_same_echo_dump('[1, [[3, [[5], 4]], 2]]', { 1, { { 3, { { 5 }, 4 } }, 2 } }) end) it('does not error when dumping recursive lists', function() - meths.set_var('l', {}) + api.nvim_set_var('l', {}) eval('add(l, l)') eq(0, exc_exec('echo String(l)')) end) it('dumps recursive lists without error', function() - meths.set_var('l', {}) + api.nvim_set_var('l', {}) eval('add(l, l)') eq('[[...@0]]', exec_capture('echo String(l)')) eq('[[[...@1]]]', exec_capture('echo String([l])')) @@ -308,27 +326,25 @@ describe(':echo :echon :echomsg :echoerr', function() it('dumps list with two same empty dictionaries, also in partials', function() command('let d = {}') assert_same_echo_dump('[{}, {}]', '[d, d]', true) - eq('[function(\'tr\', {}), {}]', eval('String([function("tr", d), d])')) - eq('[{}, function(\'tr\', {})]', eval('String([d, function("tr", d)])')) + 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() - assert_same_echo_dump("{'t''est': 1}", {["t'est"]=1}) + assert_same_echo_dump("{'t''est': 1}", { ["t'est"] = 1 }) end) it('does not error when dumping recursive dictionaries', function() - meths.set_var('d', {d=1}) + api.nvim_set_var('d', { d = 1 }) eval('extend(d, {"d": d})') eq(0, exc_exec('echo String(d)')) end) it('dumps recursive dictionaries without the error', function() - meths.set_var('d', {d=1}) + api.nvim_set_var('d', { d = 1 }) eval('extend(d, {"d": d})') - eq('{\'d\': {...@0}}', - exec_capture('echo String(d)')) - eq('{\'out\': {\'d\': {...@1}}}', - exec_capture('echo String({"out": d})')) + eq("{'d': {...@0}}", exec_capture('echo String(d)')) + eq("{'out': {'d': {...@1}}}", exec_capture('echo String({"out": d})')) end) end) @@ -342,43 +358,43 @@ describe(':echo :echon :echomsg :echoerr', function() it('displays hex as hex', function() -- Regression: due to missing (uint8_t) cast \x80 was represented as -- ~@<80>. - eq('<80>', funcs.String(chr(0x80))) - eq('<81>', funcs.String(chr(0x81))) - eq('<8e>', funcs.String(chr(0x8e))) - eq('<c2>', funcs.String(('«'):sub(1, 1))) - eq('«', funcs.String(('«'):sub(1, 2))) - - eq('<80>', funcs.StringMsg(chr(0x80))) - eq('<81>', funcs.StringMsg(chr(0x81))) - eq('<8e>', funcs.StringMsg(chr(0x8e))) - eq('<c2>', funcs.StringMsg(('«'):sub(1, 1))) - eq('«', funcs.StringMsg(('«'):sub(1, 2))) + eq('<80>', fn.String(chr(0x80))) + eq('<81>', fn.String(chr(0x81))) + eq('<8e>', fn.String(chr(0x8e))) + eq('<c2>', fn.String(('«'):sub(1, 1))) + eq('«', fn.String(('«'):sub(1, 2))) + + eq('<80>', fn.StringMsg(chr(0x80))) + eq('<81>', fn.StringMsg(chr(0x81))) + eq('<8e>', fn.StringMsg(chr(0x8e))) + eq('<c2>', fn.StringMsg(('«'):sub(1, 1))) + eq('«', fn.StringMsg(('«'):sub(1, 2))) end) it('displays ASCII control characters using ^X notation', function() - eq('^C', funcs.String(ctrl('c'))) - eq('^A', funcs.String(ctrl('a'))) - eq('^F', funcs.String(ctrl('f'))) - eq('^C', funcs.StringMsg(ctrl('c'))) - eq('^A', funcs.StringMsg(ctrl('a'))) - eq('^F', funcs.StringMsg(ctrl('f'))) + eq('^C', fn.String(ctrl('c'))) + eq('^A', fn.String(ctrl('a'))) + eq('^F', fn.String(ctrl('f'))) + eq('^C', fn.StringMsg(ctrl('c'))) + eq('^A', fn.StringMsg(ctrl('a'))) + eq('^F', fn.StringMsg(ctrl('f'))) end) it('prints CR, NL and tab as-is', function() - eq('\n', funcs.String('\n')) - eq('\r', funcs.String('\r')) - eq('\t', funcs.String('\t')) + eq('\n', fn.String('\n')) + eq('\r', fn.String('\r')) + eq('\t', fn.String('\t')) end) it('prints non-printable UTF-8 in <> notation', function() -- SINGLE SHIFT TWO, unicode control - eq('<8e>', funcs.String(funcs.nr2char(0x8E))) - eq('<8e>', funcs.StringMsg(funcs.nr2char(0x8E))) + eq('<8e>', fn.String(fn.nr2char(0x8E))) + eq('<8e>', fn.StringMsg(fn.nr2char(0x8E))) -- Surrogate pair: U+1F0A0 PLAYING CARD BACK is represented in UTF-16 as -- 0xD83C 0xDCA0. This is not valid in UTF-8. - eq('<d83c>', funcs.String(funcs.nr2char(0xD83C))) - eq('<dca0>', funcs.String(funcs.nr2char(0xDCA0))) - eq('<d83c><dca0>', funcs.String(funcs.nr2char(0xD83C) .. funcs.nr2char(0xDCA0))) - eq('<d83c>', funcs.StringMsg(funcs.nr2char(0xD83C))) - eq('<dca0>', funcs.StringMsg(funcs.nr2char(0xDCA0))) - eq('<d83c><dca0>', funcs.StringMsg(funcs.nr2char(0xD83C) .. funcs.nr2char(0xDCA0))) + eq('<d83c>', fn.String(fn.nr2char(0xD83C))) + eq('<dca0>', fn.String(fn.nr2char(0xDCA0))) + eq('<d83c><dca0>', fn.String(fn.nr2char(0xD83C) .. fn.nr2char(0xDCA0))) + eq('<d83c>', fn.StringMsg(fn.nr2char(0xD83C))) + eq('<dca0>', fn.StringMsg(fn.nr2char(0xDCA0))) + eq('<d83c><dca0>', fn.StringMsg(fn.nr2char(0xD83C) .. fn.nr2char(0xDCA0))) end) end) end) |