llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Ebuka Ezike (da-viper) <details> <summary>Changes</summary> Migrated Tests - TestDAP_console.py - TestDAP_redirection_to_console.py - TestDAP_restart.py - TestDAP_restart_console.py --- Patch is 25.66 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/213019.diff 4 Files Affected: - (modified) lldb/test/API/tools/lldb-dap/console/TestDAP_console.py (+98-91) - (modified) lldb/test/API/tools/lldb-dap/console/TestDAP_redirection_to_console.py (+23-17) - (modified) lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py (+46-49) - (modified) lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_console.py (+43-39) ``````````diff diff --git a/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py b/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py index ceddaeb50cd3b..11e8cf5e8f692 100644 --- a/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py +++ b/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py @@ -1,15 +1,24 @@ """ -Test lldb-dap setBreakpoints request +Test lldb-dap debug console output. """ -import dap_server -import lldbdap_testcase -from lldbsuite.test import lldbutil -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * +import importlib.util +import os +import unittest +from lldbsuite.test.decorators import skipIfWindows +from lldbsuite.test.lldbtest import line_number +from lldbsuite.test.tools.lldb_dap.types import LaunchArgs +from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase, DAPTestSession -def get_subprocess(root_process, process_name): + +skipUnlessPsutil = unittest.skipUnless( + importlib.util.find_spec("psutil") is not None, + "psutil not installed, please install using 'pip install psutil'.", +) + + +def get_subprocess(root_process, process_name: str): queue = [root_process] while queue: process = queue.pop() @@ -17,26 +26,40 @@ def get_subprocess(root_process, process_name): return process queue.extend(process.children()) - self.assertTrue(False, "No subprocess with name %s found" % process_name) + raise AssertionError(f"No subprocess with name {process_name!r} found") -class TestDAP_console(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_console(DAPTestCaseBase): def check_lldb_command( - self, lldb_command, contains_string, assert_msg, command_escape_prefix="`" + self, + session: DAPTestSession, + lldb_command: str, + contains: str, + escape_prefix: str = "`", ): - response = self.dap_server.request_evaluate( - f"{command_escape_prefix}{lldb_command}", context="repl" - ) - output = response["body"]["result"] - self.assertIn( - contains_string, - output, - ( - """Verify %s by checking the command output:\n""" - """'''\n%s'''\nfor the string: "%s" """ - % (assert_msg, output, contains_string) - ), + resp_body = session.evaluate(f"{escape_prefix}{lldb_command}", context="repl") + session.verify_evaluate(resp_body, matches=f".*{contains}.*") + + def do_test_with_escape_prefix(self, escape_prefix: str): + """Launch with the given `commandEscapePrefix`, stop on the breakpoint, + run `help` with the prefix, and exit.""" + session = self.build_and_create_session() + program = self.getBuildArtifact("a.out") + source = "main.cpp" + breakpoint1_line = line_number(source, "// breakpoint 1") + + launch_args = LaunchArgs(program, commandEscapePrefix=escape_prefix) + with session.configure(launch_args) as ctx: + bp_ids = session.resolve_source_breakpoints(source, [breakpoint1_line]) + session.verify_stopped_on_breakpoint(bp_ids, after=ctx.process_event) + + self.check_lldb_command( + session, + "help", + "For more information on any command", + escape_prefix=escape_prefix, ) + session.continue_to_exit() def test_scopes_variables_setVariable_evaluate(self): """ @@ -52,131 +75,115 @@ def test_scopes_variables_setVariable_evaluate(self): evaluated and the lldb commands that start with the backtick character. """ + session = self.build_and_create_session() program = self.getBuildArtifact("a.out") - self.build_and_launch(program) source = "main.cpp" breakpoint1_line = line_number(source, "// breakpoint 1") - lines = [breakpoint1_line] - # Set breakpoint in the thread function so we can step the threads - breakpoint_ids = self.set_source_breakpoints(source, lines) - self.assertEqual( - len(breakpoint_ids), len(lines), "expect correct number of breakpoints" + with session.configure(LaunchArgs(program)) as ctx: + bp_ids = session.resolve_source_breakpoints(source, [breakpoint1_line]) + stop_event = session.verify_stopped_on_breakpoint( + bp_ids, after=ctx.process_event ) - self.continue_to_breakpoints(breakpoint_ids) + # Cause a "scopes" to be sent for frame zero which should update the # selected thread and frame to frame 0. - self.dap_server.get_local_variables(frameIndex=0) + thread_ctx = session.thread_context_from(stop_event) + frame_ctxs = thread_ctx.frames() + frame_ctxs[0].locals.variables() # Verify frame #0 is selected in the command interpreter by running # the "frame select" command with no frame index which will print the # currently selected frame. - self.check_lldb_command("frame select", "frame #0", "frame 0 is selected") + self.check_lldb_command(session, "frame select", "frame #0") # Cause a "scopes" to be sent for frame one which should update the # selected thread and frame to frame 1. - self.dap_server.get_local_variables(frameIndex=1) + frame_ctxs[1].locals.variables() # Verify frame #1 is selected in the command interpreter by running # the "frame select" command with no frame index which will print the # currently selected frame. - self.check_lldb_command("frame select", "frame #1", "frame 1 is selected") + self.check_lldb_command(session, "frame select", "frame #1") - def test_custom_escape_prefix(self): - program = self.getBuildArtifact("a.out") - self.build_and_launch(program, commandEscapePrefix="::") - source = "main.cpp" - breakpoint1_line = line_number(source, "// breakpoint 1") - breakpoint_ids = self.set_source_breakpoints(source, [breakpoint1_line]) - self.continue_to_breakpoints(breakpoint_ids) + session.continue_to_exit() - self.check_lldb_command( - "help", - "For more information on any command", - "Help can be invoked", - command_escape_prefix="::", - ) + def test_custom_escape_prefix(self): + self.do_test_with_escape_prefix("::") def test_empty_escape_prefix(self): - program = self.getBuildArtifact("a.out") - self.build_and_launch(program, commandEscapePrefix="") - source = "main.cpp" - breakpoint1_line = line_number(source, "// breakpoint 1") - breakpoint_ids = self.set_source_breakpoints(source, [breakpoint1_line]) - self.continue_to_breakpoints(breakpoint_ids) - - self.check_lldb_command( - "help", - "For more information on any command", - "Help can be invoked", - command_escape_prefix="", - ) + self.do_test_with_escape_prefix("") @skipIfWindows + @skipUnlessPsutil def test_exit_status_message_sigterm(self): + import psutil + + debug_server_path = self.get_debug_server_path() + if debug_server_path is None: + self.skipTest(f"{self.getPlatform()!r} does not have a debug server.") + + session = self.build_and_create_session() source = "main.cpp" program = self.getBuildArtifact("a.out") - self.build_and_launch(program, commandEscapePrefix="") breakpoint1_line = line_number(source, "// breakpoint 1") - breakpoint_ids = self.set_source_breakpoints(source, [breakpoint1_line]) - self.continue_to_breakpoints(breakpoint_ids) + with session.configure(LaunchArgs(program, commandEscapePrefix="")) as ctx: + breakpoint_ids = session.resolve_source_breakpoints( + source, [breakpoint1_line] + ) - # Kill lldb-server process. - process_name = ( - "debugserver" if platform.system() in ["Darwin"] else "lldb-server" + stop_event = session.verify_stopped_on_breakpoint( + breakpoint_ids, after=ctx.process_event ) - try: - import psutil - except ImportError: - print( - "psutil not installed, please install using 'pip install psutil'. " - "Skipping test_exit_status_message_sigterm test.", - file=sys.stderr, - ) - return - process = get_subprocess(psutil.Process(os.getpid()), process_name) + # Kill lldb-server process. + debug_server_name = debug_server_path.stem + process = get_subprocess(psutil.Process(os.getpid()), debug_server_name) process.terminate() process.wait() # Get the console output - console_output = self.collect_console(pattern="exited with status") + captured = session.collect_console(after=stop_event, until="exited with status") # Verify the exit status message is printed. self.assertRegex( - console_output, + captured.seen_texts, ".*exited with status = -1 .* died with signal SIGTERM.*", - "Exit status does not contain message 'exited with status'", + "exit status does not contain message 'exited with status'", ) def test_exit_status_message_ok(self): + session = self.build_and_create_session() program = self.getBuildArtifact("a.out") - self.build_and_launch(program, commandEscapePrefix="") - self.continue_to_exit() + process_event = session.launch(LaunchArgs(program, commandEscapePrefix="")) + session.verify_process_exited() - # Get the console output - console_output = self.collect_console(pattern="exited with status") + # Get the console output. + captured = session.collect_console( + after=process_event, until="exited with status" + ) # Verify the exit status message is printed. self.assertIn( "exited with status = 0 (0x00000000)", - console_output, - "Exit status does not contain message 'exited with status'", + captured.seen_texts, + "exit status does not contain message 'exited with status'", ) - def test_diagnositcs(self): + def test_diagnostics(self): + session = self.build_and_create_session() program = self.getBuildArtifact("a.out") - self.build_and_launch(program) + process_event = session.launch(LaunchArgs(program, stopOnEntry=True)) + stop_event = session.verify_stopped_on_entry(after=process_event) core = self.getBuildArtifact("minidump.core") self.yaml2obj("minidump.yaml", core) - self.dap_server.request_evaluate( - f"target create --core {core}", context="repl" - ) + session.evaluate(f"target create --core {core}", context="repl") - diagnostics = self.collect_important(pattern="minidump file") + captured = session.collect_important(after=stop_event, until="minidump file") self.assertIn( "warning: unable to retrieve process ID from minidump file", - diagnostics, + captured.seen_texts, "diagnostic found in important output", ) + session.continue_to_exit() diff --git a/lldb/test/API/tools/lldb-dap/console/TestDAP_redirection_to_console.py b/lldb/test/API/tools/lldb-dap/console/TestDAP_redirection_to_console.py index e367c327d4295..a904f77770e9a 100644 --- a/lldb/test/API/tools/lldb-dap/console/TestDAP_redirection_to_console.py +++ b/lldb/test/API/tools/lldb-dap/console/TestDAP_redirection_to_console.py @@ -1,12 +1,15 @@ -import dap_server -import json -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil -import lldbdap_testcase +"""Test that lldb-dap keeps stdout/stderr redirection working even when the +inferior's output is routed back through the debug console.""" +from lldbsuite.test.lldbtest import line_number +from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase +from lldbsuite.test.tools.lldb_dap.types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.utils import DebugAdapterOptions + + +class TestDAP_redirection_to_console(DAPTestCaseBase): + USE_DEFAULT_DEBUG_ADAPTER = False -class TestDAP_redirection_to_console(lldbdap_testcase.DAPTestCaseBase): def test(self): """ Without proper stderr and stdout redirection, the following code would throw an @@ -14,19 +17,22 @@ def test(self): Exception: unexpected malformed message from lldb-dap """ + self.build() program = self.getBuildArtifact("a.out") - self.build_and_launch( - program, lldbDAPEnv={"LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION": ""} + adapter = self.create_stdio_debug_adapter( + DebugAdapterOptions( + env={"LLDB_DAP_TEST_STDOUT_STDERR_REDIRECTION": ""}, + ) ) + session = self.create_session(adapter) source = "main.cpp" - breakpoint1_line = line_number(source, "// breakpoint 1") - breakpoint_ids = self.set_source_breakpoints(source, [breakpoint1_line]) + with session.configure(LaunchArgs(program)) as ctx: + [bp_id] = session.resolve_source_breakpoints(source, [breakpoint1_line]) - self.assertEqual(len(breakpoint_ids), 1, "expect correct number of breakpoints") - self.continue_to_breakpoints(breakpoint_ids) - - self.assertIn( - "argc", json.dumps(self.dap_server.get_local_variables(frameIndex=1)) - ) + stop = session.verify_stopped_on_breakpoint(bp_id, after=ctx.process_event) + thread_ctx = session.thread_context_from(stop) + _, second_frame, *_ = thread_ctx.frames() + local_names = [var.name for var in second_frame.locals.variables()] + self.assertIn("argc", local_names) diff --git a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py index 19f37203f4947..516bfd3d79e6b 100644 --- a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py +++ b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py @@ -2,44 +2,49 @@ Test lldb-dap RestartRequest. """ -from lldbsuite.test.decorators import * +from lldbsuite.test.decorators import skipIfWindows from lldbsuite.test.lldbtest import line_number -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase +from lldbsuite.test.tools.lldb_dap.types import LaunchArgs -class TestDAP_restart(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_restart(DAPTestCaseBase): @skipIfWindows def test_basic_functionality(self): """ Tests the basic restarting functionality: set two breakpoints in sequence, restart at the second, check that we hit the first one. """ + program = self.getBuildArtifact("a.out") + session = self.build_and_create_session() line_A = line_number("main.c", "// breakpoint A") line_B = line_number("main.c", "// breakpoint B") - program = self.getBuildArtifact("a.out") - self.build_and_launch(program) - [bp_A, bp_B] = self.set_source_breakpoints("main.c", [line_A, line_B]) + with session.configure(LaunchArgs(program)) as ctx: + [bp_A, bp_B] = session.resolve_source_breakpoints( + "main.c", [line_A, line_B] + ) # Verify we hit A, then B. - self.continue_to_breakpoints([bp_A]) - self.continue_to_breakpoints([bp_B]) + session.verify_stopped_on_breakpoint(bp_A, after=ctx.process_event) + stop_event = session.continue_to_breakpoint(bp_B) # Make sure i has been modified from its initial value of 0. + top_frame = session.top_frame_from(stop_event) + i_val = top_frame.locals["i"] self.assertEqual( - int(self.dap_server.get_local_variable_value("i")), - 1234, - "i != 1234 after hitting breakpoint B", + i_val.value_as_int, 1234, "i != 1234 after hitting breakpoint B" ) # Restart then check we stop back at A and program state has been reset. - resp = self.dap_server.request_restart() - self.assertTrue(resp["success"]) - self.verify_breakpoint_hit([bp_A]) + last_event = session.last_event() + session.do_restart() + + stop_event = session.verify_stopped_on_breakpoint(bp_A, after=last_event) + top_frame = session.top_frame_from(stop_event) + i_val = top_frame.locals["i"] self.assertEqual( - int(self.dap_server.get_local_variable_value("i")), - 0, - "i != 0 after hitting breakpoint A on restart", + i_val.value_as_int, 0, "i != 0 after hitting breakpoint A on restart" ) @skipIfWindows @@ -48,20 +53,19 @@ def test_stopOnEntry(self): Check that the stopOnEntry setting is still honored after a restart. """ program = self.getBuildArtifact("a.out") - self.build_and_launch(program, stopOnEntry=True) - [bp_main] = self.set_function_breakpoints(["main"]) + session = self.build_and_create_session() + with session.configure(LaunchArgs(program, stopOnEntry=True)) as ctx: + [bp_main] = session.resolve_function_breakpoints(["main"]) - self.verify_configuration_done() - self.verify_stop_on_entry() + session.verify_stopped_on_entry(after=ctx.process_event) # Then, if we continue, we should hit the breakpoint at main. - self.continue_to_breakpoints([bp_main]) + bp_stop_event = session.continue_to_breakpoint(bp_main) # Restart and check that we still get a stopped event before reaching # main. - resp = self.dap_server.request_restart() - self.assertTrue(resp["success"]) - self.verify_stop_on_entry() + session.do_restart() + session.verify_stopped_on_entry(after=bp_stop_event) @skipIfWindows def test_arguments(self): @@ -69,37 +73,30 @@ def test_arguments(self): Tests that lldb-dap will use updated launch arguments included with a restart request. """ + session = self.build_and_create_session() + program = self.getBuildArtifact("a.out") line_A = line_number("main.c", "// breakpoint A") - program = self.getBuildArtifact("a.out") - self.build_and_launch(program) - [bp_A] = self.set_source_breakpoints("main.c", [line_A]) + with session.configure(LaunchArgs(program)) as ctx: + [bp_A] = session.resolve_source_breakpoints("main.c", [line_A]) # Verify we hit A, then B. - self.continue_to_breakpoints([bp_A]) + stop_event = session.verify_stopped_on_breakpoint(bp_A, after=ctx.process_event) + top_frame = session.top_frame_from(stop_event) + argc_val = top_frame.locals["argc"] # We don't set any arguments in the initial launch request, so argc # should be 1. - self.assertEqual( - int(self.dap_server.get_local_variable_value("argc")), - 1, - "argc != 1 before restart", - ) + self.assertEqual(argc_val.value_as_int, 1, "argc != 1 before restart") + last_event = session.last_event() # Restart with some extra 'args' and check that the new argc reflects # the updated launch config. - resp = self.dap_server.request_restart( - restartArguments={ - "arguments": { - "program": program, - "args": ["a", "b", "c", "d"], - } - } - ) - self.assertTrue(resp["success"]) - self.verify_breakpoint_hit([bp_A]) - self.assertEqual( - int(self.dap_server.get_local_variable_value("argc")), - 5, - "argc != 5 after restart", - ) + session.do_restart(LaunchArgs(program, args=["a", "b", "c", "d"])) + + stop_event = session.verify_stopped_on_breakpoint(bp_A, after=last_event) + ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/213019 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
