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