aboutsummaryrefslogtreecommitdiff
path: root/test/unit
diff options
context:
space:
mode:
authorJakob Schnitzer <mail@jakobschnitzer.de>2017-04-24 11:35:10 +0200
committerJakob Schnitzer <mail@jakobschnitzer.de>2017-04-24 11:35:10 +0200
commitff8b2eb435c518f0eafd0e509afe1f5ee4a81fd1 (patch)
tree526b1df09b06121bdbc6ef5254ef53821958a6cb /test/unit
parent4049492b6d7b8805686b14dbacb3b729abd03308 (diff)
parent7f6d3d305269fd1139bc2aec9a91bf98ad595199 (diff)
downloadrneovim-ff8b2eb435c518f0eafd0e509afe1f5ee4a81fd1.tar.gz
rneovim-ff8b2eb435c518f0eafd0e509afe1f5ee4a81fd1.tar.bz2
rneovim-ff8b2eb435c518f0eafd0e509afe1f5ee4a81fd1.zip
Merge branch 'master' into option-fixes
Diffstat (limited to 'test/unit')
-rw-r--r--test/unit/eval/decode_spec.lua7
-rw-r--r--test/unit/eval/helpers.lua2
-rw-r--r--test/unit/eval/typval_spec.lua87
-rw-r--r--test/unit/fixtures/multiqueue.c3
-rw-r--r--test/unit/fixtures/rbuffer.c3
-rw-r--r--test/unit/helpers.lua266
-rw-r--r--test/unit/os/env_spec.lua27
-rw-r--r--test/unit/os/fileio_spec.lua85
-rw-r--r--test/unit/testtest_spec.lua19
9 files changed, 389 insertions, 110 deletions
diff --git a/test/unit/eval/decode_spec.lua b/test/unit/eval/decode_spec.lua
index 0b2a423cd6..0c444b33f2 100644
--- a/test/unit/eval/decode_spec.lua
+++ b/test/unit/eval/decode_spec.lua
@@ -2,7 +2,6 @@ local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local cimport = helpers.cimport
-local to_cstr = helpers.to_cstr
local eq = helpers.eq
local neq = helpers.neq
local ffi = helpers.ffi
@@ -72,7 +71,7 @@ describe('json_decode_string()', function()
end
itp('does not overflow in error messages', function()
- local saved_p_enc = decode.p_enc
+ collectgarbage('restart')
check_failure(']test', 1, 'E474: No container to close: ]')
check_failure('[}test', 2, 'E474: Closing list with curly bracket: }')
check_failure('{]test', 2,
@@ -105,10 +104,6 @@ describe('json_decode_string()', function()
check_failure('"\194"test', 3, 'E474: Only UTF-8 strings allowed: \194"')
check_failure('"\252\144\128\128\128\128"test', 8, 'E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"')
check_failure('"test', 1, 'E474: Expected string end: "')
- decode.p_enc = to_cstr('latin1')
- check_failure('"\\uABCD"test', 8,
- 'E474: Failed to convert string "ꯍ" from UTF-8')
- decode.p_enc = saved_p_enc
check_failure('-test', 1, 'E474: Missing number after minus sign: -')
check_failure('-1.test', 3, 'E474: Missing number after decimal dot: -1.')
check_failure('-1.0etest', 5, 'E474: Missing exponent: -1.0e')
diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/helpers.lua
index fa76113756..5bc482216e 100644
--- a/test/unit/eval/helpers.lua
+++ b/test/unit/eval/helpers.lua
@@ -468,7 +468,7 @@ local function tbl2callback(tbl)
data={funcref=eval.xstrdup(tbl.fref)}}})
elseif tbl.type == 'pt' then
local pt = ffi.gc(ffi.cast('partial_T*',
- eval.xcalloc(1, ffi.sizeof('partial_T'))), eval.partial_unref)
+ eval.xcalloc(1, ffi.sizeof('partial_T'))), nil)
ret = ffi.new('Callback[1]', {{type=eval.kCallbackPartial,
data={partial=populate_partial(pt, tbl.pt, {})}}})
else
diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua
index 258b5c4c1f..6308ae7367 100644
--- a/test/unit/eval/typval_spec.lua
+++ b/test/unit/eval/typval_spec.lua
@@ -47,6 +47,15 @@ local lib = cimport('./src/nvim/eval/typval.h', './src/nvim/memory.h',
'./src/nvim/eval.h', './src/nvim/vim.h',
'./src/nvim/globals.h')
+local function vimconv_alloc()
+ return ffi.gc(
+ ffi.cast('vimconv_T*', lib.xcalloc(1, ffi.sizeof('vimconv_T'))),
+ function(vc)
+ lib.convert_setup(vc, nil, nil)
+ lib.xfree(vc)
+ end)
+end
+
local function list_watch_alloc(li)
return ffi.cast('listwatch_T*', ffi.new('listwatch_T[1]', {{lw_item=li}}))
end
@@ -237,24 +246,33 @@ describe('typval.c', function()
list_watch(l, lis[4]),
list_watch(l, lis[7]),
}
+ alloc_log:check({
+ a.list(l),
+ a.li(lis[1]),
+ a.li(lis[2]),
+ a.li(lis[3]),
+ a.li(lis[4]),
+ a.li(lis[5]),
+ a.li(lis[6]),
+ a.li(lis[7]),
+ })
lib.tv_list_item_remove(l, lis[4])
- ffi.gc(lis[4], lib.tv_list_item_free)
+ alloc_log:check({a.freed(lis[4])})
eq({lis[1], lis[5], lis[7]}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item})
lib.tv_list_item_remove(l, lis[2])
- ffi.gc(lis[2], lib.tv_list_item_free)
+ alloc_log:check({a.freed(lis[2])})
eq({lis[1], lis[5], lis[7]}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item})
lib.tv_list_item_remove(l, lis[7])
- ffi.gc(lis[7], lib.tv_list_item_free)
+ alloc_log:check({a.freed(lis[7])})
eq({lis[1], lis[5], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil})
lib.tv_list_item_remove(l, lis[1])
- ffi.gc(lis[1], lib.tv_list_item_free)
+ alloc_log:check({a.freed(lis[1])})
eq({lis[3], lis[5], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil})
- alloc_log:clear()
lib.tv_list_watch_remove(l, lws[2])
lib.tv_list_watch_remove(l, lws[3])
lib.tv_list_watch_remove(l, lws[1])
@@ -460,6 +478,10 @@ describe('typval.c', function()
eq(empty_list, typvalt2lua(l_tv))
eq({true, true, true}, {lws[1].lw_item == nil, lws[2].lw_item == nil, lws[3].lw_item == nil})
+ lib.tv_list_watch_remove(l, lws[1])
+ lib.tv_list_watch_remove(l, lws[2])
+ lib.tv_list_watch_remove(l, lws[3])
+
alloc_log:check({})
end)
end)
@@ -730,10 +752,8 @@ describe('typval.c', function()
collectgarbage()
end)
itp('copies list correctly and converts items', function()
- local vc = ffi.gc(ffi.new('vimconv_T[1]'), function(vc)
- lib.convert_setup(vc, nil, nil)
- end)
- -- UTF-8 ↔ latin1 conversions need no iconv
+ local vc = vimconv_alloc()
+ -- UTF-8 ↔ latin1 conversions needs no iconv
eq(OK, lib.convert_setup(vc, to_cstr('utf-8'), to_cstr('latin1')))
local v = {{['«']='»'}, {'„'}, 1, '“', null_string, null_list, null_dict}
@@ -1087,12 +1107,16 @@ describe('typval.c', function()
end)
end)
describe('join()', function()
- local function list_join(l, sep, ret)
+ local function list_join(l, sep, join_ret)
local ga = ga_alloc()
- eq(ret or OK, lib.tv_list_join(ga, l, sep))
- if ga.ga_data == nil then return ''
- else return ffi.string(ga.ga_data)
+ eq(join_ret or OK, lib.tv_list_join(ga, l, sep))
+ local ret = ''
+ if ga.ga_data ~= nil then
+ ret = ffi.string(ga.ga_data)
end
+ -- For some reason this is not working well in GC
+ lib.ga_clear(ffi.gc(ga, nil))
+ return ret
end
itp('works', function()
local l
@@ -1508,7 +1532,7 @@ describe('typval.c', function()
eq(s:sub(1, len), ffi.string(di.di_key))
alloc_log:check({a.di(di, len)})
if tv then
- di.di_tv = tv
+ di.di_tv = ffi.gc(tv, nil)
else
di.di_tv.v_type = lib.VAR_UNKNOWN
end
@@ -1539,7 +1563,7 @@ describe('typval.c', function()
alloc_log:check({a.dict(d)})
local di = ffi.gc(lib.tv_dict_item_alloc(''), nil)
local tv = lua2typvalt('test')
- di.di_tv = tv
+ di.di_tv = ffi.gc(tv, nil)
alloc_log:check({a.di(di, ''), a.str(tv.vval.v_string, 'test')})
eq(OK, lib.tv_dict_add(d, di))
alloc_log:check({})
@@ -2131,9 +2155,7 @@ describe('typval.c', function()
collectgarbage()
end)
itp('copies dict correctly and converts items', function()
- local vc = ffi.gc(ffi.new('vimconv_T[1]'), function(vc)
- lib.convert_setup(vc, nil, nil)
- end)
+ local vc = vimconv_alloc()
-- UTF-8 ↔ latin1 conversions need no iconv
eq(OK, lib.convert_setup(vc, to_cstr('utf-8'), to_cstr('latin1')))
@@ -2428,6 +2450,10 @@ describe('typval.c', function()
'E741: Value is locked: Unknown'))
eq(true, tv_check_lock(lib.VAR_FIXED, nil, 0,
'E742: Cannot change value of Unknown'))
+ eq(true, tv_check_lock(lib.VAR_LOCKED, nil, lib.kTVCstring,
+ 'E741: Value is locked: Unknown'))
+ eq(true, tv_check_lock(lib.VAR_FIXED, 'test', lib.kTVCstring,
+ 'E742: Cannot change value of test'))
end)
end)
describe('equal()', function()
@@ -2659,7 +2685,8 @@ describe('typval.c', function()
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 0},
{lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0},
}) do
- local tv = typvalt(v[1], v[2])
+ -- Using to_cstr, cannot free with tv_clear
+ local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
@@ -2687,7 +2714,8 @@ describe('typval.c', function()
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 0},
{lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0},
}) do
- local tv = typvalt(v[1], v[2])
+ -- Using to_cstr, cannot free with tv_clear
+ local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = {v[4], not not emsg}
@@ -2721,7 +2749,8 @@ describe('typval.c', function()
{lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', -1},
}) do
lib.curwin.w_cursor.lnum = 46
- local tv = typvalt(v[1], v[2])
+ -- Using to_cstr, cannot free with tv_clear
+ local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
@@ -2749,7 +2778,8 @@ describe('typval.c', function()
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, 'E907: Using a special value as a Float', 0},
{lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_float(UNKNOWN)', 0},
}) do
- local tv = typvalt(v[1], v[2])
+ -- Using to_cstr, cannot free with tv_clear
+ local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
@@ -2780,7 +2810,9 @@ describe('typval.c', function()
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'},
{lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', ''},
}) do
- local tv = typvalt(v[1], v[2])
+ -- Using to_cstr in place of Neovim allocated string, cannot
+ -- tv_clear() that.
+ local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
@@ -2821,7 +2853,8 @@ describe('typval.c', function()
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'},
{lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', nil},
}) do
- local tv = typvalt(v[1], v[2])
+ -- Using to_cstr, cannot free with tv_clear
+ local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
@@ -2861,7 +2894,8 @@ describe('typval.c', function()
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'},
{lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', ''},
}) do
- local tv = typvalt(v[1], v[2])
+ -- Using to_cstr, cannot free with tv_clear
+ local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
@@ -2902,7 +2936,8 @@ describe('typval.c', function()
{lib.VAR_SPECIAL, {v_special=lib.kSpecialVarFalse}, nil, 'false'},
{lib.VAR_UNKNOWN, nil, 'E908: using an invalid value as a String', nil},
}) do
- local tv = typvalt(v[1], v[2])
+ -- Using to_cstr, cannot free with tv_clear
+ local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
diff --git a/test/unit/fixtures/multiqueue.c b/test/unit/fixtures/multiqueue.c
index da63e55919..a8dca0a844 100644
--- a/test/unit/fixtures/multiqueue.c
+++ b/test/unit/fixtures/multiqueue.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
#include <string.h>
#include <stdlib.h>
#include "nvim/event/multiqueue.h"
diff --git a/test/unit/fixtures/rbuffer.c b/test/unit/fixtures/rbuffer.c
index d587d6b054..3f4062fa18 100644
--- a/test/unit/fixtures/rbuffer.c
+++ b/test/unit/fixtures/rbuffer.c
@@ -1,3 +1,6 @@
+// This is an open source non-commercial project. Dear PVS-Studio, please check
+// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+
#include "nvim/rbuffer.h"
#include "rbuffer.h"
diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua
index 8aad3acd98..4b9f185156 100644
--- a/test/unit/helpers.lua
+++ b/test/unit/helpers.lua
@@ -11,6 +11,7 @@ local posix = nil
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 eq = global_helpers.eq
@@ -511,6 +512,212 @@ if os.getenv('NVIM_TEST_PRINT_SYSCALLS') == '1' then
end
end
+local function just_fail(_)
+ return false
+end
+say:set('assertion.just_fail.positive', '%s')
+say:set('assertion.just_fail.negative', '%s')
+assert:register('assertion', 'just_fail', just_fail,
+ 'assertion.just_fail.positive',
+ 'assertion.just_fail.negative')
+
+local hook_fnamelen = 30
+local hook_sfnamelen = 30
+local hook_numlen = 5
+local hook_msglen = 1 + 1 + 1 + (1 + hook_fnamelen) + (1 + hook_sfnamelen) + (1 + hook_numlen) + 1
+
+local tracehelp = dedent([[
+ ┌ Trace type: _r_eturn from function , function _c_all, _l_ine executed,
+ │ _t_ail return, _C_ount (should not actually appear),
+ │ _s_aved from previous run for reference.
+ │┏ Function type: _L_ua function, _C_ function, _m_ain part of chunk,
+ │┃ function that did _t_ail call.
+ │┃┌ Function name type: _g_lobal, _l_ocal, _m_ethod, _f_ield, _u_pvalue,
+ │┃│ space for unknown.
+ │┃│ ┏ Source file name ┌ Function name ┏ Line
+ │┃│ ┃ (trunc to 30 bytes, no .lua) │ (truncated to last 30 bytes) ┃ number
+ CWN SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:LLLLL\n
+]])
+
+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
+ else
+ trace_level = tonumber(trace_level)
+ end
+ if trace_level <= 0 then
+ return
+ end
+ local trace_only_c = trace_level <= 1
+ local prev_info, prev_reason, prev_lnum
+ local function hook(reason, lnum, use_prev)
+ local info = nil
+ if use_prev then
+ info = prev_info
+ elseif reason ~= 'tail return' then -- tail return
+ info = debug.getinfo(2, 'nSl')
+ end
+
+ if trace_only_c and (not info or info.what ~= 'C') and not use_prev then
+ if info.source:sub(-9) == '_spec.lua' then
+ prev_info = info
+ prev_reason = 'saved'
+ prev_lnum = lnum
+ end
+ return
+ end
+ if trace_only_c and not use_prev and prev_reason then
+ hook(prev_reason, prev_lnum, true)
+ prev_reason = nil
+ end
+
+ local whatchar = ' '
+ local namewhatchar = ' '
+ local funcname = ''
+ local source = ''
+ local msgchar = reason:sub(1, 1)
+
+ if reason == 'count' then
+ msgchar = 'C'
+ end
+
+ if info then
+ funcname = (info.name or ''):sub(1, hook_fnamelen)
+ whatchar = info.what:sub(1, 1)
+ namewhatchar = info.namewhat:sub(1, 1)
+ if namewhatchar == '' then
+ namewhatchar = ' '
+ end
+ source = info.source
+ if source:sub(1, 1) == '@' then
+ if source:sub(-4, -1) == '.lua' then
+ source = source:sub(1, -5)
+ end
+ source = source:sub(-hook_sfnamelen, -1)
+ end
+ lnum = lnum or info.currentline
+ end
+
+ -- assert(-1 <= lnum and lnum <= 99999)
+ local lnum_s
+ if lnum == -1 then
+ lnum_s = 'nknwn'
+ else
+ lnum_s = ('%u'):format(lnum)
+ end
+ local msg = ( -- lua does not support %*
+ ''
+ .. msgchar
+ .. whatchar
+ .. namewhatchar
+ .. ' '
+ .. source .. (' '):rep(hook_sfnamelen - #source)
+ .. ':'
+ .. funcname .. (' '):rep(hook_fnamelen - #funcname)
+ .. ':'
+ .. ('0'):rep(hook_numlen - #lnum_s) .. lnum_s
+ .. '\n'
+ )
+ -- eq(hook_msglen, #msg)
+ sc.write(wr, msg)
+ end
+ debug.sethook(hook, 'crl')
+end
+
+local trace_end_msg = ('E%s\n'):format((' '):rep(hook_msglen - 2))
+
+local function itp_child(wr, func)
+ init()
+ collectgarbage('stop')
+ child_sethook(wr)
+ local err, emsg = pcall(func)
+ collectgarbage('restart')
+ collectgarbage()
+ debug.sethook()
+ emsg = tostring(emsg)
+ sc.write(wr, trace_end_msg)
+ if not err then
+ if #emsg > 99999 then
+ emsg = emsg:sub(1, 99999)
+ end
+ sc.write(wr, ('-\n%05u\n%s'):format(#emsg, emsg))
+ deinit()
+ sc.close(wr)
+ sc.exit(1)
+ else
+ sc.write(wr, '+\n')
+ deinit()
+ sc.close(wr)
+ sc.exit(0)
+ end
+end
+
+local function check_child_err(rd)
+ local trace = {}
+ local did_traceline = false
+ while true do
+ local traceline = sc.read(rd, hook_msglen)
+ if #traceline ~= hook_msglen then
+ if #traceline == 0 then
+ break
+ else
+ trace[#trace + 1] = 'Partial read: <' .. trace .. '>\n'
+ end
+ end
+ if traceline == trace_end_msg then
+ did_traceline = true
+ break
+ end
+ trace[#trace + 1] = traceline
+ end
+ local res = sc.read(rd, 2)
+ if #res ~= 2 then
+ local error
+ if #trace == 0 then
+ error = '\nTest crashed, no trace available\n'
+ else
+ error = '\nTest crashed, trace:\n' .. tracehelp
+ for i = 1, #trace do
+ error = error .. trace[i]
+ end
+ end
+ if not did_traceline then
+ error = error .. '\nNo end of trace occurred'
+ end
+ local cc_err, cc_emsg = pcall(check_cores, Paths.test_luajit_prg, true)
+ if not cc_err then
+ error = error .. '\ncheck_cores failed: ' .. cc_emsg
+ end
+ assert.just_fail(error)
+ end
+ if res == '+\n' then
+ return
+ end
+ eq('-\n', res)
+ local len_s = sc.read(rd, 5)
+ local len = tonumber(len_s)
+ neq(0, len)
+ local err = sc.read(rd, len + 1)
+ assert.just_fail(err)
+end
+
+local function itp_parent(rd, pid, allow_failure)
+ local err, emsg = pcall(check_child_err, rd)
+ sc.wait(pid)
+ sc.close(rd)
+ if not err then
+ if allow_failure then
+ io.stderr:write('Errorred out:\n' .. tostring(emsg) .. '\n')
+ os.execute([[
+ sh -c "source ci/common/test.sh
+ check_core_dumps --delete \"]] .. Paths.test_luajit_prg .. [[\""]])
+ else
+ error(emsg)
+ end
+ end
+end
+
local function gen_itp(it)
child_calls_mod = {}
child_calls_mod_once = {}
@@ -518,14 +725,6 @@ local function gen_itp(it)
preprocess_cache_mod = map(function(v) return v end, preprocess_cache_init)
previous_defines_mod = previous_defines_init
cdefs_mod = cdefs_init:copy()
- local function just_fail(_)
- return false
- end
- say:set('assertion.just_fail.positive', '%s')
- say:set('assertion.just_fail.negative', '%s')
- assert:register('assertion', 'just_fail', just_fail,
- 'assertion.just_fail.positive',
- 'assertion.just_fail.negative')
local function itp(name, func, allow_failure)
if allow_failure and os.getenv('NVIM_TEST_RUN_FAILING_TESTS') ~= '1' then
-- FIXME Fix tests with this true
@@ -535,50 +734,13 @@ local function gen_itp(it)
local rd, wr = sc.pipe()
child_pid = sc.fork()
if child_pid == 0 then
- init()
sc.close(rd)
- collectgarbage('stop')
- local err, emsg = pcall(func)
- collectgarbage('restart')
- emsg = tostring(emsg)
- if not err then
- sc.write(wr, ('-\n%05u\n%s'):format(#emsg, emsg))
- deinit()
- sc.close(wr)
- sc.exit(1)
- else
- sc.write(wr, '+\n')
- deinit()
- sc.close(wr)
- sc.exit(0)
- end
+ itp_child(wr, func)
else
sc.close(wr)
- sc.wait(child_pid)
+ local saved_child_pid = child_pid
child_pid = nil
- local function check()
- local res = sc.read(rd, 2)
- eq(2, #res)
- if res == '+\n' then
- return
- end
- eq('-\n', res)
- local len_s = sc.read(rd, 5)
- local len = tonumber(len_s)
- neq(0, len)
- local err = sc.read(rd, len + 1)
- assert.just_fail(err)
- end
- local err, emsg = pcall(check)
- sc.close(rd)
- if not err then
- if allow_failure then
- io.stderr:write('Errorred out:\n' .. tostring(emsg) .. '\n')
- os.execute([[sh -c "source .ci/common/test.sh ; check_core_dumps --delete \"]] .. Paths.test_luajit_prg .. [[\""]])
- else
- error(emsg)
- end
- end
+ itp_parent(rd, saved_child_pid, allow_failure)
end
end)
end
@@ -610,12 +772,8 @@ local module = {
only_separate = only_separate,
child_call_once = child_call_once,
child_cleanup_once = child_cleanup_once,
+ sc = sc,
}
-return function(after_each)
- if after_each then
- after_each(function()
- check_cores(Paths.test_luajit_prg)
- end)
- end
+return function()
return module
end
diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua
index 823b6d6a85..575787a25e 100644
--- a/test/unit/os/env_spec.lua
+++ b/test/unit/os/env_spec.lua
@@ -67,12 +67,37 @@ describe('env function', function()
end)
end)
+ describe('os_shell_is_cmdexe', function()
+ itp('returns true for expected names', function()
+ eq(true, cimp.os_shell_is_cmdexe(to_cstr('cmd.exe')))
+ eq(true, cimp.os_shell_is_cmdexe(to_cstr('cmd')))
+ eq(true, cimp.os_shell_is_cmdexe(to_cstr('CMD.EXE')))
+ eq(true, cimp.os_shell_is_cmdexe(to_cstr('CMD')))
+
+ os_setenv('COMSPEC', '/foo/bar/cmd.exe', 0)
+ eq(true, cimp.os_shell_is_cmdexe(to_cstr('$COMSPEC')))
+ os_setenv('COMSPEC', [[C:\system32\cmd.exe]], 0)
+ eq(true, cimp.os_shell_is_cmdexe(to_cstr('$COMSPEC')))
+ end)
+ itp('returns false for unexpected names', function()
+ eq(false, cimp.os_shell_is_cmdexe(to_cstr('')))
+ eq(false, cimp.os_shell_is_cmdexe(to_cstr('powershell')))
+ eq(false, cimp.os_shell_is_cmdexe(to_cstr(' cmd.exe ')))
+ eq(false, cimp.os_shell_is_cmdexe(to_cstr('cm')))
+ eq(false, cimp.os_shell_is_cmdexe(to_cstr('md')))
+ eq(false, cimp.os_shell_is_cmdexe(to_cstr('cmd.ex')))
+
+ os_setenv('COMSPEC', '/foo/bar/cmd', 0)
+ eq(false, cimp.os_shell_is_cmdexe(to_cstr('$COMSPEC')))
+ end)
+ end)
+
describe('os_getenv', function()
itp('reads an env variable', function()
local name = 'NVIM_UNIT_TEST_GETENV_1N'
local value = 'NVIM_UNIT_TEST_GETENV_1V'
eq(NULL, os_getenv(name))
- -- need to use os_setenv, because lua dosn't have a setenv function
+ -- Use os_setenv because Lua dosen't have setenv.
os_setenv(name, value, 1)
eq(value, os_getenv(name))
end)
diff --git a/test/unit/os/fileio_spec.lua b/test/unit/os/fileio_spec.lua
index 7a738ce85c..e3c8e616ce 100644
--- a/test/unit/os/fileio_spec.lua
+++ b/test/unit/os/fileio_spec.lua
@@ -80,6 +80,10 @@ local function file_read(fp, size)
return ret1, ret2
end
+local function file_flush(fp)
+ return m.file_flush(fp)
+end
+
local function file_fsync(fp)
return m.file_fsync(fp)
end
@@ -94,7 +98,7 @@ describe('file_open', function()
eq(0, err)
local attrs = lfs.attributes(filec)
eq('rwx------', attrs.permissions)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can create a rw------- file with kFileCreate', function()
@@ -102,7 +106,7 @@ describe('file_open', function()
eq(0, err)
local attrs = lfs.attributes(filec)
eq('rw-------', attrs.permissions)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can create a rwx------ file with kFileCreateOnly', function()
@@ -110,7 +114,7 @@ describe('file_open', function()
eq(0, err)
local attrs = lfs.attributes(filec)
eq('rwx------', attrs.permissions)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can create a rw------- file with kFileCreateOnly', function()
@@ -118,7 +122,7 @@ describe('file_open', function()
eq(0, err)
local attrs = lfs.attributes(filec)
eq('rw-------', attrs.permissions)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('fails to open an existing file with kFileCreateOnly', function()
@@ -137,35 +141,35 @@ describe('file_open', function()
local err, fp = file_open(file1, m.kFileCreate, 384)
eq(0, err)
eq(true, fp.wr)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can open an existing file read-only with zero', function()
local err, fp = file_open(file1, 0, 384)
eq(0, err)
eq(false, fp.wr)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can open an existing file read-only with kFileReadOnly', function()
local err, fp = file_open(file1, m.kFileReadOnly, 384)
eq(0, err)
eq(false, fp.wr)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can open an existing file read-only with kFileNoSymlink', function()
local err, fp = file_open(file1, m.kFileNoSymlink, 384)
eq(0, err)
eq(false, fp.wr)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can truncate an existing file with kFileTruncate', function()
local err, fp = file_open(file1, m.kFileTruncate, 384)
eq(0, err)
eq(true, fp.wr)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
local attrs = lfs.attributes(file1)
eq(0, attrs.size)
end)
@@ -174,7 +178,7 @@ describe('file_open', function()
local err, fp = file_open(file1, m.kFileWriteOnly, 384)
eq(0, err)
eq(true, fp.wr)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
local attrs = lfs.attributes(file1)
eq(4096, attrs.size)
end)
@@ -191,7 +195,7 @@ describe('file_open', function()
local err, fp = file_open(linkf, m.kFileTruncate, 384)
eq(0, err)
eq(true, fp.wr)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
local attrs = lfs.attributes(file1)
eq(0, attrs.size)
end)
@@ -217,7 +221,7 @@ describe('file_open_new', function()
local err, fp = file_open_new(file1, 0, 384)
eq(0, err)
eq(false, fp.wr)
- eq(0, m.file_free(fp))
+ eq(0, m.file_free(fp, false))
end)
itp('fails to open an existing file with kFileCreateOnly', function()
@@ -227,7 +231,29 @@ describe('file_open_new', function()
end)
end)
--- file_close is called above, so it is not tested directly
+describe('file_close', function()
+ itp('can flush writes to disk also with true argument', function()
+ local err, fp = file_open(filec, m.kFileCreateOnly, 384)
+ eq(0, err)
+ local wsize = file_write(fp, 'test')
+ eq(4, wsize)
+ eq(0, lfs.attributes(filec).size)
+ eq(0, m.file_close(fp, true))
+ eq(wsize, lfs.attributes(filec).size)
+ end)
+end)
+
+describe('file_free', function()
+ itp('can flush writes to disk also with true argument', function()
+ local err, fp = file_open_new(filec, m.kFileCreateOnly, 384)
+ eq(0, err)
+ local wsize = file_write(fp, 'test')
+ eq(4, wsize)
+ eq(0, lfs.attributes(filec).size)
+ eq(0, m.file_free(fp, true))
+ eq(wsize, lfs.attributes(filec).size)
+ end)
+end)
describe('file_fsync', function()
itp('can flush writes to disk', function()
@@ -240,7 +266,22 @@ describe('file_fsync', function()
eq(0, lfs.attributes(filec).size)
eq(0, file_fsync(fp))
eq(wsize, lfs.attributes(filec).size)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
+ end)
+end)
+
+describe('file_flush', function()
+ itp('can flush writes to disk', function()
+ local err, fp = file_open(filec, m.kFileCreateOnly, 384)
+ eq(0, file_flush(fp))
+ eq(0, err)
+ eq(0, lfs.attributes(filec).size)
+ local wsize = file_write(fp, 'test')
+ eq(4, wsize)
+ eq(0, lfs.attributes(filec).size)
+ eq(0, file_flush(fp))
+ eq(wsize, lfs.attributes(filec).size)
+ eq(0, m.file_close(fp, false))
end)
end)
@@ -262,7 +303,7 @@ describe('file_read', function()
eq({exp_err, exp_s}, {file_read(fp, size)})
shift = shift + size
end
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can read the whole file at once', function()
@@ -271,7 +312,7 @@ describe('file_read', function()
eq(false, fp.wr)
eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
eq({0, ('\0'):rep(#fcontents)}, {file_read(fp, #fcontents)})
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can read more then 1024 bytes after reading a small chunk', function()
@@ -281,7 +322,7 @@ describe('file_read', function()
eq({5, fcontents:sub(1, 5)}, {file_read(fp, 5)})
eq({#fcontents - 5, fcontents:sub(6) .. (('\0'):rep(5))},
{file_read(fp, #fcontents)})
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
itp('can read file by 768-byte-chunks', function()
@@ -301,7 +342,7 @@ describe('file_read', function()
eq({exp_err, exp_s}, {file_read(fp, size)})
shift = shift + size
end
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
end)
@@ -312,7 +353,7 @@ describe('file_write', function()
eq(true, fp.wr)
local wr = file_write(fp, fcontents)
eq(#fcontents, wr)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
eq(wr, lfs.attributes(filec).size)
eq(fcontents, io.open(filec):read('*a'))
end)
@@ -329,7 +370,7 @@ describe('file_write', function()
eq(wr, #s)
shift = shift + size
end
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
eq(#fcontents, lfs.attributes(filec).size)
eq(fcontents, io.open(filec):read('*a'))
end)
@@ -346,7 +387,7 @@ describe('file_write', function()
eq(wr, #s)
shift = shift + size
end
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
eq(#fcontents, lfs.attributes(filec).size)
eq(fcontents, io.open(filec):read('*a'))
end)
@@ -361,6 +402,6 @@ describe('file_skip', function()
local rd, s = file_read(fp, 3)
eq(3, rd)
eq(fcontents:sub(4, 6), s)
- eq(0, m.file_close(fp))
+ eq(0, m.file_close(fp, false))
end)
end)
diff --git a/test/unit/testtest_spec.lua b/test/unit/testtest_spec.lua
new file mode 100644
index 0000000000..d2f3632b6f
--- /dev/null
+++ b/test/unit/testtest_spec.lua
@@ -0,0 +1,19 @@
+local helpers = require('test.unit.helpers')(after_each)
+local assert = require('luassert')
+
+local itp = helpers.gen_itp(it)
+
+local sc = helpers.sc
+
+-- All of the below tests must fail. Check how exactly they fail.
+if os.getenv('NVIM_TEST_RUN_TESTTEST') ~= '1' then
+ return
+end
+describe('test code', function()
+ itp('does not hang when working with lengthy errors', function()
+ assert.just_fail(('x'):rep(65536))
+ end)
+ itp('shows trace after exiting abnormally', function()
+ sc.exit(0)
+ end)
+end)