mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 19:38:20 +00:00

Note: this will *still* crash when using API in cases similar to the one described in first commit. Just it needs different code to reproduce.
144 lines
5.1 KiB
Lua
144 lines
5.1 KiB
Lua
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 curbufmeths = helpers.curbufmeths
|
|
|
|
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
|
|
|
|
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)()")'))
|
|
|
|
-- The following should not crash: conversion error happens inside
|
|
eq("Vim(call):E5101: Cannot convert given lua type",
|
|
exc_exec('call luaeval("vim.api")'))
|
|
end)
|
|
end)
|