| """ |
| Test thread until with inlined functions. |
| """ |
| |
| import lldb |
| from lldbsuite.test.decorators import * |
| from lldbsuite.test.lldbtest import * |
| from lldbsuite.test import lldbutil |
| |
| |
| class TestInlineFrameUntil(TestBase): |
| NO_DEBUG_INFO_TESTCASE = True |
| |
| def run_to_sink(self): |
| self.build() |
| _, _, thread, _ = lldbutil.run_to_name_breakpoint(self, "sink") |
| return thread |
| |
| def until_from_frame(self, frame_idx, marker): |
| thread = self.run_to_sink() |
| self.runCmd(f"thread until -f {frame_idx} {line_number('main.c', marker)}") |
| return thread.GetFrameAtIndex(0) |
| |
| def check_stops_at(self, frame_idx, marker): |
| frame = self.until_from_frame(frame_idx, marker) |
| self.assertEqual(frame.GetLineEntry().GetLine(), line_number("main.c", marker)) |
| |
| def check_rejected(self, frame_idx, marker): |
| self.run_to_sink() |
| self.expect( |
| f"thread until -f {frame_idx} {line_number('main.c', marker)}", |
| error=True, |
| substrs=["Until target outside of the current function"], |
| ) |
| |
| def test_until_in_same_inline_frame(self): |
| self.check_stops_at(1, "// until in level3") |
| |
| def test_until_in_parent_inline_frame(self): |
| self.check_stops_at(2, "// until in level2") |
| |
| def test_until_in_inlining_caller(self): |
| self.check_rejected(1, "// until in level2") |
| |
| def test_until_in_inlined_callee(self): |
| self.check_rejected(2, "// until in level3") |
| |
| def test_step_over_until_in_inlining_caller(self): |
| thread = self.run_to_sink() |
| error = thread.StepOverUntil( |
| thread.GetFrameAtIndex(1), |
| lldb.SBFileSpec("main.c"), |
| line_number("main.c", "// until in level2"), |
| ) |
| self.assertIn( |
| "Until target outside of the current function", error.GetCString() |
| ) |