mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
unittests: Add tests for tv_dict_extend
This commit is contained in:
parent
fa852e7cdc
commit
8b9a1fbf7a
@ -498,6 +498,16 @@ local function dict_watchers(d)
|
|||||||
return ret, qs, key_patterns
|
return ret, qs, key_patterns
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function eval0(expr)
|
||||||
|
local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}),
|
||||||
|
eval.tv_clear)
|
||||||
|
if eval.eval0(to_cstr(expr), tv, nil, true) == 0 then
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
return tv
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
int=int,
|
int=int,
|
||||||
|
|
||||||
@ -540,5 +550,7 @@ return {
|
|||||||
tbl2callback=tbl2callback,
|
tbl2callback=tbl2callback,
|
||||||
callback2tbl=callback2tbl,
|
callback2tbl=callback2tbl,
|
||||||
|
|
||||||
|
eval0=eval0,
|
||||||
|
|
||||||
empty_list = {[type_key]=list_type},
|
empty_list = {[type_key]=list_type},
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
local helpers = require('test.unit.helpers')(after_each)
|
local helpers = require('test.unit.helpers')(after_each)
|
||||||
|
local eval_helpers = require('test.unit.eval.helpers')
|
||||||
|
|
||||||
local itp = helpers.gen_itp(it)
|
local itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local cimport = helpers.cimport
|
local cimport = helpers.cimport
|
||||||
@ -6,19 +8,11 @@ local to_cstr = helpers.to_cstr
|
|||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
|
|
||||||
|
local eval0 = eval_helpers.eval0
|
||||||
|
|
||||||
local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h',
|
local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h',
|
||||||
'./src/nvim/memory.h')
|
'./src/nvim/memory.h')
|
||||||
|
|
||||||
local eval0 = function(expr)
|
|
||||||
local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}),
|
|
||||||
eval.tv_clear)
|
|
||||||
if eval.eval0(to_cstr(expr), tv, nil, true) == 0 then
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
return tv
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe('NULL typval_T', function()
|
describe('NULL typval_T', function()
|
||||||
itp('is produced by $XXX_UNEXISTENT_VAR_XXX', function()
|
itp('is produced by $XXX_UNEXISTENT_VAR_XXX', function()
|
||||||
-- Required for various tests which need to check whether typval_T with NULL
|
-- Required for various tests which need to check whether typval_T with NULL
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
local bit = require('bit')
|
||||||
local helpers = require('test.unit.helpers')(after_each)
|
local helpers = require('test.unit.helpers')(after_each)
|
||||||
local global_helpers = require('test.helpers')
|
|
||||||
local eval_helpers = require('test.unit.eval.helpers')
|
local eval_helpers = require('test.unit.eval.helpers')
|
||||||
|
local global_helpers = require('test.helpers')
|
||||||
|
|
||||||
local itp = helpers.gen_itp(it)
|
local itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ local a = eval_helpers.alloc_logging_helpers
|
|||||||
local int = eval_helpers.int
|
local int = eval_helpers.int
|
||||||
local list = eval_helpers.list
|
local list = eval_helpers.list
|
||||||
local dict = eval_helpers.dict
|
local dict = eval_helpers.dict
|
||||||
|
local eval0 = eval_helpers.eval0
|
||||||
local lst2tbl = eval_helpers.lst2tbl
|
local lst2tbl = eval_helpers.lst2tbl
|
||||||
local dct2tbl = eval_helpers.dct2tbl
|
local dct2tbl = eval_helpers.dct2tbl
|
||||||
local typvalt = eval_helpers.typvalt
|
local typvalt = eval_helpers.typvalt
|
||||||
@ -1905,5 +1907,130 @@ describe('typval.c', function()
|
|||||||
eq({}, dct2tbl(d))
|
eq({}, dct2tbl(d))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
describe('extend()', function()
|
||||||
|
local function tv_dict_extend(d1, d2, action, emsg)
|
||||||
|
action = action or "force"
|
||||||
|
check_emsg(function() return lib.tv_dict_extend(d1, d2, action) end, emsg)
|
||||||
|
end
|
||||||
|
itp('works', function()
|
||||||
|
local d1 = dict()
|
||||||
|
alloc_log:check({a.dict(d1)})
|
||||||
|
eq({}, dct2tbl(d1))
|
||||||
|
local d2 = dict()
|
||||||
|
alloc_log:check({a.dict(d2)})
|
||||||
|
eq({}, dct2tbl(d2))
|
||||||
|
tv_dict_extend(d1, d2, 'error')
|
||||||
|
tv_dict_extend(d1, d2, 'keep')
|
||||||
|
tv_dict_extend(d1, d2, 'force')
|
||||||
|
alloc_log:check({})
|
||||||
|
|
||||||
|
d1 = dict({a='TEST'})
|
||||||
|
eq({a='TEST'}, dct2tbl(d1))
|
||||||
|
local dis1 = dict_items(d1)
|
||||||
|
local a1_s = dis1.a.di_tv.vval.v_string
|
||||||
|
alloc_log:clear_tmp_allocs()
|
||||||
|
alloc_log:check({
|
||||||
|
a.dict(d1),
|
||||||
|
a.di(dis1.a),
|
||||||
|
a.str(a1_s),
|
||||||
|
})
|
||||||
|
d2 = dict({a='TSET'})
|
||||||
|
eq({a='TSET'}, dct2tbl(d2))
|
||||||
|
local dis2 = dict_items(d2)
|
||||||
|
local a2_s = dis2.a.di_tv.vval.v_string
|
||||||
|
alloc_log:clear_tmp_allocs()
|
||||||
|
alloc_log:check({
|
||||||
|
a.dict(d2),
|
||||||
|
a.di(dis2.a),
|
||||||
|
a.str(a2_s),
|
||||||
|
})
|
||||||
|
|
||||||
|
tv_dict_extend(d1, d2, 'error', 'E737: Key already exists: a')
|
||||||
|
eq({a='TEST'}, dct2tbl(d1))
|
||||||
|
eq({a='TSET'}, dct2tbl(d2))
|
||||||
|
alloc_log:clear()
|
||||||
|
|
||||||
|
tv_dict_extend(d1, d2, 'keep')
|
||||||
|
alloc_log:check({})
|
||||||
|
eq({a='TEST'}, dct2tbl(d1))
|
||||||
|
eq({a='TSET'}, dct2tbl(d2))
|
||||||
|
|
||||||
|
tv_dict_extend(d1, d2, 'force')
|
||||||
|
alloc_log:check({
|
||||||
|
a.freed(a1_s),
|
||||||
|
a.str(dis1.a.di_tv.vval.v_string),
|
||||||
|
})
|
||||||
|
eq({a='TSET'}, dct2tbl(d1))
|
||||||
|
eq({a='TSET'}, dct2tbl(d2))
|
||||||
|
end)
|
||||||
|
itp('disallows overriding builtin or user functions', function()
|
||||||
|
local d = dict()
|
||||||
|
d.dv_scope = lib.VAR_DEF_SCOPE
|
||||||
|
local f_lua = {
|
||||||
|
[type_key]=func_type,
|
||||||
|
value='tr',
|
||||||
|
}
|
||||||
|
local f_tv = lua2typvalt(f_lua)
|
||||||
|
local p_lua = {
|
||||||
|
[type_key]=func_type,
|
||||||
|
value='tr',
|
||||||
|
args={1},
|
||||||
|
}
|
||||||
|
local p_tv = lua2typvalt(p_lua)
|
||||||
|
eq(lib.VAR_PARTIAL, p_tv.v_type)
|
||||||
|
local d2 = dict({tr=f_tv})
|
||||||
|
local d3 = dict({tr=p_tv})
|
||||||
|
local d4 = dict({['TEST:THIS']=p_tv})
|
||||||
|
local d5 = dict({Test=f_tv})
|
||||||
|
local d6 = dict({Test=p_tv})
|
||||||
|
eval0([[execute("function Test()\nendfunction")]])
|
||||||
|
tv_dict_extend(d, d2, 'force',
|
||||||
|
'E704: Funcref variable name must start with a capital: tr')
|
||||||
|
tv_dict_extend(d, d3, 'force',
|
||||||
|
'E704: Funcref variable name must start with a capital: tr')
|
||||||
|
tv_dict_extend(d, d4, 'force',
|
||||||
|
'E461: Illegal variable name: TEST:THIS')
|
||||||
|
tv_dict_extend(d, d5, 'force',
|
||||||
|
'E705: Variable name conflicts with existing function: Test')
|
||||||
|
tv_dict_extend(d, d6, 'force',
|
||||||
|
'E705: Variable name conflicts with existing function: Test')
|
||||||
|
eq({}, dct2tbl(d))
|
||||||
|
d.dv_scope = lib.VAR_SCOPE
|
||||||
|
tv_dict_extend(d, d4, 'force',
|
||||||
|
'E461: Illegal variable name: TEST:THIS')
|
||||||
|
eq({}, dct2tbl(d))
|
||||||
|
tv_dict_extend(d, d2, 'force')
|
||||||
|
eq({tr=f_lua}, dct2tbl(d))
|
||||||
|
tv_dict_extend(d, d3, 'force')
|
||||||
|
eq({tr=p_lua}, dct2tbl(d))
|
||||||
|
tv_dict_extend(d, d5, 'force')
|
||||||
|
eq({tr=p_lua, Test=f_lua}, dct2tbl(d))
|
||||||
|
tv_dict_extend(d, d6, 'force')
|
||||||
|
eq({tr=p_lua, Test=p_lua}, dct2tbl(d))
|
||||||
|
end)
|
||||||
|
itp('cares about locks and read-only items', function()
|
||||||
|
local d_lua = {tv_locked=1, tv_fixed=2, di_ro=3, di_ro_sbx=4}
|
||||||
|
local d = dict(d_lua)
|
||||||
|
local dis = dict_items(d)
|
||||||
|
dis.tv_locked.di_tv.v_lock = lib.VAR_LOCKED
|
||||||
|
dis.tv_fixed.di_tv.v_lock = lib.VAR_FIXED
|
||||||
|
dis.di_ro.di_flags = bit.bor(dis.di_ro.di_flags, lib.DI_FLAGS_RO)
|
||||||
|
dis.di_ro_sbx.di_flags = bit.bor(dis.di_ro_sbx.di_flags, lib.DI_FLAGS_RO_SBX)
|
||||||
|
lib.sandbox = true
|
||||||
|
local d1 = dict({tv_locked=41})
|
||||||
|
local d2 = dict({tv_fixed=42})
|
||||||
|
local d3 = dict({di_ro=43})
|
||||||
|
local d4 = dict({di_ro_sbx=44})
|
||||||
|
tv_dict_extend(d, d1, 'force', 'E741: Value is locked: extend() argument')
|
||||||
|
tv_dict_extend(d, d2, 'force', 'E742: Cannot change value of extend() argument')
|
||||||
|
tv_dict_extend(d, d3, 'force', 'E46: Cannot change read-only variable "extend() argument"')
|
||||||
|
tv_dict_extend(d, d4, 'force', 'E794: Cannot set variable in the sandbox: "extend() argument"')
|
||||||
|
eq(d_lua, dct2tbl(d))
|
||||||
|
lib.sandbox = false
|
||||||
|
tv_dict_extend(d, d4, 'force')
|
||||||
|
d_lua.di_ro_sbx = 44
|
||||||
|
eq(d_lua, dct2tbl(d))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user