Author: Ebuka Ezike Date: 2026-07-07T12:04:06+01:00 New Revision: baddc8f7778881120a2a206de817454e13f762bc
URL: https://github.com/llvm/llvm-project/commit/baddc8f7778881120a2a206de817454e13f762bc DIFF: https://github.com/llvm/llvm-project/commit/baddc8f7778881120a2a206de817454e13f762bc.diff LOG: [lldb-dap] Migrate DAP launch tests (#207023) Migrate all the tests in `lldb-dap/launch` base directory only. Fixes any grammar if needed. Added: Modified: lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_args.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_commands.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_cwd.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_debuggerRoot.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_disableSTDIO.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_array.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_object.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_console.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_launch_commands.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_launch_commands_and_console.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_program.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_no_lldbinit_flag.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_disabled.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_enabled.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_sourcePath.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection_and_console.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stopOnEntry.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_terminate_commands.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_termination.py lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_version.py lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp Removed: ################################################################################ diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_args.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_args.py index 6774f0516ae79..98091e63d58cf 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_args.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_args.py @@ -2,11 +2,11 @@ Test lldb-dap launch request. """ -from lldbsuite.test.decorators import expectedFailureWindows -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_args(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_args(DAPTestCaseBase): """ Tests launch of a simple program with arguments """ @@ -14,20 +14,21 @@ class TestDAP_launch_args(lldbdap_testcase.DAPTestCaseBase): def test(self): program = self.getBuildArtifact("a.out") args = ["one", "with space", "'with single quotes'", '"with double quotes"'] - self.build_and_launch(program, args=args) - self.continue_to_exit() + session = self.build_and_create_session() + session.launch(LaunchArgs(program=program, args=args)) + session.verify_process_exited() - # Now get the STDOUT and verify our arguments got passed correctly - output = self.get_stdout() + output = session.get_stdout() self.assertTrue(output and len(output) > 0, "expect program output") lines = output.splitlines() - # Skip the first argument that contains the program name + # Skip the first argument that contains the program name. lines.pop(0) - # Make sure arguments we specified are correct - for i, arg in enumerate(args): - quoted_arg = '"%s"' % (arg) + # Make sure arguments we specified are correct. + args_and_lines = zip(args, lines) + for i, (arg, line) in enumerate(args_and_lines, start=1): + quoted_arg = f'"{arg}"' self.assertIn( quoted_arg, - lines[i], - 'arg[%i] "%s" not in "%s"' % (i + 1, quoted_arg, lines[i]), + line, + f'arg[{i}] "{arg}" not in {line!r}', ) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_commands.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_commands.py index 48398e5915069..21a3f61460de5 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_commands.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_commands.py @@ -4,10 +4,11 @@ from lldbsuite.test.decorators import skipIf from lldbsuite.test.lldbtest import line_number -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_commands(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_commands(DAPTestCaseBase): """ Tests the "initCommands", "preRunCommands", "stopCommands", "terminateCommands" and "exitCommands" that can be passed during @@ -34,7 +35,9 @@ def test(self): stopCommands = ["frame variable", "bt"] exitCommands = ["expr 2+3", "expr 3+4"] terminateCommands = ["expr 4+2"] - self.build_and_launch( + session = self.build_and_create_session() + + launch_args = LaunchArgs( program, initCommands=initCommands, preRunCommands=preRunCommands, @@ -43,49 +46,52 @@ def test(self): exitCommands=exitCommands, terminateCommands=terminateCommands, ) - self.dap_server.wait_for_initialized() + with session.configure(launch_args) as ctx: + # Get output from the console. This should contain the + # "initCommands", "preRunCommands", and "postRunCommands". + coutput = session.collect_console( + after=ctx.init_response, until=postRunCommands[-1] + ) + output = coutput.seen_texts + session.verify_commands("initCommands", output, initCommands) + session.verify_commands("preRunCommands", output, preRunCommands) + session.verify_commands("postRunCommands", output, postRunCommands) - # Get output from the console. This should contain both the - # "initCommands" and the "preRunCommands". - output = self.collect_console(pattern=postRunCommands[-1]) - # Verify all "initCommands" were found in console output - self.verify_commands("initCommands", output, initCommands) - # Verify all "preRunCommands" were found in console output - self.verify_commands("preRunCommands", output, preRunCommands) - # Verify all "postRunCommands" were found in console output - self.verify_commands("postRunCommands", output, postRunCommands) + source = "main.c" + first_line = line_number(source, "// breakpoint 1") + second_line = line_number(source, "// breakpoint 2") + lines = [first_line, second_line] - source = "main.c" - first_line = line_number(source, "// breakpoint 1") - second_line = line_number(source, "// breakpoint 2") - lines = [first_line, second_line] + # Set 2 breakpoints so we can verify that "stopCommands" get run as the + # breakpoints get hit. + [first_bp, second_bp] = session.resolve_source_breakpoints(source, lines) - # Set 2 breakpoints so we can verify that "stopCommands" get run as the - # breakpoints get hit - breakpoint_ids = self.set_source_breakpoints(source, lines) - self.assertEqual( - len(breakpoint_ids), len(lines), "expect correct number of breakpoints" - ) + launch_response = ctx.launch_or_attach_response # Continue after launch and hit the first breakpoint. - # Get output from the console. This should contain both the - # "stopCommands" that were run after the first breakpoint was hit - self.continue_to_breakpoints(breakpoint_ids) - output = self.collect_console(pattern=stopCommands[-1]) - self.verify_commands("stopCommands", output, stopCommands) + # Get output from the console. This should contain the + # "stopCommands" that were run after the first breakpoint was hit. + session.verify_stopped_on_breakpoint(first_bp, after=ctx.process_event) + coutput = session.collect_console(after=launch_response, until=stopCommands[-1]) + output = coutput.seen_texts + session.verify_commands("stopCommands", output, stopCommands) # Continue again and hit the second breakpoint. - # Get output from the console. This should contain both the - # "stopCommands" that were run after the second breakpoint was hit - self.continue_to_breakpoints(breakpoint_ids) - output = self.collect_console(pattern=stopCommands[-1]) - self.verify_commands("stopCommands", output, stopCommands) + # Get output from the console. This should contain the + # "stopCommands" that were run after the second breakpoint was hit. + session.continue_to_breakpoint(second_bp) + coutput = session.collect_console(after=coutput.event, until=stopCommands[-1]) + output = coutput.seen_texts + session.verify_commands("stopCommands", output, stopCommands) - # Continue until the program exits - self.continue_to_exit() - # Get output from the console. This should contain both the - # "exitCommands" that were run after the second breakpoint was hit - # and the "terminateCommands" due to the debugging session ending - output = self.collect_console(pattern=terminateCommands[0]) - self.verify_commands("exitCommands", output, exitCommands) - self.verify_commands("terminateCommands", output, terminateCommands) + # Continue until the program exits. + # Get output from the console. This should contain the + # "exitCommands" run on process exit and the "terminateCommands" + # run when the debugging session ends. + session.continue_to_exit() + coutput = session.collect_console( + after=coutput.event, until=terminateCommands[0] + ) + output = coutput.seen_texts + session.verify_commands("exitCommands", output, exitCommands) + session.verify_commands("terminateCommands", output, terminateCommands) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_cwd.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_cwd.py index c2b2b98635134..a7e4ffab3d640 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_cwd.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_cwd.py @@ -2,35 +2,37 @@ Test lldb-dap launch request. """ -from lldbsuite.test.decorators import skipIfWindows -import lldbdap_testcase import os +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_cwd(lldbdap_testcase.DAPTestCaseBase): + +class TestDAP_launch_cwd(DAPTestCaseBase): """ Tests the default launch of a simple program with a current working directory. """ - @skipIfWindows def test(self): program = self.getBuildArtifact("a.out") program_parent_dir = os.path.realpath(os.path.dirname(os.path.dirname(program))) - self.build_and_launch(program, cwd=program_parent_dir) - self.continue_to_exit() - # Now get the STDOUT and verify our program argument is correct - output = self.get_stdout() + session = self.build_and_create_session() + session.launch(LaunchArgs(program=program, cwd=program_parent_dir)) + session.verify_process_exited() + + # Now get the STDOUT and verify our program's working directory is correct + output = session.get_stdout() self.assertTrue(output and len(output) > 0, "expect program output") + lines = output.splitlines() - found = False - for line in lines: - if line.startswith('cwd = "'): - quote_path = '"%s"' % (program_parent_dir) - found = True - self.assertIn( - quote_path, - line, - "working directory '%s' not in '%s'" % (program_parent_dir, line), - ) - self.assertTrue(found, "verified program working directory") + cwd_lines = [line for line in lines if line.startswith('cwd = "')] + self.assertEqual(len(cwd_lines), 1, "verified program working directory") + cwd_line = cwd_lines[0] + + quote_path = f'"{program_parent_dir}"' + self.assertIn( + quote_path, + cwd_line, + f"working directory '{program_parent_dir}' not in '{cwd_line}'", + ) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_debuggerRoot.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_debuggerRoot.py index deeab23d3ec56..6bf470ed142e3 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_debuggerRoot.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_debuggerRoot.py @@ -2,13 +2,14 @@ Test lldb-dap launch request. """ -from lldbsuite.test.decorators import expectedFailureWindows -from lldbsuite.test import lldbplatformutil -import lldbdap_testcase import os +from lldbsuite.test import lldbplatformutil +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase + -class TestDAP_launch_debuggerRoot(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_debuggerRoot(DAPTestCaseBase): """ Tests the "debuggerRoot" will change the working directory of the lldb-dap debug adapter. @@ -19,24 +20,29 @@ def test(self): program_parent_dir = os.path.realpath(os.path.dirname(os.path.dirname(program))) var = "%cd%" if lldbplatformutil.getHostPlatform() == "windows" else "$PWD" - commands = [f"platform shell echo cwd = {var}"] + init_commands = [f"platform shell echo cwd = {var}"] - self.build_and_launch( - program, debuggerRoot=program_parent_dir, initCommands=commands + session = self.build_and_create_session() + process_event = session.launch( + LaunchArgs( + program=program, + debuggerRoot=program_parent_dir, + initCommands=init_commands, + ) ) - self.continue_to_exit() - output = self.get_console() + session.verify_process_exited(after=process_event) + + output = session.get_console() self.assertTrue(output and len(output) > 0, "expect console output") - lines = output.splitlines() + prefix = "cwd = " - found = False - for line in lines: - if line.startswith(prefix): - found = True - self.assertEqual( - program_parent_dir, - line.strip()[len(prefix) :], - "lldb-dap working dir '%s' == '%s'" - % (program_parent_dir, line[len(prefix) :]), - ) - self.assertTrue(found, "verified lldb-dap working directory") + cwd_lines = [line for line in output.splitlines() if line.startswith(prefix)] + self.assertEqual( + len(cwd_lines), 1, "expected exactly one cwd line in console output" + ) + self.assertEqual( + cwd_lines[0].strip()[len(prefix) :], + program_parent_dir, + f"lldb-dap working dir mismatch: expected '{program_parent_dir}', " + f"got '{cwd_lines[0]}'", + ) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_disableSTDIO.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_disableSTDIO.py index 0a780f5771fdb..39d350f3e9d57 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_disableSTDIO.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_disableSTDIO.py @@ -3,10 +3,11 @@ """ from lldbsuite.test.decorators import skipIfWindows -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_disableSTDIO(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_disableSTDIO(DAPTestCaseBase): """ Tests the default launch of a simple program with STDIO disabled. """ @@ -14,8 +15,10 @@ class TestDAP_launch_disableSTDIO(lldbdap_testcase.DAPTestCaseBase): @skipIfWindows def test(self): program = self.getBuildArtifact("a.out") - self.build_and_launch(program, disableSTDIO=True) - self.continue_to_exit() - # Now get the STDOUT and verify our program argument is correct - output = self.get_stdout() + session = self.build_and_create_session() + session.launch(LaunchArgs(program=program, disableSTDIO=True)) + session.verify_process_exited() + + # Now get the STDOUT and verify our program argument is correct. + output = session.get_stdout() self.assertEqual(output, "", "expect no program output") diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_array.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_array.py index 1595f4a30dbe5..2e96a1139c937 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_array.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_array.py @@ -3,10 +3,11 @@ """ from lldbsuite.test.decorators import skipIfWindows -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_environment_with_array(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_environment_with_array(DAPTestCaseBase): """ Tests launch of a simple program with environment variables """ @@ -14,26 +15,28 @@ class TestDAP_launch_environment_with_array(lldbdap_testcase.DAPTestCaseBase): @skipIfWindows def test(self): program = self.getBuildArtifact("a.out") - env = ["NO_VALUE", "WITH_VALUE=BAR", "EMPTY_VALUE=", "SPACE=Hello World"] + expected_env = [ + "NO_VALUE", + "WITH_VALUE=BAR", + "EMPTY_VALUE=", + "SPACE=Hello World", + ] - self.build_and_launch(program, env=env) - self.continue_to_exit() + session = self.build_and_create_session() + process_event = session.launch(LaunchArgs(program=program, env=expected_env)) + session.verify_process_exited(after=process_event) - # Now get the STDOUT and verify our arguments got passed correctly - output = self.get_stdout() - self.assertTrue(output and len(output) > 0, "expect program output") - lines = output.splitlines() - # Skip the all arguments so we have only environment vars left - while len(lines) and lines[0].startswith("arg["): - lines.pop(0) - # Make sure each environment variable in "env" is actually set in the - # program environment that was printed to STDOUT - for var in env: - found = False - for program_var in lines: - if var in program_var: - found = True - break - self.assertTrue( - found, '"%s" must exist in program environment (%s)' % (var, lines) + # Now get the STDOUT and verify our arguments got passed correctly. + output = session.get_stdout() + self.assertTrue(output, "expect program output") + + # Collect environment lines. + env_output = "\n".join(l for l in output.splitlines() if l.startswith("env[")) + # Make sure each environment variable in "expected_env" is actually set in the + # program environment and contains the right value. + for expected_str in expected_env: + self.assertIn( + expected_str, + env_output, + f"\n{expected_str} must exist in program's environment \n{env_output}", ) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_object.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_object.py index 8c7994eac7926..a853bbc341791 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_object.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_environment_with_object.py @@ -2,41 +2,43 @@ Test lldb-dap launch request. """ -from lldbsuite.test.decorators import expectedFailureWindows -import lldbdap_testcase +from lldbsuite.test.decorators import skipIfWindows +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch(lldbdap_testcase.DAPTestCaseBase): - def test_environment_with_object(self): - """ - Tests launch of a simple program with environment variables - """ +class TestDAP_launch_environment_with_object(DAPTestCaseBase): + """ + Tests launch of a simple program with environment variables + """ + + @skipIfWindows + def test(self): program = self.getBuildArtifact("a.out") - env = { - "NO_VALUE": "", + expected_env = { + "NO_VALUE": None, "WITH_VALUE": "BAR", "EMPTY_VALUE": "", "SPACE": "Hello World", } - self.build_and_launch(program, env=env) - self.continue_to_exit() + session = self.build_and_create_session() + process_event = session.launch(LaunchArgs(program=program, env=expected_env)) + session.verify_process_exited(after=process_event) + + # Now get the STDOUT and verify our arguments got passed correctly. + output = session.get_stdout() + self.assertTrue(output, "expect program output") - # Now get the STDOUT and verify our arguments got passed correctly - output = self.get_stdout() - self.assertTrue(output and len(output) > 0, "expect program output") - lines = output.splitlines() - # Skip the all arguments so we have only environment vars left - while len(lines) and lines[0].startswith("arg["): - lines.pop(0) - # Make sure each environment variable in "env" is actually set in the - # program environment that was printed to STDOUT - for var in env: - found = False - for program_var in lines: - if var in program_var: - found = True - break - self.assertTrue( - found, '"%s" must exist in program environment (%s)' % (var, lines) + # Collect environment lines. + env_output = "\n".join(l for l in output.splitlines() if l.startswith("env[")) + # Make sure each environment variable in "expected_env" is actually set in the + # program environment and contains the right value. + for variable, value in expected_env.items(): + expected_value = value or "" + expected_str = f'"{variable}={expected_value}"' + self.assertIn( + expected_str, + env_output, + f"\n{expected_str} must exist in program's environment \n{env_output}", ) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py index ad48af6364aba..92c481ad9d42d 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_extra_launch_commands.py @@ -4,10 +4,11 @@ from lldbsuite.test.decorators import skipIf from lldbsuite.test.lldbtest import line_number -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_extra_launch_commands(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_extra_launch_commands(DAPTestCaseBase): """ Tests the "launchCommands" with extra launching settings """ @@ -15,18 +16,17 @@ class TestDAP_launch_extra_launch_commands(lldbdap_testcase.DAPTestCaseBase): # Flakey on 32-bit Arm Linux. @skipIf(oslist=["linux"], archs=["arm$"]) def test(self): - self.build_and_create_debug_adapter() program = self.getBuildArtifact("a.out") - - source = "main.c" + session = self.build_and_create_session() + source = self.getSourcePath("main.c") first_line = line_number(source, "// breakpoint 1") second_line = line_number(source, "// breakpoint 2") - # Set target binary and 2 breakpoints - # then we can verify the "launchCommands" get run - # also we can verify that "stopCommands" get run as the - # breakpoints get hit + + # Set target binary and 2 breakpoints, so we can verify the + # "launchCommands" get run, and verify "stopCommands" get run + # as the breakpoints get hit. launchCommands = [ - 'target create "%s"' % (program), + f'target create "{program}"', "process launch --stop-at-entry", ] initCommands = ["target list", "platform list"] @@ -34,51 +34,48 @@ def test(self): postRunCommands = ['script print("hello world")'] stopCommands = ["frame variable", "bt"] exitCommands = ["expr 2+3", "expr 3+4"] - self.launch( - program, - initCommands=initCommands, - preRunCommands=preRunCommands, - postRunCommands=postRunCommands, - stopCommands=stopCommands, - exitCommands=exitCommands, - launchCommands=launchCommands, - ) - self.set_source_breakpoints("main.c", [first_line, second_line]) - - # Get output from the console. This should contain both the - # "initCommands" and the "preRunCommands". - output = self.get_console() - # Verify all "initCommands" were found in console output - self.verify_commands("initCommands", output, initCommands) - # Verify all "preRunCommands" were found in console output - self.verify_commands("preRunCommands", output, preRunCommands) - # Verify all "launchCommands" were found in console output - # After execution, program should launch - self.verify_commands("launchCommands", output, launchCommands) - self.verify_commands("postRunCommands", output, postRunCommands) + with session.configure( + LaunchArgs( + program=program, + launchCommands=launchCommands, + initCommands=initCommands, + preRunCommands=preRunCommands, + postRunCommands=postRunCommands, + stopCommands=stopCommands, + exitCommands=exitCommands, + ) + ) as ctx: + session.resolve_source_breakpoints(source, [first_line, second_line]) + process_event = ctx.process_event + # The launchCommands stop the process at entry, but lldb-dap auto-continues + # after configurationDone (since stopOnEntry isn't set), so the first + # observable stop is hitting the first breakpoint, not entry. + first_stop = session.verify_stopped_on_breakpoint(after=process_event) - # Finish configuration and continue target - self.verify_configuration_done() + # Get output from the console. This should contain the + # "initCommands", "preRunCommands", "launchCommands", and "postRunCommands". + output = session.get_console() + session.verify_commands("initCommands", output, initCommands) + session.verify_commands("preRunCommands", output, preRunCommands) + session.verify_commands("launchCommands", output, launchCommands) + session.verify_commands("postRunCommands", output, postRunCommands) - # Check that we got module events from target - modules = self.dap_server.wait_for_module_events() - self.assertGreater(len(modules), 0) + # Check that we got module events from target. + session.wait_for_module_event(after=ctx.init_response) - # Verify the "stopCommands" here - output = self.get_console() - self.verify_commands("stopCommands", output, stopCommands) + # Verify the "stopCommands" ran on the first breakpoint hit. + # Wait until the last stopCommand's output arrives to avoid racing it. + output = session.collect_console(after=first_stop, until=stopCommands[-1]) + session.verify_commands("stopCommands", output.seen_texts, stopCommands) - # Continue and hit the second breakpoint. - # Get output from the console. This should contain both the - # "stopCommands" that were run after the first breakpoint was hit - self.continue_to_next_stop() - output = self.get_console() - self.verify_commands("stopCommands", output, stopCommands) + # Continue and hit the second breakpoint, then verify "stopCommands" + # ran again. + session.continue_to_next_stop() + output = session.collect_console(after=output.event, until=stopCommands[-1]) + session.verify_commands("stopCommands", output.seen_texts, stopCommands) - # Continue until the program exits - self.continue_to_exit() - # Get output from the console. This should contain both the - # "exitCommands" that were run after the second breakpoint was hit - output = self.get_console() - self.verify_commands("exitCommands", output, exitCommands) + # Continue until the program exits, then verify "exitCommands" ran. + session.continue_to_exit() + output = session.collect_console(after=output.event, until=exitCommands[-1]) + session.verify_commands("exitCommands", output.seen_texts, exitCommands) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_console.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_console.py index c59a5fed50dae..c4dc50ad463e6 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_console.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_console.py @@ -2,22 +2,31 @@ Test lldb-dap launch request. """ -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_failing_console(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_failing_console(DAPTestCaseBase): """ Tests launching in console with an invalid terminal type. """ def test(self): program = self.getBuildArtifact("a.out") - self.create_debug_adapter() - launch_seq = self.launch(program, console="invalid") - response = self.dap_server.receive_response(launch_seq) - self.assertFalse(response["success"]) - self.assertTrue(self.get_dict_value(response, ["body", "error", "showUser"])) + # No build needed: the launch request should be rejected during arg + # validation, before lldb-dap touches the program path. + session = self.create_session() + session.initialize_sequence(session.initialize_args) + + err_response = session.send_request( + LaunchArgs(program=program, console="invalid") + ).error() + error_msg = self.expect_not_none( + err_response.body and err_response.body.error, + "expected an error message in the launch response", + ) + self.assertTrue(error_msg.showUser, "expected showUser=true") self.assertRegex( - response["body"]["error"]["format"], - r"unexpected value, expected 'internalConsole\', 'integratedTerminal\' or 'externalTerminal\' at arguments.console", + error_msg.format, + r"unexpected value, expected 'internalConsole', 'integratedTerminal' or 'externalTerminal' at arguments.console", ) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_launch_commands.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_launch_commands.py index ad48fb9a8a3f6..13730ed311206 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_launch_commands.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_failing_launch_commands.py @@ -2,50 +2,55 @@ Test lldb-dap launch request. """ -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -import lldbdap_testcase import os import re +from lldbsuite.test.tools.lldb_dap.dap_types import InitializedEvent, LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_failing_launch_commands(lldbdap_testcase.DAPTestCaseBase): + +class TestDAP_launch_failing_launch_commands(DAPTestCaseBase): """ Tests "launchCommands" failures prevents a launch. """ def test(self): - self.build_and_create_debug_adapter() + session = self.build_and_create_session() program = self.getBuildArtifact("a.out") + init_response = session.initialize_sequence(session.initialize_args) # Run an invalid launch command, in this case a bad path. bad_path = os.path.join("bad", "path") - launchCommands = ['!target create "%s%s"' % (bad_path, program)] - + launchCommands = [f'!target create "{bad_path}{program}"'] initCommands = ["target list", "platform list"] preRunCommands = ["image list a.out", "image dump sections a.out"] - response = self.launch_and_configurationDone( - program, - initCommands=initCommands, - preRunCommands=preRunCommands, - launchCommands=launchCommands, + + launch_handle = session.send_request( + LaunchArgs( + program=program, + initCommands=initCommands, + preRunCommands=preRunCommands, + launchCommands=launchCommands, + ) ) + session.wait_for_event(InitializedEvent, after=init_response) + session.configuration_done().result_or_error() + err_response = launch_handle.error() - self.assertFalse(response["success"]) + error_msg = self.expect_not_none( + err_response.body and err_response.body.error, + "expected an error message in the launch response", + ) self.assertRegex( - response["body"]["error"]["format"], + error_msg.format, r"Failed to run launch commands\. See the Debug Console for more details", ) - # Get output from the console. This should contain both the - # "initCommands" and the "preRunCommands". - output = self.get_console() - # Verify all "initCommands" were found in console output - self.verify_commands("initCommands", output, initCommands) - # Verify all "preRunCommands" were found in console output - self.verify_commands("preRunCommands", output, preRunCommands) - - # Verify all "launchCommands" were founc in console output + # Get output from the console. This should contain the + # "initCommands", "preRunCommands", and "launchCommands". + output = session.get_console() + session.verify_commands("initCommands", output, initCommands) + session.verify_commands("preRunCommands", output, preRunCommands) + session.verify_commands("launchCommands", output, launchCommands) # The launch should fail due to the invalid command. - self.verify_commands("launchCommands", output, launchCommands) self.assertRegex(output, re.escape(bad_path) + r".*does not exist") diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_launch_commands_and_console.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_launch_commands_and_console.py index 14d7dbe551729..dfd28e6b7f783 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_launch_commands_and_console.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_launch_commands_and_console.py @@ -2,26 +2,35 @@ Test lldb-dap launch request. """ -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.dap_types import Console, LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_failing_launch_commands_and_console( - lldbdap_testcase.DAPTestCaseBase -): +class TestDAP_launch_invalid_launch_commands_and_console(DAPTestCaseBase): """ Tests launching with launch commands in an integrated terminal. """ def test(self): program = self.getBuildArtifact("a.out") - self.create_debug_adapter() - launch_seq = self.launch( - program, launchCommands=["a b c"], console="integratedTerminal" + # No build needed: the launch request should be rejected during + # argument validation, before lldb-dap touches the program path. + session = self.create_session() + session.initialize_sequence(session.initialize_args) + + err_response = session.send_request( + LaunchArgs( + program=program, + launchCommands=["a b c"], + console=Console.INTEGRATED_TERMINAL, + ) + ).error() + error_msg = self.expect_not_none( + err_response.body and err_response.body.error, + "expected an error message in the launch response", ) - response = self.dap_server.receive_response(launch_seq) - self.assertFalse(response["success"]) - self.assertTrue(self.get_dict_value(response, ["body", "error", "showUser"])) + self.assertTrue(error_msg.showUser, "expected showUser=true") self.assertIn( "'launchCommands' and non-internal 'console' are mutually exclusive", - self.get_dict_value(response, ["body", "error", "format"]), + error_msg.format, ) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_program.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_program.py index d70426ff8710d..60746599a2638 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_program.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_invalid_program.py @@ -2,22 +2,26 @@ Test lldb-dap launch request. """ -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_invalid_program(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_invalid_program(DAPTestCaseBase): """ Tests launching with an invalid program. """ def test(self): program = self.getBuildArtifact("a.out") - self.create_debug_adapter() - launch_seq = self.launch(program) - self.dap_server.wait_for_initialized() - self.dap_server.request_configurationDone() - response = self.dap_server.receive_response(launch_seq) - self.assertFalse(response["success"]) - self.assertEqual( - "'{0}' does not exist".format(program), response["body"]["error"]["format"] + session = self.create_session() + session.initialize_sequence(session.initialize_args) + launch_handle = session.send_request(LaunchArgs(program=program)) + session.ensure_initialized() + session.verify_configuration_done(expected_success=False) + + err_response = launch_handle.error() + error_msg = self.expect_not_none( + err_response.body and err_response.body.error, + "expected an error message in the launch response", ) + self.assertEqual(error_msg.format, f"'{program}' does not exist") diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_no_lldbinit_flag.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_no_lldbinit_flag.py index 8a48075a0fa76..22cfcf3078b11 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_no_lldbinit_flag.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_no_lldbinit_flag.py @@ -2,16 +2,21 @@ Test lldb-dap launch request. """ -import lldbdap_testcase import os import tempfile +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase +from lldbsuite.test.tools.lldb_dap.utils import DebugAdapterOptions -class TestDAP_launch_no_lldbinit_flag(lldbdap_testcase.DAPTestCaseBase): + +class TestDAP_launch_no_lldbinit_flag(DAPTestCaseBase): """ Test that the --no-lldbinit flag prevents sourcing .lldbinit files. """ + USE_DEFAULT_DEBUG_ADAPTER = False + def test(self): # Create a temporary .lldbinit file in the home directory with tempfile.TemporaryDirectory() as temp_home: @@ -22,29 +27,35 @@ def test(self): f.write("settings set stop-disassembly-display never\n") f.write("settings set target.x86-disassembly-flavor intel\n") - # Test with --no-lldbinit flag (should NOT source .lldbinit) - self.build_and_create_debug_adapter( - lldbDAPEnv={"HOME": temp_home}, additional_args=["--no-lldbinit"] - ) + # Build, then spin up a debug adapter with HOME pointing at the + # temp dir and the --no-lldbinit flag. + self.build() program = self.getBuildArtifact("a.out") + adapter = self.create_stdio_debug_adapter( + DebugAdapterOptions( + env={"HOME": temp_home}, + args=["--no-lldbinit"], + ) + ) + session = self.create_session(adapter=adapter) - # Use initCommands to check if .lldbinit was sourced + # Use initCommands to check if .lldbinit was sourced. initCommands = ["settings show stop-disassembly-display"] + process_event = session.launch( + LaunchArgs(program=program, initCommands=initCommands) + ) + session.verify_process_exited(after=process_event) - # Launch with initCommands to check the setting - self.launch(program, initCommands=initCommands) - self.continue_to_exit() - - # Get console output to verify the setting was NOT set from .lldbinit - output = self.get_console() + # Get console output to verify the setting was NOT set from .lldbinit. + output = session.get_console() self.assertTrue(output and len(output) > 0, "expect console output") - # Verify the setting has default value, not "never" from .lldbinit + # Verify the setting has default value, not "never" from .lldbinit. self.assertNotIn( "never", output, "Setting should have default value when --no-lldbinit is used", ) - # Verify the initCommands were executed - self.verify_commands("initCommands", output, initCommands) + # Verify the initCommands were executed. + session.verify_commands("initCommands", output, initCommands) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_disabled.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_disabled.py index d7b8579845956..38157849facfb 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_disabled.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_disabled.py @@ -2,12 +2,13 @@ Test lldb-dap launch request. """ -from lldbsuite.test.decorators import expectedFailureWindows -import lldbdap_testcase import os +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_shellExpandArguments_disabled(lldbdap_testcase.DAPTestCaseBase): + +class TestDAP_launch_shellExpandArguments_disabled(DAPTestCaseBase): """ Tests the default launch of a simple program with shell expansion disabled. @@ -17,15 +18,16 @@ def test(self): program = self.getBuildArtifact("a.out") program_dir = os.path.dirname(program) glob = os.path.join(program_dir, "*.out") - self.build_and_launch(program, args=[glob], shellExpandArguments=False) - self.continue_to_exit() + session = self.build_and_create_session() + process_event = session.launch( + LaunchArgs(program=program, args=[glob], shellExpandArguments=False) + ) + session.verify_process_exited(after=process_event) + # Now get the STDOUT and verify our program argument is correct - output = self.get_stdout() - self.assertTrue(output and len(output) > 0, "expect no program output") - lines = output.splitlines() - for line in lines: - quote_path = '"%s"' % (glob) + output = session.get_stdout() + self.assertTrue(output and len(output) > 0, "expect program output") + for line in output.splitlines(): if line.startswith("arg[1] ="): - self.assertIn( - quote_path, line, 'verify "%s" stayed to "%s"' % (glob, glob) - ) + quote_path = f'"{glob}"' + self.assertIn(quote_path, line, f'verify "{glob}" stayed as "{glob}"') diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_enabled.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_enabled.py index 7ddde219fc88d..e5ba6a4852714 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_enabled.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_shellExpandArguments_enabled.py @@ -2,16 +2,14 @@ Test lldb-dap launch request. """ -from lldbsuite.test.decorators import ( - skipIfLinux, - expectedFailureWindows, - expectedFailureAll, -) -import lldbdap_testcase import os +from lldbsuite.test.decorators import expectedFailureAll, skipIfLinux +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_shellExpandArguments_enabled(lldbdap_testcase.DAPTestCaseBase): + +class TestDAP_launch_shellExpandArguments_enabled(DAPTestCaseBase): """ Tests the default launch of a simple program with shell expansion enabled. @@ -25,15 +23,20 @@ def test(self): program = self.getBuildArtifact("a.out") program_dir = os.path.dirname(program) glob = os.path.join(program_dir, "*.out") - self.build_and_launch(program, args=[glob], shellExpandArguments=True) - self.continue_to_exit() + session = self.build_and_create_session() + process_event = session.launch( + LaunchArgs(program=program, args=[glob], shellExpandArguments=True) + ) + session.verify_process_exited(after=process_event) + # Now get the STDOUT and verify our program argument is correct - output = self.get_stdout() - self.assertTrue(output and len(output) > 0, "expect no program output") - lines = output.splitlines() - for line in lines: - quote_path = '"%s"' % (program) + output = session.get_stdout() + self.assertTrue(output and len(output) > 0, "expect program output") + for line in output.splitlines(): if line.startswith("arg[1] ="): + quote_path = f'"{program}"' self.assertIn( - quote_path, line, 'verify "%s" expanded to "%s"' % (glob, program) + quote_path, + line, + f'verify "{glob}" expanded to "{program}"', ) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_sourcePath.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_sourcePath.py index 4e09816fefc31..b62276c25f285 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_sourcePath.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_sourcePath.py @@ -2,11 +2,13 @@ Test lldb-dap launch request. """ -import lldbdap_testcase import os +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_sourcePath(lldbdap_testcase.DAPTestCaseBase): + +class TestDAP_launch_sourcePath(DAPTestCaseBase): """ Tests the "sourcePath" will set the target.source-map. """ @@ -14,20 +16,23 @@ class TestDAP_launch_sourcePath(lldbdap_testcase.DAPTestCaseBase): def test(self): program = self.getBuildArtifact("a.out") program_dir = os.path.dirname(program) - self.build_and_launch(program, sourcePath=program_dir) - self.continue_to_exit() - output = self.get_console() + session = self.build_and_create_session() + process_event = session.launch( + LaunchArgs(program=program, sourcePath=program_dir) + ) + session.verify_process_exited(after=process_event) + + output = session.get_console() self.assertTrue(output and len(output) > 0, "expect console output") - lines = output.splitlines() prefix = '(lldb) settings set target.source-map "." ' found = False - for line in lines: + for line in output.splitlines(): if line.startswith(prefix): found = True - quoted_path = '"%s"' % (program_dir) + quoted_path = f'"{program_dir}"' self.assertEqual( quoted_path, line[len(prefix) :], - "lldb-dap working dir %s == %s" % (quoted_path, line[6:]), + f"lldb-dap working dir {quoted_path} == {line[6:]}", ) self.assertTrue(found, 'found "sourcePath" in console output') diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection.py index 81501702624be..21d311076513d 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection.py @@ -2,22 +2,26 @@ Test lldb-dap launch request. """ -import lldbdap_testcase import tempfile +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_stdio_redirection(lldbdap_testcase.DAPTestCaseBase): + +class TestDAP_launch_stdio_redirection(DAPTestCaseBase): """ Test stdio redirection. """ def test(self): - self.build_and_create_debug_adapter() program = self.getBuildArtifact("a.out") + session = self.build_and_create_session() with tempfile.NamedTemporaryFile("rt") as f: - self.launch_and_configurationDone(program, stdio=[None, f.name]) - self.verify_process_exited() + process_event = session.launch( + LaunchArgs(program=program, stdio=[None, f.name]) + ) + session.verify_process_exited(after=process_event) lines = f.readlines() self.assertIn( program, lines[0], "make sure program path is in first argument" diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection_and_console.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection_and_console.py index f4512a5c7bb63..fa503c2aae312 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection_and_console.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stdio_redirection_and_console.py @@ -2,18 +2,20 @@ Test lldb-dap launch request. """ +import tempfile + from lldbsuite.test.decorators import ( - skipIfAsan, + no_match, skipIf, + skipIfAsan, skipIfBuildType, - no_match, skipIfWindows, ) -import lldbdap_testcase -import tempfile +from lldbsuite.test.tools.lldb_dap.dap_types import Console, LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_stdio_redirection_and_console(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_stdio_redirection_and_console(DAPTestCaseBase): """ Test stdio redirection and console. """ @@ -23,14 +25,18 @@ class TestDAP_launch_stdio_redirection_and_console(lldbdap_testcase.DAPTestCaseB @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) @skipIfBuildType(["debug"]) def test(self): - self.build_and_create_debug_adapter() program = self.getBuildArtifact("a.out") + session = self.build_and_create_session() with tempfile.NamedTemporaryFile("rt") as f: - self.launch_and_configurationDone( - program, console="integratedTerminal", stdio=[None, f.name, None] + process_event = session.launch( + LaunchArgs( + program=program, + console=Console.INTEGRATED_TERMINAL, + stdio=[None, f.name, None], + ) ) - self.verify_process_exited() + session.verify_process_exited(after=process_event) lines = f.readlines() self.assertIn( program, lines[0], "make sure program path is in first argument" diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stopOnEntry.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stopOnEntry.py index 24ceaf3f89656..bbeefc5d1f793 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stopOnEntry.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_stopOnEntry.py @@ -2,10 +2,15 @@ Test lldb-dap launch request. """ -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.dap_types import ( + ExitedEvent, + LaunchArgs, + StoppedEvent, +) +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_stopOnEntry(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_stopOnEntry(DAPTestCaseBase): """ Tests the default launch of a simple program that stops at the entry point instead of continuing. @@ -13,16 +18,25 @@ class TestDAP_launch_stopOnEntry(lldbdap_testcase.DAPTestCaseBase): def test(self): program = self.getBuildArtifact("a.out") - self.build_and_launch(program, stopOnEntry=True) - self.dap_server.request_configurationDone() - self.dap_server.wait_for_stopped() - self.assertTrue( - len(self.dap_server.thread_stop_reasons) > 0, - "expected stopped event during launch", + session = self.build_and_create_session() + process_event = session.launch(LaunchArgs(program, stopOnEntry=True)) + stop_event = session.verify_stopped_on_entry(after=process_event) + exit_event = session.continue_to_exit() + + seen_stop_events = [] + + def matches_exit_event(evt): + if isinstance(evt, StoppedEvent): + seen_stop_events.append(evt) + return evt.seq == exit_event.seq + + # Collect stopped events until the ExitEvent. + session.wait_for_any_event( + (StoppedEvent, ExitedEvent), after=stop_event, until=matches_exit_event + ) + # Verify we did not receive any other stop event. + self.assertEqual( + len(seen_stop_events), + 0, + f"expected no new stopped events. seen events: {seen_stop_events}", ) - for _, body in self.dap_server.thread_stop_reasons.items(): - if "reason" in body: - reason = body["reason"] - self.assertNotEqual( - reason, "breakpoint", 'verify stop isn\'t "main" breakpoint' - ) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_terminate_commands.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_terminate_commands.py index e2eed86fe2799..7e89a38d6ad96 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_terminate_commands.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_terminate_commands.py @@ -2,32 +2,35 @@ Test lldb-dap launch request. """ -from lldbsuite.test.decorators import skipIfNetBSD, skipIf -import lldbdap_testcase +from lldbsuite.test.decorators import skipIf, skipIfNetBSD +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -class TestDAP_launch_terminate_commands(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_terminate_commands(DAPTestCaseBase): """ - Tests that the "terminateCommands", that can be passed during - launch, are run when the debugger is disconnected. + Tests that the "terminateCommands", that can be passed during launch, + are run when the debugger is disconnected. """ @skipIfNetBSD # Hangs on NetBSD as well @skipIf(archs=["arm$", "aarch64"], oslist=["linux"]) def test(self): - self.build_and_create_debug_adapter() program = self.getBuildArtifact("a.out") + session = self.build_and_create_session(disconnect_automatically=False) - terminateCommands = ["expr 4+2"] - self.launch( - program, - stopOnEntry=True, - terminateCommands=terminateCommands, - disconnectAutomatically=False, + terminate_commands = ["history"] + process_event = session.launch( + LaunchArgs( + program=program, + stopOnEntry=True, + terminateCommands=terminate_commands, + ) + ) + stop_event = session.verify_stopped_on_entry(after=process_event) + # Once it's disconnected the console should contain the "terminateCommands". + session.disconnect(terminateDebuggee=True) + output = session.collect_console(after=stop_event, until=terminate_commands[0]) + session.verify_commands( + "terminateCommands", output.seen_texts, terminate_commands ) - self.get_console() - # Once it's disconnected the console should contain the - # "terminateCommands" - self.dap_server.request_disconnect(terminateDebuggee=True) - output = self.collect_console(pattern=terminateCommands[0]) - self.verify_commands("terminateCommands", output, terminateCommands) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_termination.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_termination.py index 71e5a45bebaec..35cad17018113 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_termination.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_termination.py @@ -2,25 +2,41 @@ Test lldb-dap launch request. """ -import lldbdap_testcase +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase +from lldbsuite.test.tools.lldb_dap.utils import DebugAdapter -class TestDAP_launch_termination(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_termination(DAPTestCaseBase): """ Tests the correct termination of lldb-dap upon a 'disconnect' request. """ - def test(self): - self.create_debug_adapter() - # The underlying lldb-dap process must be alive - self.assertEqual(self.dap_server.process.poll(), None) + USE_DEFAULT_DEBUG_ADAPTER = False + def test_termination_socket(self): + adapter = self.create_server_debug_adapter( + connection="listen://localhost:0", + connection_timeout=1, + ) + self.do_test_termination(adapter) + + def test_termination_stdio(self): + adapter = self.create_stdio_debug_adapter() + self.do_test_termination(adapter) + + def do_test_termination(self, adapter: DebugAdapter): + # The underlying lldb-dap process must be alive. + self.assertTrue(adapter.is_alive, f"adapter is dead: {adapter.process.args}") + session = self.create_session(adapter, disconnect_automatically=False) + + session.initialize_sequence(session.initialize_args) # The lldb-dap process should finish even though - # we didn't close the communication socket explicitly - self.dap_server.request_disconnect() + # we didn't close the communication socket explicitly. + session.disconnect() # Wait until the underlying lldb-dap process dies. - self.dap_server.process.wait(timeout=self.DEFAULT_TIMEOUT) + adapter.process.wait(timeout=self.DEFAULT_TIMEOUT) + self.assertFalse(session.is_running(), f"expected ended session.") - # Check the return code - self.assertEqual(self.dap_server.process.poll(), 0) + # Check the return code. + self.assertEqual(adapter.process.poll(), 0) diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_version.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_version.py index fca153044da82..0c3609f66c7df 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_version.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch_version.py @@ -1,13 +1,8 @@ -""" -Test lldb-dap launch request. -""" +from lldbsuite.test.tools.lldb_dap.dap_types import LaunchArgs +from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase -from lldbsuite.test.decorators import expectedFailureWindows -from lldbsuite.test.lldbtest import line_number -import lldbdap_testcase - -class TestDAP_launch_version(lldbdap_testcase.DAPTestCaseBase): +class TestDAP_launch_version(DAPTestCaseBase): """ Tests that "initialize" response contains the "version" string the same as the one returned by "version" command. @@ -15,21 +10,14 @@ class TestDAP_launch_version(lldbdap_testcase.DAPTestCaseBase): def test(self): program = self.getBuildArtifact("a.out") - self.build_and_launch(program) + session = self.build_and_create_session() - source = "main.c" - breakpoint_line = line_number(source, "// breakpoint 1") - lines = [breakpoint_line] - # Set breakpoint in the thread function so we can step the threads - breakpoint_ids = self.set_source_breakpoints(source, lines) - self.continue_to_breakpoints(breakpoint_ids) + process_event = session.launch(LaunchArgs(program=program, stopOnEntry=True)) + session.verify_stopped_on_entry(after=process_event) - version_eval_response = self.dap_server.request_evaluate( - "`version", context="repl" - ) - version_eval_output = version_eval_response["body"]["result"] + version_eval_output = session.evaluate("`version", context="repl").result + version_string = self.expect_not_none(session.capabilities().lldb_version) - version_string = self.dap_server.get_capability("$__lldb_version") self.assertEqual( version_eval_output.splitlines(), version_string.splitlines(), diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp index 75f3bc3ef8152..078f607dec2b8 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Base64.h" #include "llvm/Support/JSON.h" +#include <optional> #include <utility> using namespace llvm; @@ -35,13 +36,15 @@ static bool parseEnv(const json::Value &Params, return true; if (const json::Object *env_obj = value->getAsObject()) { - for (const auto &kv : *env_obj) { - const std::optional<StringRef> value = kv.second.getAsString(); - if (!value) { - P.field("env").field(kv.first).report("expected string value"); + for (const auto &[key, val] : *env_obj) { + if (const std::optional<StringRef> val_str = val.getAsString()) { + env.insert({key.str(), val_str->str()}); + } else if (val.getAsNull()) { + env.insert({key.str(), ""}); + } else { + P.field("env").field(key).report("expected string value"); return false; } - env.insert({kv.first.str(), value->str()}); } return true; } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
