1"""
2Test breakpoint ignore count features.
3"""
4
5import os, time
6import re
7import unittest2
8import lldb, lldbutil
9from lldbtest import *
10
11class BreakpointIgnoreCountTestCase(TestBase):
12
13    mydir = os.path.join("functionalities", "breakpoint", "breakpoint_ignore_count")
14
15    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
16    @dsym_test
17    def test_with_dsym_and_run_command(self):
18        """Exercise breakpoint ignore count with 'breakpoint set -i <count>'."""
19        self.buildDsym()
20        self.breakpoint_ignore_count()
21
22    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
23    @python_api_test
24    @dsym_test
25    def test_with_dsym_and_python_api(self):
26        """Use Python APIs to set breakpoint ignore count."""
27        self.buildDsym()
28        self.breakpoint_ignore_count_python()
29
30    @dwarf_test
31    def test_with_dwarf_and_run_command(self):
32        """Exercise breakpoint ignore count with 'breakpoint set -i <count>'."""
33        self.buildDwarf()
34        self.breakpoint_ignore_count()
35
36    @python_api_test
37    @dwarf_test
38    def test_with_dwarf_and_python_api(self):
39        """Use Python APIs to set breakpoint ignore count."""
40        self.buildDwarf()
41        self.breakpoint_ignore_count_python()
42
43    def setUp(self):
44        # Call super's setUp().
45        TestBase.setUp(self)
46        # Find the line number to of function 'c'.
47        self.line1 = line_number('main.c', '// Find the line number of function "c" here.')
48        self.line2 = line_number('main.c', '// b(2) -> c(2) Find the call site of b(2).')
49        self.line3 = line_number('main.c', '// a(3) -> c(3) Find the call site of c(3).')
50        self.line4 = line_number('main.c', '// a(3) -> c(3) Find the call site of a(3).')
51        self.line5 = line_number('main.c', '// Find the call site of c in main.')
52
53    def breakpoint_ignore_count(self):
54        """Exercise breakpoint ignore count with 'breakpoint set -i <count>'."""
55        exe = os.path.join(os.getcwd(), "a.out")
56        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
57
58        # Create a breakpoint in main.c at line1.
59        lldbutil.run_break_set_by_file_and_line (self, 'main.c', self.line1, extra_options='-i 1', num_expected_locations=1, loc_exact=True)
60
61        # Now run the program.
62        self.runCmd("run", RUN_SUCCEEDED)
63
64        # The process should be stopped at this point.
65        self.expect("process status", PROCESS_STOPPED,
66            patterns = ['Process .* stopped'])
67
68        # Also check the hit count, which should be 2, due to ignore count of 1.
69        self.expect("breakpoint list -f", BREAKPOINT_HIT_THRICE,
70            substrs = ["resolved = 1",
71                       "hit count = 2"])
72
73        # The frame #0 should correspond to main.c:37, the executable statement
74        # in function name 'c'.  And frame #2 should point to main.c:45.
75        self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT,
76            #substrs = ["stop reason = breakpoint"],
77            patterns = ["frame #0.*main.c:%d" % self.line1,
78                        "frame #2.*main.c:%d" % self.line2])
79
80        # continue -i 1 is the same as setting the ignore count to 1 again, try that:
81        # Now run the program.
82        self.runCmd("process continue -i 1", RUN_SUCCEEDED)
83
84        # The process should be stopped at this point.
85        self.expect("process status", PROCESS_STOPPED,
86            patterns = ['Process .* stopped'])
87
88        # Also check the hit count, which should be 2, due to ignore count of 1.
89        self.expect("breakpoint list -f", BREAKPOINT_HIT_THRICE,
90            substrs = ["resolved = 1",
91                       "hit count = 4"])
92
93        # The frame #0 should correspond to main.c:37, the executable statement
94        # in function name 'c'.  And frame #2 should point to main.c:45.
95        self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT,
96            #substrs = ["stop reason = breakpoint"],
97            patterns = ["frame #0.*main.c:%d" % self.line1,
98                        "frame #1.*main.c:%d" % self.line5])
99
100
101
102    def breakpoint_ignore_count_python(self):
103        """Use Python APIs to set breakpoint ignore count."""
104        exe = os.path.join(os.getcwd(), "a.out")
105
106        # Create a target by the debugger.
107        target = self.dbg.CreateTarget(exe)
108        self.assertTrue(target, VALID_TARGET)
109
110        # Now create a breakpoint on main.c by name 'c'.
111        breakpoint = target.BreakpointCreateByName('c', 'a.out')
112        self.assertTrue(breakpoint and
113                        breakpoint.GetNumLocations() == 1,
114                        VALID_BREAKPOINT)
115
116        # Get the breakpoint location from breakpoint after we verified that,
117        # indeed, it has one location.
118        location = breakpoint.GetLocationAtIndex(0)
119        self.assertTrue(location and
120                        location.IsEnabled(),
121                        VALID_BREAKPOINT_LOCATION)
122
123        # Set the ignore count on the breakpoint location.
124        location.SetIgnoreCount(2)
125        self.assertTrue(location.GetIgnoreCount() == 2,
126                        "SetIgnoreCount() works correctly")
127
128        # Now launch the process, and do not stop at entry point.
129        process = target.LaunchSimple(None, None, os.getcwd())
130        self.assertTrue(process, PROCESS_IS_VALID)
131
132        # Frame#0 should be on main.c:37, frame#1 should be on main.c:25, and
133        # frame#2 should be on main.c:48.
134        #lldbutil.print_stacktraces(process)
135        from lldbutil import get_stopped_thread
136        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
137        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
138        frame0 = thread.GetFrameAtIndex(0)
139        frame1 = thread.GetFrameAtIndex(1)
140        frame2 = thread.GetFrameAtIndex(2)
141        self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1 and
142                        frame1.GetLineEntry().GetLine() == self.line3 and
143                        frame2.GetLineEntry().GetLine() == self.line4,
144                        STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT)
145
146        # The hit count for the breakpoint should be 3.
147        self.assertTrue(breakpoint.GetHitCount() == 3)
148
149        process.Continue()
150
151
152if __name__ == '__main__':
153    import atexit
154    lldb.SBDebugger.Initialize()
155    atexit.register(lambda: lldb.SBDebugger.Terminate())
156    unittest2.main()
157