1""" 2Test that lldb watchpoint works for multiple threads. 3""" 4 5import re 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10 11 12class WatchpointForMultipleThreadsTestCase(TestBase): 13 NO_DEBUG_INFO_TESTCASE = True 14 main_spec = lldb.SBFileSpec("main.cpp", False) 15 16 @skipIfWindows # This test is flaky on Windows 17 def test_watchpoint_before_thread_start(self): 18 """Test that we can hit a watchpoint we set before starting another thread""" 19 self.do_watchpoint_test("Before running the thread") 20 21 @skipIfWindows # This test is flaky on Windows 22 def test_watchpoint_after_thread_launch(self): 23 """Test that we can hit a watchpoint we set after launching another thread""" 24 self.do_watchpoint_test("After launching the thread") 25 26 def test_watchpoint_after_thread_start(self): 27 """Test that we can hit a watchpoint we set after another thread starts""" 28 self.do_watchpoint_test("After running the thread") 29 30 def do_watchpoint_test(self, line): 31 self.build() 32 lldbutil.run_to_source_breakpoint(self, line, self.main_spec) 33 34 # Now let's set a write-type watchpoint for variable 'g_val'. 35 self.expect( 36 "watchpoint set variable -w write g_val", 37 WATCHPOINT_CREATED, 38 substrs=["Watchpoint created", "size = 4", "type = w"], 39 ) 40 41 # Use the '-v' option to do verbose listing of the watchpoint. 42 # The hit count should be 0 initially. 43 self.expect("watchpoint list -v", substrs=["hit_count = 0"]) 44 45 self.runCmd("process continue") 46 47 self.runCmd("thread list") 48 if "stop reason = watchpoint" in self.res.GetOutput(): 49 # Good, we verified that the watchpoint works! 50 self.runCmd("thread backtrace all") 51 else: 52 self.fail("The stop reason should be either break or watchpoint") 53 54 # Use the '-v' option to do verbose listing of the watchpoint. 55 # The hit count should now be 1. 56 self.expect("watchpoint list -v", substrs=["hit_count = 1"]) 57 58 def test_watchpoint_multiple_threads_wp_set_and_then_delete(self): 59 """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires.""" 60 self.build() 61 self.setTearDownCleanup() 62 63 lldbutil.run_to_source_breakpoint( 64 self, "After running the thread", self.main_spec 65 ) 66 67 # Now let's set a write-type watchpoint for variable 'g_val'. 68 self.expect( 69 "watchpoint set variable -w write g_val", 70 WATCHPOINT_CREATED, 71 substrs=["Watchpoint created", "size = 4", "type = w"], 72 ) 73 74 # Use the '-v' option to do verbose listing of the watchpoint. 75 # The hit count should be 0 initially. 76 self.expect("watchpoint list -v", substrs=["hit_count = 0"]) 77 78 watchpoint_stops = 0 79 while True: 80 self.runCmd("process continue") 81 self.runCmd("process status") 82 if re.search("Process .* exited", self.res.GetOutput()): 83 # Great, we are done with this test! 84 break 85 86 self.runCmd("thread list") 87 if "stop reason = watchpoint" in self.res.GetOutput(): 88 self.runCmd("thread backtrace all") 89 watchpoint_stops += 1 90 if watchpoint_stops > 1: 91 self.fail("Watchpoint hits not supposed to exceed 1 by design!") 92 # Good, we verified that the watchpoint works! Now delete the 93 # watchpoint. 94 if self.TraceOn(): 95 print( 96 "watchpoint_stops=%d at the moment we delete the watchpoint" 97 % watchpoint_stops 98 ) 99 self.runCmd("watchpoint delete 1") 100 self.expect( 101 "watchpoint list -v", substrs=["No watchpoints currently set."] 102 ) 103 continue 104 else: 105 self.fail("The stop reason should be either break or watchpoint") 106