1"""
2Test lldb data formatter subsystem.
3"""
4
5import os
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class SkipSummaryDataFormatterTestCase(TestBase):
13
14    @expectedFailureAll(
15        oslist=["windows"],
16        bugnumber="llvm.org/pr24462, Data formatters have problems on Windows")
17    def test_with_run_command(self):
18        """Test data formatter commands."""
19        self.build()
20        self.data_formatter_commands()
21
22    def setUp(self):
23        # Call super's setUp().
24        TestBase.setUp(self)
25        # Find the line number to break at.
26        self.line = line_number('main.cpp', '// Set break point at this line.')
27
28    def data_formatter_commands(self):
29        """Test that that file and class static variables display correctly."""
30        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
31
32        #import lldbsuite.test.lldbutil as lldbutil
33        lldbutil.run_break_set_by_file_and_line(
34            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
35
36        self.runCmd("run", RUN_SUCCEEDED)
37
38        # The stop reason of the thread should be breakpoint.
39        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
40                    substrs=['stopped',
41                             'stop reason = breakpoint'])
42
43        # This is the function to remove the custom formats in order to have a
44        # clean slate for the next test case.
45        def cleanup():
46            self.runCmd('type format clear', check=False)
47            self.runCmd('type summary clear', check=False)
48
49        # Execute the cleanup function during test case tear down.
50        self.addTearDownHook(cleanup)
51
52        # Setup the summaries for this scenario
53        #self.runCmd("type summary add --summary-string \"${var._M_dataplus._M_p}\" std::string")
54        self.runCmd(
55            "type summary add --summary-string \"Level 1\" \"DeepData_1\"")
56        self.runCmd(
57            "type summary add --summary-string \"Level 2\" \"DeepData_2\" -e")
58        self.runCmd(
59            "type summary add --summary-string \"Level 3\" \"DeepData_3\"")
60        self.runCmd(
61            "type summary add --summary-string \"Level 4\" \"DeepData_4\"")
62        self.runCmd(
63            "type summary add --summary-string \"Level 5\" \"DeepData_5\"")
64
65        # Default case, just print out summaries
66        self.expect('frame variable',
67                    substrs=['(DeepData_1) data1 = Level 1',
68                             '(DeepData_2) data2 = Level 2 {',
69                             'm_child1 = Level 3',
70                             'm_child2 = Level 3',
71                             'm_child3 = Level 3',
72                             'm_child4 = Level 3',
73                             '}'])
74
75        # Skip the default (should be 1) levels of summaries
76        self.expect('frame variable --no-summary-depth',
77                    substrs=['(DeepData_1) data1 = {',
78                             'm_child1 = 0x',
79                             '}',
80                             '(DeepData_2) data2 = {',
81                             'm_child1 = Level 3',
82                             'm_child2 = Level 3',
83                             'm_child3 = Level 3',
84                             'm_child4 = Level 3',
85                             '}'])
86
87        # Now skip 2 levels of summaries
88        self.expect('frame variable --no-summary-depth=2',
89                    substrs=['(DeepData_1) data1 = {',
90                             'm_child1 = 0x',
91                             '}',
92                             '(DeepData_2) data2 = {',
93                             'm_child1 = {',
94                             'm_child1 = 0x',
95                             'Level 4',
96                             'm_child2 = {',
97                             'm_child3 = {',
98                             '}'])
99
100        # Check that no "Level 3" comes out
101        self.expect(
102            'frame variable data1.m_child1 --no-summary-depth=2',
103            matching=False,
104            substrs=['Level 3'])
105
106        # Now expand a pointer with 2 level of skipped summaries
107        self.expect('frame variable data1.m_child1 --no-summary-depth=2',
108                    substrs=['(DeepData_2 *) data1.m_child1 = 0x'])
109
110        # Deref and expand said pointer
111        self.expect('frame variable *data1.m_child1 --no-summary-depth=2',
112                    substrs=['(DeepData_2) *data1.m_child1 = {',
113                             'm_child2 = {',
114                             'm_child1 = 0x',
115                             'Level 4',
116                             '}'])
117
118        # Expand an expression, skipping 2 layers of summaries
119        self.expect(
120            'frame variable data1.m_child1->m_child2 --no-summary-depth=2',
121            substrs=[
122                '(DeepData_3) data1.m_child1->m_child2 = {',
123                'm_child2 = {',
124                'm_child1 = Level 5',
125                'm_child2 = Level 5',
126                'm_child3 = Level 5',
127                '}'])
128
129        # Expand same expression, skipping only 1 layer of summaries
130        self.expect(
131            'frame variable data1.m_child1->m_child2 --no-summary-depth=1',
132            substrs=[
133                '(DeepData_3) data1.m_child1->m_child2 = {',
134                'm_child1 = 0x',
135                'Level 4',
136                'm_child2 = Level 4',
137                '}'])
138
139        # Bad debugging info on SnowLeopard gcc (Apple Inc. build 5666).
140        # Skip the following tests if the condition is met.
141        if self.getCompiler().endswith('gcc') and not self.getCompiler().endswith('llvm-gcc'):
142            import re
143            gcc_version_output = system(
144                [[lldbutil.which(self.getCompiler()), "-v"]])
145            self.trace("my output:", gcc_version_output)
146            for line in gcc_version_output.split(os.linesep):
147                m = re.search('\(Apple Inc\. build ([0-9]+)\)', line)
148                self.trace("line:", line)
149                if m:
150                    gcc_build = int(m.group(1))
151                    self.trace("gcc build:", gcc_build)
152                    if gcc_build >= 5666:
153                        # rdar://problem/9804600"
154                        self.skipTest(
155                            "rdar://problem/9804600 wrong namespace for std::string in debug info")
156
157        # Expand same expression, skipping 3 layers of summaries
158        self.expect(
159            'frame variable data1.m_child1->m_child2 --show-types --no-summary-depth=3',
160            substrs=[
161                '(DeepData_3) data1.m_child1->m_child2 = {',
162                'm_some_text = "Just a test"',
163                'm_child2 = {',
164                'm_some_text = "Just a test"'])
165
166        # Change summary and expand, first without --no-summary-depth then with
167        # --no-summary-depth
168        self.runCmd(
169            "type summary add --summary-string \"${var.m_some_text}\" DeepData_5")
170
171        self.expect('fr var data2.m_child4.m_child2.m_child2', substrs=[
172                    '(DeepData_5) data2.m_child4.m_child2.m_child2 = "Just a test"'])
173
174        self.expect(
175            'fr var data2.m_child4.m_child2.m_child2 --no-summary-depth',
176            substrs=[
177                '(DeepData_5) data2.m_child4.m_child2.m_child2 = {',
178                'm_some_text = "Just a test"',
179                '}'])
180