1 """ 2 Test lldb breakpoint command add/list/delete. 3 """ 4 5 import os, time 6 import unittest2 7 import lldb 8 from lldbtest import * 9 import lldbutil 10 11 class BreakpointCommandTestCase(TestBase): 12 13 mydir = os.path.join("functionalities", "breakpoint", "breakpoint_command") 14 15 @classmethod 16 def classCleanup(cls): 17 """Cleanup the test byproduct of breakpoint_command_sequence(self).""" 18 cls.RemoveTempFile("output.txt") 19 cls.RemoveTempFile("output2.txt") 20 21 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 22 @dsym_test 23 def test_with_dsym(self): 24 """Test a sequence of breakpoint command add, list, and delete.""" 25 self.buildDsym() 26 self.breakpoint_command_sequence() 27 self.breakpoint_command_script_parameters () 28 29 @dwarf_test 30 def test_with_dwarf(self): 31 """Test a sequence of breakpoint command add, list, and delete.""" 32 self.buildDwarf() 33 self.breakpoint_command_sequence() 34 self.breakpoint_command_script_parameters () 35 36 def setUp(self): 37 # Call super's setUp(). 38 TestBase.setUp(self) 39 # Find the line number to break inside main(). 40 self.line = line_number('main.c', '// Set break point at this line.') 41 # disable "There is a running process, kill it and restart?" prompt 42 self.runCmd("settings set auto-confirm true") 43 self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm")) 44 45 def breakpoint_command_sequence(self): 46 """Test a sequence of breakpoint command add, list, and delete.""" 47 exe = os.path.join(os.getcwd(), "a.out") 48 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 49 50 # Add three breakpoints on the same line. The first time we don't specify the file, 51 # since the default file is the one containing main: 52 lldbutil.run_break_set_by_file_and_line (self, None, self.line, num_expected_locations=1, loc_exact=True) 53 lldbutil.run_break_set_by_file_and_line (self, "main.c", self.line, num_expected_locations=1, loc_exact=True) 54 lldbutil.run_break_set_by_file_and_line (self, "main.c", self.line, num_expected_locations=1, loc_exact=True) 55 56 # Now add callbacks for the breakpoints just created. 57 self.runCmd("breakpoint command add -s command -o 'frame variable --show-types --scope' 1") 58 self.runCmd("breakpoint command add -s python -o 'here = open(\"output.txt\", \"w\"); print >> here, \"lldb\"; here.close()' 2") 59 self.runCmd("breakpoint command add --python-function bktptcmd.function 3") 60 61 # Check that the breakpoint commands are correctly set. 62 63 # The breakpoint list now only contains breakpoint 1. 64 self.expect("breakpoint list", "Breakpoints 1 & 2 created", 65 substrs = ["2: file = 'main.c', line = %d, locations = 1" % self.line], 66 patterns = ["1: file = '.*main.c', line = %d, locations = 1" % self.line] ) 67 68 self.expect("breakpoint list -f", "Breakpoints 1 & 2 created", 69 substrs = ["2: file = 'main.c', line = %d, locations = 1" % self.line], 70 patterns = ["1: file = '.*main.c', line = %d, locations = 1" % self.line, 71 "1.1: .+at main.c:%d, .+unresolved, hit count = 0" % self.line, 72 "2.1: .+at main.c:%d, .+unresolved, hit count = 0" % self.line]) 73 74 self.expect("breakpoint command list 1", "Breakpoint 1 command ok", 75 substrs = ["Breakpoint commands:", 76 "frame variable --show-types --scope"]) 77 self.expect("breakpoint command list 2", "Breakpoint 2 command ok", 78 substrs = ["Breakpoint commands:", 79 "here = open", 80 "print >> here", 81 "here.close()"]) 82 self.expect("breakpoint command list 3", "Breakpoint 3 command ok", 83 substrs = ["Breakpoint commands:", 84 "bktptcmd.function(frame, bp_loc, internal_dict)"]) 85 86 self.runCmd("command script import --allow-reload ./bktptcmd.py") 87 88 # Next lets try some other breakpoint kinds. First break with a regular expression 89 # and then specify only one file. The first time we should get two locations, 90 # the second time only one: 91 92 lldbutil.run_break_set_by_regexp (self, r"._MyFunction", num_expected_locations=2) 93 94 lldbutil.run_break_set_by_regexp (self, r"._MyFunction", extra_options="-f a.c", num_expected_locations=1) 95 96 lldbutil.run_break_set_by_regexp (self, r"._MyFunction", extra_options="-f a.c -f b.c", num_expected_locations=2) 97 98 # Now try a source regex breakpoint: 99 lldbutil.run_break_set_by_source_regexp (self, r"is about to return [12]0", extra_options="-f a.c -f b.c", num_expected_locations=2) 100 101 lldbutil.run_break_set_by_source_regexp (self, r"is about to return [12]0", extra_options="-f a.c", num_expected_locations=1) 102 103 # Run the program. Remove 'output.txt' if it exists. 104 self.RemoveTempFile("output.txt") 105 self.RemoveTempFile("output2.txt") 106 self.runCmd("run", RUN_SUCCEEDED) 107 108 # Check that the file 'output.txt' exists and contains the string "lldb". 109 110 # The 'output.txt' file should now exist. 111 self.assertTrue(os.path.isfile("output.txt"), 112 "'output.txt' exists due to breakpoint command for breakpoint 2.") 113 self.assertTrue(os.path.isfile("output2.txt"), 114 "'output2.txt' exists due to breakpoint command for breakpoint 3.") 115 116 # Read the output file produced by running the program. 117 with open('output.txt', 'r') as f: 118 output = f.read() 119 120 self.expect(output, "File 'output.txt' and the content matches", exe=False, 121 startstr = "lldb") 122 123 with open('output2.txt', 'r') as f: 124 output = f.read() 125 126 self.expect(output, "File 'output2.txt' and the content matches", exe=False, 127 startstr = "lldb") 128 129 130 # Finish the program. 131 self.runCmd("process continue") 132 133 # Remove the breakpoint command associated with breakpoint 1. 134 self.runCmd("breakpoint command delete 1") 135 136 # Remove breakpoint 2. 137 self.runCmd("breakpoint delete 2") 138 139 self.expect("breakpoint command list 1", 140 startstr = "Breakpoint 1 does not have an associated command.") 141 self.expect("breakpoint command list 2", error=True, 142 startstr = "error: '2' is not a currently valid breakpoint id.") 143 144 # The breakpoint list now only contains breakpoint 1. 145 self.expect("breakpoint list -f", "Breakpoint 1 exists", 146 patterns = ["1: file = '.*main.c', line = %d, locations = 1, resolved = 1" % 147 self.line, 148 "hit count = 1"]) 149 150 # Not breakpoint 2. 151 self.expect("breakpoint list -f", "No more breakpoint 2", matching=False, 152 substrs = ["2: file = 'main.c', line = %d, locations = 1, resolved = 1" % 153 self.line]) 154 155 # Run the program again, with breakpoint 1 remaining. 156 self.runCmd("run", RUN_SUCCEEDED) 157 158 # We should be stopped again due to breakpoint 1. 159 160 # The stop reason of the thread should be breakpoint. 161 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 162 substrs = ['stopped', 163 'stop reason = breakpoint']) 164 165 # The breakpoint should have a hit count of 2. 166 self.expect("breakpoint list -f", BREAKPOINT_HIT_TWICE, 167 substrs = ['resolved, hit count = 2']) 168 169 def breakpoint_command_script_parameters (self): 170 """Test that the frame and breakpoint location are being properly passed to the script breakpoint command function.""" 171 exe = os.path.join(os.getcwd(), "a.out") 172 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 173 174 # Add a breakpoint. 175 lldbutil.run_break_set_by_file_and_line (self, "main.c", self.line, num_expected_locations=1, loc_exact=True) 176 177 # Now add callbacks for the breakpoints just created. 178 self.runCmd("breakpoint command add -s python -o 'here = open(\"output-2.txt\", \"w\"); print >> here, frame; print >> here, bp_loc; here.close()' 1") 179 180 # Remove 'output-2.txt' if it already exists. 181 182 if (os.path.exists('output-2.txt')): 183 os.remove ('output-2.txt') 184 185 # Run program, hit breakpoint, and hopefully write out new version of 'output-2.txt' 186 self.runCmd ("run", RUN_SUCCEEDED) 187 188 # Check that the file 'output.txt' exists and contains the string "lldb". 189 190 # The 'output-2.txt' file should now exist. 191 self.assertTrue(os.path.isfile("output-2.txt"), 192 "'output-2.txt' exists due to breakpoint command for breakpoint 1.") 193 194 # Read the output file produced by running the program. 195 with open('output-2.txt', 'r') as f: 196 output = f.read() 197 198 self.expect (output, "File 'output-2.txt' and the content matches", exe=False, 199 startstr = "frame #0:", 200 patterns = ["1.* where = .*main .* resolved, hit count = 1" ]) 201 202 # Now remove 'output-2.txt' 203 os.remove ('output-2.txt') 204 205 if __name__ == '__main__': 206 import atexit 207 lldb.SBDebugger.Initialize() 208 atexit.register(lambda: lldb.SBDebugger.Terminate()) 209 unittest2.main() 210