Home | History | Annotate | Download | only in multiple_threads
      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