| """ | |
| Test lldb-dap threads request | |
| """ | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test import lldbutil | |
| import lldbdap_testcase | |
| @skipIfTargetDoesNotSupportThreads() | |
| class TestDAP_threads(lldbdap_testcase.DAPTestCaseBase): | |
| def test_correct_thread(self): | |
| """ | |
| Tests that the correct thread is selected if we continue from | |
| a thread that goes away and hit a breakpoint in another thread. | |
| In this case, the selected thread should be the thread that | |
| just hit the breakpoint, and not the first thread in the list. | |
| """ | |
| program = self.getBuildArtifact("a.out") | |
| self.build_and_launch(program) | |
| source = "main.cpp" | |
| breakpoint_line = line_number(source, "// break here") | |
| lines = [breakpoint_line] | |
| # Set breakpoint in the thread function | |
| breakpoint_ids = self.set_source_breakpoints(source, lines) | |
| self.assertEqual( | |
| len(breakpoint_ids), len(lines), "expect correct number of breakpoints" | |
| ) | |
| self.continue_to_breakpoints(breakpoint_ids) | |
| # We're now stopped at the breakpoint in the first thread, thread #2. | |
| # Continue to join the first thread and hit the breakpoint in the | |
| # second thread, thread #3. | |
| self.dap_server.request_continue() | |
| stopped_event = self.dap_server.wait_for_stopped() | |
| # Verify that the description is the relevant breakpoint, | |
| # preserveFocusHint is False and threadCausedFocus is True | |
| self.assertTrue( | |
| stopped_event[0]["body"]["description"].startswith( | |
| "breakpoint %s." % breakpoint_ids[0] | |
| ) | |
| ) | |
| self.assertNotIn("preserveFocusHint", stopped_event[0]["body"]) | |
| # All threads should be named Thread {index} | |
| threads = self.dap_server.get_threads() | |
| self.assertTrue(all(len(t["name"]) > 0 for t in threads)) | |
| def test_thread_format(self): | |
| """ | |
| Tests the support for custom thread formats. | |
| """ | |
| program = self.getBuildArtifact("a.out") | |
| self.build_and_launch( | |
| program, | |
| customThreadFormat="This is thread index #${thread.index}", | |
| stopCommands=["thread list"], | |
| ) | |
| source = "main.cpp" | |
| breakpoint_line = line_number(source, "// break here") | |
| lines = [breakpoint_line] | |
| # Set breakpoint in the thread function | |
| breakpoint_ids = self.set_source_breakpoints(source, lines) | |
| self.assertEqual( | |
| len(breakpoint_ids), len(lines), "expect correct number of breakpoints" | |
| ) | |
| self.continue_to_breakpoints(breakpoint_ids) | |
| # We are stopped at the first thread | |
| threads = self.dap_server.get_threads() | |
| print("got thread", threads) | |
| if self.getPlatform() == "windows": | |
| # Windows creates a thread pool once WaitForSingleObject is called | |
| # by thread.join(). As we are in the thread function, we can't be | |
| # certain that join() has been called yet and a thread pool has | |
| # been created, thus we only check for the first two threads. | |
| names = list(sorted(t["name"] for t in threads))[:2] | |
| self.assertEqual( | |
| names, ["This is thread index #1", "This is thread index #2"] | |
| ) | |
| else: | |
| self.assertEqual(threads[0]["name"], "This is thread index #1") | |
| self.assertEqual(threads[1]["name"], "This is thread index #2") |