TestClassTypes.py revision b794017ee4b085b28249af1511b3bdcaef8924ce
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        error = lldb.SBError()
123        process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error)
124
125        if not error.Success() or not process:
126            self.fail("SBTarget.Launch() failed")
127
128        if process.GetState() != lldb.eStateStopped:
129            self.fail("Process should be in the 'stopped' state, "
130                      "instead the actual state is: '%s'" %
131                      lldbutil.state_type_to_str(process.GetState()))
132
133        # The stop reason of the thread should be breakpoint.
134        thread = process.GetThreadAtIndex(0)
135        if thread.GetStopReason() != lldb.eStopReasonBreakpoint:
136            from lldbutil import stop_reason_to_str
137            self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS %
138                      stop_reason_to_str(thread.GetStopReason()))
139
140        # The filename of frame #0 should be 'main.cpp' and the line number
141        # should be 93.
142        self.expect("%s:%d" % (lldbutil.get_filenames(thread)[0],
143                               lldbutil.get_line_numbers(thread)[0]),
144                    "Break correctly at main.cpp:%d" % self.line, exe=False,
145            startstr = "main.cpp:")
146            ### clang compiled code reported main.cpp:94?
147            ### startstr = "main.cpp:93")
148
149        # We should be stopped on the breakpoint with a hit count of 1.
150        self.assertTrue(breakpoint.GetHitCount() == 1, BREAKPOINT_HIT_ONCE)
151
152        process.Continue()
153
154    def class_types_expr_parser(self):
155        """Test 'frame variable this' and 'expr this' when stopped inside a constructor."""
156        exe = os.path.join(os.getcwd(), "a.out")
157        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
158
159        # rdar://problem/8516141
160        # Is this a case of clang (116.1) generating bad debug info?
161        #
162        # Break on the ctor function of class C.
163        self.expect("breakpoint set -M C", BREAKPOINT_CREATED,
164            startstr = "Breakpoint created: 1: name = 'C', locations = 1")
165
166        self.runCmd("run", RUN_SUCCEEDED)
167
168        # The stop reason of the thread should be breakpoint.
169        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
170            substrs = ['stopped',
171                       'stop reason = breakpoint'])
172
173        # The breakpoint should have a hit count of 1.
174        self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
175            substrs = [' resolved, hit count = 1'])
176
177        # Continue on inside the ctor() body...
178        self.runCmd("thread step-over")
179
180        # Verify that 'frame variable this' gets the data type correct.
181        self.expect("frame variable this",VARIABLES_DISPLAYED_CORRECTLY,
182            substrs = ['C *'])
183
184        # Verify that frame variable -T this->m_c_int behaves correctly.
185        self.expect("frame variable -T this->m_c_int", VARIABLES_DISPLAYED_CORRECTLY,
186            startstr = '(int) this->m_c_int = 66')
187
188        # Verify that 'expression this' gets the data type correct.
189        self.expect("expression this", VARIABLES_DISPLAYED_CORRECTLY,
190            substrs = ['C *'])
191
192        # rdar://problem/8430916
193        # expr this->m_c_int returns an incorrect value
194        #
195        # Verify that expr this->m_c_int behaves correctly.
196        self.expect("expression this->m_c_int", VARIABLES_DISPLAYED_CORRECTLY,
197            patterns = ['\(int\) \$[0-9]+ = 66'])
198
199
200if __name__ == '__main__':
201    import atexit
202    lldb.SBDebugger.Initialize()
203    atexit.register(lambda: lldb.SBDebugger.Terminate())
204    unittest2.main()
205