xref: /llvm-project/lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py (revision 19ecdedcd2b7fb44689ce3cd59a6a078539eef3f)
15b4100ccSJohn Harrison"""
25b4100ccSJohn HarrisonTest lldb-dap stackTrace request with an extended backtrace thread.
35b4100ccSJohn Harrison"""
45b4100ccSJohn Harrison
55b4100ccSJohn Harrison
65b4100ccSJohn Harrisonimport os
75b4100ccSJohn Harrison
85b4100ccSJohn Harrisonimport lldbdap_testcase
95b4100ccSJohn Harrisonfrom lldbsuite.test.decorators import *
105b4100ccSJohn Harrisonfrom lldbsuite.test.lldbtest import *
115b4100ccSJohn Harrisonfrom lldbsuite.test.lldbplatformutil import *
125b4100ccSJohn Harrison
135b4100ccSJohn Harrison
145b4100ccSJohn Harrisonclass TestDAP_extendedStackTrace(lldbdap_testcase.DAPTestCaseBase):
155b4100ccSJohn Harrison    @skipUnlessDarwin
165b4100ccSJohn Harrison    def test_stackTrace(self):
175b4100ccSJohn Harrison        """
185b4100ccSJohn Harrison        Tests the 'stackTrace' packet on a thread with an extended backtrace.
195b4100ccSJohn Harrison        """
205b4100ccSJohn Harrison        backtrace_recording_lib = findBacktraceRecordingDylib()
215b4100ccSJohn Harrison        if not backtrace_recording_lib:
225b4100ccSJohn Harrison            self.skipTest(
235b4100ccSJohn Harrison                "Skipped because libBacktraceRecording.dylib was present on the system."
245b4100ccSJohn Harrison            )
255b4100ccSJohn Harrison
265b4100ccSJohn Harrison        if not os.path.isfile("/usr/lib/system/introspection/libdispatch.dylib"):
275b4100ccSJohn Harrison            self.skipTest(
285b4100ccSJohn Harrison                "Skipped because introspection libdispatch dylib is not present."
295b4100ccSJohn Harrison            )
305b4100ccSJohn Harrison
315b4100ccSJohn Harrison        program = self.getBuildArtifact("a.out")
325b4100ccSJohn Harrison
335b4100ccSJohn Harrison        self.build_and_launch(
345b4100ccSJohn Harrison            program,
355b4100ccSJohn Harrison            env=[
365b4100ccSJohn Harrison                "DYLD_LIBRARY_PATH=/usr/lib/system/introspection",
375b4100ccSJohn Harrison                "DYLD_INSERT_LIBRARIES=" + backtrace_recording_lib,
385b4100ccSJohn Harrison            ],
39*19ecdedcSAdrian Vogelsgesang            displayExtendedBacktrace=True,
405b4100ccSJohn Harrison        )
415b4100ccSJohn Harrison        source = "main.m"
425b4100ccSJohn Harrison        breakpoint = line_number(source, "breakpoint 1")
435b4100ccSJohn Harrison        lines = [breakpoint]
445b4100ccSJohn Harrison
455b4100ccSJohn Harrison        breakpoint_ids = self.set_source_breakpoints(source, lines)
465b4100ccSJohn Harrison        self.assertEqual(
475b4100ccSJohn Harrison            len(breakpoint_ids), len(lines), "expect correct number of breakpoints"
485b4100ccSJohn Harrison        )
495b4100ccSJohn Harrison
505b4100ccSJohn Harrison        events = self.continue_to_next_stop()
515b4100ccSJohn Harrison
525b4100ccSJohn Harrison        stackFrames, totalFrames = self.get_stackFrames_and_totalFramesCount(
535b4100ccSJohn Harrison            threadId=events[0]["body"]["threadId"]
545b4100ccSJohn Harrison        )
555b4100ccSJohn Harrison        self.assertGreaterEqual(len(stackFrames), 3, "expect >= 3 frames")
565b4100ccSJohn Harrison        self.assertEqual(len(stackFrames), totalFrames)
575b4100ccSJohn Harrison        self.assertEqual(stackFrames[0]["name"], "one")
585b4100ccSJohn Harrison        self.assertEqual(stackFrames[1]["name"], "two")
595b4100ccSJohn Harrison        self.assertEqual(stackFrames[2]["name"], "three")
605b4100ccSJohn Harrison
615b4100ccSJohn Harrison        stackLabels = [
625b4100ccSJohn Harrison            (i, frame)
635b4100ccSJohn Harrison            for i, frame in enumerate(stackFrames)
645b4100ccSJohn Harrison            if frame.get("presentationHint", "") == "label"
655b4100ccSJohn Harrison        ]
665b4100ccSJohn Harrison        self.assertEqual(len(stackLabels), 2, "expected two label stack frames")
675b4100ccSJohn Harrison        self.assertRegex(
685b4100ccSJohn Harrison            stackLabels[0][1]["name"],
695b4100ccSJohn Harrison            "Enqueued from com.apple.root.default-qos \(Thread \d\)",
705b4100ccSJohn Harrison        )
715b4100ccSJohn Harrison        self.assertRegex(
725b4100ccSJohn Harrison            stackLabels[1][1]["name"],
735b4100ccSJohn Harrison            "Enqueued from com.apple.main-thread \(Thread \d\)",
745b4100ccSJohn Harrison        )
755b4100ccSJohn Harrison
765b4100ccSJohn Harrison        for i, frame in stackLabels:
775b4100ccSJohn Harrison            # Ensure requesting startFrame+levels across thread backtraces works as expected.
785b4100ccSJohn Harrison            stackFrames, totalFrames = self.get_stackFrames_and_totalFramesCount(
795b4100ccSJohn Harrison                threadId=events[0]["body"]["threadId"], startFrame=i - 1, levels=3
805b4100ccSJohn Harrison            )
815b4100ccSJohn Harrison            self.assertEqual(len(stackFrames), 3, "expected 3 frames with levels=3")
825b4100ccSJohn Harrison            self.assertGreaterEqual(
835b4100ccSJohn Harrison                totalFrames, i + 3, "total frames should include a pagination offset"
845b4100ccSJohn Harrison            )
855b4100ccSJohn Harrison            self.assertEqual(stackFrames[1], frame)
865b4100ccSJohn Harrison
875b4100ccSJohn Harrison            # Ensure requesting startFrame+levels at the beginning of a thread backtraces works as expected.
885b4100ccSJohn Harrison            stackFrames, totalFrames = self.get_stackFrames_and_totalFramesCount(
895b4100ccSJohn Harrison                threadId=events[0]["body"]["threadId"], startFrame=i, levels=3
905b4100ccSJohn Harrison            )
915b4100ccSJohn Harrison            self.assertEqual(len(stackFrames), 3, "expected 3 frames with levels=3")
925b4100ccSJohn Harrison            self.assertGreaterEqual(
935b4100ccSJohn Harrison                totalFrames, i + 3, "total frames should include a pagination offset"
945b4100ccSJohn Harrison            )
955b4100ccSJohn Harrison            self.assertEqual(stackFrames[0], frame)
965b4100ccSJohn Harrison
975b4100ccSJohn Harrison            # Ensure requests with startFrame+levels that end precisely on the last frame includes the totalFrames pagination offset.
985b4100ccSJohn Harrison            stackFrames, totalFrames = self.get_stackFrames_and_totalFramesCount(
995b4100ccSJohn Harrison                threadId=events[0]["body"]["threadId"], startFrame=i - 1, levels=1
1005b4100ccSJohn Harrison            )
1015b4100ccSJohn Harrison            self.assertEqual(len(stackFrames), 1, "expected 1 frames with levels=1")
1025b4100ccSJohn Harrison            self.assertGreaterEqual(
1035b4100ccSJohn Harrison                totalFrames, i, "total frames should include a pagination offset"
1045b4100ccSJohn Harrison            )
105