diff options
Diffstat (limited to 'lldb/test/API')
8 files changed, 103 insertions, 54 deletions
diff --git a/lldb/test/API/CMakeLists.txt b/lldb/test/API/CMakeLists.txt index b1ace6296f46..c719ac3382a6 100644 --- a/lldb/test/API/CMakeLists.txt +++ b/lldb/test/API/CMakeLists.txt @@ -74,6 +74,16 @@ else() endif() endif() +find_program(LLDB_DIRNAME_PATH dirname) +if(LLDB_DIRNAME_PATH) + message(STATUS "Found dirname: ${LLDB_DIRNAME_PATH}") +else() + message(STATUS "Could NOT find 'dirname'") + message(WARNING + "Many LLDB API tests require the GNU coreutils tools. Please make " + "sure they are installed and in PATH.") +endif() + if (TARGET clang) set(LLDB_DEFAULT_TEST_COMPILER "${LLVM_TOOLS_BINARY_DIR}/clang${CMAKE_EXECUTABLE_SUFFIX}") else() @@ -140,7 +150,12 @@ if(CMAKE_HOST_APPLE) endif() if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL Debug) - set(LLDB_PYTHON_API_TEST_EXECUTABLE "${Python3_EXECUTABLE_DEBUG}") + if(${CMAKE_VERSION} VERSION_LESS "3.30") + message(WARNING "CMake version is inferior to 3.30. Some lldb tests will fail.") + set(LLDB_PYTHON_API_TEST_EXECUTABLE "${Python3_EXECUTABLE}") + else() + set(LLDB_PYTHON_API_TEST_EXECUTABLE "${Python3_EXECUTABLE_DEBUG}") + endif() else() set(LLDB_PYTHON_API_TEST_EXECUTABLE "${Python3_EXECUTABLE}") endif() diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestContinue.py b/lldb/test/API/functionalities/gdb_remote_client/TestContinue.py index 3af4ca859f86..67f0783167a3 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestContinue.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestContinue.py @@ -41,7 +41,7 @@ class TestContinue(GDBRemoteTestBase): lldbutil.expect_state_changes( self, self.dbg.GetListener(), process, [lldb.eStateExited] ) - self.assertPacketLogContains(["vCont;C13:401"]) + self.assertPacketLogReceived(["vCont;C13:401"]) def test_continue_no_vCont(self): class MyResponder(self.BaseResponder): @@ -61,7 +61,7 @@ class TestContinue(GDBRemoteTestBase): lldbutil.expect_state_changes( self, self.dbg.GetListener(), process, [lldb.eStateExited] ) - self.assertPacketLogContains(["Hc401", "C13"]) + self.assertPacketLogReceived(["Hc401", "C13"]) def test_continue_multiprocess(self): class MyResponder(self.BaseResponder): @@ -74,4 +74,4 @@ class TestContinue(GDBRemoteTestBase): lldbutil.expect_state_changes( self, self.dbg.GetListener(), process, [lldb.eStateExited] ) - self.assertPacketLogContains(["vCont;C13:p400.401"]) + self.assertPacketLogReceived(["vCont;C13:p400.401"]) diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py index 67c5d7d55846..8cf04522153d 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py @@ -36,7 +36,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase): """Test connecting to a remote gdb server""" target = self.createTarget("a.yaml") process = self.connect(target) - self.assertPacketLogContains(["qProcessInfo", "qfThreadInfo"]) + self.assertPacketLogReceived(["qProcessInfo", "qfThreadInfo"]) def test_attach_fail(self): error_msg = "mock-error-msg" @@ -142,15 +142,16 @@ class TestGDBRemoteClient(GDBRemoteTestBase): # But there certainly should be no p packets after the g packet. self.read_registers(process) - print(f"\nPACKET LOG:\n{self.server.responder.packetLog}\n") + received = self.server.responder.packetLog.get_received() + print(f"\nPACKET LOG:\n{received}\n") g_pos = 0 try: - g_pos = self.server.responder.packetLog.index("g") + g_pos = received.index("g") except err: self.fail("'g' packet not found after fetching registers") try: - second_g = self.server.responder.packetLog.index("g", g_pos) + second_g = received.index("g", g_pos + 1) self.fail("Found more than one 'g' packet") except: pass @@ -158,13 +159,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase): # Make sure there aren't any `p` packets after the `g` packet: self.assertEqual( 0, - len( - [ - p - for p in self.server.responder.packetLog[g_pos:] - if p.startswith("p") - ] - ), + len([p for p in received[g_pos:] if p.startswith("p")]), ) def test_read_registers_using_p_packets(self): @@ -177,10 +172,9 @@ class TestGDBRemoteClient(GDBRemoteTestBase): process = self.connect(target) self.read_registers(process) - self.assertNotIn("g", self.server.responder.packetLog) - self.assertGreater( - len([p for p in self.server.responder.packetLog if p.startswith("p")]), 0 - ) + received = self.server.responder.packetLog.get_received() + self.assertNotIn("g", received) + self.assertGreater(len([p for p in received if p.startswith("p")]), 0) def test_write_registers_using_P_packets(self): """Test writing registers using 'P' packets (default behavior)""" @@ -189,12 +183,9 @@ class TestGDBRemoteClient(GDBRemoteTestBase): process = self.connect(target) self.write_registers(process) - self.assertEqual( - 0, len([p for p in self.server.responder.packetLog if p.startswith("G")]) - ) - self.assertGreater( - len([p for p in self.server.responder.packetLog if p.startswith("P")]), 0 - ) + received = self.server.responder.packetLog.get_received() + self.assertEqual(0, len([p for p in received if p.startswith("G")])) + self.assertGreater(len([p for p in received if p.startswith("P")]), 0) def test_write_registers_using_G_packets(self): """Test writing registers using 'G' packets""" @@ -209,12 +200,9 @@ class TestGDBRemoteClient(GDBRemoteTestBase): process = self.connect(target) self.write_registers(process) - self.assertEqual( - 0, len([p for p in self.server.responder.packetLog if p.startswith("P")]) - ) - self.assertGreater( - len([p for p in self.server.responder.packetLog if p.startswith("G")]), 0 - ) + received = self.server.responder.packetLog.get_received() + self.assertEqual(0, len([p for p in received if p.startswith("P")])) + self.assertGreater(len([p for p in received if p.startswith("G")]), 0) def read_registers(self, process): self.for_each_gpr( @@ -291,7 +279,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase): self.assertTrue(process, PROCESS_IS_VALID) self.assertEqual(process.GetProcessID(), 16) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "A%d,0,%s,8,1,61726731,8,2,61726732,8,3,61726733" % (len(exe_hex), exe_hex), @@ -352,7 +340,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase): self.assertTrue(process, PROCESS_IS_VALID) self.assertEqual(process.GetProcessID(), 16) - self.assertPacketLogContains( + self.assertPacketLogReceived( ["vRun;%s;61726731;61726732;61726733" % (exe_hex,)] ) @@ -424,7 +412,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase): self.assertTrue(process, PROCESS_IS_VALID) self.assertEqual(process.GetProcessID(), 16) - self.assertPacketLogContains( + self.assertPacketLogReceived( ["vRun;%s;61726731;61726732;61726733" % (exe_hex,)] ) @@ -468,7 +456,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase): lldb.SBError(), ) # error - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "QEnvironment:EQUALS=foo=bar", "QEnvironmentHexEncoded:4e45454453454e433d66726f6224", @@ -522,7 +510,7 @@ class TestGDBRemoteClient(GDBRemoteTestBase): lldb.SBError(), ) # error - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "QEnvironmentHexEncoded:455155414c533d666f6f3d626172", "QEnvironmentHexEncoded:4e45454453454e433d66726f6224", diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteLoad.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteLoad.py index f0a5429e6c1c..d8214ae6b9a2 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteLoad.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteLoad.py @@ -22,7 +22,7 @@ class TestGDBRemoteLoad(GDBRemoteTestBase): target = self.createTarget("a.yaml") process = self.connect(target) self.dbg.HandleCommand("target modules load -l -s0") - self.assertPacketLogContains(["M1000,4:c3c3c3c3", "M1004,2:3232"]) + self.assertPacketLogReceived(["M1000,4:c3c3c3c3", "M1004,2:3232"]) @skipIfXmlSupportMissing def test_flash_load(self): @@ -63,7 +63,7 @@ class TestGDBRemoteLoad(GDBRemoteTestBase): target = self.createTarget("a.yaml") process = self.connect(target) self.dbg.HandleCommand("target modules load -l -s0") - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFlashErase:1000,100", "vFlashWrite:1000:\xc3\xc3\xc3\xc3", diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py index 69e04df81bc6..a3def8165586 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py @@ -30,7 +30,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): ) self.match("platform file write 16 -o 11 -d teststring", [r"Return = 10"]) self.match("platform file close 16", [r"file 16 closed."]) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:open:2f736f6d652f66696c652e747874,00000202,000001ed", "vFile:pread:10,d,b", @@ -66,7 +66,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): error=True, ) self.match("platform file close 16", [enosys_regex], error=True) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:open:2f736f6d652f66696c652e747874,00000202,000001ed", "vFile:pread:10,d,b", @@ -88,7 +88,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): "platform get-size /some/file.txt", [r"File size of /some/file\.txt \(remote\): 4096"], ) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:size:2f736f6d652f66696c652e747874", ] @@ -113,7 +113,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): "platform get-size /some/file.txt", [r"File size of /some/file\.txt \(remote\): 66051"], ) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:size:2f736f6d652f66696c652e747874", "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000", @@ -135,7 +135,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): [r"File size of /other/file\.txt \(remote\): 66051"], ) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:size:2f6f746865722f66696c652e747874", "vFile:open:2f6f746865722f66696c652e747874,00000000,00000000", @@ -161,7 +161,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): "platform get-permissions /some/file.txt", [r"File permissions of /some/file\.txt \(remote\): 0o0644"], ) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:mode:2f736f6d652f66696c652e747874", ] @@ -190,7 +190,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): "platform get-permissions /some/file.txt", [r"File permissions of /some/file\.txt \(remote\): 0o0644"], ) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:mode:2f736f6d652f66696c652e747874", "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000", @@ -214,7 +214,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): "platform file-exists /some/file.txt", [r"File /some/file\.txt \(remote\) exists"], ) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:exists:2f736f6d652f66696c652e747874", ] @@ -233,7 +233,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): "platform file-exists /some/file.txt", [r"File /some/file\.txt \(remote\) does not exist"], ) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:exists:2f736f6d652f66696c652e747874", ] @@ -256,7 +256,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): "platform file-exists /some/file.txt", [r"File /some/file\.txt \(remote\) exists"], ) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:exists:2f736f6d652f66696c652e747874", "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000", @@ -279,7 +279,7 @@ class TestGDBRemotePlatformFile(GDBPlatformClientTestBase): "platform file-exists /some/file.txt", [r"File /some/file\.txt \(remote\) does not exist"], ) - self.assertPacketLogContains( + self.assertPacketLogReceived( [ "vFile:exists:2f736f6d652f66696c652e747874", "vFile:open:2f736f6d652f66696c652e747874,00000000,00000000", diff --git a/lldb/test/API/functionalities/thread/finish-from-empty-func/TestEmptyFuncThreadStepOut.py b/lldb/test/API/functionalities/thread/finish-from-empty-func/TestEmptyFuncThreadStepOut.py index f5d3da530f4f..c95a57ff5581 100644 --- a/lldb/test/API/functionalities/thread/finish-from-empty-func/TestEmptyFuncThreadStepOut.py +++ b/lldb/test/API/functionalities/thread/finish-from-empty-func/TestEmptyFuncThreadStepOut.py @@ -13,12 +13,31 @@ class FinishFromEmptyFunctionTestCase(TestBase): @skipIf(compiler="clang", compiler_version=['<', '17.0']) def test_finish_from_empty_function(self): - """Test that when stopped at a breakpoint in an empty function, finish leaves it correctly.""" + """Test that when stopped at a breakpoint located at the last instruction + of a function, finish leaves it correctly.""" self.build() - exe = self.getBuildArtifact("a.out") - target, process, thread, _ = lldbutil.run_to_name_breakpoint( - self, "done", exe_name=exe + target, _, thread, _ = lldbutil.run_to_source_breakpoint( + self, "// Set breakpoint here", lldb.SBFileSpec("main.c") ) + # Find the address of the last instruction of 'done()' and set a breakpoint there. + # Even though 'done()' is empty, it may contain prologue and epilogue code, so + # simply setting a breakpoint at the function can place it before 'ret'. + error = lldb.SBError() + ret_bp_addr = lldb.SBAddress() + while True: + thread.StepInstruction(False, error) + self.assertTrue(error.Success()) + frame = thread.GetSelectedFrame() + if "done" in frame.GetFunctionName(): + ret_bp_addr = frame.GetPCAddress() + elif ret_bp_addr.IsValid(): + # The entire function 'done()' has been stepped through, so 'ret_bp_addr' + # now contains the address of its last instruction, i.e. 'ret'. + break + ret_bp = target.BreakpointCreateByAddress(ret_bp_addr.GetLoadAddress(target)) + self.assertTrue(ret_bp.IsValid()) + # Resume the execution and hit the new breakpoint. + self.runCmd("cont") if self.TraceOn(): self.runCmd("bt") @@ -29,7 +48,6 @@ class FinishFromEmptyFunctionTestCase(TestBase): ) self.assertTrue(safety_bp.IsValid()) - error = lldb.SBError() thread.StepOut(error) self.assertTrue(error.Success()) diff --git a/lldb/test/API/functionalities/thread/finish-from-empty-func/main.c b/lldb/test/API/functionalities/thread/finish-from-empty-func/main.c index bc66a548a89d..b3f90db5e256 100644 --- a/lldb/test/API/functionalities/thread/finish-from-empty-func/main.c +++ b/lldb/test/API/functionalities/thread/finish-from-empty-func/main.c @@ -2,6 +2,7 @@ void done() {} int main() { puts("in main"); + done(); // Set breakpoint here done(); puts("leaving main"); return 0; diff --git a/lldb/test/API/lang/objc/foundation/TestObjCMethodsNSError.py b/lldb/test/API/lang/objc/foundation/TestObjCMethodsNSError.py index a14035db5e05..a9fbe54e074f 100644 --- a/lldb/test/API/lang/objc/foundation/TestObjCMethodsNSError.py +++ b/lldb/test/API/lang/objc/foundation/TestObjCMethodsNSError.py @@ -45,3 +45,30 @@ class FoundationTestCaseNSError(TestBase): ], ) self.runCmd("process continue") + + @skipIfOutOfTreeDebugserver + def test_runtime_types_efficient_memreads(self): + # Test that we use an efficient reading of memory when reading + # Objective-C method descriptions. + logfile = os.path.join(self.getBuildDir(), "log.txt") + self.runCmd(f"log enable -f {logfile} gdb-remote packets process") + self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote packets")) + + self.build() + self.target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, "// Break here for NSString tests", lldb.SBFileSpec("main.m", False) + ) + + self.runCmd(f"proc plugin packet send StartTesting", check=False) + self.expect('expression str = [NSString stringWithCString: "new"]') + self.runCmd(f"proc plugin packet send EndTesting", check=False) + + self.assertTrue(os.path.exists(logfile)) + log_text = open(logfile).read() + log_text = log_text.split("StartTesting", 1)[-1].split("EndTesting", 1)[0] + + # This test is only checking that the packet it used at all (and that + # no errors are produced). It doesn't check that the packet is being + # used to solve a problem in an optimal way. + self.assertIn("MultiMemRead:", log_text) + self.assertNotIn("MultiMemRead error", log_text) |
