Home | History | Annotate | Download | only in breakpoint_conditions
      1 """
      2 Test breakpoint conditions with 'breakpoint modify -c <expr> id'.
      3 """
      4 
      5 import os, time
      6 import re
      7 import unittest2
      8 import lldb, lldbutil
      9 from lldbtest import *
     10 
     11 class BreakpointConditionsTestCase(TestBase):
     12 
     13     mydir = os.path.join("functionalities", "breakpoint", "breakpoint_conditions")
     14 
     15     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     16     @dsym_test
     17     def test_breakpoint_condition_with_dsym_and_run_command(self):
     18         """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'."""
     19         self.buildDsym()
     20         self.breakpoint_conditions()
     21 
     22     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     23     @dsym_test
     24     def test_breakpoint_condition_inline_with_dsym_and_run_command(self):
     25         """Exercise breakpoint condition inline with 'breakpoint set'."""
     26         self.buildDsym()
     27         self.breakpoint_conditions(inline=True)
     28 
     29     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     30     @python_api_test
     31     @dsym_test
     32     def test_breakpoint_condition_with_dsym_and_python_api(self):
     33         """Use Python APIs to set breakpoint conditions."""
     34         self.buildDsym()
     35         self.breakpoint_conditions_python()
     36 
     37     @dwarf_test
     38     def test_breakpoint_condition_with_dwarf_and_run_command(self):
     39         """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'."""
     40         self.buildDwarf()
     41         self.breakpoint_conditions()
     42 
     43     @dwarf_test
     44     def test_breakpoint_condition_inline_with_dwarf_and_run_command(self):
     45         """Exercise breakpoint condition inline with 'breakpoint set'."""
     46         self.buildDwarf()
     47         self.breakpoint_conditions(inline=True)
     48 
     49     @python_api_test
     50     @dwarf_test
     51     def test_breakpoint_condition_with_dwarf_and_python_api(self):
     52         """Use Python APIs to set breakpoint conditions."""
     53         self.buildDwarf()
     54         self.breakpoint_conditions_python()
     55 
     56     def setUp(self):
     57         # Call super's setUp().
     58         TestBase.setUp(self)
     59         # Find the line number to of function 'c'.
     60         self.line1 = line_number('main.c', '// Find the line number of function "c" here.')
     61         self.line2 = line_number('main.c', "// Find the line number of c's parent call here.")
     62 
     63     def breakpoint_conditions(self, inline=False):
     64         """Exercise breakpoint condition with 'breakpoint modify -c <expr> id'."""
     65         exe = os.path.join(os.getcwd(), "a.out")
     66         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
     67 
     68         if inline:
     69             # Create a breakpoint by function name 'c' and set the condition.
     70             lldbutil.run_break_set_by_symbol (self, "c", extra_options="-c 'val == 3'", num_expected_locations=1, sym_exact=True)
     71         else:
     72             # Create a breakpoint by function name 'c'.
     73             lldbutil.run_break_set_by_symbol (self, "c", num_expected_locations=1, sym_exact=True)
     74 
     75             # And set a condition on the breakpoint to stop on when 'val == 3'.
     76             self.runCmd("breakpoint modify -c 'val == 3' 1")
     77 
     78         # Now run the program.
     79         self.runCmd("run", RUN_SUCCEEDED)
     80 
     81         # The process should be stopped at this point.
     82         self.expect("process status", PROCESS_STOPPED,
     83             patterns = ['Process .* stopped'])
     84 
     85         # 'frame variable --show-types val' should return 3 due to breakpoint condition.
     86         self.expect("frame variable --show-types val", VARIABLES_DISPLAYED_CORRECTLY,
     87             startstr = '(int) val = 3')
     88 
     89         # Also check the hit count, which should be 3, by design.
     90         self.expect("breakpoint list -f", BREAKPOINT_HIT_THRICE,
     91             substrs = ["resolved = 1",
     92                        "Condition: val == 3",
     93                        "hit count = 3"])
     94 
     95         # The frame #0 should correspond to main.c:36, the executable statement
     96         # in function name 'c'.  And the parent frame should point to main.c:24.
     97         self.expect("thread backtrace", STOPPED_DUE_TO_BREAKPOINT_CONDITION,
     98             #substrs = ["stop reason = breakpoint"],
     99             patterns = ["frame #0.*main.c:%d" % self.line1,
    100                         "frame #1.*main.c:%d" % self.line2])
    101 
    102         # Test that "breakpoint modify -c ''" clears the condition for the last
    103         # created breakpoint, so that when the breakpoint hits, val == 1.
    104         self.runCmd("process kill")
    105         self.runCmd("breakpoint modify -c ''")
    106         self.expect("breakpoint list -f", BREAKPOINT_STATE_CORRECT, matching=False,
    107             substrs = ["Condition:"])
    108 
    109         # Now run the program again.
    110         self.runCmd("run", RUN_SUCCEEDED)
    111 
    112         # The process should be stopped at this point.
    113         self.expect("process status", PROCESS_STOPPED,
    114             patterns = ['Process .* stopped'])
    115 
    116         # 'frame variable --show-types val' should return 1 since it is the first breakpoint hit.
    117         self.expect("frame variable --show-types val", VARIABLES_DISPLAYED_CORRECTLY,
    118             startstr = '(int) val = 1')
    119 
    120         self.runCmd("process kill")
    121         self.runCmd("breakpoint disable")
    122 
    123         self.runCmd("breakpoint set -p Loop")
    124         self.runCmd("breakpoint modify -c ($eax&&i)")
    125         self.runCmd("run")
    126         
    127         self.expect("process status", PROCESS_STOPPED,
    128             patterns = ['Process .* stopped'])
    129 
    130         self.runCmd("continue")
    131 
    132         self.expect("process status", PROCESS_EXITED,
    133             patterns = ['Process .* exited'])
    134 
    135     def breakpoint_conditions_python(self):
    136         """Use Python APIs to set breakpoint conditions."""
    137         exe = os.path.join(os.getcwd(), "a.out")
    138 
    139         # Create a target by the debugger.
    140         target = self.dbg.CreateTarget(exe)
    141         self.assertTrue(target, VALID_TARGET)
    142 
    143         # Now create a breakpoint on main.c by name 'c'.
    144         breakpoint = target.BreakpointCreateByName('c', 'a.out')
    145         #print "breakpoint:", breakpoint
    146         self.assertTrue(breakpoint and
    147                         breakpoint.GetNumLocations() == 1,
    148                         VALID_BREAKPOINT)
    149 
    150         # We didn't associate a thread index with the breakpoint, so it should be invalid.
    151         self.assertTrue(breakpoint.GetThreadIndex() == lldb.UINT32_MAX,
    152                         "The thread index should be invalid")
    153         # The thread name should be invalid, too.
    154         self.assertTrue(breakpoint.GetThreadName() is None,
    155                         "The thread name should be invalid")
    156 
    157         # Let's set the thread index for this breakpoint and verify that it is,
    158         # indeed, being set correctly.
    159         breakpoint.SetThreadIndex(1) # There's only one thread for the process.
    160         self.assertTrue(breakpoint.GetThreadIndex() == 1,
    161                         "The thread index has been set correctly")
    162 
    163         # Get the breakpoint location from breakpoint after we verified that,
    164         # indeed, it has one location.
    165         location = breakpoint.GetLocationAtIndex(0)
    166         self.assertTrue(location and
    167                         location.IsEnabled(),
    168                         VALID_BREAKPOINT_LOCATION)
    169 
    170         # Set the condition on the breakpoint location.
    171         location.SetCondition('val == 3')
    172         self.expect(location.GetCondition(), exe=False,
    173             startstr = 'val == 3')
    174 
    175         # Now launch the process, and do not stop at entry point.
    176         process = target.LaunchSimple(None, None, os.getcwd())
    177         self.assertTrue(process, PROCESS_IS_VALID)
    178 
    179         # Frame #0 should be on self.line1 and the break condition should hold.
    180         from lldbutil import get_stopped_thread
    181         thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
    182         self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
    183         frame0 = thread.GetFrameAtIndex(0)
    184         var = frame0.FindValue('val', lldb.eValueTypeVariableArgument)
    185         self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1 and
    186                         var.GetValue() == '3')
    187 
    188         # The hit count for the breakpoint should be 3.
    189         self.assertTrue(breakpoint.GetHitCount() == 3)
    190 
    191         process.Continue()
    192 
    193         
    194 if __name__ == '__main__':
    195     import atexit
    196     lldb.SBDebugger.Initialize()
    197     atexit.register(lambda: lldb.SBDebugger.Terminate())
    198     unittest2.main()
    199