262 lines · python
1"""2Test breakpoint conditions with 'breakpoint modify -c <expr> id'.3"""4 5import lldb6from lldbsuite.test.decorators import *7from lldbsuite.test.lldbtest import *8from lldbsuite.test import lldbutil9 10 11class BreakpointConditionsTestCase(TestBase):12 def test_breakpoint_condition_and_run_command(self):13 """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'."""14 self.build()15 self.breakpoint_conditions()16 17 def test_breakpoint_condition_inline_and_run_command(self):18 """Exercise breakpoint condition inline with 'breakpoint set'."""19 self.build()20 self.breakpoint_conditions(inline=True)21 22 def test_breakpoint_condition_and_run_command_language(self):23 """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'."""24 self.build()25 self.breakpoint_conditions(cpp=True)26 27 def test_breakpoint_condition_inline_and_run_command_language(self):28 """Exercise breakpoint condition inline with 'breakpoint set'."""29 self.build()30 self.breakpoint_conditions(inline=True, cpp=True)31 32 @add_test_categories(["pyapi"])33 def test_breakpoint_condition_and_python_api(self):34 """Use Python APIs to set breakpoint conditions."""35 self.build()36 self.breakpoint_conditions_python()37 38 @add_test_categories(["pyapi"])39 def test_breakpoint_invalid_condition_and_python_api(self):40 """Use Python APIs to set breakpoint conditions."""41 self.build()42 self.breakpoint_invalid_conditions_python()43 44 def setUp(self):45 # Call super's setUp().46 TestBase.setUp(self)47 # Find the line number to of function 'c'.48 self.line1 = line_number(49 "main.c", '// Find the line number of function "c" here.'50 )51 self.line2 = line_number(52 "main.c", "// Find the line number of c's parent call here."53 )54 55 def breakpoint_conditions(self, inline=False, cpp=False):56 """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'."""57 exe = self.getBuildArtifact("a.out")58 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)59 60 if cpp:61 condition = "&val != nullptr && val == 3"62 cmd_args = " -c '{}' -Y c++".format(condition)63 else:64 condition = "val == 3"65 cmd_args = "-c '{}'".format(condition)66 67 if inline:68 # Create a breakpoint by function name 'c' and set the condition.69 lldbutil.run_break_set_by_symbol(70 self,71 "c",72 extra_options=cmd_args,73 num_expected_locations=1,74 sym_exact=True,75 )76 else:77 # Create a breakpoint by function name 'c'.78 lldbutil.run_break_set_by_symbol(79 self, "c", num_expected_locations=1, sym_exact=True80 )81 82 # And set a condition on the breakpoint to stop on when 'val == 3'.83 self.runCmd("breakpoint modify " + cmd_args + " 1")84 85 # Now run the program.86 self.runCmd("run", RUN_SUCCEEDED)87 88 # The process should be stopped at this point.89 self.expect("process status", PROCESS_STOPPED, patterns=["Process .* stopped"])90 91 # 'frame variable --show-types val' should return 3 due to breakpoint condition.92 self.expect(93 "frame variable --show-types val",94 VARIABLES_DISPLAYED_CORRECTLY,95 startstr="(int) val = 3",96 )97 98 # Also check the hit count, which should be 3, by design.99 self.expect(100 "breakpoint list -f",101 BREAKPOINT_HIT_ONCE,102 substrs=[103 "resolved = 1",104 "Condition: {}".format(condition),105 "hit count = 1",106 ],107 )108 109 # The frame #0 should correspond to main.c:36, the executable statement110 # in function name 'c'. And the parent frame should point to111 # main.c:24.112 self.expect(113 "thread backtrace",114 STOPPED_DUE_TO_BREAKPOINT_CONDITION,115 # substrs = ["stop reason = breakpoint"],116 patterns=[117 "frame #0.*main.c:%d" % self.line1,118 "frame #1.*main.c:%d" % self.line2,119 ],120 )121 122 # Test that "breakpoint modify -c ''" clears the condition for the last123 # created breakpoint, so that when the breakpoint hits, val == 1.124 self.runCmd("process kill")125 self.runCmd("breakpoint modify -c ''")126 self.expect(127 "breakpoint list -f",128 BREAKPOINT_STATE_CORRECT,129 matching=False,130 substrs=["Condition:"],131 )132 133 # Now run the program again.134 self.runCmd("run", RUN_SUCCEEDED)135 136 # The process should be stopped at this point.137 self.expect("process status", PROCESS_STOPPED, patterns=["Process .* stopped"])138 139 # 'frame variable --show-types val' should return 1 since it is the first breakpoint hit.140 self.expect(141 "frame variable --show-types val",142 VARIABLES_DISPLAYED_CORRECTLY,143 startstr="(int) val = 1",144 )145 146 self.runCmd("process kill")147 148 def breakpoint_conditions_python(self):149 """Use Python APIs to set breakpoint conditions."""150 target = self.createTestTarget()151 152 # Now create a breakpoint on main.c by name 'c'.153 breakpoint = target.BreakpointCreateByName("c", "a.out")154 self.trace("breakpoint:", breakpoint)155 self.assertTrue(156 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT157 )158 159 # We didn't associate a thread index with the breakpoint, so it should160 # be invalid.161 self.assertEqual(162 breakpoint.GetThreadIndex(),163 lldb.UINT32_MAX,164 "The thread index should be invalid",165 )166 # The thread name should be invalid, too.167 self.assertIsNone(168 breakpoint.GetThreadName(), "The thread name should be invalid"169 )170 171 # Let's set the thread index for this breakpoint and verify that it is,172 # indeed, being set correctly.173 # There's only one thread for the process.174 breakpoint.SetThreadIndex(1)175 self.assertEqual(176 breakpoint.GetThreadIndex(), 1, "The thread index has been set correctly"177 )178 179 # Get the breakpoint location from breakpoint after we verified that,180 # indeed, it has one location.181 location = breakpoint.GetLocationAtIndex(0)182 self.assertTrue(location and location.IsEnabled(), VALID_BREAKPOINT_LOCATION)183 184 # Set the condition on the breakpoint location.185 location.SetCondition("val == 3")186 self.expect(location.GetCondition(), exe=False, startstr="val == 3")187 188 # Now launch the process, and do not stop at entry point.189 process = target.LaunchSimple(None, None, self.get_process_working_directory())190 self.assertTrue(process, PROCESS_IS_VALID)191 192 # Frame #0 should be on self.line1 and the break condition should hold.193 from lldbsuite.test.lldbutil import get_stopped_thread194 195 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)196 self.assertTrue(197 thread.IsValid(),198 "There should be a thread stopped due to breakpoint condition",199 )200 201 frame0 = thread.GetFrameAtIndex(0)202 var = frame0.FindValue("val", lldb.eValueTypeVariableArgument)203 self.assertEqual(204 frame0.GetLineEntry().GetLine(),205 self.line1,206 "The debugger stopped on the correct line",207 )208 self.assertEqual(var.GetValue(), "3")209 210 # The hit count for the breakpoint should be 1.211 self.assertEqual(breakpoint.GetHitCount(), 1)212 213 # Test that the condition expression didn't create a result variable:214 options = lldb.SBExpressionOptions()215 value = frame0.EvaluateExpression("$0", options)216 self.assertTrue(217 value.GetError().Fail(), "Conditions should not make result variables."218 )219 process.Continue()220 221 def breakpoint_invalid_conditions_python(self):222 """Use Python APIs to set breakpoint conditions."""223 exe = self.getBuildArtifact("a.out")224 225 # Create a target by the debugger.226 target = self.dbg.CreateTarget(exe)227 self.assertTrue(target, VALID_TARGET)228 229 # Now create a breakpoint on main.c by name 'c'.230 breakpoint = target.BreakpointCreateByName("c", "a.out")231 self.trace("breakpoint:", breakpoint)232 self.assertTrue(233 breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT234 )235 236 # Set the condition on the breakpoint.237 breakpoint.SetCondition("no_such_variable == not_this_one_either")238 self.expect(239 breakpoint.GetCondition(),240 exe=False,241 startstr="no_such_variable == not_this_one_either",242 )243 244 # Now launch the process, and do not stop at entry point.245 process = target.LaunchSimple(None, None, self.get_process_working_directory())246 self.assertTrue(process, PROCESS_IS_VALID)247 248 # Frame #0 should be on self.line1 and the break condition should hold.249 from lldbsuite.test.lldbutil import get_stopped_thread250 251 thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)252 self.assertTrue(253 thread.IsValid(),254 "There should be a thread stopped due to breakpoint condition",255 )256 frame0 = thread.GetFrameAtIndex(0)257 var = frame0.FindValue("val", lldb.eValueTypeVariableArgument)258 self.assertEqual(frame0.GetLineEntry().GetLine(), self.line1)259 260 # The hit count for the breakpoint should be 1.261 self.assertEqual(breakpoint.GetHitCount(), 1)262