mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
unittests: Do not import libnvim or headers in main process
Slows down unit tests much, but gets rid of as much preserved state as possible.
This commit is contained in:
parent
9400466282
commit
e2a578f40d
@ -19,47 +19,46 @@ local api = cimport('./src/nvim/api/private/defs.h',
|
|||||||
|
|
||||||
local obj2lua
|
local obj2lua
|
||||||
|
|
||||||
local obj2lua_tab = {
|
|
||||||
[tonumber(api.kObjectTypeArray)] = function(obj)
|
|
||||||
local ret = {[type_key]=list_type}
|
|
||||||
for i = 1,tonumber(obj.data.array.size) do
|
|
||||||
ret[i] = obj2lua(obj.data.array.items[i - 1])
|
|
||||||
end
|
|
||||||
if ret[1] then
|
|
||||||
ret[type_key] = nil
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end,
|
|
||||||
[tonumber(api.kObjectTypeDictionary)] = function(obj)
|
|
||||||
local ret = {}
|
|
||||||
for i = 1,tonumber(obj.data.dictionary.size) do
|
|
||||||
local kv_pair = obj.data.dictionary.items[i - 1]
|
|
||||||
ret[ffi.string(kv_pair.key.data, kv_pair.key.size)] = obj2lua(kv_pair.value)
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end,
|
|
||||||
[tonumber(api.kObjectTypeBoolean)] = function(obj)
|
|
||||||
if obj.data.boolean == false then
|
|
||||||
return false
|
|
||||||
else
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
[tonumber(api.kObjectTypeNil)] = function(_)
|
|
||||||
return nil_value
|
|
||||||
end,
|
|
||||||
[tonumber(api.kObjectTypeFloat)] = function(obj)
|
|
||||||
return tonumber(obj.data.floating)
|
|
||||||
end,
|
|
||||||
[tonumber(api.kObjectTypeInteger)] = function(obj)
|
|
||||||
return {[type_key]=int_type, value=tonumber(obj.data.integer)}
|
|
||||||
end,
|
|
||||||
[tonumber(api.kObjectTypeString)] = function(obj)
|
|
||||||
return ffi.string(obj.data.string.data, obj.data.string.size)
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
obj2lua = function(obj)
|
obj2lua = function(obj)
|
||||||
|
local obj2lua_tab = {
|
||||||
|
[tonumber(api.kObjectTypeArray)] = function(obj)
|
||||||
|
local ret = {[type_key]=list_type}
|
||||||
|
for i = 1,tonumber(obj.data.array.size) do
|
||||||
|
ret[i] = obj2lua(obj.data.array.items[i - 1])
|
||||||
|
end
|
||||||
|
if ret[1] then
|
||||||
|
ret[type_key] = nil
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end,
|
||||||
|
[tonumber(api.kObjectTypeDictionary)] = function(obj)
|
||||||
|
local ret = {}
|
||||||
|
for i = 1,tonumber(obj.data.dictionary.size) do
|
||||||
|
local kv_pair = obj.data.dictionary.items[i - 1]
|
||||||
|
ret[ffi.string(kv_pair.key.data, kv_pair.key.size)] = obj2lua(kv_pair.value)
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end,
|
||||||
|
[tonumber(api.kObjectTypeBoolean)] = function(obj)
|
||||||
|
if obj.data.boolean == false then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
[tonumber(api.kObjectTypeNil)] = function(_)
|
||||||
|
return nil_value
|
||||||
|
end,
|
||||||
|
[tonumber(api.kObjectTypeFloat)] = function(obj)
|
||||||
|
return tonumber(obj.data.floating)
|
||||||
|
end,
|
||||||
|
[tonumber(api.kObjectTypeInteger)] = function(obj)
|
||||||
|
return {[type_key]=int_type, value=tonumber(obj.data.integer)}
|
||||||
|
end,
|
||||||
|
[tonumber(api.kObjectTypeString)] = function(obj)
|
||||||
|
return ffi.string(obj.data.string.data, obj.data.string.size)
|
||||||
|
end,
|
||||||
|
}
|
||||||
return ((obj2lua_tab[tonumber(obj['type'])] or function(obj_inner)
|
return ((obj2lua_tab[tonumber(obj['type'])] or function(obj_inner)
|
||||||
assert(false, 'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet')
|
assert(false, 'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet')
|
||||||
end)(obj))
|
end)(obj))
|
||||||
|
@ -12,20 +12,6 @@ local decode = cimport('./src/nvim/eval/decode.h', './src/nvim/eval_defs.h',
|
|||||||
'./src/nvim/message.h')
|
'./src/nvim/message.h')
|
||||||
|
|
||||||
describe('json_decode_string()', function()
|
describe('json_decode_string()', function()
|
||||||
local saved_p_enc = nil
|
|
||||||
|
|
||||||
before_each(function()
|
|
||||||
saved_p_enc = decode.p_enc
|
|
||||||
end)
|
|
||||||
|
|
||||||
after_each(function()
|
|
||||||
decode.emsg_silent = 0
|
|
||||||
decode.p_enc = saved_p_enc
|
|
||||||
while decode.delete_first_msg() == 1 do
|
|
||||||
-- Delete all messages
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
local char = function(c)
|
local char = function(c)
|
||||||
return ffi.gc(decode.xmemdup(c, 1), decode.xfree)
|
return ffi.gc(decode.xmemdup(c, 1), decode.xfree)
|
||||||
end
|
end
|
||||||
|
@ -46,12 +46,6 @@ local function list(...)
|
|||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
local special_tab = {
|
|
||||||
[eval.kSpecialVarFalse] = false,
|
|
||||||
[eval.kSpecialVarNull] = nil_value,
|
|
||||||
[eval.kSpecialVarTrue] = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
local ptr2key = function(ptr)
|
local ptr2key = function(ptr)
|
||||||
return tostring(ptr)
|
return tostring(ptr)
|
||||||
end
|
end
|
||||||
@ -60,64 +54,74 @@ local lst2tbl
|
|||||||
local dct2tbl
|
local dct2tbl
|
||||||
|
|
||||||
local typvalt2lua
|
local typvalt2lua
|
||||||
local typvalt2lua_tab
|
local typvalt2lua_tab = nil
|
||||||
|
|
||||||
typvalt2lua_tab = {
|
local function typvalt2lua_tab_init()
|
||||||
[tonumber(eval.VAR_SPECIAL)] = function(t)
|
if typvalt2lua_tab then
|
||||||
return special_tab[t.vval.v_special]
|
return
|
||||||
end,
|
end
|
||||||
[tonumber(eval.VAR_NUMBER)] = function(t)
|
typvalt2lua_tab = {
|
||||||
return {[type_key]=int_type, value=tonumber(t.vval.v_number)}
|
[tonumber(eval.VAR_SPECIAL)] = function(t)
|
||||||
end,
|
return ({
|
||||||
[tonumber(eval.VAR_FLOAT)] = function(t)
|
[eval.kSpecialVarFalse] = false,
|
||||||
return tonumber(t.vval.v_float)
|
[eval.kSpecialVarNull] = nil_value,
|
||||||
end,
|
[eval.kSpecialVarTrue] = true,
|
||||||
[tonumber(eval.VAR_STRING)] = function(t)
|
})[t.vval.v_special]
|
||||||
local str = t.vval.v_string
|
end,
|
||||||
if str == nil then
|
[tonumber(eval.VAR_NUMBER)] = function(t)
|
||||||
return null_string
|
return {[type_key]=int_type, value=tonumber(t.vval.v_number)}
|
||||||
else
|
end,
|
||||||
return ffi.string(str)
|
[tonumber(eval.VAR_FLOAT)] = function(t)
|
||||||
end
|
return tonumber(t.vval.v_float)
|
||||||
end,
|
end,
|
||||||
[tonumber(eval.VAR_LIST)] = function(t, processed)
|
[tonumber(eval.VAR_STRING)] = function(t)
|
||||||
return lst2tbl(t.vval.v_list, processed)
|
local str = t.vval.v_string
|
||||||
end,
|
if str == nil then
|
||||||
[tonumber(eval.VAR_DICT)] = function(t, processed)
|
return null_string
|
||||||
return dct2tbl(t.vval.v_dict, processed)
|
else
|
||||||
end,
|
return ffi.string(str)
|
||||||
[tonumber(eval.VAR_FUNC)] = function(t, processed)
|
|
||||||
return {[type_key]=func_type, value=typvalt2lua_tab[eval.VAR_STRING](t, processed or {})}
|
|
||||||
end,
|
|
||||||
[tonumber(eval.VAR_PARTIAL)] = function(t, processed)
|
|
||||||
local p_key = ptr2key(t)
|
|
||||||
if processed[p_key] then
|
|
||||||
return processed[p_key]
|
|
||||||
end
|
|
||||||
local pt = t.vval.v_partial
|
|
||||||
local value, auto, dict, argv = nil, nil, nil, nil
|
|
||||||
if pt ~= nil then
|
|
||||||
value = ffi.string(pt.pt_name)
|
|
||||||
auto = pt.pt_auto and true or nil
|
|
||||||
argv = {}
|
|
||||||
for i = 1, pt.pt_argc do
|
|
||||||
argv[i] = typvalt2lua(pt.pt_argv[i - 1], processed)
|
|
||||||
end
|
end
|
||||||
if pt.pt_dict ~= nil then
|
end,
|
||||||
dict = dct2tbl(pt.pt_dict)
|
[tonumber(eval.VAR_LIST)] = function(t, processed)
|
||||||
|
return lst2tbl(t.vval.v_list, processed)
|
||||||
|
end,
|
||||||
|
[tonumber(eval.VAR_DICT)] = function(t, processed)
|
||||||
|
return dct2tbl(t.vval.v_dict, processed)
|
||||||
|
end,
|
||||||
|
[tonumber(eval.VAR_FUNC)] = function(t, processed)
|
||||||
|
return {[type_key]=func_type, value=typvalt2lua_tab[eval.VAR_STRING](t, processed or {})}
|
||||||
|
end,
|
||||||
|
[tonumber(eval.VAR_PARTIAL)] = function(t, processed)
|
||||||
|
local p_key = ptr2key(t)
|
||||||
|
if processed[p_key] then
|
||||||
|
return processed[p_key]
|
||||||
end
|
end
|
||||||
end
|
local pt = t.vval.v_partial
|
||||||
return {
|
local value, auto, dict, argv = nil, nil, nil, nil
|
||||||
[type_key]=func_type,
|
if pt ~= nil then
|
||||||
value=value,
|
value = ffi.string(pt.pt_name)
|
||||||
auto=auto,
|
auto = pt.pt_auto and true or nil
|
||||||
args=argv,
|
argv = {}
|
||||||
dict=dict,
|
for i = 1, pt.pt_argc do
|
||||||
}
|
argv[i] = typvalt2lua(pt.pt_argv[i - 1], processed)
|
||||||
end,
|
end
|
||||||
}
|
if pt.pt_dict ~= nil then
|
||||||
|
dict = dct2tbl(pt.pt_dict)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return {
|
||||||
|
[type_key]=func_type,
|
||||||
|
value=value,
|
||||||
|
auto=auto,
|
||||||
|
args=argv,
|
||||||
|
dict=dict,
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
typvalt2lua = function(t, processed)
|
typvalt2lua = function(t, processed)
|
||||||
|
typvalt2lua_tab_init()
|
||||||
return ((typvalt2lua_tab[tonumber(t.v_type)] or function(t_inner)
|
return ((typvalt2lua_tab[tonumber(t.v_type)] or function(t_inner)
|
||||||
assert(false, 'Converting ' .. tonumber(t_inner.v_type) .. ' was not implemented yet')
|
assert(false, 'Converting ' .. tonumber(t_inner.v_type) .. ' was not implemented yet')
|
||||||
end)(t, processed or {}))
|
end)(t, processed or {}))
|
||||||
@ -169,9 +173,10 @@ lst2tbl = function(l, processed)
|
|||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
local hi_key_removed = eval._hash_key_removed()
|
local hi_key_removed = nil
|
||||||
|
|
||||||
local function dict_iter(d, return_hi)
|
local function dict_iter(d, return_hi)
|
||||||
|
hi_key_removed = hi_key_removed or eval._hash_key_removed()
|
||||||
local init_s = {
|
local init_s = {
|
||||||
todo=d.dv_hashtab.ht_used,
|
todo=d.dv_hashtab.ht_used,
|
||||||
hi=d.dv_hashtab.ht_array,
|
hi=d.dv_hashtab.ht_array,
|
||||||
@ -320,25 +325,28 @@ local lua2typvalt_type_tab = {
|
|||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
local special_vals = {
|
local special_vals = nil
|
||||||
[null_string] = {eval.VAR_STRING, {v_string=ffi.cast('char_u*', nil)}},
|
|
||||||
[null_list] = {eval.VAR_LIST, {v_list=ffi.cast('list_T*', nil)}},
|
|
||||||
[null_dict] = {eval.VAR_DICT, {v_dict=ffi.cast('dict_T*', nil)}},
|
|
||||||
[nil_value] = {eval.VAR_SPECIAL, {v_special=eval.kSpecialVarNull}},
|
|
||||||
[true] = {eval.VAR_SPECIAL, {v_special=eval.kSpecialVarTrue}},
|
|
||||||
[false] = {eval.VAR_SPECIAL, {v_special=eval.kSpecialVarFalse}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v in pairs(special_vals) do
|
|
||||||
local tmp = function(typ, vval)
|
|
||||||
special_vals[k] = function()
|
|
||||||
return typvalt(typ, vval)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tmp(v[1], v[2])
|
|
||||||
end
|
|
||||||
|
|
||||||
lua2typvalt = function(l, processed)
|
lua2typvalt = function(l, processed)
|
||||||
|
if not special_vals then
|
||||||
|
special_vals = {
|
||||||
|
[null_string] = {'VAR_STRING', {v_string=ffi.cast('char_u*', nil)}},
|
||||||
|
[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}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v in pairs(special_vals) do
|
||||||
|
local tmp = function(typ, vval)
|
||||||
|
special_vals[k] = function()
|
||||||
|
return typvalt(eval[typ], vval)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tmp(v[1], v[2])
|
||||||
|
end
|
||||||
|
end
|
||||||
processed = processed or {}
|
processed = processed or {}
|
||||||
if l == nil or l == nil_value then
|
if l == nil or l == nil_value then
|
||||||
return special_vals[nil_value]()
|
return special_vals[nil_value]()
|
||||||
@ -360,7 +368,7 @@ lua2typvalt = function(l, processed)
|
|||||||
return typvalt(eval.VAR_STRING, {v_string=eval.xmemdupz(to_cstr(l), #l)})
|
return typvalt(eval.VAR_STRING, {v_string=eval.xmemdupz(to_cstr(l), #l)})
|
||||||
elseif type(l) == 'cdata' then
|
elseif type(l) == 'cdata' then
|
||||||
local tv = typvalt(eval.VAR_UNKNOWN)
|
local tv = typvalt(eval.VAR_UNKNOWN)
|
||||||
eval.tv_copy(l, tv)
|
eval.copy_tv(l, tv)
|
||||||
return tv
|
return tv
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -9,7 +9,7 @@ local ffi = helpers.ffi
|
|||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
local NULL = helpers.NULL
|
local NULL = helpers.NULL
|
||||||
|
|
||||||
local garray = cimport('stdlib.h', './src/nvim/garray.h')
|
local garray = cimport('./src/nvim/garray.h')
|
||||||
|
|
||||||
local itemsize = 14
|
local itemsize = 14
|
||||||
local growsize = 95
|
local growsize = 95
|
||||||
@ -157,7 +157,7 @@ local ga_append_ints = function(garr, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- enhanced constructors
|
-- enhanced constructors
|
||||||
local garray_ctype = ffi.typeof('garray_T[1]')
|
local garray_ctype = function(...) return ffi.typeof('garray_T[1]')(...) end
|
||||||
local new_garray = function()
|
local new_garray = function()
|
||||||
local garr = garray_ctype()
|
local garr = garray_ctype()
|
||||||
return ffi.gc(garr, ga_clear)
|
return ffi.gc(garr, ga_clear)
|
||||||
|
@ -13,6 +13,7 @@ local syscall = nil
|
|||||||
local check_cores = global_helpers.check_cores
|
local check_cores = global_helpers.check_cores
|
||||||
local which = global_helpers.which
|
local which = global_helpers.which
|
||||||
local neq = global_helpers.neq
|
local neq = global_helpers.neq
|
||||||
|
local map = global_helpers.map
|
||||||
local eq = global_helpers.eq
|
local eq = global_helpers.eq
|
||||||
local ok = global_helpers.ok
|
local ok = global_helpers.ok
|
||||||
|
|
||||||
@ -22,13 +23,82 @@ local NULL = ffi.cast('void*', 0)
|
|||||||
local OK = 1
|
local OK = 1
|
||||||
local FAIL = 0
|
local FAIL = 0
|
||||||
|
|
||||||
|
local cimport
|
||||||
|
|
||||||
-- add some standard header locations
|
-- add some standard header locations
|
||||||
for _, p in ipairs(Paths.include_paths) do
|
for _, p in ipairs(Paths.include_paths) do
|
||||||
Preprocess.add_to_include_path(p)
|
Preprocess.add_to_include_path(p)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- load neovim shared library
|
local pid = nil
|
||||||
local libnvim = ffi.load(Paths.test_libnvim_path)
|
local function only_separate(func)
|
||||||
|
return function(...)
|
||||||
|
if pid ~= 0 then
|
||||||
|
eq(0, 'This function must be run in a separate process only')
|
||||||
|
end
|
||||||
|
return func(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local deferred_calls_init = {}
|
||||||
|
local deferred_calls_mod = nil
|
||||||
|
local function deferred_call(func, ret)
|
||||||
|
return function(...)
|
||||||
|
local deferred_calls = deferred_calls_mod or deferred_calls_init
|
||||||
|
if pid ~= 0 then
|
||||||
|
deferred_calls[#deferred_calls + 1] = {func=func, args={...}}
|
||||||
|
return ret
|
||||||
|
else
|
||||||
|
return func(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local separate_cleanups_mod = nil
|
||||||
|
local function separate_cleanup(func)
|
||||||
|
return function(...)
|
||||||
|
local separate_cleanups = separate_cleanups_mod
|
||||||
|
if pid ~= 0 then
|
||||||
|
separate_cleanups[#separate_cleanups + 1] = {args={...}}
|
||||||
|
else
|
||||||
|
func(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local libnvim = nil
|
||||||
|
|
||||||
|
local lib = setmetatable({}, {
|
||||||
|
__index = only_separate(function(tbl, idx)
|
||||||
|
return libnvim[idx]
|
||||||
|
end),
|
||||||
|
__newindex = deferred_call(function(tbl, idx, val)
|
||||||
|
libnvim[idx] = val
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
local init = only_separate(function()
|
||||||
|
-- load neovim shared library
|
||||||
|
libnvim = ffi.load(Paths.test_libnvim_path)
|
||||||
|
for _, c in ipairs(deferred_calls_init) do
|
||||||
|
c.func(unpack(c.args))
|
||||||
|
end
|
||||||
|
libnvim.time_init()
|
||||||
|
libnvim.early_init()
|
||||||
|
libnvim.event_init()
|
||||||
|
if deferred_calls_mod then
|
||||||
|
for _, c in ipairs(deferred_calls_mod) do
|
||||||
|
c.func(unpack(c.args))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local deinit = only_separate(function()
|
||||||
|
if separate_cleanups_mod then
|
||||||
|
for _, c in ipairs(separate_cleanups_mod) do
|
||||||
|
c.func(unpack(c.args))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
local function trim(s)
|
local function trim(s)
|
||||||
return s:match('^%s*(.*%S)') or ''
|
return s:match('^%s*(.*%S)') or ''
|
||||||
@ -58,52 +128,74 @@ local function filter_complex_blocks(body)
|
|||||||
return table.concat(result, "\n")
|
return table.concat(result, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
local previous_defines = ''
|
|
||||||
|
|
||||||
local cdef = ffi.cdef
|
local cdef = ffi.cdef
|
||||||
|
|
||||||
local cimportstr
|
local cimportstr
|
||||||
|
|
||||||
|
local previous_defines_init = ''
|
||||||
|
local preprocess_cache_init = {}
|
||||||
|
local previous_defines_mod = ''
|
||||||
|
local preprocess_cache_mod = nil
|
||||||
|
|
||||||
-- use this helper to import C files, you can pass multiple paths at once,
|
-- use this helper to import C files, you can pass multiple paths at once,
|
||||||
-- this helper will return the C namespace of the nvim library.
|
-- this helper will return the C namespace of the nvim library.
|
||||||
local function cimport(...)
|
cimport = function(...)
|
||||||
local paths = {}
|
local previous_defines, preprocess_cache
|
||||||
local args = {...}
|
if preprocess_cache_mod then
|
||||||
|
preprocess_cache = preprocess_cache_mod
|
||||||
-- filter out paths we've already imported
|
previous_defines = previous_defines_mod
|
||||||
for _,path in pairs(args) do
|
else
|
||||||
if path ~= nil and not imported:contains(path) then
|
preprocess_cache = preprocess_cache_init
|
||||||
paths[#paths + 1] = path
|
previous_defines = previous_defines_init
|
||||||
|
end
|
||||||
|
for _, path in ipairs({...}) do
|
||||||
|
if not (path:sub(1, 1) == '/' or path:sub(1, 1) == '.'
|
||||||
|
or path:sub(2, 2) == ':') then
|
||||||
|
path = './' .. path
|
||||||
end
|
end
|
||||||
|
local body
|
||||||
|
if preprocess_cache[path] then
|
||||||
|
body = preprocess_cache[path]
|
||||||
|
else
|
||||||
|
body, previous_defines = Preprocess.preprocess(previous_defines, path)
|
||||||
|
-- format it (so that the lines are "unique" statements), also filter out
|
||||||
|
-- Objective-C blocks
|
||||||
|
if os.getenv('NVIM_TEST_PRINT_I') == '1' then
|
||||||
|
local lnum = 0
|
||||||
|
for line in body:gmatch('[^\n]+') do
|
||||||
|
lnum = lnum + 1
|
||||||
|
print(lnum, line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
body = formatc(body)
|
||||||
|
body = filter_complex_blocks(body)
|
||||||
|
preprocess_cache[path] = body
|
||||||
|
end
|
||||||
|
cimportstr(preprocess_cache, path)
|
||||||
end
|
end
|
||||||
|
return lib
|
||||||
for _,path in pairs(paths) do
|
|
||||||
imported:add(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
if #paths == 0 then
|
|
||||||
return libnvim
|
|
||||||
end
|
|
||||||
|
|
||||||
local body
|
|
||||||
body, previous_defines = Preprocess.preprocess(previous_defines, unpack(paths))
|
|
||||||
|
|
||||||
return cimportstr(body)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
cimportstr = function(body)
|
local cimport_immediate = function(...)
|
||||||
-- format it (so that the lines are "unique" statements), also filter out
|
local saved_pid = pid
|
||||||
-- Objective-C blocks
|
pid = 0
|
||||||
if os.getenv('NVIM_TEST_PRINT_I') == '1' then
|
local err, emsg = pcall(cimport, ...)
|
||||||
local lnum = 0
|
pid = saved_pid
|
||||||
for line in body:gmatch('[^\n]+') do
|
if not err then
|
||||||
lnum = lnum + 1
|
emsg = tostring(emsg)
|
||||||
print(lnum, line)
|
io.stderr:write(emsg .. '\n')
|
||||||
end
|
assert(false)
|
||||||
|
else
|
||||||
|
return lib
|
||||||
end
|
end
|
||||||
body = formatc(body)
|
end
|
||||||
body = filter_complex_blocks(body)
|
|
||||||
|
|
||||||
|
cimportstr = deferred_call(function(preprocess_cache, path)
|
||||||
|
if imported:contains(path) then
|
||||||
|
return lib
|
||||||
|
end
|
||||||
|
local body = preprocess_cache[path]
|
||||||
-- add the formatted lines to a set
|
-- add the formatted lines to a set
|
||||||
local new_cdefs = Set:new()
|
local new_cdefs = Set:new()
|
||||||
for line in body:gmatch("[^\r\n]+") do
|
for line in body:gmatch("[^\r\n]+") do
|
||||||
@ -126,7 +218,7 @@ cimportstr = function(body)
|
|||||||
|
|
||||||
if new_cdefs:size() == 0 then
|
if new_cdefs:size() == 0 then
|
||||||
-- if there's no new lines, just return
|
-- if there's no new lines, just return
|
||||||
return libnvim
|
return lib
|
||||||
end
|
end
|
||||||
|
|
||||||
-- request a sorted version of the new lines (same relative order as the
|
-- request a sorted version of the new lines (same relative order as the
|
||||||
@ -138,13 +230,10 @@ cimportstr = function(body)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
cdef(table.concat(new_lines, "\n"))
|
cdef(table.concat(new_lines, "\n"))
|
||||||
|
imported:add(path)
|
||||||
|
|
||||||
return libnvim
|
return lib
|
||||||
end
|
end, lib)
|
||||||
|
|
||||||
local function cppimport(path)
|
|
||||||
return cimport(Paths.test_include_path .. '/' .. path)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function alloc_log_new()
|
local function alloc_log_new()
|
||||||
local log = {
|
local log = {
|
||||||
@ -156,9 +245,12 @@ local function alloc_log_new()
|
|||||||
local allocator_functions = {'malloc', 'free', 'calloc', 'realloc'}
|
local allocator_functions = {'malloc', 'free', 'calloc', 'realloc'}
|
||||||
function log:save_original_functions()
|
function log:save_original_functions()
|
||||||
for _, funcname in ipairs(allocator_functions) do
|
for _, funcname in ipairs(allocator_functions) do
|
||||||
self.original_functions[funcname] = self.lib['mem_' .. funcname]
|
if not self.original_functions[funcname] then
|
||||||
|
self.original_functions[funcname] = self.lib['mem_' .. funcname]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
log.save_original_functions = deferred_call(log.save_original_functions)
|
||||||
function log:set_mocks()
|
function log:set_mocks()
|
||||||
for _, k in ipairs(allocator_functions) do
|
for _, k in ipairs(allocator_functions) do
|
||||||
do
|
do
|
||||||
@ -185,6 +277,7 @@ local function alloc_log_new()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
log.set_mocks = deferred_call(log.set_mocks)
|
||||||
function log:clear()
|
function log:clear()
|
||||||
self.log = {}
|
self.log = {}
|
||||||
end
|
end
|
||||||
@ -193,22 +286,28 @@ local function alloc_log_new()
|
|||||||
self:clear()
|
self:clear()
|
||||||
end
|
end
|
||||||
function log:restore_original_functions()
|
function log:restore_original_functions()
|
||||||
for k, v in pairs(self.original_functions) do
|
-- Do nothing: set mocks live in a separate process
|
||||||
self.lib['mem_' .. k] = v
|
return
|
||||||
end
|
--[[
|
||||||
|
[ for k, v in pairs(self.original_functions) do
|
||||||
|
[ self.lib['mem_' .. k] = v
|
||||||
|
[ end
|
||||||
|
]]
|
||||||
end
|
end
|
||||||
function log:before_each()
|
function log:setup()
|
||||||
log:save_original_functions()
|
log:save_original_functions()
|
||||||
log:set_mocks()
|
log:set_mocks()
|
||||||
end
|
end
|
||||||
|
function log:before_each()
|
||||||
|
return
|
||||||
|
end
|
||||||
function log:after_each()
|
function log:after_each()
|
||||||
log:restore_original_functions()
|
log:restore_original_functions()
|
||||||
end
|
end
|
||||||
|
log:setup()
|
||||||
return log
|
return log
|
||||||
end
|
end
|
||||||
|
|
||||||
cimport('./src/nvim/types.h')
|
|
||||||
|
|
||||||
-- take a pointer to a C-allocated string and return an interned
|
-- take a pointer to a C-allocated string and return an interned
|
||||||
-- version while also freeing the memory
|
-- version while also freeing the memory
|
||||||
local function internalize(cdata, len)
|
local function internalize(cdata, len)
|
||||||
@ -221,16 +320,6 @@ local function to_cstr(string)
|
|||||||
return cstr(#string + 1, string)
|
return cstr(#string + 1, string)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- initialize some global variables, this is still necessary to unit test
|
|
||||||
-- functions that rely on global state.
|
|
||||||
do
|
|
||||||
local main = cimport('./src/nvim/main.h')
|
|
||||||
local time = cimport('./src/nvim/os/time.h')
|
|
||||||
time.time_init()
|
|
||||||
main.early_init()
|
|
||||||
main.event_init()
|
|
||||||
end
|
|
||||||
|
|
||||||
local sc
|
local sc
|
||||||
|
|
||||||
if posix ~= nil then
|
if posix ~= nil then
|
||||||
@ -263,7 +352,7 @@ elseif syscall ~= nil then
|
|||||||
exit = syscall.exit,
|
exit = syscall.exit,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cimport('./test/unit/fixtures/posix.h')
|
cimport_immediate('./test/unit/fixtures/posix.h')
|
||||||
sc = {
|
sc = {
|
||||||
fork = function()
|
fork = function()
|
||||||
return tonumber(ffi.C.fork())
|
return tonumber(ffi.C.fork())
|
||||||
@ -291,7 +380,7 @@ else
|
|||||||
len - total_bytes_read))
|
len - total_bytes_read))
|
||||||
if bytes_read == -1 then
|
if bytes_read == -1 then
|
||||||
local err = ffi.errno(0)
|
local err = ffi.errno(0)
|
||||||
if err ~= libnvim.kPOSIXErrnoEINTR then
|
if err ~= ffi.C.kPOSIXErrnoEINTR then
|
||||||
assert(false, ("read() error: %u: %s"):format(
|
assert(false, ("read() error: %u: %s"):format(
|
||||||
err, ffi.string(ffi.C.strerror(err))))
|
err, ffi.string(ffi.C.strerror(err))))
|
||||||
end
|
end
|
||||||
@ -314,7 +403,7 @@ else
|
|||||||
#s - total_bytes_written))
|
#s - total_bytes_written))
|
||||||
if bytes_written == -1 then
|
if bytes_written == -1 then
|
||||||
local err = ffi.errno(0)
|
local err = ffi.errno(0)
|
||||||
if err ~= libnvim.kPOSIXErrnoEINTR then
|
if err ~= ffi.C.kPOSIXErrnoEINTR then
|
||||||
assert(false, ("write() error: %u: %s"):format(
|
assert(false, ("write() error: %u: %s"):format(
|
||||||
err, ffi.string(ffi.C.strerror(err))))
|
err, ffi.string(ffi.C.strerror(err))))
|
||||||
end
|
end
|
||||||
@ -330,12 +419,12 @@ else
|
|||||||
wait = function(pid)
|
wait = function(pid)
|
||||||
ffi.errno(0)
|
ffi.errno(0)
|
||||||
while true do
|
while true do
|
||||||
local r = ffi.C.waitpid(pid, nil, libnvim.kPOSIXWaitWUNTRACED)
|
local r = ffi.C.waitpid(pid, nil, ffi.C.kPOSIXWaitWUNTRACED)
|
||||||
if r == -1 then
|
if r == -1 then
|
||||||
local err = ffi.errno(0)
|
local err = ffi.errno(0)
|
||||||
if err == libnvim.kPOSIXErrnoECHILD then
|
if err == ffi.C.kPOSIXErrnoECHILD then
|
||||||
break
|
break
|
||||||
elseif err ~= libnvim.kPOSIXErrnoEINTR then
|
elseif err ~= ffi.C.kPOSIXErrnoEINTR then
|
||||||
assert(false, ("waitpid() error: %u: %s"):format(
|
assert(false, ("waitpid() error: %u: %s"):format(
|
||||||
err, ffi.string(ffi.C.strerror(err))))
|
err, ffi.string(ffi.C.strerror(err))))
|
||||||
end
|
end
|
||||||
@ -371,6 +460,10 @@ if os.getenv('NVIM_TEST_PRINT_SYSCALLS') == '1' then
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function gen_itp(it)
|
local function gen_itp(it)
|
||||||
|
deferred_calls_mod = {}
|
||||||
|
deferred_cleanups_mod = {}
|
||||||
|
preprocess_cache_mod = map(function(v) return v end, preprocess_cache_init)
|
||||||
|
previous_defines_mod = previous_defines_init
|
||||||
local function just_fail(_)
|
local function just_fail(_)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@ -386,8 +479,9 @@ local function gen_itp(it)
|
|||||||
end
|
end
|
||||||
it(name, function()
|
it(name, function()
|
||||||
local rd, wr = sc.pipe()
|
local rd, wr = sc.pipe()
|
||||||
local pid = sc.fork()
|
pid = sc.fork()
|
||||||
if pid == 0 then
|
if pid == 0 then
|
||||||
|
init()
|
||||||
sc.close(rd)
|
sc.close(rd)
|
||||||
collectgarbage('stop')
|
collectgarbage('stop')
|
||||||
local err, emsg = pcall(func)
|
local err, emsg = pcall(func)
|
||||||
@ -395,16 +489,19 @@ local function gen_itp(it)
|
|||||||
emsg = tostring(emsg)
|
emsg = tostring(emsg)
|
||||||
if not err then
|
if not err then
|
||||||
sc.write(wr, ('-\n%05u\n%s'):format(#emsg, emsg))
|
sc.write(wr, ('-\n%05u\n%s'):format(#emsg, emsg))
|
||||||
|
deinit()
|
||||||
sc.close(wr)
|
sc.close(wr)
|
||||||
sc.exit(1)
|
sc.exit(1)
|
||||||
else
|
else
|
||||||
sc.write(wr, '+\n')
|
sc.write(wr, '+\n')
|
||||||
|
deinit()
|
||||||
sc.close(wr)
|
sc.close(wr)
|
||||||
sc.exit(0)
|
sc.exit(0)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
sc.close(wr)
|
sc.close(wr)
|
||||||
sc.wait(pid)
|
sc.wait(pid)
|
||||||
|
pid = nil
|
||||||
local function check()
|
local function check()
|
||||||
local res = sc.read(rd, 2)
|
local res = sc.read(rd, 2)
|
||||||
eq(2, #res)
|
eq(2, #res)
|
||||||
@ -433,6 +530,12 @@ local function gen_itp(it)
|
|||||||
return itp
|
return itp
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function cppimport(path)
|
||||||
|
return cimport(Paths.test_include_path .. '/' .. path)
|
||||||
|
end
|
||||||
|
|
||||||
|
cimport('./src/nvim/types.h', './src/nvim/main.h', './src/nvim/os/time.h')
|
||||||
|
|
||||||
local module = {
|
local module = {
|
||||||
cimport = cimport,
|
cimport = cimport,
|
||||||
cppimport = cppimport,
|
cppimport = cppimport,
|
||||||
@ -441,7 +544,7 @@ local module = {
|
|||||||
eq = eq,
|
eq = eq,
|
||||||
neq = neq,
|
neq = neq,
|
||||||
ffi = ffi,
|
ffi = ffi,
|
||||||
lib = libnvim,
|
lib = lib,
|
||||||
cstr = cstr,
|
cstr = cstr,
|
||||||
to_cstr = to_cstr,
|
to_cstr = to_cstr,
|
||||||
NULL = NULL,
|
NULL = NULL,
|
||||||
@ -449,6 +552,9 @@ local module = {
|
|||||||
FAIL = FAIL,
|
FAIL = FAIL,
|
||||||
alloc_log_new = alloc_log_new,
|
alloc_log_new = alloc_log_new,
|
||||||
gen_itp = gen_itp,
|
gen_itp = gen_itp,
|
||||||
|
only_separate = only_separate,
|
||||||
|
deferred_call = deferred_call,
|
||||||
|
separate_cleanup = separate_cleanup,
|
||||||
}
|
}
|
||||||
return function(after_each)
|
return function(after_each)
|
||||||
if after_each then
|
if after_each then
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
local helpers = require("test.unit.helpers")(after_each)
|
local helpers = require("test.unit.helpers")(after_each)
|
||||||
local itp = helpers.gen_itp(it)
|
local itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local ffi = helpers.ffi
|
local deferred_call = helpers.deferred_call
|
||||||
local eq = helpers.eq
|
local cimport = helpers.cimport
|
||||||
|
local ffi = helpers.ffi
|
||||||
|
local eq = helpers.eq
|
||||||
|
|
||||||
local multiqueue = helpers.cimport("./test/unit/fixtures/multiqueue.h")
|
local multiqueue = cimport("./test/unit/fixtures/multiqueue.h")
|
||||||
|
|
||||||
describe("multiqueue (multi-level event-queue)", function()
|
describe("multiqueue (multi-level event-queue)", function()
|
||||||
local parent, child1, child2, child3
|
local parent, child1, child2, child3
|
||||||
@ -21,7 +23,7 @@ describe("multiqueue (multi-level event-queue)", function()
|
|||||||
multiqueue.multiqueue_free(q)
|
multiqueue.multiqueue_free(q)
|
||||||
end
|
end
|
||||||
|
|
||||||
before_each(function()
|
before_each(deferred_call(function()
|
||||||
parent = multiqueue.multiqueue_new_parent(ffi.NULL, ffi.NULL)
|
parent = multiqueue.multiqueue_new_parent(ffi.NULL, ffi.NULL)
|
||||||
child1 = multiqueue.multiqueue_new_child(parent)
|
child1 = multiqueue.multiqueue_new_child(parent)
|
||||||
child2 = multiqueue.multiqueue_new_child(parent)
|
child2 = multiqueue.multiqueue_new_child(parent)
|
||||||
@ -35,7 +37,7 @@ describe("multiqueue (multi-level event-queue)", function()
|
|||||||
put(child2, 'c2i4')
|
put(child2, 'c2i4')
|
||||||
put(child3, 'c3i1')
|
put(child3, 'c3i1')
|
||||||
put(child3, 'c3i2')
|
put(child3, 'c3i2')
|
||||||
end)
|
end))
|
||||||
|
|
||||||
itp('keeps count of added events', function()
|
itp('keeps count of added events', function()
|
||||||
eq(3, multiqueue.multiqueue_size(child1))
|
eq(3, multiqueue.multiqueue_size(child1))
|
||||||
|
@ -16,10 +16,10 @@ local to_cstr = helpers.to_cstr
|
|||||||
local OK = helpers.OK
|
local OK = helpers.OK
|
||||||
local FAIL = helpers.FAIL
|
local FAIL = helpers.FAIL
|
||||||
local NULL = helpers.NULL
|
local NULL = helpers.NULL
|
||||||
|
|
||||||
local NODE_NORMAL = 0
|
local NODE_NORMAL = 0
|
||||||
local NODE_WRITABLE = 1
|
local NODE_WRITABLE = 1
|
||||||
|
|
||||||
cimport('unistd.h')
|
|
||||||
cimport('./src/nvim/os/shell.h')
|
cimport('./src/nvim/os/shell.h')
|
||||||
cimport('./src/nvim/option_defs.h')
|
cimport('./src/nvim/option_defs.h')
|
||||||
cimport('./src/nvim/main.h')
|
cimport('./src/nvim/main.h')
|
||||||
@ -66,13 +66,10 @@ local function os_getperm(filename)
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe('fs function', function()
|
describe('fs function', function()
|
||||||
local orig_test_file_perm
|
before_each(function()
|
||||||
|
|
||||||
setup(function()
|
|
||||||
lfs.mkdir('unit-test-directory');
|
lfs.mkdir('unit-test-directory');
|
||||||
|
|
||||||
io.open('unit-test-directory/test.file', 'w').close()
|
io.open('unit-test-directory/test.file', 'w').close()
|
||||||
orig_test_file_perm = os_getperm('unit-test-directory/test.file')
|
|
||||||
|
|
||||||
io.open('unit-test-directory/test_2.file', 'w').close()
|
io.open('unit-test-directory/test_2.file', 'w').close()
|
||||||
lfs.link('test.file', 'unit-test-directory/test_link.file', true)
|
lfs.link('test.file', 'unit-test-directory/test_link.file', true)
|
||||||
@ -84,7 +81,7 @@ describe('fs function', function()
|
|||||||
directory, executable_name = string.match(absolute_executable, '^(.*)/(.*)$')
|
directory, executable_name = string.match(absolute_executable, '^(.*)/(.*)$')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
teardown(function()
|
after_each(function()
|
||||||
os.remove('unit-test-directory/test.file')
|
os.remove('unit-test-directory/test.file')
|
||||||
os.remove('unit-test-directory/test_2.file')
|
os.remove('unit-test-directory/test_2.file')
|
||||||
os.remove('unit-test-directory/test_link.file')
|
os.remove('unit-test-directory/test_link.file')
|
||||||
@ -217,10 +214,6 @@ describe('fs function', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe('file permissions', function()
|
describe('file permissions', function()
|
||||||
before_each(function()
|
|
||||||
os_setperm('unit-test-directory/test.file', orig_test_file_perm)
|
|
||||||
end)
|
|
||||||
|
|
||||||
local function os_fchown(filename, user_id, group_id)
|
local function os_fchown(filename, user_id, group_id)
|
||||||
local fd = ffi.C.open(filename, 0)
|
local fd = ffi.C.open(filename, 0)
|
||||||
local res = fs.os_fchown(fd, user_id, group_id)
|
local res = fs.os_fchown(fd, user_id, group_id)
|
||||||
|
@ -11,6 +11,7 @@ local ffi, eq = helpers.ffi, helpers.eq
|
|||||||
local intern = helpers.internalize
|
local intern = helpers.internalize
|
||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
local NULL = ffi.cast('void *', 0)
|
local NULL = ffi.cast('void *', 0)
|
||||||
|
local deferred_call = deferred_call
|
||||||
|
|
||||||
describe('shell functions', function()
|
describe('shell functions', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
@ -73,25 +74,13 @@ describe('shell functions', function()
|
|||||||
eq(0, status)
|
eq(0, status)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it ('returns non-zero exit code', function()
|
itp('returns non-zero exit code', function()
|
||||||
local status = os_system('exit 2')
|
local status = os_system('exit 2')
|
||||||
eq(2, status)
|
eq(2, status)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('shell_build_argv', function()
|
describe('shell_build_argv', function()
|
||||||
local saved_opts = {}
|
|
||||||
|
|
||||||
setup(function()
|
|
||||||
saved_opts.p_sh = cimported.p_sh
|
|
||||||
saved_opts.p_shcf = cimported.p_shcf
|
|
||||||
end)
|
|
||||||
|
|
||||||
teardown(function()
|
|
||||||
cimported.p_sh = saved_opts.p_sh
|
|
||||||
cimported.p_shcf = saved_opts.p_shcf
|
|
||||||
end)
|
|
||||||
|
|
||||||
itp('works with NULL arguments', function()
|
itp('works with NULL arguments', function()
|
||||||
eq({'/bin/bash'}, shell_build_argv(nil, nil))
|
eq({'/bin/bash'}, shell_build_argv(nil, nil))
|
||||||
end)
|
end)
|
||||||
|
@ -15,13 +15,6 @@ local FAIL = helpers.FAIL
|
|||||||
cimport('string.h')
|
cimport('string.h')
|
||||||
local path = cimport('./src/nvim/path.h')
|
local path = cimport('./src/nvim/path.h')
|
||||||
|
|
||||||
-- import constants parsed by ffi
|
|
||||||
local kEqualFiles = path.kEqualFiles
|
|
||||||
local kDifferentFiles = path.kDifferentFiles
|
|
||||||
local kBothFilesMissing = path.kBothFilesMissing
|
|
||||||
local kOneFileMissing = path.kOneFileMissing
|
|
||||||
local kEqualFileNames = path.kEqualFileNames
|
|
||||||
|
|
||||||
local length = 0
|
local length = 0
|
||||||
local buffer = nil
|
local buffer = nil
|
||||||
|
|
||||||
@ -93,25 +86,25 @@ describe('path function', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
itp('returns kEqualFiles when passed the same file', function()
|
itp('returns kEqualFiles when passed the same file', function()
|
||||||
eq(kEqualFiles, (path_full_compare(f1, f1)))
|
eq(path.kEqualFiles, (path_full_compare(f1, f1)))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('returns kEqualFileNames when files that dont exist and have same name', function()
|
itp('returns kEqualFileNames when files that dont exist and have same name', function()
|
||||||
eq(kEqualFileNames, (path_full_compare('null.txt', 'null.txt', true)))
|
eq(path.kEqualFileNames, (path_full_compare('null.txt', 'null.txt', true)))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('returns kBothFilesMissing when files that dont exist', function()
|
itp('returns kBothFilesMissing when files that dont exist', function()
|
||||||
eq(kBothFilesMissing, (path_full_compare('null.txt', 'null.txt')))
|
eq(path.kBothFilesMissing, (path_full_compare('null.txt', 'null.txt')))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('returns kDifferentFiles when passed different files', function()
|
itp('returns kDifferentFiles when passed different files', function()
|
||||||
eq(kDifferentFiles, (path_full_compare(f1, f2)))
|
eq(path.kDifferentFiles, (path_full_compare(f1, f2)))
|
||||||
eq(kDifferentFiles, (path_full_compare(f2, f1)))
|
eq(path.kDifferentFiles, (path_full_compare(f2, f1)))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('returns kOneFileMissing if only one does not exist', function()
|
itp('returns kOneFileMissing if only one does not exist', function()
|
||||||
eq(kOneFileMissing, (path_full_compare(f1, 'null.txt')))
|
eq(path.kOneFileMissing, (path_full_compare(f1, 'null.txt')))
|
||||||
eq(kOneFileMissing, (path_full_compare('null.txt', f1)))
|
eq(path.kOneFileMissing, (path_full_compare('null.txt', f1)))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
local helpers = require 'test.unit.helpers'
|
local helpers = require('test.unit.helpers')(after_each)
|
||||||
local itp = helpers.gen_itp(it)
|
local itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local prof = helpers.cimport './src/nvim/profile.h'
|
local cimport = helpers.cimport
|
||||||
local ffi = helpers.ffi
|
local ffi = helpers.ffi
|
||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local neq = helpers.neq
|
local neq = helpers.neq
|
||||||
|
|
||||||
|
local prof = cimport('./src/nvim/profile.h')
|
||||||
|
|
||||||
local function split(inputstr, sep)
|
local function split(inputstr, sep)
|
||||||
if sep == nil then
|
if sep == nil then
|
||||||
sep = "%s"
|
sep = "%s"
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
local helpers = require("test.unit.helpers")(after_each)
|
local helpers = require("test.unit.helpers")(after_each)
|
||||||
local itp = helpers.gen_itp(it)
|
local itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local ffi = helpers.ffi
|
local eq = helpers.eq
|
||||||
local eq = helpers.eq
|
local ffi = helpers.ffi
|
||||||
local cstr = helpers.cstr
|
local cstr = helpers.cstr
|
||||||
local to_cstr = helpers.to_cstr
|
local to_cstr = helpers.to_cstr
|
||||||
|
local deferred_call = helpers.deferred_call
|
||||||
|
|
||||||
local rbuffer = helpers.cimport("./test/unit/fixtures/rbuffer.h")
|
local rbuffer = helpers.cimport("./test/unit/fixtures/rbuffer.h")
|
||||||
|
|
||||||
@ -31,11 +32,11 @@ describe('rbuffer functions', function()
|
|||||||
return ffi.string(rbuffer.rbuffer_get(rbuf, idx), 1)
|
return ffi.string(rbuffer.rbuffer_get(rbuf, idx), 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
before_each(function()
|
before_each(deferred_call(function()
|
||||||
rbuf = ffi.gc(rbuffer.rbuffer_new(capacity), rbuffer.rbuffer_free)
|
rbuf = ffi.gc(rbuffer.rbuffer_new(capacity), rbuffer.rbuffer_free)
|
||||||
-- fill the internal buffer with the character '0' to simplify inspecting
|
-- fill the internal buffer with the character '0' to simplify inspecting
|
||||||
ffi.C.memset(rbuf.start_ptr, string.byte('0'), capacity)
|
ffi.C.memset(rbuf.start_ptr, string.byte('0'), capacity)
|
||||||
end)
|
end))
|
||||||
|
|
||||||
describe('RBUFFER_UNTIL_FULL', function()
|
describe('RBUFFER_UNTIL_FULL', function()
|
||||||
local chunks
|
local chunks
|
||||||
@ -58,59 +59,44 @@ describe('rbuffer functions', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with partially empty buffer in one contiguous chunk', function()
|
describe('with partially empty buffer in one contiguous chunk', function()
|
||||||
before_each(function()
|
|
||||||
write('string')
|
|
||||||
end)
|
|
||||||
|
|
||||||
itp('is called once with the empty chunk', function()
|
itp('is called once with the empty chunk', function()
|
||||||
|
write('string')
|
||||||
collect_write_chunks()
|
collect_write_chunks()
|
||||||
eq({'0000000000'}, chunks)
|
eq({'0000000000'}, chunks)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with filled buffer in one contiguous chunk', function()
|
describe('with filled buffer in one contiguous chunk', function()
|
||||||
before_each(function()
|
|
||||||
write('abcdefghijklmnopq')
|
|
||||||
end)
|
|
||||||
|
|
||||||
itp('is not called', function()
|
itp('is not called', function()
|
||||||
|
write('abcdefghijklmnopq')
|
||||||
collect_write_chunks()
|
collect_write_chunks()
|
||||||
eq({}, chunks)
|
eq({}, chunks)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with buffer partially empty in two contiguous chunks', function()
|
describe('with buffer partially empty in two contiguous chunks', function()
|
||||||
before_each(function()
|
itp('is called twice with each filled chunk', function()
|
||||||
write('1234567890')
|
write('1234567890')
|
||||||
read(8)
|
read(8)
|
||||||
end)
|
|
||||||
|
|
||||||
itp('is called twice with each filled chunk', function()
|
|
||||||
collect_write_chunks()
|
collect_write_chunks()
|
||||||
eq({'000000', '12345678'}, chunks)
|
eq({'000000', '12345678'}, chunks)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with buffer empty in two contiguous chunks', function()
|
describe('with buffer empty in two contiguous chunks', function()
|
||||||
before_each(function()
|
itp('is called twice with each filled chunk', function()
|
||||||
write('12345678')
|
write('12345678')
|
||||||
read(8)
|
read(8)
|
||||||
end)
|
|
||||||
|
|
||||||
itp('is called twice with each filled chunk', function()
|
|
||||||
collect_write_chunks()
|
collect_write_chunks()
|
||||||
eq({'00000000', '12345678'}, chunks)
|
eq({'00000000', '12345678'}, chunks)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with buffer filled in two contiguous chunks', function()
|
describe('with buffer filled in two contiguous chunks', function()
|
||||||
before_each(function()
|
itp('is not called', function()
|
||||||
write('12345678')
|
write('12345678')
|
||||||
read(8)
|
read(8)
|
||||||
write('abcdefghijklmnopq')
|
write('abcdefghijklmnopq')
|
||||||
end)
|
|
||||||
|
|
||||||
itp('is not called', function()
|
|
||||||
collect_write_chunks()
|
collect_write_chunks()
|
||||||
eq({}, chunks)
|
eq({}, chunks)
|
||||||
end)
|
end)
|
||||||
@ -138,48 +124,36 @@ describe('rbuffer functions', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with partially filled buffer in one contiguous chunk', function()
|
describe('with partially filled buffer in one contiguous chunk', function()
|
||||||
before_each(function()
|
|
||||||
write('string')
|
|
||||||
end)
|
|
||||||
|
|
||||||
itp('is called once with the filled chunk', function()
|
itp('is called once with the filled chunk', function()
|
||||||
|
write('string')
|
||||||
collect_read_chunks()
|
collect_read_chunks()
|
||||||
eq({'string'}, chunks)
|
eq({'string'}, chunks)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with filled buffer in one contiguous chunk', function()
|
describe('with filled buffer in one contiguous chunk', function()
|
||||||
before_each(function()
|
|
||||||
write('abcdefghijklmnopq')
|
|
||||||
end)
|
|
||||||
|
|
||||||
itp('is called once with the filled chunk', function()
|
itp('is called once with the filled chunk', function()
|
||||||
|
write('abcdefghijklmnopq')
|
||||||
collect_read_chunks()
|
collect_read_chunks()
|
||||||
eq({'abcdefghijklmnop'}, chunks)
|
eq({'abcdefghijklmnop'}, chunks)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with buffer partially filled in two contiguous chunks', function()
|
describe('with buffer partially filled in two contiguous chunks', function()
|
||||||
before_each(function()
|
itp('is called twice with each filled chunk', function()
|
||||||
write('1234567890')
|
write('1234567890')
|
||||||
read(10)
|
read(10)
|
||||||
write('long string')
|
write('long string')
|
||||||
end)
|
|
||||||
|
|
||||||
itp('is called twice with each filled chunk', function()
|
|
||||||
collect_read_chunks()
|
collect_read_chunks()
|
||||||
eq({'long s', 'tring'}, chunks)
|
eq({'long s', 'tring'}, chunks)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with buffer filled in two contiguous chunks', function()
|
describe('with buffer filled in two contiguous chunks', function()
|
||||||
before_each(function()
|
itp('is called twice with each filled chunk', function()
|
||||||
write('12345678')
|
write('12345678')
|
||||||
read(8)
|
read(8)
|
||||||
write('abcdefghijklmnopq')
|
write('abcdefghijklmnopq')
|
||||||
end)
|
|
||||||
|
|
||||||
itp('is called twice with each filled chunk', function()
|
|
||||||
collect_read_chunks()
|
collect_read_chunks()
|
||||||
eq({'abcdefgh', 'ijklmnop'}, chunks)
|
eq({'abcdefgh', 'ijklmnop'}, chunks)
|
||||||
end)
|
end)
|
||||||
@ -206,13 +180,10 @@ describe('rbuffer functions', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with buffer filled in two contiguous chunks', function()
|
describe('with buffer filled in two contiguous chunks', function()
|
||||||
before_each(function()
|
itp('collects each character and index', function()
|
||||||
write('1234567890')
|
write('1234567890')
|
||||||
read(10)
|
read(10)
|
||||||
write('long string')
|
write('long string')
|
||||||
end)
|
|
||||||
|
|
||||||
itp('collects each character and index', function()
|
|
||||||
collect_chars()
|
collect_chars()
|
||||||
eq({{'l', 0}, {'o', 1}, {'n', 2}, {'g', 3}, {' ', 4}, {'s', 5},
|
eq({{'l', 0}, {'o', 1}, {'n', 2}, {'g', 3}, {' ', 4}, {'s', 5},
|
||||||
{'t', 6}, {'r', 7}, {'i', 8}, {'n', 9}, {'g', 10}}, chars)
|
{'t', 6}, {'r', 7}, {'i', 8}, {'n', 9}, {'g', 10}}, chars)
|
||||||
@ -240,13 +211,10 @@ describe('rbuffer functions', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe('with buffer filled in two contiguous chunks', function()
|
describe('with buffer filled in two contiguous chunks', function()
|
||||||
before_each(function()
|
itp('collects each character and index', function()
|
||||||
write('1234567890')
|
write('1234567890')
|
||||||
read(10)
|
read(10)
|
||||||
write('long string')
|
write('long string')
|
||||||
end)
|
|
||||||
|
|
||||||
itp('collects each character and index', function()
|
|
||||||
collect_chars()
|
collect_chars()
|
||||||
eq({{'g', 10}, {'n', 9}, {'i', 8}, {'r', 7}, {'t', 6}, {'s', 5},
|
eq({{'g', 10}, {'n', 9}, {'i', 8}, {'r', 7}, {'t', 6}, {'s', 5},
|
||||||
{' ', 4}, {'g', 3}, {'n', 2}, {'o', 1}, {'l', 0}}, chars)
|
{' ', 4}, {'g', 3}, {'n', 2}, {'o', 1}, {'l', 0}}, chars)
|
||||||
@ -265,13 +233,10 @@ describe('rbuffer functions', function()
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe('with buffer filled in two contiguous chunks', function()
|
describe('with buffer filled in two contiguous chunks', function()
|
||||||
before_each(function()
|
itp('compares the common longest sequence', function()
|
||||||
write('1234567890')
|
write('1234567890')
|
||||||
read(10)
|
read(10)
|
||||||
write('long string')
|
write('long string')
|
||||||
end)
|
|
||||||
|
|
||||||
itp('compares the common longest sequence', function()
|
|
||||||
eq(0, cmp('long string'))
|
eq(0, cmp('long string'))
|
||||||
eq(0, cmp('long strin'))
|
eq(0, cmp('long strin'))
|
||||||
eq(-1, cmp('long striM'))
|
eq(-1, cmp('long striM'))
|
||||||
|
@ -1,20 +1,25 @@
|
|||||||
local lfs = require 'lfs'
|
local lfs = require('lfs')
|
||||||
local helpers = require 'test.unit.helpers'
|
local helpers = require('test.unit.helpers')(after_each)
|
||||||
local itp = helpers.gen_itp(it)
|
local itp = helpers.gen_itp(it)
|
||||||
|
|
||||||
local os = helpers.cimport './src/nvim/os/os.h'
|
local eq = helpers.eq
|
||||||
local tempfile = helpers.cimport './src/nvim/fileio.h'
|
local neq = helpers.neq
|
||||||
|
local cimport = helpers.cimport
|
||||||
|
local deferred_call = helpers.deferred_call
|
||||||
|
local separate_cleanup = helpers.separate_cleanup
|
||||||
|
|
||||||
|
local lib = cimport('./src/nvim/os/os.h', './src/nvim/fileio.h')
|
||||||
|
|
||||||
describe('tempfile related functions', function()
|
describe('tempfile related functions', function()
|
||||||
before_each(function()
|
before_each(deferred_call(function()
|
||||||
tempfile.vim_deltempdir()
|
lib.vim_deltempdir()
|
||||||
end)
|
end))
|
||||||
after_each(function()
|
separate_cleanup(function()
|
||||||
tempfile.vim_deltempdir()
|
lib.vim_deltempdir()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local vim_gettempdir = function()
|
local vim_gettempdir = function()
|
||||||
return helpers.ffi.string(tempfile.vim_gettempdir())
|
return helpers.ffi.string(lib.vim_gettempdir())
|
||||||
end
|
end
|
||||||
|
|
||||||
describe('vim_gettempdir', function()
|
describe('vim_gettempdir', function()
|
||||||
@ -23,7 +28,7 @@ describe('tempfile related functions', function()
|
|||||||
assert.True(dir ~= nil and dir:len() > 0)
|
assert.True(dir ~= nil and dir:len() > 0)
|
||||||
-- os_file_is_writable returns 2 for a directory which we have rights
|
-- os_file_is_writable returns 2 for a directory which we have rights
|
||||||
-- to write into.
|
-- to write into.
|
||||||
assert.equals(os.os_file_is_writable(helpers.to_cstr(dir)), 2)
|
eq(lib.os_file_is_writable(helpers.to_cstr(dir)), 2)
|
||||||
for entry in lfs.dir(dir) do
|
for entry in lfs.dir(dir) do
|
||||||
assert.True(entry == '.' or entry == '..')
|
assert.True(entry == '.' or entry == '..')
|
||||||
end
|
end
|
||||||
@ -32,25 +37,25 @@ describe('tempfile related functions', function()
|
|||||||
itp('returns the same directory on each call', function()
|
itp('returns the same directory on each call', function()
|
||||||
local dir1 = vim_gettempdir()
|
local dir1 = vim_gettempdir()
|
||||||
local dir2 = vim_gettempdir()
|
local dir2 = vim_gettempdir()
|
||||||
assert.equals(dir1, dir2)
|
eq(dir1, dir2)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('vim_tempname', function()
|
describe('vim_tempname', function()
|
||||||
local vim_tempname = function()
|
local vim_tempname = function()
|
||||||
return helpers.ffi.string(tempfile.vim_tempname())
|
return helpers.ffi.string(lib.vim_tempname())
|
||||||
end
|
end
|
||||||
|
|
||||||
itp('generate name of non-existing file', function()
|
itp('generate name of non-existing file', function()
|
||||||
local file = vim_tempname()
|
local file = vim_tempname()
|
||||||
assert.truthy(file)
|
assert.truthy(file)
|
||||||
assert.False(os.os_path_exists(file))
|
assert.False(lib.os_path_exists(file))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('generate different names on each call', function()
|
itp('generate different names on each call', function()
|
||||||
local fst = vim_tempname()
|
local fst = vim_tempname()
|
||||||
local snd = vim_tempname()
|
local snd = vim_tempname()
|
||||||
assert.not_equals(fst, snd)
|
neq(fst, snd)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
itp('generate file name in Neovim own temp directory', function()
|
itp('generate file name in Neovim own temp directory', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user