Skip to content

[lldb-dap] Migrate lldb-dap stackTrace tests#209236

Open
da-viper wants to merge 1 commit into
llvm:mainfrom
da-viper:migrate-test-dap-stacktrace
Open

[lldb-dap] Migrate lldb-dap stackTrace tests#209236
da-viper wants to merge 1 commit into
llvm:mainfrom
da-viper:migrate-test-dap-stacktrace

Conversation

@da-viper

Copy link
Copy Markdown
Contributor

Migrate

  • TestDAP_stackTrace
  • TestDAP_stackTraceDisassemblyDisplay
  • TestDAP_stackTraceDisassemblyDisplay
  • TestDAP_stackTraceMissingFunctionName
  • TestDAP_stackTraceMissingModule

Migrate
- TestDAP_stackTrace
- TestDAP_stackTraceDisassemblyDisplay
- TestDAP_stackTraceDisassemblyDisplay
- TestDAP_stackTraceMissingFunctionName
- TestDAP_stackTraceMissingModule
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-lldb

Author: Ebuka Ezike (da-viper)

Changes

Migrate

  • TestDAP_stackTrace
  • TestDAP_stackTraceDisassemblyDisplay
  • TestDAP_stackTraceDisassemblyDisplay
  • TestDAP_stackTraceMissingFunctionName
  • TestDAP_stackTraceMissingModule

Patch is 41.44 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/209236.diff

5 Files Affected:

  • (modified) lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py (+196-173)
  • (modified) lldb/test/API/tools/lldb-dap/stackTraceCompilerGeneratedCode/TestDAP_stackTraceCompilerGeneratedCode.py (+26-25)
  • (modified) lldb/test/API/tools/lldb-dap/stackTraceDisassemblyDisplay/TestDAP_stackTraceDisassemblyDisplay.py (+86-100)
  • (modified) lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py (+9-7)
  • (modified) lldb/test/API/tools/lldb-dap/stackTraceMissingModule/TestDAP_stackTraceMissingModule.py (+28-34)
diff --git a/lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py b/lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py
index fd2037b5762d1..f28cf9eac2e6a 100644
--- a/lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py
+++ b/lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py
@@ -3,275 +3,298 @@
 """
 
 import os
-
-import lldbdap_testcase
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-
-
-class TestDAP_stackTrace(lldbdap_testcase.DAPTestCaseBase):
-    name_key_path = ["name"]
-    source_key_path = ["source", "path"]
-    line_key_path = ["line"]
-
-    # stackTrace additioanl frames for paginated traces
-    page_size = 20
-
-    def verify_stackFrames(self, start_idx, stackFrames):
-        frame_idx = start_idx
-        for stackFrame in stackFrames:
-            # Don't care about frame above main
+from typing import List, NamedTuple
+
+from lldbsuite.test.decorators import skipIfWindows
+from lldbsuite.test.lldbtest import line_number
+from lldbsuite.test.tools.lldb_dap.dap_types import (
+    LaunchArgs,
+    StackFrame,
+    StackFrameFormat,
+)
+from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase
+
+
+class _RecurseSource(NamedTuple):
+    path: str
+    end_line: int
+    call_line: int
+    invocation_line: int
+
+
+class TestDAP_stackTrace(DAPTestCaseBase):
+    def verify_stack_frames(self, start_idx: int, stack_frames: List[StackFrame]):
+        recourse_source = self.recourse_source
+        for frame_idx, frame in enumerate(stack_frames, start_idx):
+            # Don't care about frames above main.
             if frame_idx > 40:
                 return
-            self.verify_stackFrame(frame_idx, stackFrame)
-            frame_idx += 1
+            self.verify_stack_frame(frame_idx, frame, recourse_source)
+
+    def verify_stack_frame(
+        self,
+        frame_idx: int,
+        stack_frame: StackFrame,
+        r_source: _RecurseSource,
+    ):
+        frame_name = stack_frame.name
+        frame_source = self.expect_not_none(stack_frame.source)
+        frame_source_path = frame_source.path
+        frame_line = stack_frame.line
 
-    def verify_stackFrame(self, frame_idx, stackFrame):
-        frame_name = self.get_dict_value(stackFrame, self.name_key_path)
-        frame_source = self.get_dict_value(stackFrame, self.source_key_path)
-        frame_line = self.get_dict_value(stackFrame, self.line_key_path)
         if frame_idx == 0:
-            expected_line = self.recurse_end
+            expected_line = r_source.end_line
             expected_name = "recurse"
         elif frame_idx < 40:
-            expected_line = self.recurse_call
+            expected_line = r_source.call_line
             expected_name = "recurse"
         else:
-            expected_line = self.recurse_invocation
+            expected_line = r_source.invocation_line
             expected_name = "main"
+
         self.assertEqual(
             frame_name,
             expected_name,
-            'frame #%i name "%s" == "%s"' % (frame_idx, frame_name, expected_name),
+            f'frame #{frame_idx} name "{frame_name}" == "{expected_name}"',
         )
         self.assertEqual(
-            frame_source,
-            self.source_path,
-            'frame #%i source "%s" == "%s"'
-            % (frame_idx, frame_source, self.source_path),
+            frame_source_path,
+            r_source.path,
+            f'frame #{frame_idx} source "{frame_source_path}" == "{r_source.path}"',
         )
         self.assertEqual(
             frame_line,
             expected_line,
-            "frame #%i line %i == %i" % (frame_idx, frame_line, expected_line),
+            f"frame #{frame_idx} line {frame_line} == {expected_line}",
         )
 
     def test_stackTrace(self):
-        """
-        Tests the 'stackTrace' packet and all its variants.
-        """
+        """Test the 'stackTrace' packet and all its variants."""
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program)
-        source = "main.c"
-        self.source_path = os.path.join(os.getcwd(), source)
-        self.recurse_end = line_number(source, "recurse end")
-        self.recurse_call = line_number(source, "recurse call")
-        self.recurse_invocation = line_number(source, "recurse invocation")
+        session = self.build_and_create_session()
+        source_file = self.getSourcePath("main.c")
+        self.recourse_source = _RecurseSource(
+            path=os.path.realpath(source_file),
+            end_line=line_number(source_file, "recurse end"),
+            call_line=line_number(source_file, "recurse call"),
+            invocation_line=line_number(source_file, "recurse invocation"),
+        )
 
-        lines = [self.recurse_end]
+        with session.configure(LaunchArgs(program=program)) as ctx:
+            # Set a breakpoint at the point of deepest recursion.
+            breakpoint_ids = session.resolve_source_breakpoints(
+                source_file, [self.recourse_source.end_line]
+            )
 
-        # Set breakpoint at a point of deepest recuusion
-        breakpoint_ids = self.set_source_breakpoints(source, lines)
-        self.assertEqual(
-            len(breakpoint_ids), len(lines), "expect correct number of breakpoints"
+        stop_event = session.verify_stopped_on_breakpoint(
+            breakpoint_ids, after=ctx.process_event
         )
-
-        self.continue_to_breakpoints(breakpoint_ids)
-        startFrame = 0
-        # Verify we get all stack frames with no arguments
-        (stackFrames, totalFrames) = self.get_stackFrames_and_totalFramesCount()
-        frameCount = len(stackFrames)
+        thread_id = self.expect_not_none(stop_event.body.threadId)
+
+        start_frame = 0
+        # Verify that we get all stack frames with no arguments.
+        response = session.stack_trace(thread_id)
+        stack_frames = response.body.stackFrames
+        total_frames = response.body.totalFrames
+        frame_count = len(stack_frames)
         self.assertGreaterEqual(
-            frameCount, 40, "verify we get at least 40 frames for all frames"
+            frame_count, 40, "verify we get at least 40 frames for all frames"
         )
         self.assertEqual(
-            totalFrames,
-            frameCount,
+            total_frames,
+            frame_count,
             "verify total frames returns a speculative page size",
         )
-        self.verify_stackFrames(startFrame, stackFrames)
+        self.verify_stack_frames(start_frame, stack_frames)
 
-        # Verify totalFrames contains a speculative page size of additional frames with startFrame = 0 and levels = 0
-        (stackFrames, totalFrames) = self.get_stackFrames_and_totalFramesCount(
-            startFrame=0, levels=10
-        )
-        self.assertEqual(len(stackFrames), 10, "verify we get levels=10 frames")
+        # Verify that totalFrames includes a speculative page size of additional
+        # frames when startFrame=0 and levels=10.
+        response = session.stack_trace(thread_id, startFrame=0, levels=10)
+        stack_frames = response.body.stackFrames
+        total_frames = response.body.totalFrames
+        self.assertEqual(len(stack_frames), 10, "verify we get levels=10 frames")
+
+        page_size = 20  # Number of additional frames added by lldb-dap to a paginated stack trace.
         self.assertEqual(
-            totalFrames,
-            len(stackFrames) + self.page_size,
+            total_frames,
+            len(stack_frames) + page_size,
             "verify total frames returns a speculative page size",
         )
-        self.verify_stackFrames(startFrame, stackFrames)
+        self.verify_stack_frames(start_frame, stack_frames)
 
-        # Verify all stack frames by specifying startFrame = 0 and levels not
-        # specified
-        stackFrames = self.get_stackFrames(startFrame=startFrame)
+        # Verify all stack frames by specifying startFrame=0 and no levels.
+        response = session.stack_trace(thread_id, startFrame=start_frame)
+        stack_frames = response.body.stackFrames
         self.assertEqual(
-            frameCount,
-            len(stackFrames),
-            ("verify same number of frames with startFrame=%i") % (startFrame),
+            frame_count,
+            len(stack_frames),
+            f"verify same number of frames with startFrame={start_frame}",
         )
-        self.verify_stackFrames(startFrame, stackFrames)
+        self.verify_stack_frames(start_frame, stack_frames)
 
-        # Verify all stack frames by specifying startFrame = 0 and levels = 0
+        # Verify all stack frames by specifying startFrame=0 and levels=0.
         levels = 0
-        stackFrames = self.get_stackFrames(startFrame=startFrame, levels=levels)
+        response = session.stack_trace(thread_id, startFrame=start_frame, levels=levels)
+        stack_frames = response.body.stackFrames
         self.assertEqual(
-            frameCount,
-            len(stackFrames),
-            ("verify same number of frames with startFrame=%i and" " levels=%i")
-            % (startFrame, levels),
+            frame_count,
+            len(stack_frames),
+            f"verify same number of frames with startFrame={start_frame} and levels={levels}",
         )
-        self.verify_stackFrames(startFrame, stackFrames)
+        self.verify_stack_frames(start_frame, stack_frames)
 
-        # Get only the first stack frame by sepcifying startFrame = 0 and
-        # levels = 1
+        # Get only the first stack frame by specifying startFrame=0 and levels=1.
         levels = 1
-        stackFrames = self.get_stackFrames(startFrame=startFrame, levels=levels)
+        response = session.stack_trace(thread_id, startFrame=start_frame, levels=levels)
+        stack_frames = response.body.stackFrames
         self.assertEqual(
             levels,
-            len(stackFrames),
-            ("verify one frame with startFrame=%i and" " levels=%i")
-            % (startFrame, levels),
+            len(stack_frames),
+            f"verify one frame with {start_frame=} and {levels=}",
         )
-        self.verify_stackFrames(startFrame, stackFrames)
+        self.verify_stack_frames(start_frame, stack_frames)
 
-        # Get only the first 3 stack frames by sepcifying startFrame = 0 and
-        # levels = 3
+        # Get only the first 3 stack frames by specifying startFrame=0 and levels=3.
         levels = 3
-        stackFrames = self.get_stackFrames(startFrame=startFrame, levels=levels)
+        response = session.stack_trace(thread_id, startFrame=start_frame, levels=levels)
+        stack_frames = response.body.stackFrames
         self.assertEqual(
             levels,
-            len(stackFrames),
-            ("verify %i frames with startFrame=%i and" " levels=%i")
-            % (levels, startFrame, levels),
+            len(stack_frames),
+            f"verify {levels} frames with {start_frame=} and {levels=}",
         )
-        self.verify_stackFrames(startFrame, stackFrames)
+        self.verify_stack_frames(start_frame, stack_frames)
 
-        # Get only the first 15 stack frames by sepcifying startFrame = 5 and
-        # levels = 16
-        startFrame = 5
+        # Get the first 16 stack frames by specifying startFrame=5 and levels=16.
+        start_frame = 5
         levels = 16
-        stackFrames = self.get_stackFrames(startFrame=startFrame, levels=levels)
+        response = session.stack_trace(thread_id, startFrame=start_frame, levels=levels)
+        stack_frames = response.body.stackFrames
         self.assertEqual(
             levels,
-            len(stackFrames),
-            ("verify %i frames with startFrame=%i and" " levels=%i")
-            % (levels, startFrame, levels),
+            len(stack_frames),
+            f"verify {levels} frames with {start_frame=} and {levels=}",
         )
-        self.verify_stackFrames(startFrame, stackFrames)
+        self.verify_stack_frames(start_frame, stack_frames)
 
-        # Verify we cap things correctly when we ask for too many frames
-        startFrame = 5
+        # Verify that the count is capped correctly when we ask for too many frames.
+        start_frame = 5
         levels = 1000
-        (stackFrames, totalFrames) = self.get_stackFrames_and_totalFramesCount(
-            startFrame=startFrame, levels=levels
-        )
+        response = session.stack_trace(thread_id, startFrame=start_frame, levels=levels)
+        stack_frames = response.body.stackFrames
+        total_frames = response.body.totalFrames
         self.assertEqual(
-            len(stackFrames),
-            frameCount - startFrame,
-            ("verify less than 1000 frames with startFrame=%i and" " levels=%i")
-            % (startFrame, levels),
+            len(stack_frames),
+            frame_count - start_frame,
+            f"verify fewer than 1000 frames with {start_frame=} and {levels=}",
         )
         self.assertEqual(
-            totalFrames,
-            frameCount,
-            "verify we get correct value for totalFrames count "
-            "when requested frames not from 0 index",
+            total_frames,
+            frame_count,
+            "verify we get the correct value for totalFrames count "
+            "when requested frames do not start at index 0",
         )
-        self.verify_stackFrames(startFrame, stackFrames)
+        self.verify_stack_frames(start_frame, stack_frames)
 
-        # Verify level=0 works with non-zerp start frame
-        startFrame = 5
+        # Verify that levels=0 works with a non-zero startFrame.
+        start_frame = 5
         levels = 0
-        stackFrames = self.get_stackFrames(startFrame=startFrame, levels=levels)
+        response = session.stack_trace(thread_id, startFrame=start_frame, levels=levels)
+        stack_frames = response.body.stackFrames
         self.assertEqual(
-            len(stackFrames),
-            frameCount - startFrame,
-            ("verify less than 1000 frames with startFrame=%i and" " levels=%i")
-            % (startFrame, levels),
+            len(stack_frames),
+            frame_count - start_frame,
+            f"verify all remaining frames with startFrame={start_frame} and levels={levels}",
         )
-        self.verify_stackFrames(startFrame, stackFrames)
+        self.verify_stack_frames(start_frame, stack_frames)
 
-        # Verify we get not frames when startFrame is too high
-        startFrame = 1000
+        # Verify that we get no frames when startFrame is too high.
+        start_frame = 1000
         levels = 1
-        stackFrames = self.get_stackFrames(startFrame=startFrame, levels=levels)
+        response = session.stack_trace(thread_id, startFrame=start_frame, levels=levels)
+        stack_frames = response.body.stackFrames
         self.assertEqual(
-            0, len(stackFrames), "verify zero frames with startFrame out of bounds"
+            0, len(stack_frames), "verify zero frames with startFrame out of bounds"
         )
 
     @skipIfWindows
-    def test_functionNameWithArgs(self):
-        """
-        Test that the stack frame without a function name is given its pc in the response.
-        """
+    def test_function_name_with_args(self):
+        """Test that a stack frame's name includes its argument values."""
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program, customFrameFormat="${function.name-with-args}")
-        source = "main.c"
-
-        self.set_source_breakpoints(source, [line_number(source, "recurse end")])
+        session = self.build_and_create_session()
+        launch_args = LaunchArgs(
+            program, customFrameFormat="${function.name-with-args}"
+        )
+        with session.configure(launch_args) as ctx:
+            source = "main.c"
+            session.resolve_source_breakpoints(
+                source, [line_number(source, "recurse end")]
+            )
+        stop_event = session.verify_stopped_on_breakpoint(after=ctx.process_event)
+        thread_ctx = session.thread_context_from(stop_event)
 
-        self.continue_to_next_stop()
-        frame = self.get_stackFrames()[0]
-        self.assertEqual(frame["name"], "recurse(x=1)")
+        frame = thread_ctx.top_frame().frame
+        self.assertEqual(frame.name, "recurse(x=1)")
 
     @skipIfWindows
-    def test_StackFrameFormat(self):
+    def test_stack_frame_format(self):
         """
-        Test the StackFrameFormat.
+        Test the StackFrameFormat options.
         """
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program)
-        source = "main.c"
-
-        self.set_source_breakpoints(source, [line_number(source, "recurse end")])
+        session = self.build_and_create_session()
+        with session.configure(LaunchArgs(program)) as ctx:
+            source = "main.c"
+            bp_line = line_number(source, "recurse end")
+            session.resolve_source_breakpoints(source, [bp_line])
 
-        self.continue_to_next_stop()
-        frame = self.get_stackFrames(format={"parameters": True})[0]
-        self.assertEqual(frame["name"], "recurse(x=1)")
+        stop_event = session.verify_stopped_on_breakpoint(after=ctx.process_event)
+        thread_ctx = session.thread_context_from(stop_event)
+        frame = thread_ctx.top_frame(format=StackFrameFormat(parameters=True))
+        self.assertEqual(frame.name, "recurse(x=1)")
 
-        frame = self.get_stackFrames(format={"parameterNames": True})[0]
-        self.assertEqual(frame["name"], "recurse(x=1)")
+        frame = thread_ctx.top_frame(format=StackFrameFormat(parameterNames=True))
+        self.assertEqual(frame.name, "recurse(x=1)")
 
-        frame = self.get_stackFrames(format={"parameterValues": True})[0]
-        self.assertEqual(frame["name"], "recurse(x=1)")
+        frame = thread_ctx.top_frame(format=StackFrameFormat(parameterValues=True))
+        self.assertEqual(frame.name, "recurse(x=1)")
 
-        frame = self.get_stackFrames(format={"parameters": False, "line": True})[0]
-        self.assertEqual(frame["name"], "main.c:5:5 recurse")
+        format = StackFrameFormat(parameters=False, line=True)
+        frame = thread_ctx.top_frame(format=format)
+        self.assertEqual(frame.name, f"main.c:{bp_line}:5 recurse")
 
-        frame = self.get_stackFrames(format={"parameters": False, "module": True})[0]
-        self.assertEqual(frame["name"], "a.out recurse")
+        format = StackFrameFormat(parameters=False, module=True)
+        frame = thread_ctx.top_frame(format=format)
+        self.assertEqual(frame.name, "a.out recurse")
 
     @skipIfWindows
-    def test_stack_frame_module_id(self):
+    def test_stack_frame_module_id(self) -> None:
+        """Test that each stack frame's moduleId matches the loaded module's id."""
         program = self.getBuildArtifact("a.out")
-        self.build_and_launch(program)
-        source = "main.c"
+        session = self.build_and_create_session()
+        source = self.getSourcePath("main.c")
         lines = [line_number(source, "recurse end")]
-        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)
+        with session.configure(LaunchArgs(program=program)) as ctx:
+            breakpoint_ids = session.resolve_source_breakpoints(source, lines)
 
-        modules = self.dap_server.get_modules()
-        name_to_id = {
-            name: info["id"] for name, info in modules.items() if "id" in info
-        }
+        stop_event = session.verify_stopped_on_breakpoint(
+            breakpoint_ids, after=ctx.process_event
+        )
+        thread_id = self.expect_not_none(stop_event.body.threadId)
+        modules = session.get_modules()
+        stack_frames = session.stack_trace(thread_id).body.stackFrames
 
-        stack_frames = self.get_stackFrames()
         for frame in stack_frames:
-            module_id = frame.get("moduleId")
-            source_name = frame.get("source", {}).get("name")
+            module_id = frame.moduleId
+            source_name = frame.source and frame.source.name
             if module_id is None or source_name is None:
     ...
[truncated]

@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown

🐧 Linux x64 Test Results

  • 34030 tests passed
  • 549 tests skipped

✅ The build succeeded and all tests passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants