diff options
author | ZyX <kp-pav@yandex.ru> | 2017-01-21 01:10:44 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2017-03-27 00:12:22 +0300 |
commit | bca9c2f3c4af9c132439bbfeaed028ac3171db48 (patch) | |
tree | 0e32e3aa620a8b8a201b8c8b0c6bfebbde5489b0 | |
parent | f8d55266e461a0a85e17e5adfd33e8429e45d9a5 (diff) | |
download | rneovim-bca9c2f3c4af9c132439bbfeaed028ac3171db48.tar.gz rneovim-bca9c2f3c4af9c132439bbfeaed028ac3171db48.tar.bz2 rneovim-bca9c2f3c4af9c132439bbfeaed028ac3171db48.zip |
functests: Move existing tests from lua_spec to lua/*, fix them
-rw-r--r-- | test/functional/lua/api_spec.lua | 143 | ||||
-rw-r--r-- | test/functional/lua/luaeval_spec.lua | 181 | ||||
-rw-r--r-- | test/functional/lua_spec.lua | 328 |
3 files changed, 324 insertions, 328 deletions
diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua index 6652c60adb..31c855c2c1 100644 --- a/test/functional/lua/api_spec.lua +++ b/test/functional/lua/api_spec.lua @@ -1,8 +1,10 @@ -- Test suite for testing interactions with API bindings local helpers = require('test.functional.helpers')(after_each) +local exc_exec = helpers.exc_exec local funcs = helpers.funcs local clear = helpers.clear +local eval = helpers.eval local NIL = helpers.NIL local eq = helpers.eq @@ -33,4 +35,145 @@ describe('luaeval(vim.api.…)', function() funcs.luaeval('{pcall(vim.api.nvim_buf_set_lines, 1, 1, 2, false, {"b\\na"})}')) end) end) + + it('correctly converts from API objects', function() + eq(1, funcs.luaeval('vim.api.nvim_eval("1")')) + eq('1', funcs.luaeval([[vim.api.nvim_eval('"1"')]])) + eq({}, funcs.luaeval('vim.api.nvim_eval("[]")')) + eq({}, funcs.luaeval('vim.api.nvim_eval("{}")')) + eq(1, funcs.luaeval('vim.api.nvim_eval("1.0")')) + eq(true, funcs.luaeval('vim.api.nvim_eval("v:true")')) + eq(false, funcs.luaeval('vim.api.nvim_eval("v:false")')) + eq(NIL, funcs.luaeval('vim.api.nvim_eval("v:null")')) + + eq(0, eval([[type(luaeval('vim.api.nvim_eval("1")'))]])) + eq(1, eval([[type(luaeval('vim.api.nvim_eval("''1''")'))]])) + eq(3, eval([[type(luaeval('vim.api.nvim_eval("[]")'))]])) + eq(4, eval([[type(luaeval('vim.api.nvim_eval("{}")'))]])) + eq(5, eval([[type(luaeval('vim.api.nvim_eval("1.0")'))]])) + eq(6, eval([[type(luaeval('vim.api.nvim_eval("v:true")'))]])) + eq(6, eval([[type(luaeval('vim.api.nvim_eval("v:false")'))]])) + eq(7, eval([[type(luaeval('vim.api.nvim_eval("v:null")'))]])) + + eq({foo=42}, funcs.luaeval([[vim.api.nvim_eval('{"foo": 42}')]])) + eq({42}, funcs.luaeval([[vim.api.nvim_eval('[42]')]])) + + eq({foo={bar=42}, baz=50}, funcs.luaeval([[vim.api.nvim_eval('{"foo": {"bar": 42}, "baz": 50}')]])) + eq({{42}, {}}, funcs.luaeval([=[vim.api.nvim_eval('[[42], []]')]=])) + end) + + it('correctly converts to API objects', function() + eq(1, funcs.luaeval('vim.api._vim_id(1)')) + eq('1', funcs.luaeval('vim.api._vim_id("1")')) + eq({1}, funcs.luaeval('vim.api._vim_id({1})')) + eq({foo=1}, funcs.luaeval('vim.api._vim_id({foo=1})')) + eq(1.5, funcs.luaeval('vim.api._vim_id(1.5)')) + eq(true, funcs.luaeval('vim.api._vim_id(true)')) + eq(false, funcs.luaeval('vim.api._vim_id(false)')) + eq(NIL, funcs.luaeval('vim.api._vim_id(nil)')) + + eq(0, eval([[type(luaeval('vim.api._vim_id(1)'))]])) + eq(1, eval([[type(luaeval('vim.api._vim_id("1")'))]])) + eq(3, eval([[type(luaeval('vim.api._vim_id({1})'))]])) + eq(4, eval([[type(luaeval('vim.api._vim_id({foo=1})'))]])) + eq(5, eval([[type(luaeval('vim.api._vim_id(1.5)'))]])) + eq(6, eval([[type(luaeval('vim.api._vim_id(true)'))]])) + eq(6, eval([[type(luaeval('vim.api._vim_id(false)'))]])) + eq(7, eval([[type(luaeval('vim.api._vim_id(nil)'))]])) + + eq({foo=1, bar={42, {{baz=true}, 5}}}, funcs.luaeval('vim.api._vim_id({foo=1, bar={42, {{baz=true}, 5}}})')) + end) + + it('correctly converts container objects with type_idx to API objects', function() + eq(5, eval('type(luaeval("vim.api._vim_id({[vim.type_idx]=vim.types.float, [vim.val_idx]=0})"))')) + eq(4, eval([[type(luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.dictionary})'))]])) + eq(3, eval([[type(luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.array})'))]])) + + eq({}, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.array})')) + + -- Presence of type_idx makes Vim ignore some keys + eq({42}, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq({foo=2}, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq(10, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq({}, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})')) + end) + + it('correctly converts arrays with type_idx to API objects', function() + eq(3, eval([[type(luaeval('vim.api._vim_id_array({[vim.type_idx]=vim.types.array})'))]])) + + eq({}, funcs.luaeval('vim.api._vim_id_array({[vim.type_idx]=vim.types.array})')) + + eq({42}, funcs.luaeval('vim.api._vim_id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq({{foo=2}}, funcs.luaeval('vim.api._vim_id_array({{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) + eq({10}, funcs.luaeval('vim.api._vim_id_array({{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) + eq({}, funcs.luaeval('vim.api._vim_id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})')) + + eq({}, funcs.luaeval('vim.api._vim_id_array({})')) + eq(3, eval([[type(luaeval('vim.api._vim_id_array({})'))]])) + end) + + it('correctly converts dictionaries with type_idx to API objects', function() + eq(4, eval([[type(luaeval('vim.api._vim_id_dictionary({[vim.type_idx]=vim.types.dictionary})'))]])) + + eq({}, funcs.luaeval('vim.api._vim_id_dictionary({[vim.type_idx]=vim.types.dictionary})')) + + eq({v={42}}, funcs.luaeval('vim.api._vim_id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) + eq({foo=2}, funcs.luaeval('vim.api._vim_id_dictionary({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) + eq({v=10}, funcs.luaeval('vim.api._vim_id_dictionary({v={[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) + eq({v={}}, funcs.luaeval('vim.api._vim_id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2}})')) + + -- If API requests dictionary, then empty table will be the one. This is not + -- the case normally because empty table is an empty arrray. + eq({}, funcs.luaeval('vim.api._vim_id_dictionary({})')) + eq(4, eval([[type(luaeval('vim.api._vim_id_dictionary({})'))]])) + end) + + it('errors out correctly when working with API', function() + -- Conversion errors + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Cannot convert given lua type', + exc_exec([[call luaeval("vim.api._vim_id(vim.api._vim_id)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Cannot convert given lua table', + exc_exec([[call luaeval("vim.api._vim_id({1, foo=42})")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Cannot convert given lua type', + exc_exec([[call luaeval("vim.api._vim_id({42, vim.api._vim_id})")]])) + -- Errors in number of arguments + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected 1 argument', + exc_exec([[call luaeval("vim.api._vim_id()")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected 1 argument', + exc_exec([[call luaeval("vim.api._vim_id(1, 2)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected 2 arguments', + exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]])) + -- Error in argument types + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua string', + exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]])) + + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua number', + exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Number is not integral', + exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]])) + + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua table', + exc_exec([[call luaeval("vim.api._vim_id_float('test')")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Unexpected type', + exc_exec([[call luaeval("vim.api._vim_id_float({[vim.type_idx]=vim.types.dictionary})")]])) + + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua table', + exc_exec([[call luaeval("vim.api._vim_id_array(1)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Unexpected type', + exc_exec([[call luaeval("vim.api._vim_id_array({[vim.type_idx]=vim.types.dictionary})")]])) + + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Expected lua table', + exc_exec([[call luaeval("vim.api._vim_id_dictionary(1)")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: Unexpected type', + exc_exec([[call luaeval("vim.api._vim_id_dictionary({[vim.type_idx]=vim.types.array})")]])) + -- TODO: check for errors with Tabpage argument + -- TODO: check for errors with Window argument + -- TODO: check for errors with Buffer argument + end) + + it('accepts any value as API Boolean', function() + eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", vim, false, nil)')) + eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", 0, 1.5, "test")')) + eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", true, {}, {[vim.type_idx]=vim.types.array})')) + end) end) diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua index 5b7f365ef3..345848cfff 100644 --- a/test/functional/lua/luaeval_spec.lua +++ b/test/functional/lua/luaeval_spec.lua @@ -1,16 +1,37 @@ -- Test suite for testing luaeval() function local helpers = require('test.functional.helpers')(after_each) +local redir_exec = helpers.redir_exec +local exc_exec = helpers.exc_exec local command = helpers.command local meths = helpers.meths local funcs = helpers.funcs local clear = helpers.clear +local eval = helpers.eval local NIL = helpers.NIL local eq = helpers.eq before_each(clear) +local function startswith(expected, actual) + eq(expected, actual:sub(1, #expected)) +end + describe('luaeval()', function() + local nested_by_level = {} + local nested = {} + local nested_s = '{}' + for i=1,100 do + if i % 2 == 0 then + nested = {nested} + nested_s = '{' .. nested_s .. '}' + else + nested = {nested=nested} + nested_s = '{nested=' .. nested_s .. '}' + end + nested_by_level[i] = {o=nested, s=nested_s} + end + describe('second argument', function() it('is successfully received', function() local t = {t=true, f=false, --[[n=NIL,]] d={l={'string', 42, 0.42}}} @@ -60,4 +81,164 @@ describe('luaeval()', function() eq(1, funcs.eval('l[2]._TYPE is v:msgpack_types.binary')) end) end) + + -- Not checked: funcrefs converted to NIL. To be altered to something more + -- meaningful later. + + it('correctly evaluates scalars', function() + eq(1, funcs.luaeval('1')) + eq(0, eval('type(luaeval("1"))')) + + eq(1.5, funcs.luaeval('1.5')) + eq(5, eval('type(luaeval("1.5"))')) + + eq("test", funcs.luaeval('"test"')) + eq(1, eval('type(luaeval("\'test\'"))')) + + eq('', funcs.luaeval('""')) + eq({_TYPE={}, _VAL={'\n'}}, funcs.luaeval([['\0']])) + eq({_TYPE={}, _VAL={'\n', '\n'}}, funcs.luaeval([['\0\n\0']])) + eq(1, eval([[luaeval('"\0\n\0"')._TYPE is v:msgpack_types.binary]])) + + eq(true, funcs.luaeval('true')) + eq(false, funcs.luaeval('false')) + eq(NIL, funcs.luaeval('nil')) + end) + + it('correctly evaluates containers', function() + eq({}, funcs.luaeval('{}')) + eq(3, eval('type(luaeval("{}"))')) + + eq({test=1, foo=2}, funcs.luaeval('{test=1, foo=2}')) + eq(4, eval('type(luaeval("{test=1, foo=2}"))')) + + eq({4, 2}, funcs.luaeval('{4, 2}')) + eq(3, eval('type(luaeval("{4, 2}"))')) + + local level = 30 + eq(nested_by_level[level].o, funcs.luaeval(nested_by_level[level].s)) + + eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}}, + funcs.luaeval([[{['\0\n\0']='\0\n\0\0'}]])) + eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._TYPE is v:msgpack_types.map]])) + eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][0]._TYPE is v:msgpack_types.string]])) + eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][1]._TYPE is v:msgpack_types.binary]])) + eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}}}}, + funcs.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]])) + end) + + it('correctly passes scalars as argument', function() + eq(1, funcs.luaeval('_A', 1)) + eq(1.5, funcs.luaeval('_A', 1.5)) + eq('', funcs.luaeval('_A', '')) + eq('test', funcs.luaeval('_A', 'test')) + eq(NIL, funcs.luaeval('_A', NIL)) + eq(true, funcs.luaeval('_A', true)) + eq(false, funcs.luaeval('_A', false)) + end) + + it('correctly passes containers as argument', function() + eq({}, funcs.luaeval('_A', {})) + eq({test=1}, funcs.luaeval('_A', {test=1})) + eq({4, 2}, funcs.luaeval('_A', {4, 2})) + local level = 28 + eq(nested_by_level[level].o, funcs.luaeval('_A', nested_by_level[level].o)) + end) + + local function sp(typ, val) + return ('{"_TYPE": v:msgpack_types.%s, "_VAL": %s}'):format(typ, val) + end + local function mapsp(...) + local val = '' + for i=1,(select('#', ...)/2) do + val = ('%s[%s,%s],'):format(val, select(i * 2 - 1, ...), + select(i * 2, ...)) + end + return sp('map', '[' .. val .. ']') + end + local function luaevalarg(argexpr, expr) + return eval(([=[ + [ + extend(g:, {'_ret': luaeval(%s, %s)})._ret, + type(g:_ret)==type({})&&has_key(g:_ret, '_TYPE') + ? [ + get(keys(filter(copy(v:msgpack_types), 'v:val is g:_ret._TYPE')), 0, + g:_ret._TYPE), + get(g:_ret, '_VAL', g:_ret) + ] + : [0, g:_ret]][1] + ]=]):format(expr or '"_A"', argexpr):gsub('\n', '')) + end + + it('correctly passes special dictionaries', function() + eq({'binary', {'\n', '\n'}}, luaevalarg(sp('binary', '["\\n", "\\n"]'))) + eq({'binary', {'\n', '\n'}}, luaevalarg(sp('string', '["\\n", "\\n"]'))) + eq({0, true}, luaevalarg(sp('boolean', 1))) + eq({0, false}, luaevalarg(sp('boolean', 0))) + eq({0, NIL}, luaevalarg(sp('nil', 0))) + eq({0, {[""]=""}}, luaevalarg(mapsp(sp('binary', '[""]'), '""'))) + eq({0, {[""]=""}}, luaevalarg(mapsp(sp('string', '[""]'), '""'))) + end) + + it('issues an error in some cases', function() + eq("Vim(call):E5100: Cannot convert given lua table: table should either have a sequence of positive integer keys or contain only string keys", + exc_exec('call luaeval("{1, foo=2}")')) + eq("Vim(call):E5101: Cannot convert given lua type", + exc_exec('call luaeval("vim.api.nvim_buf_get_lines")')) + startswith("Vim(call):E5107: Error while creating lua chunk for luaeval(): ", + exc_exec('call luaeval("1, 2, 3")')) + startswith("Vim(call):E5108: Error while calling lua chunk for luaeval(): ", + exc_exec('call luaeval("(nil)()")')) + eq("Vim(call):E5101: Cannot convert given lua type", + exc_exec('call luaeval("{42, vim.api}")')) + eq("Vim(call):E5101: Cannot convert given lua type", + exc_exec('call luaeval("{foo=42, baz=vim.api}")')) + + -- The following should not crash: conversion error happens inside + eq("Vim(call):E5101: Cannot convert given lua type", + exc_exec('call luaeval("vim.api")')) + -- The following should not show internal error + eq("\nE5101: Cannot convert given lua type\n0", + redir_exec('echo luaeval("vim.api")')) + end) + + it('correctly converts containers with type_idx', function() + eq(5, eval('type(luaeval("{[vim.type_idx]=vim.types.float, [vim.val_idx]=0}"))')) + eq(4, eval([[type(luaeval('{[vim.type_idx]=vim.types.dictionary}'))]])) + eq(3, eval([[type(luaeval('{[vim.type_idx]=vim.types.array}'))]])) + + eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.array}')) + + -- Presence of type_idx makes Vim ignore some keys + eq({42}, funcs.luaeval('{[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}')) + eq({foo=2}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}')) + eq(10, funcs.luaeval('{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}')) + + -- The following should not crash + eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary}')) + end) + + it('correctly converts self-containing containers', function() + meths.set_var('l', {}) + eval('add(l, l)') + eq(true, eval('luaeval("_A == _A[1]", l)')) + eq(true, eval('luaeval("_A[1] == _A[1][1]", [l])')) + eq(true, eval('luaeval("_A.d == _A.d[1]", {"d": l})')) + eq(true, eval('luaeval("_A ~= _A[1]", [l])')) + + meths.set_var('d', {foo=42}) + eval('extend(d, {"d": d})') + eq(true, eval('luaeval("_A == _A.d", d)')) + eq(true, eval('luaeval("_A[1] == _A[1].d", [d])')) + eq(true, eval('luaeval("_A.d == _A.d.d", {"d": d})')) + eq(true, eval('luaeval("_A ~= _A.d", {"d": d})')) + end) + + it('errors out correctly when doing incorrect things in lua', function() + -- Conversion errors + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: attempt to call field \'xxx_nonexistent_key_xxx\' (a nil value)', + exc_exec([[call luaeval("vim.xxx_nonexistent_key_xxx()")]])) + eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): [string "<VimL compiled string>"]:1: ERROR', + exc_exec([[call luaeval("error('ERROR')")]])) + end) end) diff --git a/test/functional/lua_spec.lua b/test/functional/lua_spec.lua deleted file mode 100644 index 8ca47718aa..0000000000 --- a/test/functional/lua_spec.lua +++ /dev/null @@ -1,328 +0,0 @@ -local helpers = require('test.functional.helpers')(after_each) - -local eq = helpers.eq -local neq = helpers.neq -local NIL = helpers.NIL -local eval = helpers.eval -local clear = helpers.clear -local funcs = helpers.funcs -local meths = helpers.meths -local exc_exec = helpers.exc_exec -local redir_exec = helpers.redir_exec - -local function startswith(expected, actual) - eq(expected, actual:sub(1, #expected)) -end - -before_each(clear) - -describe('luaeval() function', function() - local nested_by_level = {} - local nested = {} - local nested_s = '{}' - for i=1,100 do - if i % 2 == 0 then - nested = {nested} - nested_s = '{' .. nested_s .. '}' - else - nested = {nested=nested} - nested_s = '{nested=' .. nested_s .. '}' - end - nested_by_level[i] = {o=nested, s=nested_s} - end - - -- Not checked: funcrefs converted to NIL. To be altered to something more - -- meaningful later. - - it('correctly evaluates scalars', function() - eq(1, funcs.luaeval('1')) - eq(0, eval('type(luaeval("1"))')) - - eq(1.5, funcs.luaeval('1.5')) - eq(5, eval('type(luaeval("1.5"))')) - - eq("test", funcs.luaeval('"test"')) - eq(1, eval('type(luaeval("\'test\'"))')) - - eq('', funcs.luaeval('""')) - eq({_TYPE={}, _VAL={'\n'}}, funcs.luaeval([['\0']])) - eq({_TYPE={}, _VAL={'\n', '\n'}}, funcs.luaeval([['\0\n\0']])) - eq(1, eval([[luaeval('"\0\n\0"')._TYPE is v:msgpack_types.binary]])) - - eq(true, funcs.luaeval('true')) - eq(false, funcs.luaeval('false')) - eq(NIL, funcs.luaeval('nil')) - end) - - it('correctly evaluates containers', function() - eq({}, funcs.luaeval('{}')) - eq(3, eval('type(luaeval("{}"))')) - - eq({test=1, foo=2}, funcs.luaeval('{test=1, foo=2}')) - eq(4, eval('type(luaeval("{test=1, foo=2}"))')) - - eq({4, 2}, funcs.luaeval('{4, 2}')) - eq(3, eval('type(luaeval("{4, 2}"))')) - - local level = 30 - eq(nested_by_level[level].o, funcs.luaeval(nested_by_level[level].s)) - - eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}}, - funcs.luaeval([[{['\0\n\0']='\0\n\0\0'}]])) - eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._TYPE is v:msgpack_types.map]])) - eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][0]._TYPE is v:msgpack_types.string]])) - eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][1]._TYPE is v:msgpack_types.binary]])) - eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, {_TYPE={}, _VAL={'\n', '\n\n'}}}}}}}, - funcs.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]])) - end) - - it('correctly passes scalars as argument', function() - eq(1, funcs.luaeval('_A', 1)) - eq(1.5, funcs.luaeval('_A', 1.5)) - eq('', funcs.luaeval('_A', '')) - eq('test', funcs.luaeval('_A', 'test')) - eq(NIL, funcs.luaeval('_A', NIL)) - eq(true, funcs.luaeval('_A', true)) - eq(false, funcs.luaeval('_A', false)) - end) - - it('correctly passes containers as argument', function() - eq({}, funcs.luaeval('_A', {})) - eq({test=1}, funcs.luaeval('_A', {test=1})) - eq({4, 2}, funcs.luaeval('_A', {4, 2})) - local level = 28 - eq(nested_by_level[level].o, funcs.luaeval('_A', nested_by_level[level].o)) - end) - - local function sp(typ, val) - return ('{"_TYPE": v:msgpack_types.%s, "_VAL": %s}'):format(typ, val) - end - local function mapsp(...) - local val = '' - for i=1,(select('#', ...)/2) do - val = ('%s[%s,%s],'):format(val, select(i * 2 - 1, ...), - select(i * 2, ...)) - end - return sp('map', '[' .. val .. ']') - end - local function luaevalarg(argexpr, expr) - return eval(([=[ - [ - extend(g:, {'_ret': luaeval(%s, %s)})._ret, - type(g:_ret)==type({})&&has_key(g:_ret, '_TYPE') - ? [ - get(keys(filter(copy(v:msgpack_types), 'v:val is g:_ret._TYPE')), 0, - g:_ret._TYPE), - get(g:_ret, '_VAL', g:_ret) - ] - : [0, g:_ret]][1] - ]=]):format(expr or '"_A"', argexpr):gsub('\n', '')) - end - - it('correctly passes special dictionaries', function() - eq({'binary', {'\n', '\n'}}, luaevalarg(sp('binary', '["\\n", "\\n"]'))) - eq({'binary', {'\n', '\n'}}, luaevalarg(sp('string', '["\\n", "\\n"]'))) - eq({0, true}, luaevalarg(sp('boolean', 1))) - eq({0, false}, luaevalarg(sp('boolean', 0))) - eq({0, NIL}, luaevalarg(sp('nil', 0))) - eq({0, {[""]=""}}, luaevalarg(mapsp(sp('binary', '[""]'), '""'))) - eq({0, {[""]=""}}, luaevalarg(mapsp(sp('string', '[""]'), '""'))) - end) - - it('issues an error in some cases', function() - eq("Vim(call):E5100: Cannot convert given lua table: table should either have a sequence of positive integer keys or contain only string keys", - exc_exec('call luaeval("{1, foo=2}")')) - eq("Vim(call):E5101: Cannot convert given lua type", - exc_exec('call luaeval("vim.api.buffer_get_line_slice")')) - startswith("Vim(call):E5107: Error while creating lua chunk for luaeval(): ", - exc_exec('call luaeval("1, 2, 3")')) - startswith("Vim(call):E5108: Error while calling lua chunk for luaeval(): ", - exc_exec('call luaeval("(nil)()")')) - eq("Vim(call):E5101: Cannot convert given lua type", - exc_exec('call luaeval("{42, vim.api}")')) - eq("Vim(call):E5101: Cannot convert given lua type", - exc_exec('call luaeval("{foo=42, baz=vim.api}")')) - - -- The following should not crash: conversion error happens inside - eq("Vim(call):E5101: Cannot convert given lua type", - exc_exec('call luaeval("vim.api")')) - -- The following should not show internal error - eq("\nE5101: Cannot convert given lua type\n0", - redir_exec('echo luaeval("vim.api")')) - end) - - it('correctly converts containers with type_idx', function() - eq(5, eval('type(luaeval("{[vim.type_idx]=vim.types.float, [vim.val_idx]=0}"))')) - eq(4, eval([[type(luaeval('{[vim.type_idx]=vim.types.dictionary}'))]])) - eq(3, eval([[type(luaeval('{[vim.type_idx]=vim.types.array}'))]])) - - eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.array}')) - - -- Presence of type_idx makes Vim ignore some keys - eq({42}, funcs.luaeval('{[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}')) - eq({foo=2}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}')) - eq(10, funcs.luaeval('{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}')) - - -- The following should not crash - eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary}')) - end) - - it('correctly converts from API objects', function() - eq(1, funcs.luaeval('vim.api.vim_eval("1")')) - eq('1', funcs.luaeval([[vim.api.vim_eval('"1"')]])) - eq({}, funcs.luaeval('vim.api.vim_eval("[]")')) - eq({}, funcs.luaeval('vim.api.vim_eval("{}")')) - eq(1, funcs.luaeval('vim.api.vim_eval("1.0")')) - eq(true, funcs.luaeval('vim.api.vim_eval("v:true")')) - eq(false, funcs.luaeval('vim.api.vim_eval("v:false")')) - eq(NIL, funcs.luaeval('vim.api.vim_eval("v:null")')) - - eq(0, eval([[type(luaeval('vim.api.vim_eval("1")'))]])) - eq(1, eval([[type(luaeval('vim.api.vim_eval("''1''")'))]])) - eq(3, eval([[type(luaeval('vim.api.vim_eval("[]")'))]])) - eq(4, eval([[type(luaeval('vim.api.vim_eval("{}")'))]])) - eq(5, eval([[type(luaeval('vim.api.vim_eval("1.0")'))]])) - eq(6, eval([[type(luaeval('vim.api.vim_eval("v:true")'))]])) - eq(6, eval([[type(luaeval('vim.api.vim_eval("v:false")'))]])) - eq(7, eval([[type(luaeval('vim.api.vim_eval("v:null")'))]])) - - eq({foo=42}, funcs.luaeval([[vim.api.vim_eval('{"foo": 42}')]])) - eq({42}, funcs.luaeval([[vim.api.vim_eval('[42]')]])) - - eq({foo={bar=42}, baz=50}, funcs.luaeval([[vim.api.vim_eval('{"foo": {"bar": 42}, "baz": 50}')]])) - eq({{42}, {}}, funcs.luaeval([=[vim.api.vim_eval('[[42], []]')]=])) - end) - - it('correctly converts to API objects', function() - eq(1, funcs.luaeval('vim.api._vim_id(1)')) - eq('1', funcs.luaeval('vim.api._vim_id("1")')) - eq({1}, funcs.luaeval('vim.api._vim_id({1})')) - eq({foo=1}, funcs.luaeval('vim.api._vim_id({foo=1})')) - eq(1.5, funcs.luaeval('vim.api._vim_id(1.5)')) - eq(true, funcs.luaeval('vim.api._vim_id(true)')) - eq(false, funcs.luaeval('vim.api._vim_id(false)')) - eq(NIL, funcs.luaeval('vim.api._vim_id(nil)')) - - eq(0, eval([[type(luaeval('vim.api._vim_id(1)'))]])) - eq(1, eval([[type(luaeval('vim.api._vim_id("1")'))]])) - eq(3, eval([[type(luaeval('vim.api._vim_id({1})'))]])) - eq(4, eval([[type(luaeval('vim.api._vim_id({foo=1})'))]])) - eq(5, eval([[type(luaeval('vim.api._vim_id(1.5)'))]])) - eq(6, eval([[type(luaeval('vim.api._vim_id(true)'))]])) - eq(6, eval([[type(luaeval('vim.api._vim_id(false)'))]])) - eq(7, eval([[type(luaeval('vim.api._vim_id(nil)'))]])) - - eq({foo=1, bar={42, {{baz=true}, 5}}}, funcs.luaeval('vim.api._vim_id({foo=1, bar={42, {{baz=true}, 5}}})')) - end) - - it('correctly converts container objects with type_idx to API objects', function() - eq(5, eval('type(luaeval("vim.api._vim_id({[vim.type_idx]=vim.types.float, [vim.val_idx]=0})"))')) - eq(4, eval([[type(luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.dictionary})'))]])) - eq(3, eval([[type(luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.array})'))]])) - - eq({}, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.array})')) - - -- Presence of type_idx makes Vim ignore some keys - eq({42}, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) - eq({foo=2}, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) - eq(10, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) - eq({}, funcs.luaeval('vim.api._vim_id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})')) - end) - - it('correctly converts arrays with type_idx to API objects', function() - eq(3, eval([[type(luaeval('vim.api._vim_id_array({[vim.type_idx]=vim.types.array})'))]])) - - eq({}, funcs.luaeval('vim.api._vim_id_array({[vim.type_idx]=vim.types.array})')) - - eq({42}, funcs.luaeval('vim.api._vim_id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) - eq({{foo=2}}, funcs.luaeval('vim.api._vim_id_array({{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) - eq({10}, funcs.luaeval('vim.api._vim_id_array({{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) - eq({}, funcs.luaeval('vim.api._vim_id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})')) - - eq({}, funcs.luaeval('vim.api._vim_id_array({})')) - eq(3, eval([[type(luaeval('vim.api._vim_id_array({})'))]])) - end) - - it('correctly converts dictionaries with type_idx to API objects', function() - eq(4, eval([[type(luaeval('vim.api._vim_id_dictionary({[vim.type_idx]=vim.types.dictionary})'))]])) - - eq({}, funcs.luaeval('vim.api._vim_id_dictionary({[vim.type_idx]=vim.types.dictionary})')) - - eq({v={42}}, funcs.luaeval('vim.api._vim_id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) - eq({foo=2}, funcs.luaeval('vim.api._vim_id_dictionary({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})')) - eq({v=10}, funcs.luaeval('vim.api._vim_id_dictionary({v={[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})')) - eq({v={}}, funcs.luaeval('vim.api._vim_id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2}})')) - - -- If API requests dictionary, then empty table will be the one. This is not - -- the case normally because empty table is an empty arrray. - eq({}, funcs.luaeval('vim.api._vim_id_dictionary({})')) - eq(4, eval([[type(luaeval('vim.api._vim_id_dictionary({})'))]])) - end) - - it('correctly converts self-containing containers', function() - meths.set_var('l', {}) - eval('add(l, l)') - eq(true, eval('luaeval("_A == _A[1]", l)')) - eq(true, eval('luaeval("_A[1] == _A[1][1]", [l])')) - eq(true, eval('luaeval("_A.d == _A.d[1]", {"d": l})')) - eq(true, eval('luaeval("_A ~= _A[1]", [l])')) - - meths.set_var('d', {foo=42}) - eval('extend(d, {"d": d})') - eq(true, eval('luaeval("_A == _A.d", d)')) - eq(true, eval('luaeval("_A[1] == _A[1].d", [d])')) - eq(true, eval('luaeval("_A.d == _A.d.d", {"d": d})')) - eq(true, eval('luaeval("_A ~= _A.d", {"d": d})')) - end) - - it('errors out correctly when working with API', function() - -- Conversion errors - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Cannot convert given lua type', - exc_exec([[call luaeval("vim.api._vim_id(vim.api._vim_id)")]])) - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Cannot convert given lua table', - exc_exec([[call luaeval("vim.api._vim_id({1, foo=42})")]])) - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Cannot convert given lua type', - exc_exec([[call luaeval("vim.api._vim_id({42, vim.api._vim_id})")]])) - -- Errors in number of arguments - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Expected 1 argument', - exc_exec([[call luaeval("vim.api._vim_id()")]])) - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Expected 1 argument', - exc_exec([[call luaeval("vim.api._vim_id(1, 2)")]])) - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Expected 2 arguments', - exc_exec([[call luaeval("vim.api.vim_set_var(1, 2, 3)")]])) - -- Error in argument types - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Expected lua string', - exc_exec([[call luaeval("vim.api.vim_set_var(1, 2)")]])) - - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Expected lua number', - exc_exec([[call luaeval("vim.api.buffer_get_line(0, 'test')")]])) - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Number is not integral', - exc_exec([[call luaeval("vim.api.buffer_get_line(0, 1.5)")]])) - - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Expected lua table', - exc_exec([[call luaeval("vim.api._vim_id_float('test')")]])) - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Unexpected type', - exc_exec([[call luaeval("vim.api._vim_id_float({[vim.type_idx]=vim.types.dictionary})")]])) - - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Expected lua table', - exc_exec([[call luaeval("vim.api._vim_id_array(1)")]])) - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Unexpected type', - exc_exec([[call luaeval("vim.api._vim_id_array({[vim.type_idx]=vim.types.dictionary})")]])) - - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Expected lua table', - exc_exec([[call luaeval("vim.api._vim_id_dictionary(1)")]])) - eq('Vim(call):E5108: Error while calling lua chunk for luaeval(): Unexpected type', - exc_exec([[call luaeval("vim.api._vim_id_dictionary({[vim.type_idx]=vim.types.array})")]])) - -- TODO: check for errors with Tabpage argument - -- TODO: check for errors with Window argument - -- TODO: check for errors with Buffer argument - end) - - it('accepts any value as API Boolean', function() - eq('', funcs.luaeval('vim.api.vim_replace_termcodes("", vim, false, nil)')) - eq('', funcs.luaeval('vim.api.vim_replace_termcodes("", 0, 1.5, "test")')) - eq('', funcs.luaeval('vim.api.vim_replace_termcodes("", true, {}, {[vim.type_idx]=vim.types.array})')) - end) - - -- TODO: check buffer/window/etc. -end) |