1""" 2Test breakpoint serialization. 3""" 4 5import os 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10 11 12class BreakpointSerialization(TestBase): 13 14 mydir = TestBase.compute_mydir(__file__) 15 NO_DEBUG_INFO_TESTCASE = True 16 17 @add_test_categories(['pyapi']) 18 def test_resolvers(self): 19 """Use Python APIs to test that we serialize resolvers.""" 20 self.build() 21 self.setup_targets_and_cleanup() 22 self.do_check_resolvers() 23 24 def test_filters(self): 25 """Use Python APIs to test that we serialize search filters correctly.""" 26 self.build() 27 self.setup_targets_and_cleanup() 28 self.do_check_filters() 29 30 def test_options(self): 31 """Use Python APIs to test that we serialize breakpoint options correctly.""" 32 self.build() 33 self.setup_targets_and_cleanup() 34 self.do_check_options() 35 36 def test_appending(self): 37 """Use Python APIs to test that we serialize breakpoint options correctly.""" 38 self.build() 39 self.setup_targets_and_cleanup() 40 self.do_check_appending() 41 42 def test_name_filters(self): 43 """Use python APIs to test that reading in by name works correctly.""" 44 self.build() 45 self.setup_targets_and_cleanup() 46 self.do_check_names() 47 48 def test_scripted_extra_args(self): 49 self.build() 50 self.setup_targets_and_cleanup() 51 self.do_check_extra_args() 52 53 def setup_targets_and_cleanup(self): 54 def cleanup (): 55 self.RemoveTempFile(self.bkpts_file_path) 56 57 if self.orig_target.IsValid(): 58 self.dbg.DeleteTarget(self.orig_target) 59 self.dbg.DeleteTarget(self.copy_target) 60 61 self.addTearDownHook(cleanup) 62 self.RemoveTempFile(self.bkpts_file_path) 63 64 exe = self.getBuildArtifact("a.out") 65 66 # Create the targets we are making breakpoints in and copying them to: 67 self.orig_target = self.dbg.CreateTarget(exe) 68 self.assertTrue(self.orig_target, VALID_TARGET) 69 70 self.copy_target = self.dbg.CreateTarget(exe) 71 self.assertTrue(self.copy_target, VALID_TARGET) 72 73 def setUp(self): 74 # Call super's setUp(). 75 TestBase.setUp(self) 76 77 self.bkpts_file_path = self.getBuildArtifact("breakpoints.json") 78 self.bkpts_file_spec = lldb.SBFileSpec(self.bkpts_file_path) 79 80 def check_equivalence(self, source_bps, do_write = True): 81 82 error = lldb.SBError() 83 84 if (do_write): 85 error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps) 86 self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString())) 87 88 copy_bps = lldb.SBBreakpointList(self.copy_target) 89 error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps) 90 self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString())) 91 92 num_source_bps = source_bps.GetSize() 93 num_copy_bps = copy_bps.GetSize() 94 self.assertTrue(num_source_bps == num_copy_bps, "Didn't get same number of input and output breakpoints - orig: %d copy: %d"%(num_source_bps, num_copy_bps)) 95 96 for i in range(0, num_source_bps): 97 source_bp = source_bps.GetBreakpointAtIndex(i) 98 source_desc = lldb.SBStream() 99 source_bp.GetDescription(source_desc, False) 100 source_text = source_desc.GetData() 101 102 # I am assuming here that the breakpoints will get written out in breakpoint ID order, and 103 # read back in ditto. That is true right now, and I can't see any reason to do it differently 104 # but if we do we can go to writing the breakpoints one by one, or sniffing the descriptions to 105 # see which one is which. 106 copy_id = source_bp.GetID() 107 copy_bp = copy_bps.FindBreakpointByID(copy_id) 108 self.assertTrue(copy_bp.IsValid(), "Could not find copy breakpoint %d."%(copy_id)) 109 110 copy_desc = lldb.SBStream() 111 copy_bp.GetDescription(copy_desc, False) 112 copy_text = copy_desc.GetData() 113 114 # These two should be identical. 115 # print ("Source text for %d is %s."%(i, source_text)) 116 self.assertTrue (source_text == copy_text, "Source and dest breakpoints are not identical: \nsource: %s\ndest: %s"%(source_text, copy_text)) 117 118 def do_check_resolvers(self): 119 """Use Python APIs to check serialization of breakpoint resolvers""" 120 121 empty_module_list = lldb.SBFileSpecList() 122 empty_cu_list = lldb.SBFileSpecList() 123 blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) 124 125 # It isn't actually important for these purposes that these breakpoint 126 # actually have locations. 127 source_bps = lldb.SBBreakpointList(self.orig_target) 128 source_bps.Append(self.orig_target.BreakpointCreateByLocation("blubby.c", 666)) 129 # Make sure we do one breakpoint right: 130 self.check_equivalence(source_bps) 131 source_bps.Clear() 132 133 source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list)) 134 source_bps.Append(self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list)) 135 source_bps.Append(self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec)) 136 137 # And some number greater than one: 138 self.check_equivalence(source_bps) 139 140 def do_check_filters(self): 141 """Use Python APIs to check serialization of breakpoint filters.""" 142 module_list = lldb.SBFileSpecList() 143 module_list.Append(lldb.SBFileSpec("SomeBinary")) 144 module_list.Append(lldb.SBFileSpec("SomeOtherBinary")) 145 146 cu_list = lldb.SBFileSpecList() 147 cu_list.Append(lldb.SBFileSpec("SomeCU.c")) 148 cu_list.Append(lldb.SBFileSpec("AnotherCU.c")) 149 cu_list.Append(lldb.SBFileSpec("ThirdCU.c")) 150 151 blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) 152 153 # It isn't actually important for these purposes that these breakpoint 154 # actually have locations. 155 source_bps = lldb.SBBreakpointList(self.orig_target) 156 bkpt = self.orig_target.BreakpointCreateByLocation(blubby_file_spec, 666, 0, module_list) 157 source_bps.Append(bkpt) 158 159 # Make sure we do one right: 160 self.check_equivalence(source_bps) 161 source_bps.Clear() 162 163 bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, module_list, cu_list) 164 source_bps.Append(bkpt) 165 bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, module_list, cu_list) 166 source_bps.Append(bkpt) 167 bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec) 168 source_bps.Append(bkpt) 169 170 # And some number greater than one: 171 self.check_equivalence(source_bps) 172 173 def do_check_options(self): 174 """Use Python APIs to check serialization of breakpoint options.""" 175 176 empty_module_list = lldb.SBFileSpecList() 177 empty_cu_list = lldb.SBFileSpecList() 178 blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) 179 180 # It isn't actually important for these purposes that these breakpoint 181 # actually have locations. 182 source_bps = lldb.SBBreakpointList(self.orig_target) 183 184 bkpt = self.orig_target.BreakpointCreateByLocation( 185 lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) 186 bkpt.SetEnabled(False) 187 bkpt.SetOneShot(True) 188 bkpt.SetThreadID(10) 189 source_bps.Append(bkpt) 190 191 # Make sure we get one right: 192 self.check_equivalence(source_bps) 193 source_bps.Clear() 194 195 bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list) 196 bkpt.SetIgnoreCount(10) 197 bkpt.SetThreadName("grubby") 198 source_bps.Append(bkpt) 199 200 bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list) 201 bkpt.SetCondition("gonna remove this") 202 bkpt.SetCondition("") 203 source_bps.Append(bkpt) 204 205 bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list) 206 bkpt.SetCondition("something != something_else") 207 bkpt.SetQueueName("grubby") 208 bkpt.AddName("FirstName") 209 bkpt.AddName("SecondName") 210 bkpt.SetScriptCallbackBody('\tprint("I am a function that prints.")\n\tprint("I don\'t do anything else")\n') 211 source_bps.Append(bkpt) 212 213 bkpt = self.orig_target.BreakpointCreateBySourceRegex("dont really care", blubby_file_spec) 214 cmd_list = lldb.SBStringList() 215 cmd_list.AppendString("frame var") 216 cmd_list.AppendString("thread backtrace") 217 218 bkpt.SetCommandLineCommands(cmd_list) 219 source_bps.Append(bkpt) 220 221 self.check_equivalence(source_bps) 222 223 def do_check_appending(self): 224 """Use Python APIs to check appending to already serialized options.""" 225 226 empty_module_list = lldb.SBFileSpecList() 227 empty_cu_list = lldb.SBFileSpecList() 228 blubby_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "blubby.c")) 229 230 # It isn't actually important for these purposes that these breakpoint 231 # actually have locations. 232 233 all_bps = lldb.SBBreakpointList(self.orig_target) 234 source_bps = lldb.SBBreakpointList(self.orig_target) 235 236 bkpt = self.orig_target.BreakpointCreateByLocation( 237 lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) 238 bkpt.SetEnabled(False) 239 bkpt.SetOneShot(True) 240 bkpt.SetThreadID(10) 241 source_bps.Append(bkpt) 242 all_bps.Append(bkpt) 243 244 error = lldb.SBError() 245 error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps) 246 self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString())) 247 248 source_bps.Clear() 249 250 bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeAuto, empty_module_list, empty_cu_list) 251 bkpt.SetIgnoreCount(10) 252 bkpt.SetThreadName("grubby") 253 source_bps.Append(bkpt) 254 all_bps.Append(bkpt) 255 256 bkpt = self.orig_target.BreakpointCreateByName("blubby", lldb.eFunctionNameTypeFull, empty_module_list,empty_cu_list) 257 bkpt.SetCondition("something != something_else") 258 bkpt.SetQueueName("grubby") 259 bkpt.AddName("FirstName") 260 bkpt.AddName("SecondName") 261 262 source_bps.Append(bkpt) 263 all_bps.Append(bkpt) 264 265 error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, source_bps, True) 266 self.assertTrue(error.Success(), "Failed appending breakpoints to file: %s."%(error.GetCString())) 267 268 self.check_equivalence(all_bps) 269 270 def do_check_names(self): 271 bkpt = self.orig_target.BreakpointCreateByLocation( 272 lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList()) 273 good_bkpt_name = "GoodBreakpoint" 274 write_bps = lldb.SBBreakpointList(self.orig_target) 275 bkpt.AddName(good_bkpt_name) 276 write_bps.Append(bkpt) 277 278 error = lldb.SBError() 279 error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps) 280 self.assertTrue(error.Success(), "Failed writing breakpoints to file: %s."%(error.GetCString())) 281 282 copy_bps = lldb.SBBreakpointList(self.copy_target) 283 names_list = lldb.SBStringList() 284 names_list.AppendString("NoSuchName") 285 286 error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps) 287 self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString())) 288 self.assertTrue(copy_bps.GetSize() == 0, "Found breakpoints with a nonexistent name.") 289 290 names_list.AppendString(good_bkpt_name) 291 error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, names_list, copy_bps) 292 self.assertTrue(error.Success(), "Failed reading breakpoints from file: %s"%(error.GetCString())) 293 self.assertTrue(copy_bps.GetSize() == 1, "Found the matching breakpoint.") 294 295 def do_check_extra_args(self): 296 297 import side_effect 298 interp = self.dbg.GetCommandInterpreter() 299 error = lldb.SBError() 300 301 script_name = os.path.join(self.getSourceDir(), "resolver.py") 302 303 command = "command script import " + script_name 304 result = lldb.SBCommandReturnObject() 305 interp.HandleCommand(command, result) 306 self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError())) 307 308 # First make sure a scripted breakpoint with no args works: 309 bkpt = self.orig_target.BreakpointCreateFromScript("resolver.Resolver", lldb.SBStructuredData(), 310 lldb.SBFileSpecList(), lldb.SBFileSpecList()) 311 self.assertTrue(bkpt.IsValid(), "Bkpt is valid") 312 write_bps = lldb.SBBreakpointList(self.orig_target) 313 314 error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps) 315 self.assertTrue(error.Success(), "Failed writing breakpoints: %s"%(error.GetCString())) 316 317 side_effect.g_extra_args = None 318 copy_bps = lldb.SBBreakpointList(self.copy_target) 319 error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps) 320 self.assertTrue(error.Success(), "Failed reading breakpoints: %s"%(error.GetCString())) 321 322 self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.") 323 no_keys = lldb.SBStringList() 324 side_effect.g_extra_args.GetKeys(no_keys) 325 self.assertEqual(no_keys.GetSize(), 0, "Should have no keys") 326 327 self.orig_target.DeleteAllBreakpoints() 328 self.copy_target.DeleteAllBreakpoints() 329 330 # Now try one with extra args: 331 332 extra_args = lldb.SBStructuredData() 333 stream = lldb.SBStream() 334 stream.Print('{"first_arg" : "first_value", "second_arg" : "second_value"}') 335 extra_args.SetFromJSON(stream) 336 self.assertTrue(extra_args.IsValid(), "SBStructuredData is valid.") 337 338 bkpt = self.orig_target.BreakpointCreateFromScript("resolver.Resolver", 339 extra_args, lldb.SBFileSpecList(), lldb.SBFileSpecList()) 340 self.assertTrue(bkpt.IsValid(), "Bkpt is valid") 341 write_bps = lldb.SBBreakpointList(self.orig_target) 342 343 error = self.orig_target.BreakpointsWriteToFile(self.bkpts_file_spec, write_bps) 344 self.assertTrue(error.Success(), "Failed writing breakpoints: %s"%(error.GetCString())) 345 346 orig_extra_args = side_effect.g_extra_args 347 self.assertTrue(orig_extra_args.IsValid(), "Extra args originally valid") 348 349 orig_keys = lldb.SBStringList() 350 orig_extra_args.GetKeys(orig_keys) 351 self.assertEqual(2, orig_keys.GetSize(), "Should have two keys") 352 353 side_effect.g_extra_args = None 354 355 copy_bps = lldb.SBBreakpointList(self.copy_target) 356 error = self.copy_target.BreakpointsCreateFromFile(self.bkpts_file_spec, copy_bps) 357 self.assertTrue(error.Success(), "Failed reading breakpoints: %s"%(error.GetCString())) 358 359 self.assertEqual(copy_bps.GetSize(), 1, "Got one breakpoint from file.") 360 361 copy_extra_args = side_effect.g_extra_args 362 copy_keys = lldb.SBStringList() 363 copy_extra_args.GetKeys(copy_keys) 364 self.assertEqual(2, copy_keys.GetSize(), "Copy should have two keys") 365 366 for idx in range(0, orig_keys.GetSize()): 367 key = orig_keys.GetStringAtIndex(idx) 368 copy_value = copy_extra_args.GetValueForKey(key).GetStringValue(100) 369 370 if key == "first_arg": 371 self.assertEqual(copy_value, "first_value") 372 elif key == "second_arg": 373 self.assertEqual(copy_value, "second_value") 374 else: 375 self.Fail("Unknown key: %s"%(key)) 376