Home | History | Annotate | Download | only in class_types
      1 """Test breakpoint on a class constructor; and variable list the this object."""
      2 
      3 import os, time
      4 import unittest2
      5 import lldb
      6 import lldbutil
      7 from lldbtest import *
      8 import lldbutil
      9 
     10 class ClassTypesTestCase(TestBase):
     11 
     12     mydir = os.path.join("lang", "cpp", "class_types")
     13 
     14     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     15     @dsym_test
     16     def test_with_dsym_and_run_command(self):
     17         """Test 'frame variable this' when stopped on a class constructor."""
     18         self.buildDsym()
     19         self.class_types()
     20 
     21     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     22     @python_api_test
     23     @dsym_test
     24     def test_with_dsym_and_python_api(self):
     25         """Use Python APIs to create a breakpoint by (filespec, line)."""
     26         self.buildDsym()
     27         self.breakpoint_creation_by_filespec_python()
     28 
     29     # rdar://problem/8378863
     30     # "frame variable this" returns
     31     # error: unable to find any variables named 'this'
     32     @dwarf_test
     33     def test_with_dwarf_and_run_command(self):
     34         """Test 'frame variable this' when stopped on a class constructor."""
     35         self.buildDwarf()
     36         self.class_types()
     37 
     38     @python_api_test
     39     @dwarf_test
     40     def test_with_dwarf_and_python_api(self):
     41         """Use Python APIs to create a breakpoint by (filespec, line)."""
     42         self.buildDwarf()
     43         self.breakpoint_creation_by_filespec_python()
     44 
     45     @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
     46     # rdar://problem/8557478
     47     # test/class_types test failures: runCmd: expr this->m_c_int
     48     @dsym_test
     49     def test_with_dsym_and_expr_parser(self):
     50         """Test 'frame variable this' and 'expr this' when stopped inside a constructor."""
     51         self.buildDsym()
     52         self.class_types_expr_parser()
     53 
     54     # rdar://problem/8557478
     55     # test/class_types test failures: runCmd: expr this->m_c_int
     56     @dwarf_test
     57     def test_with_dwarf_and_expr_parser(self):
     58         """Test 'frame variable this' and 'expr this' when stopped inside a constructor."""
     59         self.buildDwarf()
     60         self.class_types_expr_parser()
     61 
     62     def setUp(self):
     63         # Call super's setUp().
     64         TestBase.setUp(self)
     65         # Find the line number to break for main.cpp.
     66         self.line = line_number('main.cpp', '// Set break point at this line.')
     67 
     68     def class_types(self):
     69         """Test 'frame variable this' when stopped on a class constructor."""
     70         exe = os.path.join(os.getcwd(), "a.out")
     71         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
     72 
     73         # Break on the ctor function of class C.
     74         lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=-1)
     75 
     76         self.runCmd("run", RUN_SUCCEEDED)
     77 
     78         # The test suite sometimes shows that the process has exited without stopping.
     79         #
     80         # CC=clang ./dotest.py -v -t class_types
     81         # ...
     82         # Process 76604 exited with status = 0 (0x00000000)
     83         self.runCmd("process status")
     84 
     85         # The stop reason of the thread should be breakpoint.
     86         self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
     87             substrs = ['stopped',
     88                        'stop reason = breakpoint'])
     89 
     90         # The breakpoint should have a hit count of 1.
     91         self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
     92             substrs = [' resolved, hit count = 1'])
     93 
     94         # We should be stopped on the ctor function of class C.
     95         self.expect("frame variable --show-types this", VARIABLES_DISPLAYED_CORRECTLY,
     96             substrs = ['C *',
     97                        ' this = '])
     98 
     99     def breakpoint_creation_by_filespec_python(self):
    100         """Use Python APIs to create a breakpoint by (filespec, line)."""
    101         exe = os.path.join(os.getcwd(), "a.out")
    102 
    103         target = self.dbg.CreateTarget(exe)
    104         self.assertTrue(target, VALID_TARGET)
    105 
    106         filespec = target.GetExecutable()
    107         self.assertTrue(filespec, VALID_FILESPEC)
    108 
    109         fsDir = filespec.GetDirectory()
    110         fsFile = filespec.GetFilename()
    111 
    112         self.assertTrue(fsDir == os.getcwd() and fsFile == "a.out",
    113                         "FileSpec matches the executable")
    114 
    115         bpfilespec = lldb.SBFileSpec("main.cpp", False)
    116 
    117         breakpoint = target.BreakpointCreateByLocation(bpfilespec, self.line)
    118         self.assertTrue(breakpoint, VALID_BREAKPOINT)
    119 
    120         # Verify the breakpoint just created.
    121         self.expect(str(breakpoint), BREAKPOINT_CREATED, exe=False,
    122             substrs = ['main.cpp',
    123                        str(self.line)])
    124 
    125         # Now launch the process, and do not stop at entry point.
    126         process = target.LaunchSimple(None, None, os.getcwd())
    127 
    128         if not process:
    129             self.fail("SBTarget.Launch() failed")
    130 
    131         if process.GetState() != lldb.eStateStopped:
    132             self.fail("Process should be in the 'stopped' state, "
    133                       "instead the actual state is: '%s'" %
    134                       lldbutil.state_type_to_str(process.GetState()))
    135 
    136         # The stop reason of the thread should be breakpoint.
    137         thread = process.GetThreadAtIndex(0)
    138         if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
    139             from lldbutil import stop_reason_to_str
    140             self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS %
    141                       stop_reason_to_str(thread.GetStopReason()))
    142 
    143         # The filename of frame #0 should be 'main.cpp' and the line number
    144         # should be 93.
    145         self.expect("%s:%d" % (lldbutil.get_filenames(thread)[0],
    146                                lldbutil.get_line_numbers(thread)[0]),
    147                     "Break correctly at main.cpp:%d" % self.line, exe=False,
    148             startstr = "main.cpp:")
    149             ### clang compiled code reported main.cpp:94?
    150             ### startstr = "main.cpp:93")
    151 
    152         # We should be stopped on the breakpoint with a hit count of 1.
    153         self.assertTrue(breakpoint.GetHitCount() == 1, BREAKPOINT_HIT_ONCE)
    154 
    155         process.Continue()
    156 
    157     def class_types_expr_parser(self):
    158         """Test 'frame variable this' and 'expr this' when stopped inside a constructor."""
    159         exe = os.path.join(os.getcwd(), "a.out")
    160         self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
    161 
    162         # rdar://problem/8516141
    163         # Is this a case of clang (116.1) generating bad debug info?
    164         #
    165         # Break on the ctor function of class C.
    166         #self.expect("breakpoint set -M C", BREAKPOINT_CREATED,
    167         #    startstr = "Breakpoint created: 1: name = 'C'")
    168 
    169         # Make the test case more robust by using line number to break, instead.
    170         lldbutil.run_break_set_by_file_and_line (self, None, self.line, num_expected_locations=-1)
    171 
    172         self.runCmd("run", RUN_SUCCEEDED)
    173 
    174         # The stop reason of the thread should be breakpoint.
    175         self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
    176             substrs = ['stopped',
    177                        'stop reason = breakpoint'])
    178 
    179         # The breakpoint should have a hit count of 1.
    180         self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
    181             substrs = [' resolved, hit count = 1'])
    182 
    183         # Continue on inside the ctor() body...
    184         self.runCmd("register read pc")
    185         self.runCmd("thread step-over")
    186 
    187         # Verify that 'frame variable this' gets the data type correct.
    188         self.expect("frame variable this",VARIABLES_DISPLAYED_CORRECTLY,
    189             substrs = ['C *'])
    190 
    191         # Verify that frame variable --show-types this->m_c_int behaves correctly.
    192         self.runCmd("register read pc")
    193         self.runCmd("expr m_c_int")
    194         self.expect("frame variable --show-types this->m_c_int", VARIABLES_DISPLAYED_CORRECTLY,
    195             startstr = '(int) this->m_c_int = 66')
    196 
    197         # Verify that 'expression this' gets the data type correct.
    198         self.expect("expression this", VARIABLES_DISPLAYED_CORRECTLY,
    199             substrs = ['C *'])
    200 
    201         # rdar://problem/8430916
    202         # expr this->m_c_int returns an incorrect value
    203         #
    204         # Verify that expr this->m_c_int behaves correctly.
    205         self.expect("expression this->m_c_int", VARIABLES_DISPLAYED_CORRECTLY,
    206             patterns = ['\(int\) \$[0-9]+ = 66'])
    207 
    208 
    209 if __name__ == '__main__':
    210     import atexit
    211     lldb.SBDebugger.Initialize()
    212     atexit.register(lambda: lldb.SBDebugger.Terminate())
    213     unittest2.main()
    214