blob: ab4e663318e4114e66ee6d24e9266ea6d3e947f0 [file]
"""
Test lldb-dap threads request
"""
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import line_number
from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase
from lldbsuite.test.tools.lldb_dap.types import LaunchArgs, StoppedReason, ThreadsArgs
@requireThreadSupport
class TestDAP_threads(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.
"""
session = self.build_and_create_session()
program = self.getBuildArtifact("a.out")
source = "main.cpp"
breakpoint_line = line_number(source, "// break here")
with session.configure(LaunchArgs(program)) as ctx:
breakpoint_ids = session.resolve_source_breakpoints(
source, [breakpoint_line]
)
first_stop = session.verify_stopped_on_breakpoint(after=ctx.process_event)
# 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.
second_stop = session.continue_to_next_stop(exp_reason=StoppedReason.BREAKPOINT)
self.assertNotEqual(
first_stop.body.threadId,
second_stop.body.threadId,
"the stopped events should be on different threads.",
)
# Verify that the description is the relevant breakpoint,
# preserveFocusHint is False and threadCausedFocus is True.
stop_description = self.expect_not_none(second_stop.body.description)
self.assertTrue(stop_description.startswith(f"breakpoint {breakpoint_ids[0]}"))
self.assertIsNone(second_stop.body.preserveFocusHint)
# All threads should have a name.
threads = session.send_request(ThreadsArgs()).result().body.threads
for t in threads:
self.assertTrue(t.name, "thread name should be non-empty")
session.continue_to_exit()
def test_thread_format(self):
"""Tests the support for custom thread formats."""
session = self.build_and_create_session()
program = self.getBuildArtifact("a.out")
source = "main.cpp"
breakpoint_line = line_number(source, "// break here")
with session.configure(
LaunchArgs(
program,
customThreadFormat="This is thread index #${thread.index}",
stopCommands=["thread list"],
)
) as ctx:
bp_ids = session.resolve_source_breakpoints(source, [breakpoint_line])
session.verify_stopped_on_breakpoint(bp_ids, after=ctx.process_event)
threads = session.send_request(ThreadsArgs()).result().body.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 = 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")
# Clear the breakpoint so the second thread doesn't hit it on the way out.
session.set_source_breakpoints(source, [])
session.continue_to_exit()