diff --git a/lib/debug/dap_custom/recordInspector.rb b/lib/debug/dap_custom/recordInspector.rb index 39bdf1d51..3dcfa0c99 100644 --- a/lib/debug/dap_custom/recordInspector.rb +++ b/lib/debug/dap_custom/recordInspector.rb @@ -20,6 +20,7 @@ def custom_dap_request_rdbgRecordInspector(req) tid = req.dig('arguments', 'threadId') count = req.dig('arguments', 'count') if tc = find_waiting_tc(tid) + @ui.respond req, {} tc << [:step, :in, count] else fail_response req @@ -28,6 +29,7 @@ def custom_dap_request_rdbgRecordInspector(req) tid = req.dig('arguments', 'threadId') count = req.dig('arguments', 'count') if tc = find_waiting_tc(tid) + @ui.respond req, {} tc << [:step, :back, count] else fail_response req diff --git a/test/protocol/rdbgRecordInspctor_test.rb b/test/protocol/rdbgRecordInspctor_test.rb new file mode 100644 index 000000000..4f90a2a0d --- /dev/null +++ b/test/protocol/rdbgRecordInspctor_test.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require_relative '../support/protocol_test_case' + +module DEBUGGER__ + class RdbgRecordInspectorTest < ProtocolTestCase + PROGRAM = <<~RUBY + 1| module Foo + 2| class Bar + 3| def self.a + 4| "hello" + 5| end + 6| end + 7| Bar.a + 8| bar = Bar.new + 9| end + RUBY + + def test_defaut_setting + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments][:rdbgExtension] = ["recordInspector"] + run_protocol_scenario(PROGRAM, cdp: false) do + req_rdbgRecordInspector_enable + req_add_breakpoint 5 + req_continue + assert_rdbgRecordInspector_collect_result( + [ + { + name: "", + location: { + line: 2, + } + }, + { + name: "", + location: { + line: 3, + } + } + ] + ) + req_rdbgRecordInspector_step_back 4 + assert_line_num 2 + req_rdbgRecordInspector_step 1 + assert_line_num 3 + req_terminate_debuggee + end + ensure + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments].delete :rdbgExtension + end + + def test_restart_trace + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments][:rdbgExtension] = ["recordInspector"] + run_protocol_scenario(PROGRAM, cdp: false) do + req_rdbgRecordInspector_enable + req_rdbgRecordInspector_disable + req_rdbgRecordInspector_enable + req_add_breakpoint 5 + req_continue + assert_rdbgRecordInspector_collect_result( + [ + { + name: "", + location: { + line: 2, + } + }, + { + name: "", + location: { + line: 3, + } + } + ] + ) + req_rdbgRecordInspector_step_back 4 + assert_line_num 2 + req_rdbgRecordInspector_step 1 + assert_line_num 3 + req_terminate_debuggee + end + ensure + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments].delete :rdbgExtension + end + end +end diff --git a/test/protocol/rdbgTraceInspctor_test.rb b/test/protocol/rdbgTraceInspctor_test.rb new file mode 100644 index 000000000..f859cf2e8 --- /dev/null +++ b/test/protocol/rdbgTraceInspctor_test.rb @@ -0,0 +1,138 @@ +# frozen_string_literal: true + +require_relative '../support/protocol_test_case' + +module DEBUGGER__ + class RdbgTraceInspectorTest < ProtocolTestCase + PROGRAM = <<~RUBY + 1| def foo + 2| 'bar' + 3| end + 4| foo + 5| foo + RUBY + + def test_defaut_setting + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments][:rdbgExtension] = ["traceInspector"] + run_protocol_scenario(PROGRAM, cdp: false) do + req_rdbgTraceInspector_enable + req_add_breakpoint 5 + req_continue + assert_rdbgTraceInspector_collect_result( + [ + { + returnValue: "\"bar\"", + name: 'Object#foo', + location: { + line: 3, + } + }, + { + name: 'Object#foo', + location: { + line: 1, + } + }, + { + location: { + line: 4, + } + }, + ] + ) + req_terminate_debuggee + end + ensure + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments].delete :rdbgExtension + end + + def test_call_event + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments][:rdbgExtension] = ["traceInspector"] + run_protocol_scenario(PROGRAM, cdp: false) do + req_rdbgTraceInspector_enable(events: ['call']) + req_add_breakpoint 5 + req_continue + assert_rdbgTraceInspector_collect_result( + [ + { + name: 'Object#foo', + location: { + line: 1, + } + }, + ] + ) + req_terminate_debuggee + end + ensure + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments].delete :rdbgExtension + end + + def test_return_event + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments][:rdbgExtension] = ["traceInspector"] + run_protocol_scenario(PROGRAM, cdp: false) do + req_rdbgTraceInspector_enable(events: ['return']) + req_add_breakpoint 5 + req_continue + assert_rdbgTraceInspector_collect_result( + [ + { + returnValue: "\"bar\"", + name: 'Object#foo', + location: { + line: 3, + } + }, + ] + ) + req_terminate_debuggee + end + ensure + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments].delete :rdbgExtension + end + + def test_line_event + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments][:rdbgExtension] = ["traceInspector"] + run_protocol_scenario(PROGRAM, cdp: false) do + req_rdbgTraceInspector_enable(events: ['line']) + req_add_breakpoint 5 + req_continue + assert_rdbgTraceInspector_collect_result( + [ + { + location: { + line: 4, + } + }, + ] + ) + req_terminate_debuggee + end + ensure + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments].delete :rdbgExtension + end + + def test_restart_trace + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments][:rdbgExtension] = ["traceInspector"] + run_protocol_scenario(PROGRAM, cdp: false) do + req_rdbgTraceInspector_enable + req_rdbgTraceInspector_disable + req_rdbgTraceInspector_enable(events: ['line']) + req_add_breakpoint 5 + req_continue + assert_rdbgTraceInspector_collect_result( + [ + { + location: { + line: 4, + } + }, + ] + ) + req_terminate_debuggee + end + ensure + DEBUGGER__::INITIALIZE_DAP_MSGS[1][:arguments].delete :rdbgExtension + end + end +end diff --git a/test/support/protocol_test_case.rb b/test/support/protocol_test_case.rb index b8741e3db..76d8aa3f2 100644 --- a/test/support/protocol_test_case.rb +++ b/test/support/protocol_test_case.rb @@ -219,6 +219,22 @@ def gather_variables(frame_idx: 0, type: "locals") end end + def req_rdbgTraceInspector_enable events: ['line', 'call', 'return'] + send_custom_dap_request 'rdbgTraceInspector', command: 'enable', events: events + end + + def req_rdbgTraceInspector_disable + send_custom_dap_request 'rdbgTraceInspector', command: 'disable' + end + + def req_rdbgRecordInspector_enable + send_custom_dap_request 'rdbgRecordInspector', command: 'enable' + end + + def req_rdbgRecordInspector_disable + send_custom_dap_request 'rdbgRecordInspector', command: 'disable' + end + def assert_locals_result expected, frame_idx: 0 case get_target_ui when 'vscode' @@ -301,8 +317,51 @@ def assert_watch_result expected, expression, frame_idx: 0 end end + def req_rdbgRecordInspector_step_back count + send_custom_dap_request 'rdbgRecordInspector', command: 'stepBack', threadId: 1, count: count + end + + def req_rdbgRecordInspector_step count + send_custom_dap_request 'rdbgRecordInspector', command: 'step', threadId: 1, count: count + end + + def assert_rdbgRecordInspector_collect_result expected + res = send_custom_dap_request 'rdbgRecordInspector', command: 'collect', threadId: 1 + assert_collect_result(res, expected) do |exp, log| + check_hash_values(exp, log, :name) && + check_hash_values(exp[:location], log[:location], :line) + end + end + + def assert_rdbgTraceInspector_collect_result expected + res = send_custom_dap_request 'rdbgTraceInspector', command: 'collect' + assert_collect_result(res, expected) do |exp, log| + check_hash_values(exp, log, :returnValue) && + check_hash_values(exp, log, :name) && + check_hash_values(exp[:location], log[:location], :line) + end + end + # Not API + def assert_collect_result res, expected + logs = res.dig(:body, :logs) + expected.each{|exp| + matched = logs.find {|log| + yield exp, log + } + if matched.nil? + msg = create_protocol_message "Expected to include\n`#{JSON.pretty_generate exp}`\nIn\n`#{JSON.pretty_generate logs}`\n" + flunk(msg) + end + } + end + + def check_hash_values hash_a, hash_b, key + hash_a.has_key?(key) == hash_b.has_key?(key) && + hash_a[key] == hash_b[key] + end + def attach_to_cdp_server_ body = get_request HOST, @remote_info.port, '/json' Timeout.timeout(TIMEOUT_SEC) do @@ -558,6 +617,11 @@ def send_dap_request command, **kw res end + def send_custom_dap_request command, **kw + send_request command, **kw + return find_crt_dap_response + end + def send_cdp_request command, **kw send_request command, **kw res = find_crt_cdp_response