| """ | |
| Test that objective-c constant strings are generated correctly by the expression | |
| parser. | |
| """ | |
| import shutil | |
| import subprocess | |
| import lldb | |
| from lldbsuite.test.decorators import * | |
| from lldbsuite.test.lldbtest import * | |
| from lldbsuite.test import lldbutil | |
| class TestObjCBreakpoints(TestBase): | |
| SHARED_BUILD_TESTCASE = False | |
| @add_test_categories(["objc"]) | |
| def test_break(self): | |
| """Test setting Objective-C specific breakpoints (DWARF in .o files).""" | |
| self.build() | |
| self.setTearDownCleanup() | |
| self.check_objc_breakpoints(False) | |
| def setUp(self): | |
| # Call super's setUp(). | |
| TestBase.setUp(self) | |
| # Find the line number to break inside main(). | |
| self.main_source = "main.m" | |
| self.line = line_number(self.main_source, "// Set breakpoint here") | |
| def check_category_breakpoints(self): | |
| name_bp = self.target.BreakpointCreateByName("myCategoryFunction") | |
| selector_bp = self.target.BreakpointCreateByName( | |
| "myCategoryFunction", | |
| lldb.eFunctionNameTypeSelector, | |
| lldb.SBFileSpecList(), | |
| lldb.SBFileSpecList(), | |
| ) | |
| self.assertEqual( | |
| name_bp.GetNumLocations(), | |
| selector_bp.GetNumLocations(), | |
| 'Make sure setting a breakpoint by name "myCategoryFunction" sets a breakpoint even though it is in a category', | |
| ) | |
| for bp_loc in selector_bp: | |
| function_name = bp_loc.GetAddress().GetSymbol().GetName() | |
| self.assertIn( | |
| " myCategoryFunction]", | |
| function_name, | |
| 'Make sure all function names have " myCategoryFunction]" in their names', | |
| ) | |
| category_bp = self.target.BreakpointCreateByName( | |
| "-[MyClass(MyCategory) myCategoryFunction]" | |
| ) | |
| stripped_bp = self.target.BreakpointCreateByName( | |
| "-[MyClass myCategoryFunction]" | |
| ) | |
| stripped2_bp = self.target.BreakpointCreateByName( | |
| "[MyClass myCategoryFunction]" | |
| ) | |
| self.assertEqual( | |
| category_bp.GetNumLocations(), | |
| 1, | |
| "Make sure we can set a breakpoint using a full objective C function name with the category included (-[MyClass(MyCategory) myCategoryFunction])", | |
| ) | |
| self.assertEqual( | |
| stripped_bp.GetNumLocations(), | |
| 1, | |
| "Make sure we can set a breakpoint using a full objective C function name without the category included (-[MyClass myCategoryFunction])", | |
| ) | |
| self.assertEqual( | |
| stripped2_bp.GetNumLocations(), | |
| 1, | |
| "Make sure we can set a breakpoint using a full objective C function name without the category included ([MyClass myCategoryFunction])", | |
| ) | |
| def check_objc_breakpoints(self, have_dsym): | |
| """Test constant string generation amd comparison by the expression parser.""" | |
| # Set debugger into synchronous mode | |
| self.dbg.SetAsync(False) | |
| # Create a target by the debugger. | |
| exe = self.getBuildArtifact("a.out") | |
| self.target = self.dbg.CreateTarget(exe) | |
| self.assertTrue(self.target, VALID_TARGET) | |
| # ---------------------------------------------------------------------- | |
| # Set breakpoints on all selectors whose name is "count". This should | |
| # catch breakpoints that are both C functions _and_ anything whose | |
| # selector is "count" because just looking at "count" we can't tell | |
| # definitively if the name is a selector or a C function | |
| # ---------------------------------------------------------------------- | |
| name_bp = self.target.BreakpointCreateByName("count") | |
| selector_bp = self.target.BreakpointCreateByName( | |
| "count", | |
| lldb.eFunctionNameTypeSelector, | |
| lldb.SBFileSpecList(), | |
| lldb.SBFileSpecList(), | |
| ) | |
| self.assertGreaterEqual( | |
| name_bp.GetNumLocations(), | |
| selector_bp.GetNumLocations(), | |
| 'Make sure we get at least the same amount of breakpoints if not more when setting by name "count"', | |
| ) | |
| self.assertGreater( | |
| selector_bp.GetNumLocations(), | |
| 50, | |
| 'Make sure we find a lot of "count" selectors', | |
| ) # There are 93 on the latest MacOSX | |
| for bp_loc in selector_bp: | |
| function_name = bp_loc.GetAddress().GetSymbol().GetName() | |
| self.assertIn( | |
| " count]", | |
| function_name, | |
| 'Make sure all function names have " count]" in their names', | |
| ) | |
| # ---------------------------------------------------------------------- | |
| # Set breakpoints on all selectors whose name is "isEqual:". This should | |
| # catch breakpoints that are only ObjC selectors because no C function | |
| # can end with a : | |
| # ---------------------------------------------------------------------- | |
| name_bp = self.target.BreakpointCreateByName("isEqual:") | |
| selector_bp = self.target.BreakpointCreateByName( | |
| "isEqual:", | |
| lldb.eFunctionNameTypeSelector, | |
| lldb.SBFileSpecList(), | |
| lldb.SBFileSpecList(), | |
| ) | |
| self.assertEqual( | |
| name_bp.GetNumLocations(), | |
| selector_bp.GetNumLocations(), | |
| 'Make sure setting a breakpoint by name "isEqual:" only sets selector breakpoints', | |
| ) | |
| for bp_loc in selector_bp: | |
| function_name = bp_loc.GetAddress().GetSymbol().GetName() | |
| self.assertIn( | |
| " isEqual:]", | |
| function_name, | |
| 'Make sure all function names have " isEqual:]" in their names', | |
| ) | |
| self.check_category_breakpoints() | |
| if have_dsym: | |
| shutil.rmtree(exe + ".dSYM") | |
| self.assertEqual( | |
| subprocess.call(["/usr/bin/strip", "-Sx", exe]), | |
| 0, | |
| "stripping dylib succeeded", | |
| ) | |
| # Check breakpoints again, this time using the symbol table only | |
| self.check_category_breakpoints() |