diff options
author | ZyX <kp-pav@yandex.ru> | 2017-03-13 14:35:53 +0300 |
---|---|---|
committer | ZyX <kp-pav@yandex.ru> | 2017-03-29 10:08:45 +0300 |
commit | 8b9a1fbf7a630b68b1428a39f25e1fa38fe0cc9f (patch) | |
tree | 97377c62e6c3fe928dee87ddc8486be28c1ea9ae | |
parent | fa852e7cdc365b6fcd39d677f4067963274c44c3 (diff) | |
download | rneovim-8b9a1fbf7a630b68b1428a39f25e1fa38fe0cc9f.tar.gz rneovim-8b9a1fbf7a630b68b1428a39f25e1fa38fe0cc9f.tar.bz2 rneovim-8b9a1fbf7a630b68b1428a39f25e1fa38fe0cc9f.zip |
unittests: Add tests for tv_dict_extend
-rw-r--r-- | test/unit/eval/helpers.lua | 12 | ||||
-rw-r--r-- | test/unit/eval/tricks_spec.lua | 14 | ||||
-rw-r--r-- | test/unit/eval/typval_spec.lua | 129 |
3 files changed, 144 insertions, 11 deletions
diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/helpers.lua index 6909953022..a3cb062b7b 100644 --- a/test/unit/eval/helpers.lua +++ b/test/unit/eval/helpers.lua @@ -498,6 +498,16 @@ local function dict_watchers(d) return ret, qs, key_patterns 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 { int=int, @@ -540,5 +550,7 @@ return { tbl2callback=tbl2callback, callback2tbl=callback2tbl, + eval0=eval0, + empty_list = {[type_key]=list_type}, } diff --git a/test/unit/eval/tricks_spec.lua b/test/unit/eval/tricks_spec.lua index 54029734fb..ae569bed11 100644 --- a/test/unit/eval/tricks_spec.lua +++ b/test/unit/eval/tricks_spec.lua @@ -1,4 +1,6 @@ local helpers = require('test.unit.helpers')(after_each) +local eval_helpers = require('test.unit.eval.helpers') + local itp = helpers.gen_itp(it) local cimport = helpers.cimport @@ -6,19 +8,11 @@ local to_cstr = helpers.to_cstr local ffi = helpers.ffi local eq = helpers.eq +local eval0 = eval_helpers.eval0 + local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.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() itp('is produced by $XXX_UNEXISTENT_VAR_XXX', function() -- Required for various tests which need to check whether typval_T with NULL diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua index b16e118053..00dc230e89 100644 --- a/test/unit/eval/typval_spec.lua +++ b/test/unit/eval/typval_spec.lua @@ -1,6 +1,7 @@ +local bit = require('bit') local helpers = require('test.unit.helpers')(after_each) -local global_helpers = require('test.helpers') local eval_helpers = require('test.unit.eval.helpers') +local global_helpers = require('test.helpers') local itp = helpers.gen_itp(it) @@ -17,6 +18,7 @@ local a = eval_helpers.alloc_logging_helpers local int = eval_helpers.int local list = eval_helpers.list local dict = eval_helpers.dict +local eval0 = eval_helpers.eval0 local lst2tbl = eval_helpers.lst2tbl local dct2tbl = eval_helpers.dct2tbl local typvalt = eval_helpers.typvalt @@ -1905,5 +1907,130 @@ describe('typval.c', function() eq({}, dct2tbl(d)) 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) |