[Lldb-commits] [lldb] [lldb-dap] Miragte the DAP step and stop hooks tests (PR #209936)
Ebuka Ezike via lldb-commits
lldb-commits at lists.llvm.org
Wed Jul 15 18:54:20 PDT 2026
https://github.com/da-viper created https://github.com/llvm/llvm-project/pull/209936
Migrated Tests:
- TestDAP_step.py
- TestDAP_stepInTargets.py
- TestDAP_stop_hooks.py
>From d38347a3796893368da4636484e094d9ba56b6cf Mon Sep 17 00:00:00 2001
From: Ebuka Ezike <yerimyah1 at gmail.com>
Date: Wed, 15 Jul 2026 09:32:52 +0100
Subject: [PATCH] [lldb-dap] Miragte the DAP step and stop hooks tests
---
.../API/tools/lldb-dap/step/TestDAP_step.py | 158 +++++++++---------
.../stepInTargets/TestDAP_stepInTargets.py | 118 +++++--------
.../lldb-dap/stop-hooks/TestDAP_stop_hooks.py | 20 ++-
3 files changed, 128 insertions(+), 168 deletions(-)
diff --git a/lldb/test/API/tools/lldb-dap/step/TestDAP_step.py b/lldb/test/API/tools/lldb-dap/step/TestDAP_step.py
index 5c055f679aedc..19bf7e87a235f 100644
--- a/lldb/test/API/tools/lldb-dap/step/TestDAP_step.py
+++ b/lldb/test/API/tools/lldb-dap/step/TestDAP_step.py
@@ -2,122 +2,114 @@
Test lldb-dap setBreakpoints request
"""
+from lldbsuite.test.decorators import skipIfWindows
+from lldbsuite.test.lldbtest import line_number
+from lldbsuite.test.tools.lldb_dap.types import LaunchArgs
+from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase
-import dap_server
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-import lldbdap_testcase
-
-class TestDAP_step(lldbdap_testcase.DAPTestCaseBase):
+class TestDAP_step(DAPTestCaseBase):
@skipIfWindows
def test_step(self):
"""
Tests the stepping in/out/over in threads.
"""
program = self.getBuildArtifact("a.out")
- self.build_and_launch(program)
- source = "main.cpp"
- # source_path = os.path.join(os.getcwd(), source)
+ session = self.build_and_create_session()
+ source = self.getSourcePath("main.cpp")
breakpoint1_line = line_number(source, "// breakpoint 1")
lines = [breakpoint1_line]
- # Set breakpoint in the thread function so we can step the threads
- 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)
- threads = self.dap_server.get_threads()
- for thread in threads:
- if "reason" in thread:
- reason = thread["reason"]
- if reason == "breakpoint":
- # We have a thread that is stopped at our breakpoint.
- # Get the value of "x" and get the source file and line.
- # These will help us determine if we are stepping
- # correctly. If we step a thread correctly we will verify
- # the correct falue for x as it progresses through the
- # program.
- tid = thread["id"]
- x1 = self.get_local_as_int("x", threadId=tid)
- (src1, line1) = self.get_source_and_line(threadId=tid)
- # Now step into the "recurse()" function call again and
- # verify, using the new value of "x" and the source file
- # and line if we stepped correctly
- self.stepIn(threadId=tid, waitForStop=True)
- x2 = self.get_local_as_int("x", threadId=tid)
- (src2, line2) = self.get_source_and_line(threadId=tid)
- self.assertEqual(x1, x2 + 1, "verify step in variable")
- self.assertLess(line2, line1, "verify step in line")
- self.assertEqual(src1, src2, "verify step in source")
+ # Set breakpoint in the thread function so we can step the threads.
+ with session.configure(LaunchArgs(program)) as ctx:
+ session.resolve_source_breakpoints(source, lines)
+ process_event = ctx.process_event
+ stop_event = session.verify_stopped_on_breakpoint(after=process_event)
+
+ # We have a thread that is stopped at our breakpoint.
+ # Get the value of "x" and get the source file and line.
+ # These will help us determine if we are stepping
+ # correctly. If we step a thread correctly we will verify
+ # the correct value for x as it progresses through the
+ # program.
+ thread = session.thread_context_from(stop_event)
+ top_frame = thread.top_frame()
+ x1 = top_frame.locals["x"].value_as_int
+ src1, line1 = top_frame.source_and_line()
+
+ # Now step into the "recurse()" function call again and
+ # verify, using the new value of "x" and the source file
+ # and line if we stepped correctly.
+ thread.step_in()
+ top_frame = thread.top_frame()
+ x2 = top_frame.locals["x"].value_as_int
+ src2, line2 = top_frame.source_and_line()
- # Now step out and verify
- self.stepOut(threadId=tid, waitForStop=True)
- x3 = self.get_local_as_int("x", threadId=tid)
- (src3, line3) = self.get_source_and_line(threadId=tid)
- self.assertEqual(x1, x3, "verify step out variable")
- self.assertGreaterEqual(line3, line1, "verify step out line")
- self.assertEqual(src1, src3, "verify step in source")
+ self.assertEqual(x1, x2 + 1, "verify step in variable")
+ self.assertLess(line2, line1, "verify step in line")
+ self.assertEqual(src1, src2, "verify step in source")
- # Step over and verify
- self.stepOver(threadId=tid, waitForStop=True)
- x4 = self.get_local_as_int("x", threadId=tid)
- (src4, line4) = self.get_source_and_line(threadId=tid)
- self.assertEqual(x4, x3, "verify step over variable")
- self.assertGreater(line4, line3, "verify step over line")
- self.assertEqual(src1, src4, "verify step over source")
+ # Now step out and verify.
+ thread.step_out()
+ top_frame = thread.top_frame()
+ x3 = top_frame.locals["x"].value_as_int
+ (src3, line3) = top_frame.source_and_line()
+ self.assertEqual(x1, x3, "verify step out variable")
+ self.assertGreaterEqual(line3, line1, "verify step out line")
+ self.assertEqual(src1, src3, "verify step in source")
- # Step a single assembly instruction.
- # Unfortunately, there is no portable way to verify the correct
- # stepping behavior here, because the generated assembly code
- # depends highly on the compiler, its version, the operating
- # system, and many more factors.
- self.stepOver(
- threadId=tid, waitForStop=True, granularity="instruction"
- )
- self.stepIn(
- threadId=tid, waitForStop=True, granularity="instruction"
- )
+ # Step over and verify.
+ thread.step_over()
+ top_frame = thread.top_frame()
+ x4 = top_frame.locals["x"].value_as_int
+ (src4, line4) = top_frame.source_and_line()
+ self.assertEqual(x4, x3, "verify step over variable")
+ self.assertGreater(line4, line3, "verify step over line")
+ self.assertEqual(src1, src4, "verify step over source")
- # only step one thread that is at the breakpoint and stop
- break
+ # Step a single assembly instruction.
+ # Unfortunately, there is no portable way to verify the correct
+ # stepping behavior here, because the generated assembly code
+ # depends highly on the compiler, its version, the operating
+ # system, and many more factors.
+ thread.step_over(granularity="instruction")
+ thread.step_in(granularity="instruction")
def test_step_over_inlined_function(self):
"""
Test stepping over when the program counter is in another file.
"""
program = self.getBuildArtifact("a.out")
- self.build_and_launch(program)
- source = "main.cpp"
+ session = self.build_and_create_session()
+ source = self.getSourcePath("main.cpp")
+
breakpoint_lines = [line_number(source, "// breakpoint 2")]
step_over_pos = line_number(source, "// position_after_step_over")
- breakpoint_ids = self.set_source_breakpoints(source, breakpoint_lines)
- self.assertEqual(
- len(breakpoint_ids),
- len(breakpoint_lines),
- "expect correct number of breakpoints.",
- )
- self.continue_to_breakpoints(breakpoint_ids)
+ with session.configure(LaunchArgs(program)) as ctx:
+ session.resolve_source_breakpoints(source, breakpoint_lines)
+ process_event = ctx.process_event
+ stop_event = session.verify_stopped_on_breakpoint(after=process_event)
- thread_id = self.dap_server.get_thread_id()
- self.stepOver(thread_id)
+ thread_ctx = session.thread_context_from(stop_event)
+ thread_ctx.step_over()
levels = 1
- frames = self.get_stackFrames(thread_id, 0, levels)
+ frames = thread_ctx.frames(startFrame=0, levels=levels)
self.assertEqual(len(frames), levels, "expect current number of frame levels.")
- top_frame = frames[0]
+
+ top_frame = frames[0].frame
+ top_frame_source = self.expect_not_none(top_frame.source)
self.assertEqual(
- top_frame["source"]["name"], source, "expect we are in the same file."
+ top_frame_source.name, source, "expect we are in the same file."
)
+ top_frame_path = self.expect_not_none(top_frame_source.path)
self.assertTrue(
- top_frame["source"]["path"].endswith(source),
+ top_frame_path.endswith(source),
f"expect path ending with '{source}'.",
)
self.assertEqual(
- top_frame["line"],
+ top_frame.line,
step_over_pos,
f"expect step_over on line {step_over_pos}",
)
- self.continue_to_exit()
+ session.continue_to_exit()
diff --git a/lldb/test/API/tools/lldb-dap/stepInTargets/TestDAP_stepInTargets.py b/lldb/test/API/tools/lldb-dap/stepInTargets/TestDAP_stepInTargets.py
index 03b79a805d341..ee6b3ccb0511c 100644
--- a/lldb/test/API/tools/lldb-dap/stepInTargets/TestDAP_stepInTargets.py
+++ b/lldb/test/API/tools/lldb-dap/stepInTargets/TestDAP_stepInTargets.py
@@ -2,14 +2,13 @@
Test lldb-dap stepInTargets request
"""
-import dap_server
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-import lldbdap_testcase
-from lldbsuite.test import lldbutil
+from lldbsuite.test.decorators import expectedFailureAll, no_match, skipIf
+from lldbsuite.test.lldbtest import line_number
+from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase
+from lldbsuite.test.tools.lldb_dap.types import LaunchArgs, StepInTargetsArgs
-class TestDAP_stepInTargets(lldbdap_testcase.DAPTestCaseBase):
+class TestDAP_stepInTargets(DAPTestCaseBase):
@expectedFailureAll(oslist=["windows"])
@skipIf(archs=no_match(["x86_64"]))
# InstructionControlFlowKind for ARM is not supported yet.
@@ -20,40 +19,23 @@ def test_basic(self):
Tests the basic stepping in targets with directly calls.
"""
program = self.getBuildArtifact("a.out")
- self.build_and_launch(program)
- source = "main.cpp"
+ session = self.build_and_create_session()
+ source = self.getSourcePath("main.cpp")
breakpoint_line = line_number(source, "// set breakpoint here")
- lines = [breakpoint_line]
- # Set breakpoint in the thread function so we can step the threads
- 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)
-
- threads = self.dap_server.get_threads()
- self.assertEqual(len(threads), 1, "expect one thread")
- tid = threads[0]["id"]
+ # Set breakpoint in the thread function so we can step the threads.
+ with session.configure(LaunchArgs(program)) as ctx:
+ [bp1] = session.resolve_source_breakpoints(source, [breakpoint_line])
+ stop_event = session.verify_stopped_on_breakpoint(bp1, after=ctx.process_event)
- leaf_frame = self.dap_server.get_stackFrame()
- self.assertIsNotNone(leaf_frame, "expect a leaf frame")
+ thread_ctxs = session.thread_context_from(stop_event)
+ frame_id = thread_ctxs.top_frame().frame.id
# Request all step in targets list and verify the response.
- step_in_targets_response = self.dap_server.request_stepInTargets(
- leaf_frame["id"]
- )
- self.assertEqual(step_in_targets_response["success"], True, "expect success")
- self.assertIn(
- "body", step_in_targets_response, "expect body field in response body"
- )
- self.assertIn(
- "targets",
- step_in_targets_response["body"],
- "expect targets field in response body",
- )
+ step_args = StepInTargetsArgs(frame_id)
+ step_in_targets_resp = session.send_request(step_args).result("expect success")
+ step_in_targets = step_in_targets_resp.body.targets
- step_in_targets = step_in_targets_response["body"]["targets"]
self.assertEqual(len(step_in_targets), 3, "expect 3 step in targets")
# Verify the target names are correct.
@@ -61,70 +43,54 @@ def test_basic(self):
funcA_target = None
funcB_target = None
for target in step_in_targets[0:2]:
- if "funcB" in target["label"]:
+ if "funcB" in target.label:
funcB_target = target
- elif "funcA" in target["label"]:
+ elif "funcA" in target.label:
funcA_target = target
else:
self.fail(f"Unexpected step in target: {target}")
self.assertIsNotNone(funcA_target, "expect funcA")
self.assertIsNotNone(funcB_target, "expect funcB")
- self.assertIn("foo", step_in_targets[2]["label"], "expect foo")
+ self.assertIn("foo", step_in_targets[2].label, "expect foo")
# Choose to step into second target and verify that we are in the second target,
# be it funcA or funcB.
- self.stepIn(threadId=tid, targetId=step_in_targets[1]["id"], waitForStop=True)
- leaf_frame = self.dap_server.get_stackFrame()
- self.assertIsNotNone(leaf_frame, "expect a leaf frame")
- self.assertEqual(step_in_targets[1]["label"], leaf_frame["name"])
+ thread_ctxs.step_in(targetId=step_in_targets[1].id)
+ top_frame = thread_ctxs.top_frame().frame
+ self.assertIsNotNone(top_frame, "expect a top frame")
+ self.assertEqual(step_in_targets[1].label, top_frame.name)
+
+ session.continue_to_exit()
@skipIf(archs=no_match(["x86", "x86_64"]))
def test_supported_capability_x86_arch(self):
program = self.getBuildArtifact("a.out")
- self.build_and_launch(program)
- source = "main.cpp"
+ source = self.getSourcePath("main.cpp")
+ session = self.build_and_create_session()
bp_lines = [line_number(source, "// set breakpoint here")]
- breakpoint_ids = self.set_source_breakpoints(source, bp_lines)
- self.assertEqual(
- len(breakpoint_ids), len(bp_lines), "expect correct number of breakpoints"
- )
- self.continue_to_breakpoints(breakpoint_ids)
- is_supported = self.dap_server.get_capability("supportsStepInTargetsRequest")
+ with session.configure(LaunchArgs(program)) as ctx:
+ session.resolve_source_breakpoints(source, bp_lines)
- self.assertEqual(
- is_supported,
- True,
+ session.verify_stopped_on_breakpoint(after=ctx.process_event)
+ self.assertTrue(
+ session.capabilities().supportsStepInTargetsRequest,
f"expect capability `stepInTarget` is supported with architecture {self.getArchitecture()}",
)
- # clear breakpoints.
- self.set_source_breakpoints(source, [])
- self.continue_to_exit()
+ session.continue_to_exit()
@skipIf(archs=["x86", "x86_64"])
def test_supported_capability_other_archs(self):
- program = self.getBuildArtifact("a.out")
- self.build_and_launch(program)
- source = "main.cpp"
+ program = self.getBuildArtifact("main.cpp")
+ source = self.getSourcePath("main.cpp")
+ session = self.build_and_create_session()
bp_lines = [line_number(source, "// set breakpoint here")]
- breakpoint_ids = self.set_source_breakpoints(source, bp_lines)
- self.assertEqual(
- len(breakpoint_ids), len(bp_lines), "expect correct number of breakpoints"
- )
- self.continue_to_breakpoints(breakpoint_ids)
-
- try:
- is_supported = self.dap_server.get_capability(
- "supportsStepInTargetsRequest"
- )
- except dap_server.NotSupportedError:
- is_supported = False
+ with session.configure(LaunchArgs(program)) as ctx:
+ session.resolve_source_breakpoints(source, bp_lines)
- self.assertEqual(
- is_supported,
- False,
+ session.verify_stopped_on_breakpoint(after=ctx.process_event)
+ self.assertFalse(
+ session.capabilities().supportsStepInTargetsRequest,
f"expect capability `stepInTarget` is not supported with architecture {self.getArchitecture()}",
)
- # clear breakpoints.
- self.set_source_breakpoints(source, [])
- self.continue_to_exit()
+ session.continue_to_exit()
diff --git a/lldb/test/API/tools/lldb-dap/stop-hooks/TestDAP_stop_hooks.py b/lldb/test/API/tools/lldb-dap/stop-hooks/TestDAP_stop_hooks.py
index d630e1d14c3a0..c8b1386e15927 100644
--- a/lldb/test/API/tools/lldb-dap/stop-hooks/TestDAP_stop_hooks.py
+++ b/lldb/test/API/tools/lldb-dap/stop-hooks/TestDAP_stop_hooks.py
@@ -2,25 +2,27 @@
Test stop hooks
"""
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-import lldbdap_testcase
+from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase
+from lldbsuite.test.tools.lldb_dap.types import LaunchArgs
-class TestDAP_stop_hooks(lldbdap_testcase.DAPTestCaseBase):
+class TestDAP_stop_hooks(DAPTestCaseBase):
def test_stop_hooks_before_run(self):
"""
Test that there is no race condition between lldb-dap and
stop hooks executor
"""
program = self.getBuildArtifact("a.out")
- preRunCommands = ["target stop-hook add -o help"]
- self.build_and_launch(program, preRunCommands=preRunCommands)
- breakpoint_ids = self.set_function_breakpoints(["main"])
+ session = self.build_and_create_session()
+ launch_args = LaunchArgs(
+ program, preRunCommands=["target stop-hook add -o help"]
+ )
+ with session.configure(launch_args) as ctx:
+ breakpoint_ids = session.resolve_function_breakpoints(["main"])
# This request hangs if the race happens, because, in that case, the
# command interpreter is in synchronous mode while lldb-dap expects
# it to be in asynchronous mode, so, the process doesn't send the stop
# event to "lldb.Debugger" listener (which is monitored by lldb-dap).
- self.continue_to_breakpoints(breakpoint_ids)
+ session.verify_stopped_on_breakpoint(breakpoint_ids, after=ctx.process_event)
- self.continue_to_exit()
+ session.continue_to_exit()
More information about the lldb-commits
mailing list