1"""
2Test display and Python APIs on file and class static variables.
3"""
4
5
6
7import lldb
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11
12
13class StaticVariableTestCase(TestBase):
14
15    mydir = TestBase.compute_mydir(__file__)
16
17    def setUp(self):
18        # Call super's setUp().
19        TestBase.setUp(self)
20        # Find the line number to break at.
21        self.line = line_number('main.cpp', '// Set break point at this line.')
22
23    def test_with_run_command(self):
24        """Test that file and class static variables display correctly."""
25        self.build()
26        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
27
28        lldbutil.run_break_set_by_file_and_line(
29            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
30
31        self.runCmd("run", RUN_SUCCEEDED)
32
33        # The stop reason of the thread should be breakpoint.
34        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
35                    substrs=['stopped',
36                             'stop reason = breakpoint'])
37
38        # Global variables are no longer displayed with the "frame variable"
39        # command.
40        self.expect(
41            'target variable A::g_points',
42            VARIABLES_DISPLAYED_CORRECTLY,
43            patterns=['\(PointType \[[1-9]*\]\) A::g_points = {'])
44        self.expect('target variable g_points', VARIABLES_DISPLAYED_CORRECTLY,
45                    substrs=['(PointType [2]) g_points'])
46
47        # On Mac OS X, gcc 4.2 emits the wrong debug info for A::g_points.
48        # A::g_points is an array of two elements.
49        if self.platformIsDarwin() or self.getPlatform() == "linux":
50            self.expect(
51                "target variable A::g_points[1].x",
52                VARIABLES_DISPLAYED_CORRECTLY,
53                startstr="(int) A::g_points[1].x = 11")
54
55    @expectedFailureAll(
56        compiler=["gcc"],
57        bugnumber="Compiler emits incomplete debug info")
58    @expectedFailureAll(
59        compiler=["clang"],
60        compiler_version=["<", "3.9"],
61        bugnumber='llvm.org/pr20550')
62    def test_with_run_command_complete(self):
63        """
64        Test that file and class static variables display correctly with
65        complete debug information.
66        """
67        self.build()
68        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
69        self.assertTrue(target, VALID_TARGET)
70
71        # Global variables are no longer displayed with the "frame variable"
72        # command.
73        self.expect(
74            'target variable A::g_points',
75            VARIABLES_DISPLAYED_CORRECTLY,
76            patterns=[
77                '\(PointType \[[1-9]*\]\) A::g_points = {', '(x = 1, y = 2)',
78                '(x = 11, y = 22)'
79            ])
80
81        # Ensure that we take the context into account and only print
82        # A::g_points.
83        self.expect(
84            'target variable A::g_points',
85            VARIABLES_DISPLAYED_CORRECTLY,
86            matching=False,
87            patterns=['(x = 3, y = 4)', '(x = 33, y = 44)'])
88
89        # Finally, ensure that we print both points when not specifying a
90        # context.
91        self.expect(
92            'target variable g_points',
93            VARIABLES_DISPLAYED_CORRECTLY,
94            substrs=[
95                '(PointType [2]) g_points', '(x = 1, y = 2)',
96                '(x = 11, y = 22)', '(x = 3, y = 4)', '(x = 33, y = 44)'
97            ])
98
99    @expectedFailureAll(
100        compiler=["gcc"],
101        bugnumber="Compiler emits incomplete debug info")
102    @expectedFailureAll(
103        compiler=["clang"],
104        compiler_version=["<", "3.9"],
105        bugnumber='llvm.org/pr20550')
106    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
107    @add_test_categories(['pyapi'])
108    def test_with_python_api(self):
109        """Test Python APIs on file and class static variables."""
110        self.build()
111        exe = self.getBuildArtifact("a.out")
112
113        target = self.dbg.CreateTarget(exe)
114        self.assertTrue(target, VALID_TARGET)
115
116        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
117        self.assertTrue(breakpoint, VALID_BREAKPOINT)
118
119        # Now launch the process, and do not stop at entry point.
120        process = target.LaunchSimple(
121            None, None, self.get_process_working_directory())
122        self.assertTrue(process, PROCESS_IS_VALID)
123
124        # The stop reason of the thread should be breakpoint.
125        thread = lldbutil.get_stopped_thread(
126            process, lldb.eStopReasonBreakpoint)
127        self.assertIsNotNone(thread)
128
129        # Get the SBValue of 'A::g_points' and 'g_points'.
130        frame = thread.GetFrameAtIndex(0)
131
132        # arguments =>     False
133        # locals =>        False
134        # statics =>       True
135        # in_scope_only => False
136        valList = frame.GetVariables(False, False, True, False)
137
138        for val in valList:
139            self.DebugSBValue(val)
140            name = val.GetName()
141            self.assertTrue(name in ['g_points', 'A::g_points'])
142            if name == 'g_points':
143                self.assertTrue(
144                    val.GetValueType() == lldb.eValueTypeVariableStatic)
145                self.assertEqual(val.GetNumChildren(), 2)
146            elif name == 'A::g_points':
147                self.assertTrue(
148                    val.GetValueType() == lldb.eValueTypeVariableGlobal)
149                self.assertEqual(val.GetNumChildren(), 2)
150                child1 = val.GetChildAtIndex(1)
151                self.DebugSBValue(child1)
152                child1_x = child1.GetChildAtIndex(0)
153                self.DebugSBValue(child1_x)
154                self.assertTrue(child1_x.GetTypeName() == 'int' and
155                                child1_x.GetValue() == '11')
156
157        # SBFrame.FindValue() should also work.
158        val = frame.FindValue("A::g_points", lldb.eValueTypeVariableGlobal)
159        self.DebugSBValue(val)
160        self.assertTrue(val.GetName() == 'A::g_points')
161
162        # Also exercise the "parameter" and "local" scopes while we are at it.
163        val = frame.FindValue("argc", lldb.eValueTypeVariableArgument)
164        self.DebugSBValue(val)
165        self.assertTrue(val.GetName() == 'argc')
166
167        val = frame.FindValue("argv", lldb.eValueTypeVariableArgument)
168        self.DebugSBValue(val)
169        self.assertTrue(val.GetName() == 'argv')
170
171        val = frame.FindValue("hello_world", lldb.eValueTypeVariableLocal)
172        self.DebugSBValue(val)
173        self.assertTrue(val.GetName() == 'hello_world')
174