"""
Test that we page getting a long backtrace on more than one thread
"""
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestThreadBacktracePage(TestBase):
NO_DEBUG_INFO_TESTCASE = True
def test_thread_backtrace_one_thread(self):
"""Run a simplified version of the test that just hits one breakpoint and
doesn't care about synchronizing the two threads - hopefully this will
run on more systems."""
self.build()
(
self.inferior_target,
self.process,
thread,
bkpt,
) = lldbutil.run_to_source_breakpoint(
self, self.bkpt_string, lldb.SBFileSpec("main.cpp"), only_one_thread=False
)
(breakpoint_threads, other_threads) = ([], [])
lldbutil.sort_stopped_threads(
self.process,
breakpoint_threads=breakpoint_threads,
other_threads=other_threads,
)
self.assertGreater(
len(breakpoint_threads), 0, "We hit at least one breakpoint thread"
)
self.assertGreater(len(breakpoint_threads[0].frames), 2, "I can go up")
thread_id = breakpoint_threads[0].idx
name = breakpoint_threads[0].frame[1].name.split("(")[0]
self.check_one_thread(thread_id, name)
def setUp(self):
TestBase.setUp(self)
self.bkpt_string = "// Set breakpoint here"
def check_one_thread(self, thread_id, func_name):
interp = self.dbg.GetCommandInterpreter()
result = lldb.SBCommandReturnObject()
interp.HandleCommand(
"thread backtrace --count 10 {0}".format(thread_id), result, True
)
self.assertTrue(result.Succeeded(), "bt with count succeeded")
lines = result.GetOutput().splitlines()
self.assertEqual(len(lines), 11, "Got the right number of lines")
self.assertNotEqual(lines[1].find("stop_here"), -1, "Found Stop Here")
for line in lines[2:10]:
self.assertNotEqual(
line.find(func_name),
-1,
"Name {0} not found in line: {1}".format(func_name, line),
)
self.assertNotEqual(lines[10].find("count=43"), -1, "First show ends at 43")
interp.HandleCommand("", result, True)
self.assertTrue(
result.Succeeded(), "repeat command failed: {0}".format(result.GetError())
)
lines = result.GetOutput().splitlines()
self.assertEqual(len(lines), 11, "Repeat got 11 lines")
for line in lines[1:10]:
self.assertNotEqual(line.find(func_name), -1, "Name in every line")
self.assertNotEqual(lines[10].find("count=33"), -1, "Last one is now 33")
def check_two_threads(
self, result_str, thread_id_1, name_1, thread_id_2, name_2, start_idx, end_idx
):
self.assertEqual(
result_str.count("thread #{0}".format(thread_id_1)), 1, "One for thread 1"
)
self.assertEqual(
result_str.count("thread #{0}".format(thread_id_2)), 1, "One for thread 2"
)
self.assertEqual(result_str.count(name_1), 10, "Found 10 of {0}".format(name_1))
self.assertEqual(result_str.count(name_2), 10, "Found 10 of {0}".format(name_1))
self.assertEqual(
result_str.count("count={0}".format(start_idx)),
2,
"Two instances of start_idx",
)
self.assertEqual(
result_str.count("count={0}".format(start_idx - 1)),
0,
"No instances of start_idx - 1",
)
self.assertEqual(
result_str.count("count={0}".format(end_idx)), 2, "Two instances of end_idx"
)
self.assertEqual(
result_str.count("count={0}".format(end_idx + 1)),
0,
"No instances after end idx",
)
@skipIfWindows
@expectedFailureAll(oslist=["windows"])
@expectedFailureNetBSD
def test_thread_backtrace_two_threads(self):
"""Test that repeat works even when backtracing on more than one thread."""
self.build()
(
self.inferior_target,
self.process,
thread,
bkpt,
) = lldbutil.run_to_source_breakpoint(
self, self.bkpt_string, lldb.SBFileSpec("main.cpp"), only_one_thread=False
)
(breakpoint_threads, other_threads) = ([], [])
lldbutil.sort_stopped_threads(
self.process,
breakpoint_threads=breakpoint_threads,
other_threads=other_threads,
)
if len(breakpoint_threads) == 1:
success = thread.Suspend()
self.assertTrue(success, "Couldn't suspend a thread")
breakpoint_threads = lldbutil.continue_to_breakpoint(self.process, bkpt)
self.assertEqual(len(breakpoint_threads), 2, "Second thread stopped")
thread_id_1 = breakpoint_threads[0].idx
self.assertGreater(len(breakpoint_threads[0].frames), 2, "I can go up")
name_1 = breakpoint_threads[0].frame[1].name.split("(")[0]
thread_id_2 = breakpoint_threads[1].idx
self.assertGreater(len(breakpoint_threads[1].frames), 2, "I can go up")
name_2 = breakpoint_threads[1].frame[1].name.split("(")[0]
self.check_one_thread(thread_id_1, name_1)
self.check_one_thread(thread_id_2, name_2)
interp = self.dbg.GetCommandInterpreter()
result = lldb.SBCommandReturnObject()
interp.HandleCommand(
"thread backtrace --count 10 --start 10 {0} {1}".format(
thread_id_1, thread_id_2
),
result,
True,
)
self.assertTrue(result.Succeeded(), "command succeeded for two threads")
result.Clear()
interp.HandleCommand("", result, True)
self.assertTrue(result.Succeeded(), "repeat command succeeded for two threads")
result_str = result.GetOutput()
self.check_two_threads(
result_str, thread_id_1, name_1, thread_id_2, name_2, 23, 32
)
result.Clear()
interp.HandleCommand("", result, True)
self.assertTrue(result.Succeeded(), "repeat command succeeded for two threads")
result_str = result.GetOutput()
self.check_two_threads(
result_str, thread_id_1, name_1, thread_id_2, name_2, 13, 22
)