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