diff --git a/test/app-luatest/console_debugger_session_test.lua b/test/app-luatest/console_debugger_session_test.lua new file mode 100644 index 0000000000000000000000000000000000000000..a9697ef71596a6ffa550efa464a462ed7d06cfe3 --- /dev/null +++ b/test/app-luatest/console_debugger_session_test.lua @@ -0,0 +1,135 @@ +local t = require('luatest') +local popen = require('popen') +local tnt = require('tarantool') +local g = t.group() + +local function normalize_path(s) + return s:gsub("^@", ""):gsub("[^/]+$", "") +end + +local function unescape(s) + return s:gsub('[\27\155][][()#;?%d]*[A-PRZcf-ntqry=><~]', '') +end + +local function trim(s) + return s:gsub('%s+$', '') +end + +local function tarantool_path(arg) + local index = -2 + -- arg[-1] is guaranteed to be non-null + while arg[index] do index = index - 1 end + return arg[index + 1] +end + +local TARANTOOL_PATH = tarantool_path(arg) +local path_to_script = normalize_path(debug.getinfo(1, 'S').source) +local debug_target_script = path_to_script .. 'debug-target.lua' + +local DEBUGGER = 'luadebug.lua' +local dbg_header = DEBUGGER .. ": Loaded for " .. tnt.version +local dbg_prompt = DEBUGGER .. '>' + +local cmd_aliases = { + ['c'] = 'c|cont|continue', + ['d'] = 'd|down', + ['e'] = 'e|eval', + ['f'] = 'f|finish|step_out', + ['h'] = 'h|help|?', + ['l'] = 'l|locals', + ['n'] = 'n|next|step_over', + ['p'] = 'p|print', + ['q'] = 'q|quit', + ['s'] = 's|st|step|step_into', + ['t'] = 't|trace|bt', + ['u'] = 'u|up', + ['w'] = 'w|where', +} + +local MAX_ALIASES_COUNT = 4 + +local function get_cmd_alias(cmd, number) + if not cmd_aliases[cmd] then + return cmd + end + local cmds = {} + for v, _ in cmd_aliases[cmd]:gmatch('[^|]+') do + table.insert(cmds, v) + end + return cmds[number % #cmds + 1] +end + +--[[ + Should handle equally well both: + 'n' and 'p obj' +]] +local function get_key_arg_pair(cmd) + local gen = cmd:gmatch('[^%s]+') + return gen(), gen() +end + +local sequence = { + { ['\t'] = dbg_header }, -- \t is a special value for start + { ['n'] = dbg_prompt }, + { ['s'] = dbg_prompt }, + { ['n'] = dbg_prompt }, + { ['n'] = dbg_prompt }, + { ['p'] = 'command expects argument, but none received' }, + { ['p obj'] = 'obj => {"tzoffset" = "+0300", "hour" = 3}' }, + { ['n'] = dbg_prompt }, + { ['p ymd'] = 'ymd => false' }, + { ['w'] = 'local hms = false' }, + { ['h'] = dbg_prompt }, + { ['t'] = 'debug-target.lua:5 in chunk at' }, + { ['u'] = 'Already at the top of the stack.' }, + { ['d'] = 'debug-target.lua:5 in chunk at' }, + { ['u'] = 'Inspecting frame: builtin/datetime.lua' }, + { ['l'] = 'obj => {"tzoffset" = "+0300", "hour" = 3}' }, + { ['f'] = dbg_prompt }, + { ['n'] = dbg_prompt }, + { ['p T'] = 'T => 1970-01-01T03:00:00+0300' }, + { ['n'] = dbg_prompt }, + { [''] = dbg_prompt }, + { [''] = dbg_prompt }, + { [''] = dbg_prompt }, + { ['p S'] = 'S => "1970-01-01T0300+0300"' }, + { ['c'] = '' }, +} + +g.test_interactive_debugger_session = function() + local cmd = { TARANTOOL_PATH, debug_target_script } + --[[ + repeat multiple times to check all command aliases + ]] + for i = 1, MAX_ALIASES_COUNT do + local fh = popen.new(cmd, { + stdout = popen.opts.PIPE, + stderr = popen.opts.PIPE, + stdin = popen.opts.PIPE, + }) + t.assert_is_not(fh, nil) + for _, row in pairs(sequence) do + local cmd, expected = next(row) + if cmd ~= '\t' then + if cmd ~= '' then + local key, arg = get_key_arg_pair(cmd) + arg = arg and (' ' .. arg) or '' + cmd = get_cmd_alias(key, i) .. arg .. '\n' + else -- '' empty command - repeat prior one + cmd = cmd .. '\n' + end + fh:write(cmd) + end + + local result + local clean_cmd = trim(cmd) + repeat + result = trim(unescape(fh:read({ timeout = 1.0 }))) + until result ~= '' and result ~= clean_cmd + if expected ~= '' then + t.assert_str_contains(result, expected, false) + end + end + fh:close() + end +end diff --git a/test/app-luatest/debug-target.lua b/test/app-luatest/debug-target.lua new file mode 100644 index 0000000000000000000000000000000000000000..39c84d30a1d49b24473f601ab8f14deab84d90be --- /dev/null +++ b/test/app-luatest/debug-target.lua @@ -0,0 +1,14 @@ +local debugger = require 'luadebug' +debugger() +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)