[lldb-dap] Migrate lldb-dap stackTrace tests#209236
Open
da-viper wants to merge 1 commit into
Open
Conversation
Migrate - TestDAP_stackTrace - TestDAP_stackTraceDisassemblyDisplay - TestDAP_stackTraceDisassemblyDisplay - TestDAP_stackTraceMissingFunctionName - TestDAP_stackTraceMissingModule
|
@llvm/pr-subscribers-lldb Author: Ebuka Ezike (da-viper) ChangesMigrate
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:
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]
|
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
ashgti
approved these changes
Jul 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migrate