1"""
2Test breakpoint commands for a breakpoint ID with multiple locations.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class BreakpointLocationsTestCase(TestBase):
14
15    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
16    def test_enable(self):
17        """Test breakpoint enable/disable for a breakpoint ID with multiple locations."""
18        self.build()
19        self.breakpoint_locations_test()
20
21    def test_shadowed_cond_options(self):
22        """Test that options set on the breakpoint and location behave correctly."""
23        self.build()
24        self.shadowed_bkpt_cond_test()
25
26    def test_shadowed_command_options(self):
27        """Test that options set on the breakpoint and location behave correctly."""
28        self.build()
29        self.shadowed_bkpt_command_test()
30
31    def setUp(self):
32        # Call super's setUp().
33        TestBase.setUp(self)
34        # Find the line number to break inside main().
35        self.line = line_number('main.c', '// Set break point at this line.')
36
37    def set_breakpoint (self):
38        exe = self.getBuildArtifact("a.out")
39        target = self.dbg.CreateTarget(exe)
40        self.assertTrue(target, "Target %s is not valid"%(exe))
41
42        # This should create a breakpoint with 3 locations.
43
44        bkpt = target.BreakpointCreateByLocation("main.c", self.line)
45
46        # The breakpoint list should show 3 locations.
47        self.assertEqual(bkpt.GetNumLocations(), 3, "Wrong number of locations")
48
49        self.expect(
50            "breakpoint list -f",
51            "Breakpoint locations shown correctly",
52            substrs=[
53                "1: file = 'main.c', line = %d, exact_match = 0, locations = 3" %
54                self.line],
55            patterns=[
56                "where = a.out`func_inlined .+unresolved, hit count = 0",
57                "where = a.out`main .+\[inlined\].+unresolved, hit count = 0"])
58
59        return bkpt
60
61    def shadowed_bkpt_cond_test(self):
62        """Test that options set on the breakpoint and location behave correctly."""
63        # Breakpoint option propagation from bkpt to loc used to be done the first time
64        # a breakpoint location option was specifically set.  After that the other options
65        # on that location would stop tracking the breakpoint.  That got fixed, and this test
66        # makes sure only the option touched is affected.
67
68        bkpt = self.set_breakpoint()
69        bkpt_cond = "1 == 0"
70        bkpt.SetCondition(bkpt_cond)
71        self.assertEqual(bkpt.GetCondition(), bkpt_cond,"Successfully set condition")
72        self.assertEquals(bkpt.location[0].GetCondition(), bkpt.GetCondition(), "Conditions are the same")
73
74        # Now set a condition on the locations, make sure that this doesn't effect the bkpt:
75        bkpt_loc_1_cond = "1 == 1"
76        bkpt.location[0].SetCondition(bkpt_loc_1_cond)
77        self.assertEqual(bkpt.location[0].GetCondition(), bkpt_loc_1_cond, "Successfully changed location condition")
78        self.assertNotEqual(bkpt.GetCondition(), bkpt_loc_1_cond, "Changed location changed Breakpoint condition")
79        self.assertEqual(bkpt.location[1].GetCondition(), bkpt_cond, "Changed another location's condition")
80
81        # Now make sure that setting one options doesn't fix the value of another:
82        bkpt.SetIgnoreCount(10)
83        self.assertEqual(bkpt.GetIgnoreCount(), 10, "Set the ignore count successfully")
84        self.assertEqual(bkpt.location[0].GetIgnoreCount(), 10, "Location doesn't track top-level bkpt.")
85
86        # Now make sure resetting the condition to "" resets the tracking:
87        bkpt.location[0].SetCondition("")
88        bkpt_new_cond = "1 == 3"
89        bkpt.SetCondition(bkpt_new_cond)
90        self.assertEqual(bkpt.location[0].GetCondition(), bkpt_new_cond, "Didn't go back to tracking condition")
91
92    def shadowed_bkpt_command_test(self):
93        """Test that options set on the breakpoint and location behave correctly."""
94        # Breakpoint option propagation from bkpt to loc used to be done the first time
95        # a breakpoint location option was specifically set.  After that the other options
96        # on that location would stop tracking the breakpoint.  That got fixed, and this test
97        # makes sure only the option touched is affected.
98
99        bkpt = self.set_breakpoint()
100        commands = ["AAAAAA", "BBBBBB", "CCCCCC"]
101        str_list = lldb.SBStringList()
102        str_list.AppendList(commands, len(commands))
103
104        bkpt.SetCommandLineCommands(str_list)
105        cmd_list = lldb.SBStringList()
106        bkpt.GetCommandLineCommands(cmd_list)
107        list_size = str_list.GetSize()
108        self.assertEqual(cmd_list.GetSize() , list_size, "Added the right number of commands")
109        for i in range(0,list_size):
110            self.assertEqual(str_list.GetStringAtIndex(i), cmd_list.GetStringAtIndex(i), "Mismatched commands.")
111
112        commands = ["DDDDDD", "EEEEEE", "FFFFFF", "GGGGGG"]
113        loc_list = lldb.SBStringList()
114        loc_list.AppendList(commands, len(commands))
115        bkpt.location[1].SetCommandLineCommands(loc_list)
116        loc_cmd_list = lldb.SBStringList()
117        bkpt.location[1].GetCommandLineCommands(loc_cmd_list)
118
119        loc_list_size = loc_list.GetSize()
120
121        # Check that the location has the right commands:
122        self.assertEqual(loc_cmd_list.GetSize() , loc_list_size, "Added the right number of commands to location")
123        for i in range(0,loc_list_size):
124            self.assertEqual(loc_list.GetStringAtIndex(i), loc_cmd_list.GetStringAtIndex(i), "Mismatched commands.")
125
126        # Check that we didn't mess up the breakpoint level commands:
127        self.assertEqual(cmd_list.GetSize() , list_size, "Added the right number of commands")
128        for i in range(0,list_size):
129            self.assertEqual(str_list.GetStringAtIndex(i), cmd_list.GetStringAtIndex(i), "Mismatched commands.")
130
131        # And check we didn't mess up another location:
132        untouched_loc_cmds = lldb.SBStringList()
133        bkpt.location[0].GetCommandLineCommands(untouched_loc_cmds)
134        self.assertEqual(untouched_loc_cmds.GetSize() , 0, "Changed the wrong location")
135
136    def breakpoint_locations_test(self):
137        """Test breakpoint enable/disable for a breakpoint ID with multiple locations."""
138        self.set_breakpoint()
139
140        # The 'breakpoint disable 3.*' command should fail gracefully.
141        self.expect("breakpoint disable 3.*",
142                    "Disabling an invalid breakpoint should fail gracefully",
143                    error=True,
144                    startstr="error: '3' is not a valid breakpoint ID.")
145
146        # The 'breakpoint disable 1.*' command should disable all 3 locations.
147        self.expect(
148            "breakpoint disable 1.*",
149            "All 3 breakpoint locatons disabled correctly",
150            startstr="3 breakpoints disabled.")
151
152        # Run the program.
153        self.runCmd("run", RUN_SUCCEEDED)
154
155        # We should not stopped on any breakpoint at all.
156        self.expect("process status", "No stopping on any disabled breakpoint",
157                    patterns=["^Process [0-9]+ exited with status = 0"])
158
159        # The 'breakpoint enable 1.*' command should enable all 3 breakpoints.
160        self.expect(
161            "breakpoint enable 1.*",
162            "All 3 breakpoint locatons enabled correctly",
163            startstr="3 breakpoints enabled.")
164
165        # The 'breakpoint disable 1.1' command should disable 1 location.
166        self.expect(
167            "breakpoint disable 1.1",
168            "1 breakpoint locatons disabled correctly",
169            startstr="1 breakpoints disabled.")
170
171        # Run the program again.  We should stop on the two breakpoint
172        # locations.
173        self.runCmd("run", RUN_SUCCEEDED)
174
175        # Stopped once.
176        self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT,
177                    substrs=["stop reason = breakpoint 1."])
178
179        # Continue the program, there should be another stop.
180        self.runCmd("process continue")
181
182        # Stopped again.
183        self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT,
184                    substrs=["stop reason = breakpoint 1."])
185
186        # At this point, 1.1 has a hit count of 0 and the other a hit count of
187        # 1".
188        lldbutil.check_breakpoint(self, bpno = 1, expected_locations = 3, expected_resolved_count = 2, expected_hit_count = 2)
189        lldbutil.check_breakpoint(self, bpno = 1, location_id = 1,  expected_location_resolved = False, expected_location_hit_count = 0)
190        lldbutil.check_breakpoint(self, bpno = 1, location_id = 2, expected_location_resolved = True, expected_location_hit_count = 1)
191        lldbutil.check_breakpoint(self, bpno = 1, location_id = 3, expected_location_resolved = True, expected_location_hit_count = 1)
192