Software /
code /
prosody
Changeset
11177:37dc2a6144d1 0.11
util.debug: Fix locals being reported under wrong stack frame in some cases (+tests!!)
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 16 Oct 2020 13:38:04 +0100 |
parents | 11175:235537247aa3 |
children | 11178:44bcddecf1b5 11189:0ff148362a3d |
files | spec/util_debug_spec.lua util/debug.lua |
diffstat | 2 files changed, 94 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spec/util_debug_spec.lua Fri Oct 16 13:38:04 2020 +0100 @@ -0,0 +1,93 @@ +local dbg = require "util.debug"; + +describe("util.debug", function () + describe("traceback()", function () + it("works", function () + local tb = dbg.traceback(); + assert.is_string(tb); + end); + end); + describe("get_traceback_table()", function () + it("works", function () + local count = 0; + -- MUST stay in sync with the line numbers of these functions: + local f1_defined, f3_defined = 43, 15; + local function f3(f3_param) --luacheck: ignore 212/f3_param + count = count + 1; + + for i = 1, 2 do + local tb = dbg.get_traceback_table(i == 1 and coroutine.running() or nil, 0); + assert.is_table(tb); + --print(dbg.traceback(), "\n\n\n", require "util.serialization".serialize(tb, { fatal = false, unquoted = true})); + local found_f1, found_f3; + for _, frame in ipairs(tb) do + if frame.info.linedefined == f1_defined then + assert.equal(0, #frame.locals); + assert.equal("f2", frame.upvalues[1].name); + assert.equal("f1_upvalue", frame.upvalues[2].name); + found_f1 = true; + elseif frame.info.linedefined == f3_defined then + assert.equal("f3_param", frame.locals[1].name); + found_f3 = true; + end + end + assert.is_true(found_f1); + assert.is_true(found_f3); + end + end + local function f2() + local f2_local = "hello"; + return f3(f2_local); + end + local f1_upvalue = "upvalue1"; + local function f1() + f2(f1_upvalue); + end + + -- ok/err are caught and re-thrown so that + -- busted gets to handle them in its own way + local ok, err; + local function hook() + debug.sethook(); + ok, err = pcall(f1); + end + + -- Test the traceback is correct in various + -- types of caller environments + + -- From a Lua hook + debug.sethook(hook, "crl", 1); + local a = string.sub("abcdef", 3, 4); + assert.equal("cd", a); + debug.sethook(); + assert.equal(1, count); + + if not ok then + error(err); + end + ok, err = nil, nil; + + -- From a signal handler (C hook) + require "util.signal".signal("SIGUSR1", hook); + require "util.signal".raise("SIGUSR1"); + assert.equal(2, count); + + if not ok then + error(err); + end + ok, err = nil, nil; + + -- Inside a coroutine + local co = coroutine.create(function () + hook(); + end); + coroutine.resume(co); + + if not ok then + error(err); + end + + assert.equal(3, count); + end); + end); +end);
--- a/util/debug.lua Thu Oct 15 17:21:58 2020 +0200 +++ b/util/debug.lua Fri Oct 16 13:38:04 2020 +0100 @@ -104,7 +104,7 @@ levels[(level-start_level)+1] = { level = level; info = info; - locals = get_locals_table(thread, level+(thread and 0 or 1)); + locals = get_locals_table(thread, level+1); upvalues = get_upvalues_table(info.func); }; end