1 """ 2 Test that lldb watchpoint works for multiple threads. 3 """ 4 5 import os, time 6 import unittest2 7 import re 8 import lldb 9 from lldbtest import * 10 import lldbutil 11 12 class WatchpointForMultipleThreadsTestCase(TestBase): 13 14 mydir = os.path.join("functionalities", "watchpoint", "multiple_threads") 15 16 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 17 @dsym_test 18 def test_watchpoint_multiple_threads_with_dsym(self): 19 """Test that lldb watchpoint works for multiple threads.""" 20 self.buildDsym(dictionary=self.d) 21 self.setTearDownCleanup(dictionary=self.d) 22 self.hello_multiple_threads() 23 24 @expectedFailureFreeBSD('llvm.org/pr16706') # Watchpoints fail on FreeBSD 25 @skipIfGcc # causes intermittent gcc debian buildbot failures, skip until we can investigate 26 @dwarf_test 27 def test_watchpoint_multiple_threads_with_dwarf(self): 28 """Test that lldb watchpoint works for multiple threads.""" 29 self.buildDwarf(dictionary=self.d) 30 self.setTearDownCleanup(dictionary=self.d) 31 self.hello_multiple_threads() 32 33 @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") 34 @dsym_test 35 def test_watchpoint_multiple_threads_wp_set_and_then_delete_with_dsym(self): 36 """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" 37 self.buildDsym(dictionary=self.d) 38 self.setTearDownCleanup(dictionary=self.d) 39 self.hello_multiple_threads_wp_set_and_then_delete() 40 41 @expectedFailureFreeBSD('llvm.org/pr16706') # Watchpoints fail on FreeBSD 42 @skipIfGcc # causes intermittent gcc debian buildbot failures, skip until we can investigate 43 @dwarf_test 44 def test_watchpoint_multiple_threads_wp_set_and_then_delete_with_dwarf(self): 45 """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" 46 self.buildDwarf(dictionary=self.d) 47 self.setTearDownCleanup(dictionary=self.d) 48 self.hello_multiple_threads_wp_set_and_then_delete() 49 50 def setUp(self): 51 # Call super's setUp(). 52 TestBase.setUp(self) 53 # Our simple source filename. 54 self.source = 'main.cpp' 55 # Find the line number to break inside main(). 56 self.first_stop = line_number(self.source, '// Set break point at this line') 57 # Build dictionary to have unique executable names for each test method. 58 self.exe_name = self.testMethodName 59 self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name} 60 61 def hello_multiple_threads(self): 62 """Test that lldb watchpoint works for multiple threads.""" 63 exe = os.path.join(os.getcwd(), self.exe_name) 64 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 65 66 # Add a breakpoint to set a watchpoint when stopped on the breakpoint. 67 lldbutil.run_break_set_by_file_and_line (self, None, self.first_stop, num_expected_locations=1) 68 69 # Run the program. 70 self.runCmd("run", RUN_SUCCEEDED) 71 72 # We should be stopped again due to the breakpoint. 73 # The stop reason of the thread should be breakpoint. 74 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 75 substrs = ['stopped', 76 'stop reason = breakpoint']) 77 78 # Now let's set a write-type watchpoint for variable 'g_val'. 79 # The main.cpp, by design, misbehaves by not following the agreed upon 80 # protocol of using a mutex while accessing the global pool and by not 81 # writing to the variable. 82 self.expect("watchpoint set variable -w write g_val", WATCHPOINT_CREATED, 83 substrs = ['Watchpoint created', 'size = 4', 'type = w']) 84 85 # Use the '-v' option to do verbose listing of the watchpoint. 86 # The hit count should be 0 initially. 87 self.expect("watchpoint list -v", 88 substrs = ['hit_count = 0']) 89 90 while True: 91 self.runCmd("process continue") 92 93 self.runCmd("thread list") 94 if "stop reason = watchpoint" in self.res.GetOutput(): 95 # Good, we verified that the watchpoint works! 96 self.runCmd("thread backtrace all") 97 break 98 else: 99 self.fail("The stop reason should be either break or watchpoint") 100 101 # Use the '-v' option to do verbose listing of the watchpoint. 102 # The hit count should now be 1. 103 self.expect("watchpoint list -v", 104 substrs = ['hit_count = 1']) 105 106 def hello_multiple_threads_wp_set_and_then_delete(self): 107 """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" 108 exe = os.path.join(os.getcwd(), self.exe_name) 109 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 110 111 # Add a breakpoint to set a watchpoint when stopped on the breakpoint. 112 lldbutil.run_break_set_by_file_and_line (self, None, self.first_stop, num_expected_locations=1) 113 114 # Run the program. 115 self.runCmd("run", RUN_SUCCEEDED) 116 117 # We should be stopped again due to the breakpoint. 118 # The stop reason of the thread should be breakpoint. 119 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 120 substrs = ['stopped', 121 'stop reason = breakpoint']) 122 123 # Now let's set a write-type watchpoint for variable 'g_val'. 124 # The main.cpp, by design, misbehaves by not following the agreed upon 125 # protocol of using a mutex while accessing the global pool and by not 126 # writing to the variable. 127 self.expect("watchpoint set variable -w write g_val", WATCHPOINT_CREATED, 128 substrs = ['Watchpoint created', 'size = 4', 'type = w']) 129 130 # Use the '-v' option to do verbose listing of the watchpoint. 131 # The hit count should be 0 initially. 132 self.expect("watchpoint list -v", 133 substrs = ['hit_count = 0']) 134 135 watchpoint_stops = 0 136 while True: 137 self.runCmd("process continue") 138 self.runCmd("process status") 139 if re.search("Process .* exited", self.res.GetOutput()): 140 # Great, we are done with this test! 141 break 142 143 self.runCmd("thread list") 144 if "stop reason = watchpoint" in self.res.GetOutput(): 145 self.runCmd("thread backtrace all") 146 watchpoint_stops += 1 147 if watchpoint_stops > 1: 148 self.fail("Watchpoint hits not supposed to exceed 1 by design!") 149 # Good, we verified that the watchpoint works! Now delete the watchpoint. 150 if self.TraceOn(): 151 print "watchpoint_stops=%d at the moment we delete the watchpoint" % watchpoint_stops 152 self.runCmd("watchpoint delete 1") 153 self.expect("watchpoint list -v", 154 substrs = ['No watchpoints currently set.']) 155 continue 156 else: 157 self.fail("The stop reason should be either break or watchpoint") 158 159 160 if __name__ == '__main__': 161 import atexit 162 lldb.SBDebugger.Initialize() 163 atexit.register(lambda: lldb.SBDebugger.Terminate()) 164 unittest2.main() 165