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