1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
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)
|