aboutsummaryrefslogtreecommitdiff
path: root/test/unit
diff options
context:
space:
mode:
Diffstat (limited to 'test/unit')
-rw-r--r--test/unit/eval/helpers.lua14
-rw-r--r--test/unit/eval/typval_spec.lua94
-rw-r--r--test/unit/helpers.lua8
-rw-r--r--test/unit/marktree_spec.lua190
-rw-r--r--test/unit/mbyte_spec.lua5
-rw-r--r--test/unit/os/env_spec.lua4
-rw-r--r--test/unit/os/fs_spec.lua2
-rw-r--r--test/unit/path_spec.lua6
-rw-r--r--test/unit/preprocess.lua4
-rw-r--r--test/unit/tui_spec.lua136
10 files changed, 408 insertions, 55 deletions
diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/helpers.lua
index 3d1c42c3a0..b600f01ab2 100644
--- a/test/unit/eval/helpers.lua
+++ b/test/unit/eval/helpers.lua
@@ -136,11 +136,15 @@ local function typvalt2lua_tab_init()
return
end
typvalt2lua_tab = {
+ [tonumber(eval.VAR_BOOL)] = function(t)
+ return ({
+ [tonumber(eval.kBoolVarFalse)] = false,
+ [tonumber(eval.kBoolVarTrue)] = true,
+ })[tonumber(t.vval.v_bool)]
+ end,
[tonumber(eval.VAR_SPECIAL)] = function(t)
return ({
- [tonumber(eval.kSpecialVarFalse)] = false,
[tonumber(eval.kSpecialVarNull)] = nil_value,
- [tonumber(eval.kSpecialVarTrue)] = true,
})[tonumber(t.vval.v_special)]
end,
[tonumber(eval.VAR_NUMBER)] = function(t)
@@ -349,8 +353,8 @@ lua2typvalt = function(l, processed)
[null_list] = {'VAR_LIST', {v_list=ffi.cast('list_T*', nil)}},
[null_dict] = {'VAR_DICT', {v_dict=ffi.cast('dict_T*', nil)}},
[nil_value] = {'VAR_SPECIAL', {v_special=eval.kSpecialVarNull}},
- [true] = {'VAR_SPECIAL', {v_special=eval.kSpecialVarTrue}},
- [false] = {'VAR_SPECIAL', {v_special=eval.kSpecialVarFalse}},
+ [true] = {'VAR_BOOL', {v_bool=eval.kBoolVarTrue}},
+ [false] = {'VAR_BOOL', {v_bool=eval.kBoolVarFalse}},
}
for k, v in pairs(special_vals) do
@@ -406,7 +410,7 @@ end
local alloc_logging_helpers = {
list = function(l) return {func='calloc', args={1, ffi.sizeof('list_T')}, ret=void(l)} end,
li = function(li) return {func='malloc', args={ffi.sizeof('listitem_T')}, ret=void(li)} end,
- dict = function(d) return {func='malloc', args={ffi.sizeof('dict_T')}, ret=void(d)} end,
+ dict = function(d) return {func='calloc', args={1, ffi.sizeof('dict_T')}, ret=void(d)} end,
di = function(di, size)
size = alloc_len(size, function() return di.di_key end)
return {func='malloc', args={ffi.offsetof('dictitem_T', 'di_key') + size + 1}, ret=void(di)}
diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua
index 4535d6a0b2..7c03005529 100644
--- a/test/unit/eval/typval_spec.lua
+++ b/test/unit/eval/typval_spec.lua
@@ -14,7 +14,7 @@ local cimport = helpers.cimport
local to_cstr = helpers.to_cstr
local alloc_log_new = helpers.alloc_log_new
local concat_tables = helpers.concat_tables
-local map = helpers.map
+local map = helpers.tbl_map
local a = eval_helpers.alloc_logging_helpers
local int = eval_helpers.int
@@ -48,8 +48,7 @@ local lib = cimport('./src/nvim/eval/typval.h', './src/nvim/memory.h',
local function vimconv_alloc()
return ffi.gc(
- ffi.cast('vimconv_T*', lib.xcalloc(1, ffi.sizeof('vimconv_T'))),
- function(vc)
+ ffi.cast('vimconv_T*', lib.xcalloc(1, ffi.sizeof('vimconv_T'))), function(vc)
lib.convert_setup(vc, nil, nil)
lib.xfree(vc)
end)
@@ -1235,13 +1234,13 @@ describe('typval.c', function()
local l = list()
local l2 = list()
- -- NULL lists are not equal to empty lists
- eq(false, lib.tv_list_equal(l, nil, true, false))
- eq(false, lib.tv_list_equal(nil, l, false, false))
- eq(false, lib.tv_list_equal(nil, l, false, true))
- eq(false, lib.tv_list_equal(l, nil, true, true))
+ -- NULL lists are equal to empty lists
+ eq(true, lib.tv_list_equal(l, nil, true, false))
+ eq(true, lib.tv_list_equal(nil, l, false, false))
+ eq(true, lib.tv_list_equal(nil, l, false, true))
+ eq(true, lib.tv_list_equal(l, nil, true, true))
- -- Yet NULL lists are equal themselves
+ -- NULL lists are equal themselves
eq(true, lib.tv_list_equal(nil, nil, true, false))
eq(true, lib.tv_list_equal(nil, nil, false, false))
eq(true, lib.tv_list_equal(nil, nil, false, true))
@@ -2026,6 +2025,26 @@ describe('typval.c', function()
alloc_log:check({})
end)
end)
+ describe('float()', function()
+ itp('works', function()
+ local d = dict({test=10})
+ alloc_log:clear()
+ eq({test=10}, dct2tbl(d))
+ eq(OK, lib.tv_dict_add_float(d, 'testt', 3, 1.5))
+ local dis = dict_items(d)
+ alloc_log:check({a.di(dis.tes, 'tes')})
+ eq({test=10, tes=1.5}, dct2tbl(d))
+ eq(FAIL, check_emsg(function() return lib.tv_dict_add_float(d, 'testt', 3, 1.5) end,
+ 'E685: Internal error: hash_add()'))
+ alloc_log:clear()
+ lib.emsg_skip = lib.emsg_skip + 1
+ eq(FAIL, check_emsg(function() return lib.tv_dict_add_float(d, 'testt', 3, 1.5) end,
+ nil))
+ lib.emsg_skip = lib.emsg_skip - 1
+ alloc_log:clear_tmp_allocs()
+ alloc_log:check({})
+ end)
+ end)
describe('str()', function()
itp('works', function()
local d = dict({test=10})
@@ -2629,13 +2648,13 @@ describe('typval.c', function()
local l2 = lua2typvalt(empty_list)
local nl = lua2typvalt(null_list)
- -- NULL lists are not equal to empty lists
- eq(false, lib.tv_equal(l, nl, true, false))
- eq(false, lib.tv_equal(nl, l, false, false))
- eq(false, lib.tv_equal(nl, l, false, true))
- eq(false, lib.tv_equal(l, nl, true, true))
+ -- NULL lists are equal to empty lists
+ eq(true, lib.tv_equal(l, nl, true, false))
+ eq(true, lib.tv_equal(nl, l, false, false))
+ eq(true, lib.tv_equal(nl, l, false, true))
+ eq(true, lib.tv_equal(l, nl, true, true))
- -- Yet NULL lists are equal themselves
+ -- NULL lists are equal themselves
eq(true, lib.tv_equal(nl, nl, true, false))
eq(true, lib.tv_equal(nl, nl, false, false))
eq(true, lib.tv_equal(nl, nl, false, true))
@@ -2818,6 +2837,7 @@ describe('typval.c', function()
{lib.VAR_FUNC, 'E729: using Funcref as a String'},
{lib.VAR_LIST, 'E730: using List as a String'},
{lib.VAR_DICT, 'E731: using Dictionary as a String'},
+ {lib.VAR_BOOL, nil},
{lib.VAR_SPECIAL, nil},
{lib.VAR_UNKNOWN, 'E908: using an invalid value as a String'},
}) do
@@ -2848,8 +2868,8 @@ describe('typval.c', function()
{lib.VAR_LIST, {v_list=NULL}, 'E745: Using a List as a Number', 0},
{lib.VAR_DICT, {v_dict=NULL}, 'E728: Using a Dictionary as a Number', 0},
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 0},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 1},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 0},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 1},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 0},
{lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0},
}) do
-- Using to_cstr, cannot free with tv_clear
@@ -2877,8 +2897,8 @@ describe('typval.c', function()
{lib.VAR_LIST, {v_list=NULL}, 'E745: Using a List as a Number', 0},
{lib.VAR_DICT, {v_dict=NULL}, 'E728: Using a Dictionary as a Number', 0},
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 0},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 1},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 0},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 1},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 0},
{lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0},
}) do
-- Using to_cstr, cannot free with tv_clear
@@ -2911,8 +2931,8 @@ describe('typval.c', function()
{lib.VAR_LIST, {v_list=NULL}, 'E745: Using a List as a Number', -1},
{lib.VAR_DICT, {v_dict=NULL}, 'E728: Using a Dictionary as a Number', -1},
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 0},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 1},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 0},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 1},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 0},
{lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', -1},
}) do
lib.curwin.w_cursor.lnum = 46
@@ -2941,8 +2961,8 @@ describe('typval.c', function()
{lib.VAR_LIST, {v_list=NULL}, 'E893: Using a List as a Float', 0},
{lib.VAR_DICT, {v_dict=NULL}, 'E894: Using a Dictionary as a Float', 0},
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, 'E907: Using a special value as a Float', 0},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, 'E907: Using a special value as a Float', 0},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, 'E907: Using a special value as a Float', 0},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, 'E362: Using a boolean value as a Float', 0},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, 'E362: Using a boolean value as a Float', 0},
{lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_float(UNKNOWN)', 0},
}) do
-- Using to_cstr, cannot free with tv_clear
@@ -2973,8 +2993,8 @@ describe('typval.c', function()
{lib.VAR_LIST, {v_list=NULL}, 'E730: using List as a String', ''},
{lib.VAR_DICT, {v_dict=NULL}, 'E731: using Dictionary as a String', ''},
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'null'},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 'true'},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 'true'},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 'false'},
{lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', ''},
}) do
-- Using to_cstr in place of Neovim allocated string, cannot
@@ -2985,7 +3005,8 @@ describe('typval.c', function()
local ret = v[4]
eq(ret, check_emsg(function()
local res = lib.tv_get_string(tv)
- if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL then
+ if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL
+ or tv.v_type == lib.VAR_BOOL then
eq(buf, res)
else
neq(buf, res)
@@ -3016,8 +3037,8 @@ describe('typval.c', function()
{lib.VAR_LIST, {v_list=NULL}, 'E730: using List as a String', nil},
{lib.VAR_DICT, {v_dict=NULL}, 'E731: using Dictionary as a String', nil},
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'null'},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 'true'},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 'true'},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 'false'},
{lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', nil},
}) do
-- Using to_cstr, cannot free with tv_clear
@@ -3027,7 +3048,8 @@ describe('typval.c', function()
local ret = v[4]
eq(ret, check_emsg(function()
local res = lib.tv_get_string_chk(tv)
- if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL then
+ if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL
+ or tv.v_type == lib.VAR_BOOL then
eq(buf, res)
else
neq(buf, res)
@@ -3057,8 +3079,8 @@ describe('typval.c', function()
{lib.VAR_LIST, {v_list=NULL}, 'E730: using List as a String', ''},
{lib.VAR_DICT, {v_dict=NULL}, 'E731: using Dictionary as a String', ''},
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'null'},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 'true'},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 'true'},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 'false'},
{lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', ''},
}) do
-- Using to_cstr, cannot free with tv_clear
@@ -3069,7 +3091,8 @@ describe('typval.c', function()
eq(ret, check_emsg(function()
local buf = ffi.new('char[?]', lib.NUMBUFLEN, {0})
local res = lib.tv_get_string_buf(tv, buf)
- if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL then
+ if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL
+ or tv.v_type == lib.VAR_BOOL then
eq(buf, res)
else
neq(buf, res)
@@ -3099,8 +3122,8 @@ describe('typval.c', function()
{lib.VAR_LIST, {v_list=NULL}, 'E730: using List as a String', nil},
{lib.VAR_DICT, {v_dict=NULL}, 'E731: using Dictionary as a String', nil},
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'null'},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarTrue}, nil, 'true'},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 'true'},
+ {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 'false'},
{lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', nil},
}) do
-- Using to_cstr, cannot free with tv_clear
@@ -3111,7 +3134,8 @@ describe('typval.c', function()
eq(ret, check_emsg(function()
local buf = ffi.new('char[?]', lib.NUMBUFLEN, {0})
local res = lib.tv_get_string_buf_chk(tv, buf)
- if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL then
+ if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_SPECIAL
+ or tv.v_type == lib.VAR_BOOL then
eq(buf, res)
else
neq(buf, res)
diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua
index 24dbc65bd0..465b553693 100644
--- a/test/unit/helpers.lua
+++ b/test/unit/helpers.lua
@@ -13,7 +13,7 @@ local syscall = nil
local check_cores = global_helpers.check_cores
local dedent = global_helpers.dedent
local neq = global_helpers.neq
-local map = global_helpers.map
+local map = global_helpers.tbl_map
local eq = global_helpers.eq
local trim = global_helpers.trim
@@ -96,8 +96,8 @@ local init = only_separate(function()
c.func(unpack(c.args))
end
libnvim.time_init()
- libnvim.early_init()
libnvim.event_init()
+ libnvim.early_init(nil)
if child_calls_mod then
for _, c in ipairs(child_calls_mod) do
c.func(unpack(c.args))
@@ -545,7 +545,7 @@ local tracehelp = dedent([[
local function child_sethook(wr)
local trace_level = os.getenv('NVIM_TEST_TRACE_LEVEL')
if not trace_level or trace_level == '' then
- trace_level = 1
+ trace_level = 0
else
trace_level = tonumber(trace_level)
end
@@ -708,7 +708,7 @@ local function check_child_err(rd)
local eres = sc.read(rd, 2)
if eres ~= '$\n' then
if #trace == 0 then
- err = '\nTest crashed, no trace available\n'
+ err = '\nTest crashed, no trace available (check NVIM_TEST_TRACE_LEVEL)\n'
else
err = '\nTest crashed, trace:\n' .. tracehelp
for i = 1, #trace do
diff --git a/test/unit/marktree_spec.lua b/test/unit/marktree_spec.lua
new file mode 100644
index 0000000000..56acc0f93e
--- /dev/null
+++ b/test/unit/marktree_spec.lua
@@ -0,0 +1,190 @@
+local helpers = require("test.unit.helpers")(after_each)
+local itp = helpers.gen_itp(it)
+
+local ffi = helpers.ffi
+local eq = helpers.eq
+local ok = helpers.ok
+
+local lib = helpers.cimport("./src/nvim/marktree.h")
+
+local function tablelength(t)
+ local count = 0
+ for _ in pairs(t) do count = count + 1 end
+ return count
+end
+
+local function pos_leq(a, b)
+ return a[1] < b[1] or (a[1] == b[1] and a[2] <= b[2])
+end
+
+-- Checks that shadow and tree is consistent, and optionally
+-- return the order
+local function shadoworder(tree, shadow, iter, giveorder)
+ ok(iter ~= nil)
+ local status = lib.marktree_itr_first(tree, iter)
+ local count = 0
+ local pos2id, id2pos = {}, {}
+ local last
+ if not status and next(shadow) == nil then
+ return pos2id, id2pos
+ end
+ repeat
+ local mark = lib.marktree_itr_current(iter)
+ local id = tonumber(mark.id)
+ local spos = shadow[id]
+ if (mark.row ~= spos[1] or mark.col ~= spos[2]) then
+ error("invalid pos for "..id..":("..mark.row..", "..mark.col..") instead of ("..spos[1]..", "..spos[2]..")")
+ end
+ if mark.right_gravity ~= spos[3] then
+ error("invalid gravity for "..id..":("..mark.row..", "..mark.col..")")
+ end
+ if count > 0 then
+ if not pos_leq(last, spos) then
+ error("DISORDER")
+ end
+ end
+ count = count + 1
+ last = spos
+ if giveorder then
+ pos2id[count] = id
+ id2pos[id] = count
+ end
+ until not lib.marktree_itr_next(tree, iter)
+ local shadowlen = tablelength(shadow)
+ if shadowlen ~= count then
+ error("missed some keys? (shadow "..shadowlen..", tree "..count..")")
+ end
+ return id2pos, pos2id
+end
+
+local function shadowsplice(shadow, start, old_extent, new_extent)
+ local old_end = {start[1] + old_extent[1],
+ (old_extent[1] == 0 and start[2] or 0) + old_extent[2]}
+ local new_end = {start[1] + new_extent[1],
+ (new_extent[1] == 0 and start[2] or 0) + new_extent[2]}
+ local delta = {new_end[1] - old_end[1], new_end[2] - old_end[2]}
+ for _, pos in pairs(shadow) do
+ if pos_leq(start, pos) then
+ if pos_leq(pos, old_end) then
+ -- delete region
+ if pos[3] then -- right gravity
+ pos[1], pos[2] = new_end[1], new_end[2]
+ else
+ pos[1], pos[2] = start[1], start[2]
+ end
+ else
+ if pos[1] == old_end[1] then
+ pos[2] = pos[2] + delta[2]
+ end
+ pos[1] = pos[1] + delta[1]
+ end
+ end
+ end
+end
+
+local function dosplice(tree, shadow, start, old_extent, new_extent)
+ lib.marktree_splice(tree, start[1], start[2], old_extent[1], old_extent[2], new_extent[1], new_extent[2])
+ shadowsplice(shadow, start, old_extent, new_extent)
+end
+
+describe('marktree', function()
+ itp('works', function()
+ local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
+ local shadow = {}
+ local iter = ffi.new("MarkTreeIter[1]")
+ local iter2 = ffi.new("MarkTreeIter[1]")
+
+ for i = 1,100 do
+ for j = 1,100 do
+ local gravitate = (i%2) > 0
+ local id = tonumber(lib.marktree_put(tree, j, i, gravitate))
+ ok(id > 0)
+ eq(nil, shadow[id])
+ shadow[id] = {j,i,gravitate}
+ end
+ -- checking every insert is too slow, but this is ok
+ lib.marktree_check(tree)
+ end
+
+ -- ss = lib.mt_inspect_rec(tree)
+ -- io.stdout:write(ffi.string(ss))
+ -- io.stdout:flush()
+
+ local id2pos, pos2id = shadoworder(tree, shadow, iter)
+ eq({}, pos2id) -- not set if not requested
+ eq({}, id2pos)
+
+ for i,ipos in pairs(shadow) do
+ local pos = lib.marktree_lookup(tree, i, iter)
+ eq(ipos[1], pos.row)
+ eq(ipos[2], pos.col)
+ local k = lib.marktree_itr_current(iter)
+ eq(ipos[1], k.row)
+ eq(ipos[2], k.col, ipos[1])
+ lib.marktree_itr_next(tree, iter)
+ -- TODO(bfredl): use id2pos to check neighbour?
+ -- local k2 = lib.marktree_itr_current(iter)
+ end
+
+ for i,ipos in pairs(shadow) do
+ lib.marktree_itr_get(tree, ipos[1], ipos[2], iter)
+ local k = lib.marktree_itr_current(iter)
+ eq(i, tonumber(k.id))
+ eq(ipos[1], k.row)
+ eq(ipos[2], k.col)
+ end
+
+ ok(lib.marktree_itr_first(tree, iter))
+ local del = lib.marktree_itr_current(iter)
+
+ lib.marktree_del_itr(tree, iter, false)
+ shadow[tonumber(del.id)] = nil
+ shadoworder(tree, shadow, iter)
+
+ for _, ci in ipairs({0,-1,1,-2,2,-10,10}) do
+ for i = 1,100 do
+ lib.marktree_itr_get(tree, i, 50+ci, iter)
+ local k = lib.marktree_itr_current(iter)
+ local id = tonumber(k.id)
+ eq(shadow[id][1], k.row)
+ eq(shadow[id][2], k.col)
+ lib.marktree_del_itr(tree, iter, false)
+ shadow[id] = nil
+ end
+ lib.marktree_check(tree)
+ shadoworder(tree, shadow, iter)
+ end
+
+ -- NB: this is quite rudimentary. We rely on
+ -- functional tests exercising splicing quite a bit
+ lib.marktree_check(tree)
+ dosplice(tree, shadow, {2,2}, {0,5}, {1, 2})
+ lib.marktree_check(tree)
+ shadoworder(tree, shadow, iter)
+ dosplice(tree, shadow, {30,2}, {30,5}, {1, 2})
+ lib.marktree_check(tree)
+ shadoworder(tree, shadow, iter)
+
+ dosplice(tree, shadow, {5,3}, {0,2}, {0, 5})
+ shadoworder(tree, shadow, iter)
+ lib.marktree_check(tree)
+
+ -- build then burn (HOORAY! HOORAY!)
+ while next(shadow) do
+ lib.marktree_itr_first(tree, iter)
+ -- delete every other key for fun and profit
+ while true do
+ local k = lib.marktree_itr_current(iter)
+ lib.marktree_del_itr(tree, iter, false)
+ ok(shadow[tonumber(k.id)] ~= nil)
+ shadow[tonumber(k.id)] = nil
+ local stat = lib.marktree_itr_next(tree, iter)
+ if not stat then
+ break
+ end
+ end
+ lib.marktree_check(tree)
+ shadoworder(tree, shadow, iter2)
+ end
+ end)
+end)
diff --git a/test/unit/mbyte_spec.lua b/test/unit/mbyte_spec.lua
index d27f52923a..fdb1bceab0 100644
--- a/test/unit/mbyte_spec.lua
+++ b/test/unit/mbyte_spec.lua
@@ -8,11 +8,6 @@ local mbyte = helpers.cimport("./src/nvim/mbyte.h")
local charset = helpers.cimport('./src/nvim/charset.h')
describe('mbyte', function()
- if helpers.isCI('quickbuild') then
- pending("crashes on quickbuild", function() end)
- return
- end
-
-- Array for composing characters
local intp = ffi.typeof('int[?]')
local function to_intp()
diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua
index c543551607..ad05b134e0 100644
--- a/test/unit/os/env_spec.lua
+++ b/test/unit/os/env_spec.lua
@@ -121,7 +121,7 @@ describe('env.c', function()
local name = 'NVIM_UNIT_TEST_GETENV_1N'
local value = 'NVIM_UNIT_TEST_GETENV_1V'
eq(NULL, os_getenv(name))
- -- Use os_setenv because Lua dosen't have setenv.
+ -- Use os_setenv because Lua doesn't have setenv.
os_setenv(name, value, 1)
eq(value, os_getenv(name))
@@ -172,7 +172,7 @@ describe('env.c', function()
i = i + 1
name = cimp.os_getenvname_at_index(i)
end
- eq(true, (table.getn(names)) > 0)
+ eq(true, #names > 0)
eq(true, found_name)
end)
diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua
index 526a09e845..7fd71cb1ae 100644
--- a/test/unit/os/fs_spec.lua
+++ b/test/unit/os/fs_spec.lua
@@ -110,7 +110,7 @@ describe('fs.c', function()
describe('os_chdir', function()
itp('fails with path="~"', function()
- eq(false, os_isdir('~')) -- sanity check: no literal "~" directory.
+ eq(false, os_isdir('~'), 'sanity check: no literal "~" directory')
local length = 4096
local expected_cwd = cstr(length, '')
local cwd = cstr(length, '')
diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua
index e8ce660ce1..356c4997fa 100644
--- a/test/unit/path_spec.lua
+++ b/test/unit/path_spec.lua
@@ -66,10 +66,10 @@ describe('path.c', function()
end)
describe('path_full_compare', function()
- local function path_full_compare(s1, s2, cn)
+ local function path_full_compare(s1, s2, cn, ee)
s1 = to_cstr(s1)
s2 = to_cstr(s2)
- return cimp.path_full_compare(s1, s2, cn or 0)
+ return cimp.path_full_compare(s1, s2, cn or 0, ee or 1)
end
local f1 = 'f1.o'
@@ -456,7 +456,7 @@ describe('path.c', function()
end)
itp('fails and uses filename when the path is relative to HOME', function()
- eq(false, cimp.os_isdir('~')) -- sanity check: no literal "~" directory.
+ eq(false, cimp.os_isdir('~'), 'sanity check: no literal "~" directory')
local absolute_path = '~/home.file'
local buflen = string.len(absolute_path) + 1
local do_expand = 1
diff --git a/test/unit/preprocess.lua b/test/unit/preprocess.lua
index 1073855a7d..3786bc2122 100644
--- a/test/unit/preprocess.lua
+++ b/test/unit/preprocess.lua
@@ -89,6 +89,10 @@ local Gcc = {
get_defines_extra_flags = {'-std=c99', '-dM', '-E'},
get_declarations_extra_flags = {'-std=c99', '-P', '-E'},
}
+if ffi.abi("32bit") then
+ table.insert(Gcc.get_defines_extra_flags, '-m32')
+ table.insert(Gcc.get_declarations_extra_flags, '-m32')
+end
function Gcc:define(name, args, val)
local define = '-D' .. name
diff --git a/test/unit/tui_spec.lua b/test/unit/tui_spec.lua
new file mode 100644
index 0000000000..e6b5c889d7
--- /dev/null
+++ b/test/unit/tui_spec.lua
@@ -0,0 +1,136 @@
+local helpers = require("test.unit.helpers")(after_each)
+local cimport = helpers.cimport
+local eq = helpers.eq
+local ffi = helpers.ffi
+local itp = helpers.gen_itp(it)
+local to_cstr = helpers.to_cstr
+
+local cinput = cimport("./src/nvim/tui/input.h")
+local rbuffer = cimport("./test/unit/fixtures/rbuffer.h")
+local globals = cimport("./src/nvim/globals.h")
+local multiqueue = cimport("./test/unit/fixtures/multiqueue.h")
+
+itp('handle_background_color', function()
+ local handle_background_color = cinput.ut_handle_background_color
+ local term_input = ffi.new('TermInput', {})
+ local events = globals.main_loop.thread_events
+
+ -- Short-circuit when not waiting for response.
+ term_input.waiting_for_bg_response = 0
+ eq(false, handle_background_color(term_input))
+
+ local capacity = 100
+ local rbuf = ffi.gc(rbuffer.rbuffer_new(capacity), rbuffer.rbuffer_free)
+ term_input.read_stream.buffer = rbuf
+
+ local function assert_bg(colorspace, color, bg)
+ local term_response = '\027]11;'..colorspace..':'..color..'\007'
+ rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response)
+
+ term_input.waiting_for_bg_response = 1
+ eq(true, handle_background_color(term_input))
+ eq(0, term_input.waiting_for_bg_response)
+ eq(1, multiqueue.multiqueue_size(events))
+
+ local event = multiqueue.multiqueue_get(events)
+ local bg_event = ffi.cast("Event*", event.argv[1])
+ eq(bg, ffi.string(bg_event.argv[0]))
+
+ -- Buffer has been consumed.
+ eq(0, rbuf.size)
+ end
+
+ assert_bg('rgb', '0000/0000/0000', 'dark')
+ assert_bg('rgb', 'ffff/ffff/ffff', 'light')
+ assert_bg('rgb', '000/000/000', 'dark')
+ assert_bg('rgb', 'fff/fff/fff', 'light')
+ assert_bg('rgb', '00/00/00', 'dark')
+ assert_bg('rgb', 'ff/ff/ff', 'light')
+ assert_bg('rgb', '0/0/0', 'dark')
+ assert_bg('rgb', 'f/f/f', 'light')
+
+ assert_bg('rgb', 'f/0/0', 'dark')
+ assert_bg('rgb', '0/f/0', 'light')
+ assert_bg('rgb', '0/0/f', 'dark')
+
+ assert_bg('rgb', '1/1/1', 'dark')
+ assert_bg('rgb', '2/2/2', 'dark')
+ assert_bg('rgb', '3/3/3', 'dark')
+ assert_bg('rgb', '4/4/4', 'dark')
+ assert_bg('rgb', '5/5/5', 'dark')
+ assert_bg('rgb', '6/6/6', 'dark')
+ assert_bg('rgb', '7/7/7', 'dark')
+ assert_bg('rgb', '8/8/8', 'light')
+ assert_bg('rgb', '9/9/9', 'light')
+ assert_bg('rgb', 'a/a/a', 'light')
+ assert_bg('rgb', 'b/b/b', 'light')
+ assert_bg('rgb', 'c/c/c', 'light')
+ assert_bg('rgb', 'd/d/d', 'light')
+ assert_bg('rgb', 'e/e/e', 'light')
+
+ assert_bg('rgb', '0/e/0', 'light')
+ assert_bg('rgb', '0/d/0', 'light')
+ assert_bg('rgb', '0/c/0', 'dark')
+ assert_bg('rgb', '0/b/0', 'dark')
+
+ assert_bg('rgb', 'f/0/f', 'dark')
+ assert_bg('rgb', 'f/1/f', 'dark')
+ assert_bg('rgb', 'f/2/f', 'dark')
+ assert_bg('rgb', 'f/3/f', 'light')
+ assert_bg('rgb', 'f/4/f', 'light')
+
+ assert_bg('rgba', '0000/0000/0000/0000', 'dark')
+ assert_bg('rgba', '0000/0000/0000/ffff', 'dark')
+ assert_bg('rgba', 'ffff/ffff/ffff/0000', 'light')
+ assert_bg('rgba', 'ffff/ffff/ffff/ffff', 'light')
+ assert_bg('rgba', '000/000/000/000', 'dark')
+ assert_bg('rgba', '000/000/000/fff', 'dark')
+ assert_bg('rgba', 'fff/fff/fff/000', 'light')
+ assert_bg('rgba', 'fff/fff/fff/fff', 'light')
+ assert_bg('rgba', '00/00/00/00', 'dark')
+ assert_bg('rgba', '00/00/00/ff', 'dark')
+ assert_bg('rgba', 'ff/ff/ff/00', 'light')
+ assert_bg('rgba', 'ff/ff/ff/ff', 'light')
+ assert_bg('rgba', '0/0/0/0', 'dark')
+ assert_bg('rgba', '0/0/0/f', 'dark')
+ assert_bg('rgba', 'f/f/f/0', 'light')
+ assert_bg('rgba', 'f/f/f/f', 'light')
+
+
+ -- Incomplete sequence: not necessarily correct behavior, but tests it.
+ local term_response = '\027]11;rgba:f/f/f/f' -- missing '\007
+ rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response)
+
+ term_input.waiting_for_bg_response = 1
+ eq(false, handle_background_color(term_input))
+ eq(0, term_input.waiting_for_bg_response)
+
+ eq(0, multiqueue.multiqueue_size(events))
+ eq(0, rbuf.size)
+
+
+ -- Does nothing when not at start of buffer.
+ term_response = '123\027]11;rgba:f/f/f/f\007456'
+ rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response)
+
+ term_input.waiting_for_bg_response = 3
+ eq(false, handle_background_color(term_input))
+ eq(2, term_input.waiting_for_bg_response)
+
+ eq(0, multiqueue.multiqueue_size(events))
+ eq(#term_response, rbuf.size)
+ rbuffer.rbuffer_consumed(rbuf, #term_response)
+
+
+ -- Keeps trailing buffer.
+ term_response = '\027]11;rgba:f/f/f/f\007456'
+ rbuffer.rbuffer_write(rbuf, to_cstr(term_response), #term_response)
+
+ term_input.waiting_for_bg_response = 1
+ eq(true, handle_background_color(term_input))
+ eq(0, term_input.waiting_for_bg_response)
+
+ eq(1, multiqueue.multiqueue_size(events))
+ eq(3, rbuf.size)
+ rbuffer.rbuffer_consumed(rbuf, rbuf.size)
+end)