https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/140777
>From e50ea7d279adcb181f68a7156b5fc12d1047f402 Mon Sep 17 00:00:00 2001 From: John Harrison <harj...@google.com> Date: Tue, 20 May 2025 11:09:35 -0700 Subject: [PATCH 1/3] [lldb-dap] Test gardening, enabling tests and improving doc comments. A bit of test gardenining. Enabling tests that were marked as skipped as part of https://github.com/llvm/llvm-project/issues/137660. Fixed up some comments and doc comments and fixed some test helpers. --- .../Python/lldbsuite/test/decorators.py | 26 ++++++++ .../attach/TestDAP_attachByPortNum.py | 61 ++++++++----------- .../breakpoint/TestDAP_setBreakpoints.py | 1 - .../TestDAP_setExceptionBreakpoints.py | 1 - .../TestDAP_setFunctionBreakpoints.py | 1 - .../tools/lldb-dap/cancel/TestDAP_cancel.py | 2 - .../tools/lldb-dap/console/TestDAP_console.py | 25 ++++---- .../lldb-dap/coreFile/TestDAP_coreFile.py | 2 - .../TestDAP_setDataBreakpoints.py | 2 +- .../disassemble/TestDAP_disassemble.py | 2 - .../lldb-dap/disconnect/TestDAP_disconnect.py | 1 - .../lldb-dap/evaluate/TestDAP_evaluate.py | 3 - .../TestDAP_instruction_breakpoint.py | 37 +++++------ .../tools/lldb-dap/launch/TestDAP_launch.py | 19 +++--- .../lldb-dap/locations/TestDAP_locations.py | 5 +- .../tools/lldb-dap/memory/TestDAP_memory.py | 2 - .../module-event/TestDAP_module_event.py | 7 ++- .../tools/lldb-dap/module/TestDAP_module.py | 4 +- .../lldb-dap/optimized/TestDAP_optimized.py | 4 +- .../tools/lldb-dap/output/TestDAP_output.py | 2 +- .../lldb-dap/progress/TestDAP_Progress.py | 7 +-- .../repl-mode/TestDAP_repl_mode_detection.py | 2 - .../tools/lldb-dap/restart/TestDAP_restart.py | 2 +- .../restart/TestDAP_restart_runInTerminal.py | 22 +------ .../runInTerminal/TestDAP_runInTerminal.py | 47 ++------------ .../tools/lldb-dap/source/TestDAP_source.py | 3 - .../subtleFrames/TestDAP_subtleFrames.py | 10 ++- .../TestDAP_stackTraceDisassemblyDisplay.py | 2 +- .../TestDAP_stackTraceMissingFunctionName.py | 2 +- .../TestDAP_stackTraceMissingModule.py | 2 +- .../API/tools/lldb-dap/step/TestDAP_step.py | 4 +- .../stepInTargets/TestDAP_stepInTargets.py | 9 +-- .../TestDAP_terminatedEvent.py | 3 - .../tools/lldb-dap/threads/TestDAP_threads.py | 3 +- .../lldb-dap/variables/TestDAP_variables.py | 5 +- .../children/TestDAP_variables_children.py | 6 +- 36 files changed, 124 insertions(+), 212 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index 895f2a82547a9..5e14dfeda48a8 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -1,5 +1,6 @@ # System modules from functools import wraps +from typing import Optional from packaging import version import ctypes import locale @@ -1102,3 +1103,28 @@ def is_feature_enabled(): return "%s is not supported on this system." % feature return skipTestIfFn(is_feature_enabled) + + +def skipIfBinaryToLarge(path: Optional[str], maxSize: int): + """Skip the test if a binary is to large. + + We skip this test for debug builds because it takes too long + parsing lldb's own debug info. Release builds are fine. + Checking the size of the lldb-dap binary seems to be a decent + proxy for a quick detection. It should be far less than 1 MB in + Release builds. + """ + + def check_binary_size(): + if not path or not os.path.exists(path): + return "invalid path" + + try: + size = os.path.getsize(path) + if size <= maxSize: + return None + return f"binary {path} (size = {size} is to larger than {maxSize}" + except: + return f"failed to read size of {path}" + + return skipTestIfFn(check_binary_size) diff --git a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attachByPortNum.py b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attachByPortNum.py index 7c2b540195d15..edb87a9314d78 100644 --- a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attachByPortNum.py +++ b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attachByPortNum.py @@ -2,26 +2,16 @@ Test lldb-dap "port" configuration to "attach" request """ -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil from lldbsuite.test import lldbplatformutil from lldbgdbserverutils import Pipe import lldbdap_testcase -import os -import shutil -import subprocess -import tempfile -import threading -import sys -import socket +import lldb -@skip("https://github.com/llvm/llvm-project/issues/138803") +@skip(bugnumber="https://github.com/llvm/llvm-project/issues/138803") class TestDAP_attachByPortNum(lldbdap_testcase.DAPTestCaseBase): - default_timeout = 20 - def set_and_hit_breakpoint(self, continueToExit=True): self.dap_server.wait_for_stopped() @@ -50,7 +40,7 @@ def get_debug_server_command_line_args(self): def get_debug_server_pipe(self): pipe = Pipe(self.getBuildDir()) self.addTearDownHook(lambda: pipe.close()) - pipe.finish_connection(self.default_timeout) + pipe.finish_connection(self.DEFAULT_TIMEOUT) return pipe @skipIfWindows @@ -73,28 +63,33 @@ def test_by_port(self): ) # Read the port number from the debug server pipe. - port = pipe.read(10, self.default_timeout) + port = pipe.read(10, self.DEFAULT_TIMEOUT) # Trim null byte, convert to int port = int(port[:-1]) self.assertIsNotNone( port, " Failed to read the port number from debug server pipe" ) - self.attach(program=program, gdbRemotePort=port, sourceInitFile=True) + self.attach( + program=program, + gdbRemotePort=port, + sourceInitFile=True, + stopOnEntry=True, + ) self.set_and_hit_breakpoint(continueToExit=True) - self.process.terminate() @skipIfWindows @skipIfNetBSD - def test_by_port_and_pid(self): + def test_fails_if_both_port_and_pid_are_set(self): """ Tests attaching to a process by process ID and port number. """ program = self.build_and_create_debug_adapter_for_attach() - # It is not necessary to launch "lldb-server" to obtain the actual port and pid for attaching. - # However, when providing the port number and pid directly, "lldb-dap" throws an error message, which is expected. - # So, used random pid and port numbers here. + # It is not necessary to launch "lldb-server" to obtain the actual port + # and pid for attaching. However, when providing the port number and pid + # directly, "lldb-dap" throws an error message, which is expected. So, + # used random pid and port numbers here. pid = 1354 port = 1234 @@ -106,10 +101,9 @@ def test_by_port_and_pid(self): sourceInitFile=True, expectFailure=True, ) - if not (response and response["success"]): - self.assertFalse( - response["success"], "The user can't specify both pid and port" - ) + self.assertFalse( + response["success"], "The user can't specify both pid and port" + ) @skipIfWindows @skipIfNetBSD @@ -123,11 +117,10 @@ def test_by_invalid_port(self): response = self.attach( program=program, gdbRemotePort=port, sourceInitFile=True, expectFailure=True ) - if not (response and response["success"]): - self.assertFalse( - response["success"], - "The user can't attach with invalid port (%s)" % port, - ) + self.assertFalse( + response["success"], + "The user can't attach with invalid port (%s)" % port, + ) @skipIfWindows @skipIfNetBSD @@ -147,9 +140,7 @@ def test_by_illegal_port(self): response = self.attach( program=program, gdbRemotePort=port, sourceInitFile=True, expectFailure=True ) - if not (response and response["success"]): - self.assertFalse( - response["success"], - "The user can't attach with illegal port (%s)" % port, - ) - self.process.terminate() + self.assertFalse( + response["success"], + "The user can't attach with illegal port (%s)" % port, + ) diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py index aae1251b17c93..26df2573555df 100644 --- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py +++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py @@ -12,7 +12,6 @@ import os -@skip("Temporarily disable the breakpoint tests") class TestDAP_setBreakpoints(lldbdap_testcase.DAPTestCaseBase): def setUp(self): lldbdap_testcase.DAPTestCaseBase.setUp(self) diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py index 4dc8c5b3c7ded..92ac66cd44c5d 100644 --- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py +++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py @@ -10,7 +10,6 @@ import lldbdap_testcase -@skip("Temporarily disable the breakpoint tests") class TestDAP_setExceptionBreakpoints(lldbdap_testcase.DAPTestCaseBase): @skipIfWindows def test_functionality(self): diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py index baaca4d974d5d..946595f639edc 100644 --- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py +++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py @@ -10,7 +10,6 @@ import lldbdap_testcase -@skip("Temporarily disable the breakpoint tests") class TestDAP_setFunctionBreakpoints(lldbdap_testcase.DAPTestCaseBase): @skipIfWindows def test_set_and_clear(self): diff --git a/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py b/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py index 824ed8fe3bb97..a239664f9eef7 100644 --- a/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py +++ b/lldb/test/API/tools/lldb-dap/cancel/TestDAP_cancel.py @@ -2,8 +2,6 @@ Test lldb-dap cancel request """ -import time - from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * import lldbdap_testcase 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 7b4d1adbb2071..9f02d2f951d27 100644 --- a/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py +++ b/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py @@ -1,26 +1,23 @@ """ -Test lldb-dap setBreakpoints request +Test lldb-dap console output """ -import dap_server import lldbdap_testcase -from lldbsuite.test import lldbutil from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -def get_subprocess(root_process, process_name): - queue = [root_process] - while queue: - process = queue.pop() - if process.name() == process_name: - return process - queue.extend(process.children()) - - self.assertTrue(False, "No subprocess with name %s found" % process_name) +class TestDAP_console(lldbdap_testcase.DAPTestCaseBase): + def get_subprocess(self, root_process, process_name): + queue = [root_process] + while queue: + process = queue.pop() + if process.name() == process_name: + return process + queue.extend(process.children()) + self.assertTrue(False, "No subprocess with name %s found" % process_name) -class TestDAP_console(lldbdap_testcase.DAPTestCaseBase): def check_lldb_command( self, lldb_command, contains_string, assert_msg, command_escape_prefix="`" ): @@ -134,7 +131,7 @@ def test_exit_status_message_sigterm(self): file=sys.stderr, ) return - process = get_subprocess(psutil.Process(os.getpid()), process_name) + process = self.get_subprocess(psutil.Process(os.getpid()), process_name) process.terminate() process.wait() diff --git a/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py b/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py index db43dbaf515cf..72d7171b7c5fc 100644 --- a/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py +++ b/lldb/test/API/tools/lldb-dap/coreFile/TestDAP_coreFile.py @@ -2,10 +2,8 @@ Test lldb-dap coreFile attaching """ -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase import os diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py index a542a318050dd..e3ead1095cba0 100644 --- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py +++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py @@ -9,7 +9,7 @@ class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase): def setUp(self): - lldbdap_testcase.DAPTestCaseBase.setUp(self) + super().setUp() self.accessTypes = ["read", "write", "readWrite"] @skipIfWindows diff --git a/lldb/test/API/tools/lldb-dap/disassemble/TestDAP_disassemble.py b/lldb/test/API/tools/lldb-dap/disassemble/TestDAP_disassemble.py index 9e8ef5b289f2e..a4759084fdb9d 100644 --- a/lldb/test/API/tools/lldb-dap/disassemble/TestDAP_disassemble.py +++ b/lldb/test/API/tools/lldb-dap/disassemble/TestDAP_disassemble.py @@ -3,10 +3,8 @@ """ -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase import os diff --git a/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py b/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py index 09e3f62f0eead..3c93ec193716f 100644 --- a/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py +++ b/lldb/test/API/tools/lldb-dap/disconnect/TestDAP_disconnect.py @@ -3,7 +3,6 @@ """ -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py index 2166e88151986..923f8f511f1c5 100644 --- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py +++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py @@ -3,10 +3,7 @@ """ import re - import lldbdap_testcase -import dap_server -from lldbsuite.test import lldbutil from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * diff --git a/lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py b/lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py index 53b7df9e54af2..3793b1e136ac6 100644 --- a/lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py +++ b/lldb/test/API/tools/lldb-dap/instruction-breakpoint/TestDAP_instruction_breakpoint.py @@ -1,32 +1,25 @@ -import dap_server -import shutil +""" +Test lldb-dap setInstructionBreakpoints request +""" + +import os from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase -import os -import lldb class TestDAP_InstructionBreakpointTestCase(lldbdap_testcase.DAPTestCaseBase): NO_DEBUG_INFO_TESTCASE = True def setUp(self): - lldbdap_testcase.DAPTestCaseBase.setUp(self) + super().setUp() self.main_basename = "main-copy.cpp" self.main_path = os.path.realpath(self.getBuildArtifact(self.main_basename)) @skipIfWindows def test_instruction_breakpoint(self): - self.build() - self.instruction_breakpoint_test() - - def instruction_breakpoint_test(self): """Sample test to ensure SBFrame::Disassemble produces SOME output""" - # Create a target by the debugger. - target = self.createTestTarget() - main_line = line_number("main.cpp", "breakpoint 1") program = self.getBuildArtifact("a.out") @@ -49,15 +42,15 @@ def instruction_breakpoint_test(self): ) other_breakpoint_id = breakpoint["id"] - # Continue and then verifiy the breakpoint + # Continue and then verify the breakpoint self.dap_server.request_continue() self.verify_breakpoint_hit([other_breakpoint_id]) # now we check the stack trace making sure that we got mapped source paths frames = self.dap_server.request_stackTrace()["body"]["stackFrames"] - intstructionPointerReference = [] - setIntstructionBreakpoints = [] - intstructionPointerReference.append(frames[0]["instructionPointerReference"]) + instructionPointerReference = [] + setInstructionBreakpoints = [] + instructionPointerReference.append(frames[0]["instructionPointerReference"]) self.assertEqual( frames[0]["source"]["name"], self.main_basename, "incorrect source name" ) @@ -69,21 +62,21 @@ def instruction_breakpoint_test(self): instruction = self.disassemble(frameIndex=0) self.assertEqual( instruction["address"], - intstructionPointerReference[0], - "current breakpoint reference is not in the disaasembly view", + instructionPointerReference[0], + "current breakpoint reference is not in the disassembly view", ) # Get next instruction address to set instruction breakpoint disassembled_instruction_list = self.dap_server.disassembled_instructions instruction_addr_list = list(disassembled_instruction_list.keys()) - index = instruction_addr_list.index(intstructionPointerReference[0]) + index = instruction_addr_list.index(instructionPointerReference[0]) if len(instruction_addr_list) >= (index + 1): next_inst_addr = instruction_addr_list[index + 1] if len(next_inst_addr) > 2: - setIntstructionBreakpoints.append(next_inst_addr) + setInstructionBreakpoints.append(next_inst_addr) instruction_breakpoint_response = ( self.dap_server.request_setInstructionBreakpoints( - setIntstructionBreakpoints + setInstructionBreakpoints ) ) inst_breakpoints = instruction_breakpoint_response["body"][ diff --git a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py index 8805ce50e6a21..eb3caa9d85583 100644 --- a/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py +++ b/lldb/test/API/tools/lldb-dap/launch/TestDAP_launch.py @@ -1,15 +1,12 @@ """ -Test lldb-dap setBreakpoints request +Test lldb-dap launch request """ -import dap_server +import os +import re from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase -import time -import os -import re # Many tests are skipped on Windows because get_stdout() returns None there. # Despite the test program printing correctly. See @@ -339,7 +336,7 @@ def test_commands(self): launch. "initCommands" are a list of LLDB commands that get executed - before the targt is created. + before the target is created. "preRunCommands" are a list of LLDB commands that get executed after the target has been created and before the launch. "stopCommands" are a list of LLDB commands that get executed each @@ -425,7 +422,7 @@ def test_extra_launch_commands(self): first_line = line_number(source, "// breakpoint 1") second_line = line_number(source, "// breakpoint 2") # Set target binary and 2 breakpoints - # then we can varify the "launchCommands" get run + # then we can verify the "launchCommands" get run # also we can verify that "stopCommands" get run as the # breakpoints get hit launchCommands = [ @@ -508,12 +505,12 @@ def test_failing_launch_commands(self): # 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 + # Verify all "initCommands" are found in console output self.verify_commands("initCommands", output, initCommands) - # Verify all "preRunCommands" were found in console output + # Verify all "preRunCommands" are found in console output self.verify_commands("preRunCommands", output, preRunCommands) - # Verify all "launchCommands" were founc in console output + # Verify all "launchCommands" are found in console output # 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/locations/TestDAP_locations.py b/lldb/test/API/tools/lldb-dap/locations/TestDAP_locations.py index 45f836a2fa3c3..6b348866e44fb 100644 --- a/lldb/test/API/tools/lldb-dap/locations/TestDAP_locations.py +++ b/lldb/test/API/tools/lldb-dap/locations/TestDAP_locations.py @@ -1,12 +1,9 @@ """ -Test lldb-dap locations request +Test lldb-dap locations request. """ - -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase import os diff --git a/lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py b/lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py index 74062f3ab2164..159dd3bc1fa3a 100644 --- a/lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py +++ b/lldb/test/API/tools/lldb-dap/memory/TestDAP_memory.py @@ -3,10 +3,8 @@ """ from base64 import b64decode -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase import os diff --git a/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py b/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py index 1ef2f2a8235a4..023b69f8688dd 100644 --- a/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py +++ b/lldb/test/API/tools/lldb-dap/module-event/TestDAP_module_event.py @@ -1,9 +1,10 @@ -import dap_server +""" +Test lldb-dap module events. +""" + from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase -import re class TestDAP_module_event(lldbdap_testcase.DAPTestCaseBase): diff --git a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py index 3fc0f752ee39e..134c9cb1aee18 100644 --- a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py +++ b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py @@ -1,11 +1,9 @@ """ -Test lldb-dap setBreakpoints request +Test lldb-dap modules request. """ -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase import re diff --git a/lldb/test/API/tools/lldb-dap/optimized/TestDAP_optimized.py b/lldb/test/API/tools/lldb-dap/optimized/TestDAP_optimized.py index ae144ebdca46b..d35793c229283 100644 --- a/lldb/test/API/tools/lldb-dap/optimized/TestDAP_optimized.py +++ b/lldb/test/API/tools/lldb-dap/optimized/TestDAP_optimized.py @@ -1,10 +1,8 @@ """ -Test lldb-dap variables/stackTrace request for optimized code +Test lldb-dap variables/stackTrace request for optimized code. """ -import dap_server import lldbdap_testcase -from lldbsuite.test import lldbutil from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * diff --git a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py index 0425b55a5e552..18c7b10be1b82 100644 --- a/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py +++ b/lldb/test/API/tools/lldb-dap/output/TestDAP_output.py @@ -1,5 +1,5 @@ """ -Test lldb-dap output events +Test lldb-dap output events. """ from lldbsuite.test.decorators import * diff --git a/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py b/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py index b47d52968f8a1..58a33aaa2d582 100755 --- a/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py +++ b/lldb/test/API/tools/lldb-dap/progress/TestDAP_Progress.py @@ -1,14 +1,11 @@ """ -Test lldb-dap output events +Test lldb-dap progress events. """ from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -import json import os -import time import re - import lldbdap_testcase @@ -52,7 +49,7 @@ def verify_progress_events( self.dap_server.progress_events.clear() @skipIfWindows - def test(self): + def test_progress(self): program = self.getBuildArtifact("a.out") self.build_and_launch(program, stopOnEntry=True) progress_emitter = os.path.join(os.getcwd(), "Progress_emitter.py") diff --git a/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py b/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py index c6f59949d668e..07029c2425cff 100644 --- a/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py +++ b/lldb/test/API/tools/lldb-dap/repl-mode/TestDAP_repl_mode_detection.py @@ -3,8 +3,6 @@ """ import lldbdap_testcase -import dap_server -from lldbsuite.test import lldbutil from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * 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 83faf276852f8..70aa84e8fc210 100644 --- a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py +++ b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart.py @@ -1,5 +1,5 @@ """ -Test lldb-dap RestartRequest. +Test lldb-dap restart request. """ from lldbsuite.test.decorators import * diff --git a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py index eed769a5a0cc6..e1338dddea5da 100644 --- a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py +++ b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py @@ -1,5 +1,5 @@ """ -Test lldb-dap RestartRequest. +Test lldb-dap restart request. """ import os @@ -8,18 +8,8 @@ import lldbdap_testcase +@skipIfBinaryToLarge(os.getenv("LLDBDAP_EXEC"), 1_000_000) class TestDAP_restart_runInTerminal(lldbdap_testcase.DAPTestCaseBase): - def isTestSupported(self): - try: - # We skip this test for debug builds because it takes too long - # parsing lldb's own debug info. Release builds are fine. - # Checking the size of the lldb-dap binary seems to be a decent - # proxy for a quick detection. It should be far less than 1 MB in - # Release builds. - return os.path.getsize(os.environ["LLDBDAP_EXEC"]) < 1000000 - except: - return False - @skipIfWindows @skipIf(oslist=["linux"], archs=["arm"]) # Always times out on buildbot def test_basic_functionality(self): @@ -27,8 +17,6 @@ def test_basic_functionality(self): Test basic restarting functionality when the process is running in a terminal. """ - if not self.isTestSupported(): - return line_A = line_number("main.c", "// breakpoint A") line_B = line_number("main.c", "// breakpoint B") @@ -61,16 +49,10 @@ def test_basic_functionality(self): ) @skipIfWindows - @skipIf(oslist=["linux"], archs=["arm"]) # Always times out on buildbot def test_stopOnEntry(self): """ Check that stopOnEntry works correctly when using runInTerminal. """ - if not self.isTestSupported(): - return - 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, runInTerminal=True, stopOnEntry=True) [bp_main] = self.set_function_breakpoints(["main"]) diff --git a/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py b/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py index 9aab7ca3293db..ec03b86832069 100644 --- a/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py +++ b/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py @@ -1,21 +1,16 @@ """ -Test lldb-dap runInTerminal reverse request +Test lldb-dap runInTerminal reverse request. """ - -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase -import time import os import subprocess -import shutil import json -from threading import Thread +@skipIfBinaryToLarge(os.getenv("LLDBDAP_EXEC"), 1_000_000) class TestDAP_runInTerminal(lldbdap_testcase.DAPTestCaseBase): def readPidMessage(self, fifo_file): with open(fifo_file, "r") as file: @@ -29,28 +24,12 @@ def readErrorMessage(self, fifo_file): with open(fifo_file, "r") as file: return file.readline() - def isTestSupported(self): - # For some strange reason, this test fails on python3.6 - if not (sys.version_info.major == 3 and sys.version_info.minor >= 7): - return False - try: - # We skip this test for debug builds because it takes too long parsing lldb's own - # debug info. Release builds are fine. - # Checking the size of the lldb-dap binary seems to be a decent proxy for a quick - # detection. It should be far less than 1 MB in Release builds. - if os.path.getsize(os.environ["LLDBDAP_EXEC"]) < 1000000: - return True - except: - return False - @skipIfWindows @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) def test_runInTerminal(self): - if not self.isTestSupported(): - return """ - Tests the "runInTerminal" reverse request. It makes sure that the IDE can - launch the inferior with the correct environment variables and arguments. + Tests the "runInTerminal" reverse request. It makes sure that the IDE can + launch the inferior with the correct environment variables and arguments. """ program = self.getBuildArtifact("a.out") source = "main.c" @@ -92,11 +71,9 @@ def test_runInTerminal(self): @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) def test_runInTerminalWithObjectEnv(self): - if not self.isTestSupported(): - return """ - Tests the "runInTerminal" reverse request. It makes sure that the IDE can - launch the inferior with the correct environment variables using an object. + Tests the "runInTerminal" reverse request. It makes sure that the IDE can + launch the inferior with the correct environment variables using an object. """ program = self.getBuildArtifact("a.out") self.build_and_launch(program, runInTerminal=True, env={"FOO": "BAR"}) @@ -116,8 +93,6 @@ def test_runInTerminalWithObjectEnv(self): @skipIfWindows @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) def test_runInTerminalInvalidTarget(self): - if not self.isTestSupported(): - return self.build_and_create_debug_adapter() response = self.launch( "INVALIDPROGRAM", @@ -135,8 +110,6 @@ def test_runInTerminalInvalidTarget(self): @skipIfWindows @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) def test_missingArgInRunInTerminalLauncher(self): - if not self.isTestSupported(): - return proc = subprocess.run( [self.lldbDAPExec, "--launch-target", "INVALIDPROGRAM"], capture_output=True, @@ -150,8 +123,6 @@ def test_missingArgInRunInTerminalLauncher(self): @skipIfWindows @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) def test_FakeAttachedRunInTerminalLauncherWithInvalidProgram(self): - if not self.isTestSupported(): - return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) @@ -177,8 +148,6 @@ def test_FakeAttachedRunInTerminalLauncherWithInvalidProgram(self): @skipIfWindows @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) def test_FakeAttachedRunInTerminalLauncherWithValidProgram(self): - if not self.isTestSupported(): - return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) @@ -204,8 +173,6 @@ def test_FakeAttachedRunInTerminalLauncherWithValidProgram(self): @skipIfWindows @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) def test_FakeAttachedRunInTerminalLauncherAndCheckEnvironment(self): - if not self.isTestSupported(): - return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) @@ -225,8 +192,6 @@ def test_FakeAttachedRunInTerminalLauncherAndCheckEnvironment(self): @skipIfWindows @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) def test_NonAttachedRunInTerminalLauncher(self): - if not self.isTestSupported(): - return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) diff --git a/lldb/test/API/tools/lldb-dap/source/TestDAP_source.py b/lldb/test/API/tools/lldb-dap/source/TestDAP_source.py index edf0af0bba2ba..93f3a9a5b5c3f 100644 --- a/lldb/test/API/tools/lldb-dap/source/TestDAP_source.py +++ b/lldb/test/API/tools/lldb-dap/source/TestDAP_source.py @@ -2,9 +2,6 @@ Test lldb-dap source request """ - -import os - import lldbdap_testcase from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * diff --git a/lldb/test/API/tools/lldb-dap/stackTrace/subtleFrames/TestDAP_subtleFrames.py b/lldb/test/API/tools/lldb-dap/stackTrace/subtleFrames/TestDAP_subtleFrames.py index 1e41e841e39bc..7cce6cdf6a993 100644 --- a/lldb/test/API/tools/lldb-dap/stackTrace/subtleFrames/TestDAP_subtleFrames.py +++ b/lldb/test/API/tools/lldb-dap/stackTrace/subtleFrames/TestDAP_subtleFrames.py @@ -1,12 +1,9 @@ """ -Test lldb-dap stack trace response +Test lldb-dap stackTrace request for frames without sources. """ - -import dap_server -from lldbsuite.test.decorators import * - import lldbdap_testcase +from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -14,7 +11,8 @@ class TestDAP_subtleFrames(lldbdap_testcase.DAPTestCaseBase): @add_test_categories(["libc++"]) def test_subtleFrames(self): """ - Internal stack frames (such as the ones used by `std::function`) are marked as "subtle". + Test that internal stack frames (such as the ones used by + `std::function`) are marked as "subtle". """ program = self.getBuildArtifact("a.out") self.build_and_launch(program) diff --git a/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py index 08c225b3cada4..adf18104d7620 100644 --- a/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py +++ b/lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py @@ -1,5 +1,5 @@ """ -Test lldb-dap stack trace when some of the source paths are missing +Test lldb-dap stackTrace when some of the source paths are missing. """ from lldbsuite.test.lldbtest import line_number diff --git a/lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py b/lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py index f2131d6a82121..30a286f665dbd 100644 --- a/lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py +++ b/lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py @@ -1,5 +1,5 @@ """ -Test lldb-dap stack trace response +Test lldb-dap stackTrace request for functions without a name. """ from lldbsuite.test.decorators import * diff --git a/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/TestDAP_stackTraceMissingModule.py b/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/TestDAP_stackTraceMissingModule.py index 1eb00f9935a22..6ca9a90faa86b 100644 --- a/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/TestDAP_stackTraceMissingModule.py +++ b/lldb/test/API/tools/lldb-dap/stackTraceMissingModule/TestDAP_stackTraceMissingModule.py @@ -1,5 +1,5 @@ """ -Test lldb-dap stack trace when module is missing +Test lldb-dap stackTrace when module is missing. """ from lldbsuite.test.decorators import skipUnlessPlatform diff --git a/lldb/test/API/tools/lldb-dap/step/TestDAP_step.py b/lldb/test/API/tools/lldb-dap/step/TestDAP_step.py index 42a39e3c8c080..e553c23d7e0ba 100644 --- a/lldb/test/API/tools/lldb-dap/step/TestDAP_step.py +++ b/lldb/test/API/tools/lldb-dap/step/TestDAP_step.py @@ -1,12 +1,10 @@ """ -Test lldb-dap setBreakpoints request +Test lldb-dap step request. """ -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase diff --git a/lldb/test/API/tools/lldb-dap/stepInTargets/TestDAP_stepInTargets.py b/lldb/test/API/tools/lldb-dap/stepInTargets/TestDAP_stepInTargets.py index 07acfe07c9ffc..83d8cf73e24c8 100644 --- a/lldb/test/API/tools/lldb-dap/stepInTargets/TestDAP_stepInTargets.py +++ b/lldb/test/API/tools/lldb-dap/stepInTargets/TestDAP_stepInTargets.py @@ -2,19 +2,20 @@ Test lldb-dap stepInTargets request """ -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * import lldbdap_testcase -from lldbsuite.test import lldbutil class TestDAP_stepInTargets(lldbdap_testcase.DAPTestCaseBase): - @expectedFailureAll(oslist=["windows"]) - @skipIf(archs=no_match(["x86_64"])) # InstructionControlFlowKind for ARM is not supported yet. # On Windows, lldb-dap seems to ignore targetId when stepping into functions. # For more context, see https://github.com/llvm/llvm-project/issues/98509. + @expectedFailureAll(oslist=["windows"]) + @skipIf( + archs=no_match(["x86_64"]), + bugnumber="github.com/llvm/llvm-project/issues/98509", + ) def test_basic(self): """ Tests the basic stepping in targets with directly calls. diff --git a/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py b/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py index b0abe2a38dac4..1984fce4c0524 100644 --- a/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py +++ b/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py @@ -2,12 +2,9 @@ Test lldb-dap terminated event """ -import dap_server from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase -import re import json diff --git a/lldb/test/API/tools/lldb-dap/threads/TestDAP_threads.py b/lldb/test/API/tools/lldb-dap/threads/TestDAP_threads.py index a4658da58ac94..15676744ffd7a 100644 --- a/lldb/test/API/tools/lldb-dap/threads/TestDAP_threads.py +++ b/lldb/test/API/tools/lldb-dap/threads/TestDAP_threads.py @@ -1,10 +1,9 @@ """ -Test lldb-dap setBreakpoints request +Test lldb-dap threads request. """ from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil import lldbdap_testcase diff --git a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py index 340be0b39010d..8976670f9c458 100644 --- a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py +++ b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py @@ -1,12 +1,9 @@ """ -Test lldb-dap setBreakpoints request +Test lldb-dap variables request. """ import os - -import dap_server import lldbdap_testcase -from lldbsuite.test import lldbutil from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * diff --git a/lldb/test/API/tools/lldb-dap/variables/children/TestDAP_variables_children.py b/lldb/test/API/tools/lldb-dap/variables/children/TestDAP_variables_children.py index 75e75c4ad7c69..9454542a83f75 100644 --- a/lldb/test/API/tools/lldb-dap/variables/children/TestDAP_variables_children.py +++ b/lldb/test/API/tools/lldb-dap/variables/children/TestDAP_variables_children.py @@ -1,8 +1,8 @@ -import os +""" +Test lldb-dap variables request with nested items. +""" -import dap_server import lldbdap_testcase -from lldbsuite.test import lldbutil from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * >From ad51c73c4a00203646b4f80a939be19f25b7ba75 Mon Sep 17 00:00:00 2001 From: John Harrison <harj...@google.com> Date: Thu, 22 May 2025 12:36:09 -0700 Subject: [PATCH 2/3] Fix 'disassemble' test on macOS. --- lldb/test/API/tools/lldb-dap/disassemble/main.c | 4 +--- lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/disassemble/main.c b/lldb/test/API/tools/lldb-dap/disassemble/main.c index 9da119ef70262..b4927db10e949 100644 --- a/lldb/test/API/tools/lldb-dap/disassemble/main.c +++ b/lldb/test/API/tools/lldb-dap/disassemble/main.c @@ -6,9 +6,7 @@ int compare_ints(const void *a, const void *b) { int arg1 = *(const int *)a; int arg2 = *(const int *)b; - // breakpoint 1 - - if (arg1 < arg2) + if (arg1 < arg2) // breakpoint 1 return -1; if (arg1 > arg2) return 1; diff --git a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp index 9aa6995e5d668..fa596a842ba4f 100644 --- a/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DisassembleRequestHandler.cpp @@ -134,9 +134,8 @@ static DisassembledInstruction ConvertSBInstructionToDisassembledInstruction( auto line_entry = addr.GetLineEntry(); // If the line number is 0 then the entry represents a compiler generated // location. - - if (line_entry.GetStartAddress() == addr && line_entry.IsValid() && - line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0) { + if (line_entry.IsValid() && line_entry.GetFileSpec().IsValid() && + line_entry.GetLine() != 0) { auto source = CreateSource(line_entry); disassembled_inst.location = std::move(source); >From 10d97704b781be733f31c75a52dd92d7ae7586f4 Mon Sep 17 00:00:00 2001 From: John Harrison <harj...@google.com> Date: Thu, 22 May 2025 16:04:09 -0700 Subject: [PATCH 3/3] Adding a `skipIfBuildType` helper to skip tests that may fail or be unstable in certain build configuraitons. This revealed a number of tests that were unstable, so I also included fixes for those tests as well. --- .../Python/lldbsuite/test/configuration.py | 3 ++ .../Python/lldbsuite/test/decorators.py | 31 ++++++------------- lldb/packages/Python/lldbsuite/test/dotest.py | 1 + .../Python/lldbsuite/test/dotest_args.py | 6 ++++ .../test/tools/lldb-dap/dap_server.py | 19 +++++++----- lldb/test/API/lit.cfg.py | 3 ++ lldb/test/API/lit.site.cfg.py.in | 1 + .../restart/TestDAP_restart_runInTerminal.py | 4 +-- .../runInTerminal/TestDAP_runInTerminal.py | 12 +++++-- .../tools/lldb-dap/server/TestDAP_server.py | 9 +++--- lldb/tools/lldb-dap/DAP.cpp | 18 +++++++++-- lldb/tools/lldb-dap/DAP.h | 7 +++-- .../Handler/DisconnectRequestHandler.cpp | 12 ++++--- lldb/tools/lldb-dap/Handler/RequestHandler.h | 3 +- lldb/tools/lldb-dap/JSONUtils.cpp | 4 +-- lldb/tools/lldb-dap/JSONUtils.h | 2 +- .../lldb-dap/Protocol/ProtocolRequests.h | 4 +-- lldb/tools/lldb-dap/tool/lldb-dap.cpp | 2 +- 18 files changed, 85 insertions(+), 56 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/configuration.py b/lldb/packages/Python/lldbsuite/test/configuration.py index 18c1566176331..b2d91fd211477 100644 --- a/lldb/packages/Python/lldbsuite/test/configuration.py +++ b/lldb/packages/Python/lldbsuite/test/configuration.py @@ -137,6 +137,9 @@ # A plugin whose tests will be enabled, like intel-pt. enabled_plugins = [] +# the build type of lldb +# Typical values include Debug, Release, RelWithDebInfo and MinSizeRel +cmake_build_type = None def shouldSkipBecauseOfCategories(test_categories): if use_categories: diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index 5e14dfeda48a8..991064538c175 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -1105,26 +1105,13 @@ def is_feature_enabled(): return skipTestIfFn(is_feature_enabled) -def skipIfBinaryToLarge(path: Optional[str], maxSize: int): - """Skip the test if a binary is to large. - - We skip this test for debug builds because it takes too long - parsing lldb's own debug info. Release builds are fine. - Checking the size of the lldb-dap binary seems to be a decent - proxy for a quick detection. It should be far less than 1 MB in - Release builds. - """ - - def check_binary_size(): - if not path or not os.path.exists(path): - return "invalid path" - - try: - size = os.path.getsize(path) - if size <= maxSize: - return None - return f"binary {path} (size = {size} is to larger than {maxSize}" - except: - return f"failed to read size of {path}" +def skipIfBuildType(types: list[str]): + """Skip tests if built in a specific CMAKE_BUILD_TYPE. - return skipTestIfFn(check_binary_size) + Supported types include 'Release', 'RelWithDebInfo', 'Debug', 'MinSizeRel'. + """ + types = [name.lower() for name in types] + return unittest.skipIf( + configuration.cmake_build_type.lower() in types, + "skip on {} build type(s)".format(", ".join(types)), + ) diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 7cc8f2985043e..d7f274ac4f60e 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -297,6 +297,7 @@ def parseOptionsAndInitTestdirs(): configuration.libcxx_include_dir = args.libcxx_include_dir configuration.libcxx_include_target_dir = args.libcxx_include_target_dir configuration.libcxx_library_dir = args.libcxx_library_dir + configuration.cmake_build_type = args.cmake_build_type.lower() if args.channels: lldbtest_config.channels = args.channels diff --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py index 98210b7102e1b..e9c21388bc213 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest_args.py +++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py @@ -300,6 +300,12 @@ def create_parser(): metavar="platform-available-ports", help="Ports available for connection to a lldb server on the remote platform", ) + group.add_argument( + "--cmake-build-type", + dest="cmake_build_type", + metavar="cmake-build-type", + help="Specifies the build type on single-configuration", + ) # Test-suite behaviour group = parser.add_argument_group("Runtime behaviour options") diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index a028381a0a4f9..5daec41a0ad0e 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -164,6 +164,7 @@ def __init__( self.output: dict[str, list[str]] = {} self.configuration_done_sent = False self.initialized = False + self.terminated = False self.frame_scopes = {} self.init_commands = init_commands @@ -271,6 +272,10 @@ def _handle_recv_packet(self, packet: Optional[ProtocolMessage]) -> bool: # When a new process is attached or launched, remember the # details that are available in the body of the event self.process_event_body = body + elif event == "terminated": + # If we get the 'terminated' event then lldb-dap has exited + # itself. + self.terminated = True elif event == "exited": # Process exited, mark the status to indicate the process is not # alive. @@ -388,7 +393,7 @@ def send_recv(self, command): if response_or_request["command"] == "runInTerminal": subprocess.Popen( response_or_request["arguments"]["args"], - env=response_or_request["arguments"]["env"], + env=response_or_request["arguments"].get("env", {}), ) self.send_packet( { @@ -749,13 +754,11 @@ def request_restart(self, restartArguments=None): # Caller must still call wait_for_stopped. return response - def request_disconnect(self, terminateDebuggee=None): - args_dict = {} - if terminateDebuggee is not None: - if terminateDebuggee: - args_dict["terminateDebuggee"] = True - else: - args_dict["terminateDebuggee"] = False + def request_disconnect(self, terminateDebuggee=False, suspendDebuggee=False): + args_dict = { + "terminateDebuggee": terminateDebuggee, + "suspendDebuggee": suspendDebuggee, + } command_dict = { "command": "disconnect", "type": "request", diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py index 08cf11c8a68db..646a446c86fdb 100644 --- a/lldb/test/API/lit.cfg.py +++ b/lldb/test/API/lit.cfg.py @@ -271,6 +271,9 @@ def delete_module_cache(path): if is_configured("lldb_framework_dir"): dotest_cmd += ["--framework", config.lldb_framework_dir] +if is_configured("cmake_build_type"): + dotest_cmd += ["--cmake-build-type", config.cmake_build_type] + if "lldb-simulator-ios" in config.available_features: dotest_cmd += ["--apple-sdk", "iphonesimulator", "--platform-name", "ios-simulator"] elif "lldb-simulator-watchos" in config.available_features: diff --git a/lldb/test/API/lit.site.cfg.py.in b/lldb/test/API/lit.site.cfg.py.in index 54807de8819d2..ee31e35d257e7 100644 --- a/lldb/test/API/lit.site.cfg.py.in +++ b/lldb/test/API/lit.site.cfg.py.in @@ -40,6 +40,7 @@ config.has_libcxx = @LLDB_HAS_LIBCXX@ config.libcxx_libs_dir = "@LIBCXX_LIBRARY_DIR@" config.libcxx_include_dir = "@LIBCXX_GENERATED_INCLUDE_DIR@" config.libcxx_include_target_dir = "@LIBCXX_GENERATED_INCLUDE_TARGET_DIR@" +config.cmake_build_type = "@CMAKE_BUILD_TYPE@" # The API tests use their own module caches. config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-api") config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-api") diff --git a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py index e1338dddea5da..46cbf7532c5f7 100644 --- a/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py +++ b/lldb/test/API/tools/lldb-dap/restart/TestDAP_restart_runInTerminal.py @@ -2,13 +2,12 @@ Test lldb-dap restart request. """ -import os from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import line_number import lldbdap_testcase -@skipIfBinaryToLarge(os.getenv("LLDBDAP_EXEC"), 1_000_000) +@skipIfBuildType(["debug"]) class TestDAP_restart_runInTerminal(lldbdap_testcase.DAPTestCaseBase): @skipIfWindows @skipIf(oslist=["linux"], archs=["arm"]) # Always times out on buildbot @@ -56,6 +55,7 @@ def test_stopOnEntry(self): program = self.getBuildArtifact("a.out") self.build_and_launch(program, runInTerminal=True, stopOnEntry=True) [bp_main] = self.set_function_breakpoints(["main"]) + self.dap_server.request_configurationDone() # When using stopOnEntry, configurationDone doesn't result in a running # process, we should immediately get a stopped event instead. diff --git a/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py b/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py index ec03b86832069..a2fe2e19c6c85 100644 --- a/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py +++ b/lldb/test/API/tools/lldb-dap/runInTerminal/TestDAP_runInTerminal.py @@ -10,7 +10,7 @@ import json -@skipIfBinaryToLarge(os.getenv("LLDBDAP_EXEC"), 1_000_000) +@skipIfBuildType(["debug"]) class TestDAP_runInTerminal(lldbdap_testcase.DAPTestCaseBase): def readPidMessage(self, fifo_file): with open(fifo_file, "r") as file: @@ -90,6 +90,12 @@ def test_runInTerminalWithObjectEnv(self): self.assertIn("FOO", request_envs) self.assertEqual("BAR", request_envs["FOO"]) + # Ensure we can continue to a breakpoint. + source = "main.c" + breakpoint_line = line_number(source, "// breakpoint") + self.set_source_breakpoints(source, [breakpoint_line]) + self.continue_to_next_stop() + @skipIfWindows @skipIf(oslist=["linux"], archs=no_match(["x86_64"])) def test_runInTerminalInvalidTarget(self): @@ -103,8 +109,8 @@ def test_runInTerminalInvalidTarget(self): ) self.assertFalse(response["success"]) self.assertIn( - "Could not create a target for a program 'INVALIDPROGRAM': 'INVALIDPROGRAM' does not exist", - response["message"], + "'INVALIDPROGRAM' does not exist", + response["body"]["error"]["format"], ) @skipIfWindows diff --git a/lldb/test/API/tools/lldb-dap/server/TestDAP_server.py b/lldb/test/API/tools/lldb-dap/server/TestDAP_server.py index 7a9a4f434e04b..071b60aca355e 100644 --- a/lldb/test/API/tools/lldb-dap/server/TestDAP_server.py +++ b/lldb/test/API/tools/lldb-dap/server/TestDAP_server.py @@ -98,11 +98,12 @@ def test_server_interrupt(self): self.set_source_breakpoints(source, [breakpoint_line]) self.continue_to_next_stop() - # Interrupt the server which should disconnect all clients. - process.send_signal(signal.SIGINT) - - self.dap_server.wait_for_terminated() self.assertIsNone( self.dap_server.exit_status, "Process exited before interrupting lldb-dap server", ) + + # Interrupt the server which should disconnect all clients. + process.send_signal(signal.SIGINT) + + self.dap_server.wait_for_terminated() diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 394e8f0e6c851..1bd5a2b6188f3 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -250,7 +250,9 @@ llvm::Error DAP::ConfigureIO(std::FILE *overrideOut, std::FILE *overrideErr) { void DAP::StopEventHandlers() { if (event_thread.joinable()) { + DAP_LOG(log, "Sending eBroadcastBitStopEventThread"); broadcaster.BroadcastEventByType(eBroadcastBitStopEventThread); + DAP_LOG(log, "Waiting for join..."); event_thread.join(); } if (progress_event_thread.joinable()) { @@ -820,9 +822,9 @@ void DAP::SendTerminatedEvent() { }); } -llvm::Error DAP::Disconnect() { return Disconnect(is_attach); } +llvm::Error DAP::Disconnect() { return Disconnect(!is_attach, false); } -llvm::Error DAP::Disconnect(bool terminateDebuggee) { +llvm::Error DAP::Disconnect(bool terminate_debuggee, bool keep_stopped) { lldb::SBError error; lldb::SBProcess process = target.GetProcess(); auto state = process.GetState(); @@ -841,7 +843,7 @@ llvm::Error DAP::Disconnect(bool terminateDebuggee) { case lldb::eStateStopped: case lldb::eStateRunning: { ScopeSyncMode scope_sync_mode(debugger); - error = terminateDebuggee ? process.Kill() : process.Detach(); + error = terminate_debuggee ? process.Kill() : process.Detach(keep_stopped); break; } } @@ -886,6 +888,8 @@ llvm::Error DAP::Loop() { std::async(std::launch::async, [&]() -> lldb::SBError { llvm::set_thread_name(transport.GetClientName() + ".transport_handler"); auto cleanup = llvm::make_scope_exit([&]() { + DAP_LOG(log, "({0}) Loop queue_reader has exited", + transport.GetClientName()); // Ensure we're marked as disconnecting when the reader exits. disconnecting = true; m_queue_cv.notify_all(); @@ -950,9 +954,12 @@ llvm::Error DAP::Loop() { }); auto cleanup = llvm::make_scope_exit([&]() { + DAP_LOG(log, "({0}) Starting Loop cleanup...", transport.GetClientName()); out.Stop(); err.Stop(); StopEventHandlers(); + DAP_LOG(log, "({0}) Finished with Loop cleanup...", + transport.GetClientName()); }); while (true) { @@ -1219,7 +1226,12 @@ void DAP::EventThread() { listener, lldb::eBroadcastBitError | lldb::eBroadcastBitWarning); bool done = false; while (!done) { + DAP_LOG(log, "({0}) EventThread waiting....", transport.GetClientName()); if (listener.WaitForEvent(1, event)) { + lldb::SBStream desc; + event.GetDescription(desc); + DAP_LOG(log, "({0}) EventThread, got event {1}", + transport.GetClientName(), desc.GetData()); const auto event_mask = event.GetType(); if (lldb::SBProcess::EventIsProcessEvent(event)) { lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(event); diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h index 1bd94fab402ca..8c3e7b28fb9c3 100644 --- a/lldb/tools/lldb-dap/DAP.h +++ b/lldb/tools/lldb-dap/DAP.h @@ -279,7 +279,7 @@ struct DAP { lldb::SBTarget CreateTarget(lldb::SBError &error); /// Set given target object as a current target for lldb-dap and start - /// listeing for its breakpoint events. + /// listening for its breakpoint events. void SetTarget(const lldb::SBTarget target); bool HandleObject(const protocol::Message &M); @@ -287,8 +287,9 @@ struct DAP { /// Disconnect the DAP session. llvm::Error Disconnect(); - /// Disconnect the DAP session and optionally terminate the debuggee. - llvm::Error Disconnect(bool terminateDebuggee); + /// Disconnect the DAP session and determine how to handle the target, if it + /// is still running. + llvm::Error Disconnect(bool terminateDebuggee, bool suspendDebuggee); /// Send a "terminated" event to indicate the process is done being debugged. void SendTerminatedEvent(); diff --git a/lldb/tools/lldb-dap/Handler/DisconnectRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/DisconnectRequestHandler.cpp index 81e94c7551836..87767398c27e3 100644 --- a/lldb/tools/lldb-dap/Handler/DisconnectRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/DisconnectRequestHandler.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "DAP.h" +#include "LLDBUtils.h" #include "Protocol/ProtocolRequests.h" #include "RequestHandler.h" #include "llvm/Support/Error.h" @@ -20,12 +21,15 @@ namespace lldb_dap { /// Disconnect request; value of command field is 'disconnect'. Error DisconnectRequestHandler::Run( const std::optional<DisconnectArguments> &arguments) const { - bool terminateDebuggee = dap.is_attach ? false : true; + bool terminate_debuggee = dap.is_attach ? false : true; + bool keep_suspend = false; - if (arguments && arguments->terminateDebuggee) - terminateDebuggee = *arguments->terminateDebuggee; + if (arguments) { + terminate_debuggee = arguments->terminateDebuggee; + keep_suspend = !arguments->suspendDebuggee; + } - if (Error error = dap.Disconnect(terminateDebuggee)) + if (Error error = dap.Disconnect(terminate_debuggee, keep_suspend)) return error; return Error::success(); diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h index 3a965bcc87a5e..e01b08eba86e6 100644 --- a/lldb/tools/lldb-dap/Handler/RequestHandler.h +++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h @@ -283,7 +283,8 @@ class DisconnectRequestHandler using RequestHandler::RequestHandler; static llvm::StringLiteral GetCommand() { return "disconnect"; } FeatureSet GetSupportedFeatures() const override { - return {protocol::eAdapterFeatureTerminateDebuggee}; + return {protocol::eAdapterFeatureTerminateDebuggee, + protocol::eAdapterFeatureSuspendDebuggee}; } llvm::Error Run(const std::optional<protocol::DisconnectArguments> &args) const override; diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index dcc25c9212432..c9c6f4554c325 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -1335,7 +1335,7 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit) { /// https://microsoft.github.io/debug-adapter-protocol/specification#Reverse_Requests_RunInTerminal llvm::json::Object CreateRunInTerminalReverseRequest( llvm::StringRef program, const std::vector<std::string> &args, - const llvm::StringMap<std::string> env, llvm::StringRef cwd, + const llvm::StringMap<std::string> &env, llvm::StringRef cwd, llvm::StringRef comm_file, lldb::pid_t debugger_pid) { llvm::json::Object run_in_terminal_args; // This indicates the IDE to open an embedded terminal, instead of opening @@ -1352,7 +1352,7 @@ llvm::json::Object CreateRunInTerminalReverseRequest( req_args.push_back("--launch-target"); req_args.push_back(program.str()); req_args.insert(req_args.end(), args.begin(), args.end()); - run_in_terminal_args.try_emplace("args", args); + run_in_terminal_args.try_emplace("args", req_args); if (!cwd.empty()) run_in_terminal_args.try_emplace("cwd", cwd); diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h index ac9b39739104f..5758c3d56ec90 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -544,7 +544,7 @@ llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit); /// Microsoft. llvm::json::Object CreateRunInTerminalReverseRequest( llvm::StringRef program, const std::vector<std::string> &args, - const llvm::StringMap<std::string> env, llvm::StringRef cwd, + const llvm::StringMap<std::string> &env, llvm::StringRef cwd, llvm::StringRef comm_file, lldb::pid_t debugger_pid); /// Create a "Terminated" JSON object that contains statistics diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h index 7c774e50d6e56..4998c9b72c79d 100644 --- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h +++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h @@ -65,13 +65,13 @@ struct DisconnectArguments { /// disconnected. If unspecified, the debug adapter is free to do whatever it /// thinks is best. The attribute is only honored by a debug adapter if the /// corresponding capability `supportTerminateDebuggee` is true. - std::optional<bool> terminateDebuggee; + bool terminateDebuggee = false; /// Indicates whether the debuggee should stay suspended when the debugger is /// disconnected. If unspecified, the debuggee should resume execution. The /// attribute is only honored by a debug adapter if the corresponding /// capability `supportSuspendDebuggee` is true. - std::optional<bool> suspendDebuggee; + bool suspendDebuggee = false; }; bool fromJSON(const llvm::json::Value &, DisconnectArguments &, llvm::json::Path); diff --git a/lldb/tools/lldb-dap/tool/lldb-dap.cpp b/lldb/tools/lldb-dap/tool/lldb-dap.cpp index 7a4cc70902a56..9b9de5e21a742 100644 --- a/lldb/tools/lldb-dap/tool/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/tool/lldb-dap.cpp @@ -542,7 +542,7 @@ int main(int argc, char *argv[]) { lldb::IOObjectSP output = std::make_shared<NativeFile>( stdout_fd, File::eOpenOptionWriteOnly, NativeFile::Unowned); - constexpr llvm::StringLiteral client_name = "stdin/stdout"; + constexpr llvm::StringLiteral client_name = "stdio"; Transport transport(client_name, log.get(), input, output); DAP dap(log.get(), default_repl_mode, pre_init_commands, transport); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits