diff options
-rw-r--r-- | test/README.md | 5 | ||||
-rw-r--r-- | test/unit/helpers.lua | 102 | ||||
-rw-r--r-- | test/unit/testtest_spec.lua | 5 |
3 files changed, 111 insertions, 1 deletions
diff --git a/test/README.md b/test/README.md index dc83b1ceef..9a8701695a 100644 --- a/test/README.md +++ b/test/README.md @@ -102,3 +102,8 @@ defined and this variable is not) cores are checked for after each test. `NVIM_TEST_RUN_TESTTEST` (U) (1): allows running `test/unit/testtest_spec.lua` used to check how testing infrastructure works. + +`NVIM_TEST_NO_TRACE` (U) (1): omits getting traces from tests. This means that +if tests crashed without core dump you will have no clues regarding where, but +this makes tests run a lot faster. Combine with `NVIM_TEST_MAIN_CDEFS` for +maximal speed. diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua index 8f0d3fa429..c8296abb2a 100644 --- a/test/unit/helpers.lua +++ b/test/unit/helpers.lua @@ -520,13 +520,92 @@ 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 function child_sethook(wr) + if os.getenv('NVIM_TEST_NO_TRACE') == '1' then + return + end + -- Message: + -- |> msg char (1) + -- ||> what char (1) + -- |||> namewhat char (1) + -- ||| |> source file name (30) + -- ||| | |> function name (30) + -- ||| | | |> line number (5) + -- CWN SSSSSSSSSSSSSSSSSSSSSSSSSSSSSS:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF:LLLLL\n + local function hook(reason, lnum) + local msgchar = reason:sub(1, 1) + if reason == 'count' then + msgchar = 'C' + end + local info = nil + if reason ~= 'tail return' then -- tail return + info = debug.getinfo(2, 'nSl') + end + local whatchar = ' ' + local namewhatchar = ' ' + local funcname = '' + local source = '' + 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 function itp_child(wr, func) init() collectgarbage('stop') + child_sethook(wr) local err, emsg = pcall(func) + debug.sethook() collectgarbage('restart') emsg = tostring(emsg) + sc.write(wr, ('E%s\n'):format((' '):rep(hook_msglen - 2))) 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) @@ -540,8 +619,29 @@ local function itp_child(wr, func) end local function check_child_err(rd) + local trace = {} + 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:sub(1, 1) == 'E' then + break + end + trace[#trace + 1] = traceline + end local res = sc.read(rd, 2) - eq(2, #res) + if #res ~= 2 then + local error = 'Test crashed, trace:\n' + for i = 1, #trace do + error = error .. trace[i] + end + assert.just_fail(error) + end if res == '+\n' then return end diff --git a/test/unit/testtest_spec.lua b/test/unit/testtest_spec.lua index b469e7ed44..d2f3632b6f 100644 --- a/test/unit/testtest_spec.lua +++ b/test/unit/testtest_spec.lua @@ -3,6 +3,8 @@ 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 @@ -11,4 +13,7 @@ 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) |