| """ |
| Test the "process continue -b" option. |
| """ |
| |
| |
| import lldb |
| from lldbsuite.test.decorators import * |
| from lldbsuite.test.lldbtest import * |
| from lldbsuite.test import lldbutil |
| |
| |
| class TestContinueToBkpts(TestBase): |
| NO_DEBUG_INFO_TESTCASE = True |
| |
| @add_test_categories(["pyapi"]) |
| def test_continue_to_breakpoints(self): |
| """Test that the continue to breakpoints feature works correctly.""" |
| self.build() |
| self.do_test_continue_to_breakpoint() |
| |
| def setUp(self): |
| # Call super's setUp(). |
| TestBase.setUp(self) |
| self.main_source_spec = lldb.SBFileSpec("main.c") |
| |
| def continue_and_check(self, stop_list, bkpt_to_hit, loc_to_hit=0): |
| """Build up a command that will run a continue -b commands using the breakpoints on stop_list, and |
| ensure that we hit bkpt_to_hit. |
| If loc_to_hit is not 0, also verify that we hit that location.""" |
| command = "process continue" |
| for elem in stop_list: |
| command += " -b {0}".format(elem) |
| self.expect(command) |
| self.assertStopReason( |
| self.thread.stop_reason, lldb.eStopReasonBreakpoint, "Hit a breakpoint" |
| ) |
| self.assertEqual( |
| self.thread.GetStopReasonDataAtIndex(0), |
| bkpt_to_hit, |
| "Hit the right breakpoint", |
| ) |
| if loc_to_hit != 0: |
| self.assertEqual( |
| self.thread.GetStopReasonDataAtIndex(1), |
| loc_to_hit, |
| "Hit the right location", |
| ) |
| for bkpt_id in self.bkpt_list: |
| bkpt = self.target.FindBreakpointByID(bkpt_id) |
| self.assertTrue(bkpt.IsValid(), "Breakpoint id's round trip") |
| if bkpt.MatchesName("disabled"): |
| self.assertFalse( |
| bkpt.IsEnabled(), |
| "Disabled breakpoints stay disabled: {0}".format(bkpt.GetID()), |
| ) |
| else: |
| self.assertTrue( |
| bkpt.IsEnabled(), |
| "Enabled breakpoints stay enabled: {0}".format(bkpt.GetID()), |
| ) |
| # Also do our multiple location one: |
| bkpt = self.target.FindBreakpointByID(self.multiple_loc_id) |
| self.assertTrue(bkpt.IsValid(), "Breakpoint with locations round trip") |
| for i in range(1, 3): |
| loc = bkpt.FindLocationByID(i) |
| self.assertTrue(loc.IsValid(), "Locations round trip") |
| if i == 2: |
| self.assertTrue( |
| loc.IsEnabled(), "Locations that were enabled stay enabled" |
| ) |
| else: |
| self.assertFalse( |
| loc.IsEnabled(), "Locations that were disabled stay disabled" |
| ) |
| |
| def do_test_continue_to_breakpoint(self): |
| """Test the continue to breakpoint feature.""" |
| (self.target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint( |
| self, "Stop here to get started", self.main_source_spec |
| ) |
| |
| # Now set up all our breakpoints: |
| bkpt_pattern = "This is the {0} stop" |
| bkpt_elements = [ |
| "zeroth", |
| "first", |
| "second", |
| "third", |
| "fourth", |
| "fifth", |
| "sixth", |
| "seventh", |
| "eighth", |
| "nineth", |
| ] |
| disabled_bkpts = ["first", "eigth"] |
| bkpts_for_MyBKPT = ["first", "sixth", "nineth"] |
| self.bkpt_list = [] |
| for elem in bkpt_elements: |
| bkpt = self.target.BreakpointCreateBySourceRegex( |
| bkpt_pattern.format(elem), self.main_source_spec |
| ) |
| self.assertGreater(bkpt.GetNumLocations(), 0, "Found a bkpt match") |
| self.bkpt_list.append(bkpt.GetID()) |
| bkpt.AddName(elem) |
| if elem in disabled_bkpts: |
| bkpt.AddName("disabled") |
| bkpt.SetEnabled(False) |
| if elem in bkpts_for_MyBKPT: |
| bkpt.AddName("MyBKPT") |
| # Also make one that has several locations, so we can test locations: |
| mult_bkpt = self.target.BreakpointCreateBySourceRegex( |
| bkpt_pattern.format("(seventh|eighth|nineth)"), self.main_source_spec |
| ) |
| self.assertEqual(mult_bkpt.GetNumLocations(), 3, "Got three matches") |
| mult_bkpt.AddName("Locations") |
| # Disable all of these: |
| for i in range(1, 4): |
| loc = mult_bkpt.FindLocationByID(i) |
| self.assertTrue(loc.IsValid(), "Location {0} is valid".format(i)) |
| loc.SetEnabled(False) |
| self.assertFalse(loc.IsEnabled(), "Loc {0} wasn't disabled".format(i)) |
| self.multiple_loc_id = mult_bkpt.GetID() |
| |
| # First test out various error conditions |
| |
| # All locations of the multiple_loc_id are disabled, so running to this should be an error: |
| self.expect( |
| "process continue -b {0}".format(self.multiple_loc_id), |
| error=True, |
| msg="Running to a disabled breakpoint by number", |
| ) |
| |
| # Now re-enable the middle one so we can run to it: |
| loc = mult_bkpt.FindLocationByID(2) |
| loc.SetEnabled(True) |
| |
| self.expect( |
| "process continue -b {0}".format(self.bkpt_list[1]), |
| error=True, |
| msg="Running to a disabled breakpoint by number", |
| ) |
| self.expect( |
| "process continue -b {0}.1".format(self.bkpt_list[1]), |
| error=True, |
| msg="Running to a location of a disabled breakpoint", |
| ) |
| self.expect( |
| "process continue -b disabled", |
| error=True, |
| msg="Running to a disabled set of breakpoints", |
| ) |
| self.expect( |
| "process continue -b {0}.{1}".format(self.multiple_loc_id, 1), |
| error=True, |
| msg="Running to a disabled breakpoint location", |
| ) |
| self.expect( |
| "process continue -b {0}".format("THERE_ARE_NO_BREAKPOINTS_BY_THIS_NAME"), |
| error=True, |
| msg="Running to no such name", |
| ) |
| self.expect( |
| "process continue -b {0}".format(1000), |
| error=True, |
| msg="Running to no such breakpoint", |
| ) |
| self.expect( |
| "process continue -b {0}.{1}".format(self.multiple_loc_id, 1000), |
| error=True, |
| msg="Running to no such location", |
| ) |
| |
| # Now move forward, this time with breakpoint numbers. First time we don't skip other bkpts. |
| bkpt = self.bkpt_list[0] |
| self.continue_and_check([str(bkpt)], bkpt) |
| |
| # Now skip to the third stop, do it by name and supply one of the later breakpoints as well: |
| # This continue has to muck with the sync mode of the debugger, so let's make sure we |
| # put it back. First try if it was in sync mode: |
| orig_async = self.dbg.GetAsync() |
| self.dbg.SetAsync(True) |
| self.continue_and_check([bkpt_elements[2], bkpt_elements[7]], self.bkpt_list[2]) |
| after_value = self.dbg.GetAsync() |
| self.dbg.SetAsync(orig_async) |
| self.assertTrue(after_value, "Preserve async as True if it started that way") |
| |
| # Now try a name that has several breakpoints. |
| # This time I'm also going to check that we put the debugger async mode back if |
| # if was False to begin with: |
| self.dbg.SetAsync(False) |
| self.continue_and_check(["MyBKPT"], self.bkpt_list[6]) |
| after_value = self.dbg.GetAsync() |
| self.dbg.SetAsync(orig_async) |
| self.assertFalse(after_value, "Preserve async as False if it started that way") |
| |
| # Now let's run to a particular location. Also specify a breakpoint we've already hit: |
| self.continue_and_check( |
| [self.bkpt_list[0], self.multiple_loc_id], self.multiple_loc_id, 2 |
| ) |