From 7314a1bda6e6bdce203eca6fca044a80cfdffaa5 Mon Sep 17 00:00:00 2001 From: Timur Safin <tsafin@tarantool.org> Date: Thu, 15 Dec 2022 02:24:13 +0300 Subject: [PATCH] debugger: refactor debugging scenarios Refactor the way how we run various debugger scenarios, getting rid of external static file, and producing debuggee scripts on the fly. The idea is to have everything in the single source: both source script to be used for debugging, and corresponding debugger commands. NO_DOC=internal NO_CHANGELOG=internal --- .../console_debugger_session_test.lua | 205 ++++++++++++++---- test/app-luatest/debug-self-target.lua | 8 - test/app-luatest/debug-target.lua | 12 - 3 files changed, 158 insertions(+), 67 deletions(-) delete mode 100644 test/app-luatest/debug-self-target.lua delete mode 100644 test/app-luatest/debug-target.lua diff --git a/test/app-luatest/console_debugger_session_test.lua b/test/app-luatest/console_debugger_session_test.lua index 8fc2284503..83f588fd20 100644 --- a/test/app-luatest/console_debugger_session_test.lua +++ b/test/app-luatest/console_debugger_session_test.lua @@ -1,10 +1,7 @@ local t = require('luatest') local popen = require('popen') local tnt = require('tarantool') - -local function normalize_path(s) - return s:gsub("^@", ""):gsub("[^/]+$", "") -end +local fio = require('fio') local function unescape(s) return s and s:gsub('[\27\155][][()#;?%d]*[A-PRZcf-ntqry=><~]', '') or '' @@ -22,7 +19,6 @@ local function tarantool_path(arg) end local TARANTOOL_PATH = tarantool_path(arg) -local path_to_script = normalize_path(debug.getinfo(1, 'S').source) local DEBUGGER = 'luadebug' local dbg_header = tnt.package .. " debugger " .. tnt.version @@ -41,6 +37,47 @@ local function debuglog(...) print('--', ...) end +--[[ + Convert passed multi-line literal script + to the temporary file. Get rid of line annotations, + leaving code alone. + + Annotated lines are in a form: + 1 | local date = require 'datetime' + 2 | local T = date.new{hour = 3, tzoffset = '+0300'} +]] +local function dbg_script(content) + assert(content ~= nil) + local tmpname = os.tmpname() + local f = assert(io.open(tmpname, "wb")) + debuglog("Temporary script name:", tmpname) + -- process multi-line literal + for line in string.gmatch(content, "[^\n]+") do + --[[ + Process annotated code line, delimited with '|'. + + +-------- virtual line number (for easier maintaining) + | +------ delimiter + | | +---- Lua code to be executed + V V V + 1 | local date = require 'datetime' + + ]] + local delim = line:find('|') + + -- if there is no delimiter - write it as-is + if not delim then + f:write(line..'\n') + else + -- TODO - assert if there is incorrect line numbers + -- at the moment just ignore annotation entirely. + f:write(line:sub(delim + 1)..'\n') + end + end + f:close() + return tmpname +end + local cmd_aliases = { ['b'] = 'b|break|breakpoint|add_break|add_breakpoint', ['bd'] = 'bd|bdelete|delete_break|delete_breakpoint', @@ -83,17 +120,31 @@ local function get_key_arg_pair(cmd) end local g = t.group('debug', { - {sequence = 'full scenario'}, - {sequence = 'successful breakpoints additions'}, - {sequence = 'failed breakpoints additions'}, - {sequence = 'successful breakpoints removals'}, - {sequence = 'failed breakpoints removals'}, + {sequence = 'full'}, + {sequence = 'bp_set_ok'}, + {sequence = 'bp_set_fail'}, + {sequence = 'bp_delete_ok'}, + {sequence = 'bp_delete_fail'}, }) local sequences = { -- full, complex sequence - ['full scenario'] = { + full = { + dbg_script [[ + 1 | local date = require 'datetime' + 2 | + 3 | local T = date.new{hour = 3, tzoffset = '+0300'} + 4 | print(T) + 5 | + 6 | local fmt = '%Y-%m-%dT%H%M%z' + 7 | local S = T:format(fmt) + 8 | print(S) + 9 | local T1 = date.parse(S, {format = fmt}) + 10 | print(T1) + 11 | + 12 | os.exit(0) +]], { ['\t'] = '' }, -- \t is a special value for start { ['n'] = dbg_prompt }, { ['s'] = dbg_prompt }, @@ -107,11 +158,11 @@ local sequences = { { ['bogus;'] = 'is not recognized.' }, { ['h'] = dbg_prompt }, { ['t'] = '=> builtin/datetime.lua' }, - { ['u'] = 'debug-target.lua:3 in chunk at' }, + { ['u'] = '{file}:3 in chunk at' }, -- FIXME (gh-8190) - we should not show calling side at luadebug.lua -- { ['u'] = 'Already at the bottom of the stack.' }, { ['u'] = 'Inspecting frame: builtin/luadebug.lua' }, - { ['d'] = 'debug-target.lua:3 in chunk at' }, + { ['d'] = '{file}:3 in chunk at' }, { ['d'] = 'Inspecting frame: builtin/datetime.lua' }, { ['l'] = 'obj => {"tzoffset" = "+0300", "hour" = 3}' }, { ['f'] = dbg_prompt }, @@ -126,57 +177,98 @@ local sequences = { }, -- partial sequence with successful breakpoints added - ['successful breakpoints additions'] = { + bp_set_ok = { + dbg_script [[ + 1 | local date = require 'datetime' + 2 | + 3 | local T = date.new{hour = 3, tzoffset = '+0300'} + 4 | print(T) + 5 | + 6 | local fmt = '%Y-%m-%dT%H%M%z' + 7 | local S = T:format(fmt) + 8 | print(S) + 9 | local T1 = date.parse(S, {format = fmt}) + 10 | print(T1) + 11 | + 12 | os.exit(0) +]], { ['\t'] = '' }, -- \t is a special value for start - { ['b +10'] = dbg_prompt }, - { ['c'] = 'debug-target.lua:10' }, + { ['b +9'] = dbg_prompt }, + { ['c'] = '{file}:9' }, { ['n'] = dbg_prompt }, { ['p S'] = 'S => "1970-01-01T0300+0300"' }, { ['p T'] = 'T => 1970-01-01T03:00:00+0300' }, { ['c'] = '' }, }, - -- partial sequence with failed breakpoint additions - ['failed breakpoints additions'] = { + -- partial sequence with failed breakpoint addsitions + bp_set_fail = { + dbg_script [[ + 1 | local date = require 'datetime' + 2 | local T = date.new{hour = 3, tzoffset = '+0300'} + 3 | print(T) + 4 | os.exit(0) +]], { ['\t'] = '' }, -- \t is a special value for start { ['b'] = 'expects argument, but none received' }, { ['b 11'] = dbg_failed_bp }, - { ['b debug-target.lua'] = dbg_failed_bp }, - { ['b debug-target.lua:'] = dbg_failed_bp }, - { ['b debug-target.lua:-10'] = dbg_failed_bp }, - { ['b debug-target.lua+0'] = dbg_failed_range(0) }, + { ['b {file}'] = dbg_failed_bp }, + { ['b {file}:'] = dbg_failed_bp }, + { ['b {file}:-10'] = dbg_failed_bp }, + { ['b {file}+0'] = dbg_failed_range(0) }, { ['b +0'] = dbg_failed_range(0) }, - { ['b debug-target.lua+2147483632'] = dbg_failed_range(2147483632) }, + { ['b {file}+2147483632'] = dbg_failed_range(2147483632) }, { ['b +21474836480'] = dbg_failed_range(21474836480) }, }, -- partial sequence with breakpoints additions and removals - ['successful breakpoints removals'] = { + bp_delete_ok = { + dbg_script [[ + 1 | local date = require 'datetime' + 2 | + 3 | local T = date.new{hour = 3, tzoffset = '+0300'} + 4 | print(T) + 5 | + 6 | local fmt = '%Y-%m-%dT%H%M%z' + 7 | local S = T:format(fmt) + 8 | print(S) + 9 | local T1 = date.parse(S, {format = fmt}) + 10 | print(T1) + 11 | + 12 | os.exit(0) +]], { ['\t'] = '' }, -- \t is a special value for start - { ['b +7'] = 'debug-target.lua:7' }, - { ['bl'] = 'debug-target.lua:7' }, - { ['b :5'] = 'debug-target.lua:5' }, - { ['bl'] = 'debug-target.lua:5' }, - { ['bd :5'] = 'debug-target.lua:5' }, - { ['bl'] = 'debug-target.lua:7' }, - { ['bd +7'] = 'debug-target.lua:7' }, - { ['b :6'] = 'debug-target.lua:6' }, - { ['bl'] = 'debug-target.lua:6' }, + { ['b +7'] = '{file}:7' }, + { ['bl'] = '{file}:7' }, + { ['b :5'] = '{file}:5' }, + { ['bl'] = '{file}:5' }, + { ['bd :5'] = '{file}:5' }, + { ['bl'] = '{file}:7' }, + { ['bd +7'] = '{file}:7' }, + { ['b :6'] = '{file}:6' }, + { ['bl'] = '{file}:6' }, { ['bd *'] = 'Removed all breakpoints' }, { ['bl'] = 'No active breakpoints defined' }, }, -- partial sequence with failed breakpoints removals - ['failed breakpoints removals'] = { + bp_delete_fail = { + dbg_script [[ + 1 | local date = require 'datetime' + 2 | local T = date.new{hour = 3, tzoffset = '+0300'} + 3 | print(T) + 4 | os.exit(0) +]], { ['\t'] = '' }, -- \t is a special value for start { ['bd'] = 'expects argument, but none received' }, { ['bd 11'] = dbg_failed_bpd }, - { ['bd debug-target.lua'] = dbg_failed_bpd }, - { ['bd debug-target.lua:'] = dbg_failed_bpd }, - { ['bd debug-target.lua:-10'] = dbg_failed_bpd }, + { ['bd {file}'] = dbg_failed_bpd }, + { ['bd {file}:'] = dbg_failed_bpd }, + { ['bd {file}:-10'] = dbg_failed_bpd }, }, } -local function run_debug_session(cmdline, sequence, header) +local function run_debug_session(cmdline, sequence, tmpfile, header) + local short_src = fio.basename(tmpfile) --[[ repeat multiple times to check all command aliases ]] @@ -192,6 +284,8 @@ local function run_debug_session(cmdline, sequence, header) local first = header ~= nil for _, row in pairs(sequence) do local cmd, expected = next(row) + -- interpret template strings {file} + expected = expected:gsub('{file}', short_src) if cmd ~= '\t' then if cmd ~= '' then local key, arg = get_key_arg_pair(cmd) @@ -227,21 +321,36 @@ local function run_debug_session(cmdline, sequence, header) end fh:close() end + debuglog('Delete temporary file ', tmpfile) + os.remove(tmpfile) end -- `tarantool -d debug-target.lua` g.test_debugger = function(cg) - local debug_target_script = path_to_script .. 'debug-target.lua' - local cmd = { TARANTOOL_PATH, '-d', debug_target_script } local scenario_name = cg.params.sequence t.assert(scenario_name) - t.assert(sequences[scenario_name]) - run_debug_session(cmd, sequences[scenario_name], dbg_header) + local sequence = sequences[scenario_name] + t.assert(sequence) + local tmpfile = table.remove(sequence, 1) + t.assert(type(tmpfile) == 'string') + + local cmd = { TARANTOOL_PATH, '-d', tmpfile } + run_debug_session(cmd, sequences[scenario_name], tmpfile, dbg_header) end local g_self = t.group('self-debug') local shorter_sequence = { + dbg_script [[ + 1 | local dbg = require 'luadebug' + 2 | dbg() + 3 | local date = require 'datetime' + 4 | + 5 | local T = date.new{hour = 3, tzoffset = '+0300'} + 6 | print(T) + 7 | + 8 | os.exit(0) +]], { ['\t'] = '' }, -- \t is a special value for start { ['n'] = dbg_prompt }, { ['s'] = dbg_prompt }, @@ -249,18 +358,20 @@ local shorter_sequence = { { ['n'] = dbg_prompt }, { ['p'] = 'expects argument, but none received' }, { ['p obj'] = 'obj => {"tzoffset" = "+0300", "hour" = 3}' }, - { ['u'] = 'debug-self-target.lua:5 in chunk at' }, + { ['u'] = '{file}:5 in chunk at' }, { ['u'] = 'Already at the bottom of the stack.' }, { ['d'] = 'Inspecting frame: builtin/datetime.lua' }, { ['l'] = 'obj => {"tzoffset" = "+0300", "hour" = 3}' }, - { ['f'] = 'debug-self-target.lua:6 in chunk at' }, + { ['f'] = '{file}:6 in chunk at' }, { ['c'] = '' }, } -- `tarantool debug-self-target.lua`, where -- initiate debugging session via `require 'luadebug'()` g_self.test_debug_self_invoke = function() - local debug_target_script = path_to_script .. 'debug-self-target.lua' - local cmd = { TARANTOOL_PATH, debug_target_script } - run_debug_session(cmd, shorter_sequence) + local tmpfile = table.remove(shorter_sequence, 1) + t.assert(type(tmpfile) == 'string') + + local cmd = { TARANTOOL_PATH, tmpfile } + run_debug_session(cmd, shorter_sequence, tmpfile) end diff --git a/test/app-luatest/debug-self-target.lua b/test/app-luatest/debug-self-target.lua deleted file mode 100644 index 8aed6a967a..0000000000 --- a/test/app-luatest/debug-self-target.lua +++ /dev/null @@ -1,8 +0,0 @@ -local dbg = require 'luadebug' -dbg() -local date = require 'datetime' - -local T = date.new{hour = 3, tzoffset = '+0300'} -print(T) - -os.exit(0) diff --git a/test/app-luatest/debug-target.lua b/test/app-luatest/debug-target.lua deleted file mode 100644 index 3546ac2dde..0000000000 --- a/test/app-luatest/debug-target.lua +++ /dev/null @@ -1,12 +0,0 @@ -local date = require 'datetime' - -local T = date.new{hour = 3, tzoffset = '+0300'} -print(T) - -local fmt = '%Y-%m-%dT%H%M%z' -local S = T:format(fmt) -print(S) -local T1 = date.parse(S, {format = fmt}) -print(T1) - -os.exit(0) -- GitLab