xref: /llvm-project/lldb/test/API/functionalities/breakpoint/objc/TestObjCBreakpoints.py (revision 9c2468821ec51defd09c246fea4a47886fff8c01)
1"""
2Test that objective-c constant strings are generated correctly by the expression
3parser.
4"""
5
6
7import shutil
8import subprocess
9import lldb
10from lldbsuite.test.decorators import *
11from lldbsuite.test.lldbtest import *
12from lldbsuite.test import lldbutil
13
14
15class TestObjCBreakpoints(TestBase):
16    @add_test_categories(["objc"])
17    def test_break(self):
18        """Test setting Objective-C specific breakpoints (DWARF in .o files)."""
19        self.build()
20        self.setTearDownCleanup()
21        self.check_objc_breakpoints(False)
22
23    def setUp(self):
24        # Call super's setUp().
25        TestBase.setUp(self)
26        # Find the line number to break inside main().
27        self.main_source = "main.m"
28        self.line = line_number(self.main_source, "// Set breakpoint here")
29
30    def check_category_breakpoints(self):
31        name_bp = self.target.BreakpointCreateByName("myCategoryFunction")
32        selector_bp = self.target.BreakpointCreateByName(
33            "myCategoryFunction",
34            lldb.eFunctionNameTypeSelector,
35            lldb.SBFileSpecList(),
36            lldb.SBFileSpecList(),
37        )
38        self.assertEqual(
39            name_bp.GetNumLocations(),
40            selector_bp.GetNumLocations(),
41            'Make sure setting a breakpoint by name "myCategoryFunction" sets a breakpoint even though it is in a category',
42        )
43        for bp_loc in selector_bp:
44            function_name = bp_loc.GetAddress().GetSymbol().GetName()
45            self.assertIn(
46                " myCategoryFunction]",
47                function_name,
48                'Make sure all function names have " myCategoryFunction]" in their names',
49            )
50
51        category_bp = self.target.BreakpointCreateByName(
52            "-[MyClass(MyCategory) myCategoryFunction]"
53        )
54        stripped_bp = self.target.BreakpointCreateByName(
55            "-[MyClass myCategoryFunction]"
56        )
57        stripped2_bp = self.target.BreakpointCreateByName(
58            "[MyClass myCategoryFunction]"
59        )
60        self.assertEqual(
61            category_bp.GetNumLocations(),
62            1,
63            "Make sure we can set a breakpoint using a full objective C function name with the category included (-[MyClass(MyCategory) myCategoryFunction])",
64        )
65        self.assertEqual(
66            stripped_bp.GetNumLocations(),
67            1,
68            "Make sure we can set a breakpoint using a full objective C function name without the category included (-[MyClass myCategoryFunction])",
69        )
70        self.assertEqual(
71            stripped2_bp.GetNumLocations(),
72            1,
73            "Make sure we can set a breakpoint using a full objective C function name without the category included ([MyClass myCategoryFunction])",
74        )
75
76    def check_objc_breakpoints(self, have_dsym):
77        """Test constant string generation amd comparison by the expression parser."""
78
79        # Set debugger into synchronous mode
80        self.dbg.SetAsync(False)
81
82        # Create a target by the debugger.
83        exe = self.getBuildArtifact("a.out")
84        self.target = self.dbg.CreateTarget(exe)
85        self.assertTrue(self.target, VALID_TARGET)
86
87        # ----------------------------------------------------------------------
88        # Set breakpoints on all selectors whose name is "count". This should
89        # catch breakpoints that are both C functions _and_ anything whose
90        # selector is "count" because just looking at "count" we can't tell
91        # definitively if the name is a selector or a C function
92        # ----------------------------------------------------------------------
93        name_bp = self.target.BreakpointCreateByName("count")
94        selector_bp = self.target.BreakpointCreateByName(
95            "count",
96            lldb.eFunctionNameTypeSelector,
97            lldb.SBFileSpecList(),
98            lldb.SBFileSpecList(),
99        )
100        self.assertGreaterEqual(
101            name_bp.GetNumLocations(),
102            selector_bp.GetNumLocations(),
103            'Make sure we get at least the same amount of breakpoints if not more when setting by name "count"',
104        )
105        self.assertGreater(
106            selector_bp.GetNumLocations(),
107            50,
108            'Make sure we find a lot of "count" selectors',
109        )  # There are 93 on the latest MacOSX
110        for bp_loc in selector_bp:
111            function_name = bp_loc.GetAddress().GetSymbol().GetName()
112            self.assertIn(
113                " count]",
114                function_name,
115                'Make sure all function names have " count]" in their names',
116            )
117
118        # ----------------------------------------------------------------------
119        # Set breakpoints on all selectors whose name is "isEqual:". This should
120        # catch breakpoints that are only ObjC selectors because no C function
121        # can end with a :
122        # ----------------------------------------------------------------------
123        name_bp = self.target.BreakpointCreateByName("isEqual:")
124        selector_bp = self.target.BreakpointCreateByName(
125            "isEqual:",
126            lldb.eFunctionNameTypeSelector,
127            lldb.SBFileSpecList(),
128            lldb.SBFileSpecList(),
129        )
130        self.assertEqual(
131            name_bp.GetNumLocations(),
132            selector_bp.GetNumLocations(),
133            'Make sure setting a breakpoint by name "isEqual:" only sets selector breakpoints',
134        )
135        for bp_loc in selector_bp:
136            function_name = bp_loc.GetAddress().GetSymbol().GetName()
137            self.assertIn(
138                " isEqual:]",
139                function_name,
140                'Make sure all function names have " isEqual:]" in their names',
141            )
142
143        self.check_category_breakpoints()
144
145        if have_dsym:
146            shutil.rmtree(exe + ".dSYM")
147        self.assertEqual(
148            subprocess.call(["/usr/bin/strip", "-Sx", exe]),
149            0,
150            "stripping dylib succeeded",
151        )
152
153        # Check breakpoints again, this time using the symbol table only
154        self.check_category_breakpoints()
155