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    @expectedFailureAll(
14        oslist=["windows"],
15        bugnumber="llvm.org/pr24462, Data formatters have problems on Windows",
16    )
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
37        self.runCmd("run", RUN_SUCCEEDED)
38
39        # The stop reason of the thread should be breakpoint.
40        self.expect(
41            "thread list",
42            STOPPED_DUE_TO_BREAKPOINT,
43            substrs=["stopped", "stop reason = breakpoint"],
44        )
45
46        # This is the function to remove the custom formats in order to have a
47        # clean slate for the next test case.
48        def cleanup():
49            self.runCmd("type format clear", check=False)
50            self.runCmd("type summary clear", check=False)
51
52        # Execute the cleanup function during test case tear down.
53        self.addTearDownHook(cleanup)
54
55        # Setup the summaries for this scenario
56        # self.runCmd("type summary add --summary-string \"${var._M_dataplus._M_p}\" std::string")
57        self.runCmd('type summary add --summary-string "Level 1" "DeepData_1"')
58        self.runCmd('type summary add --summary-string "Level 2" "DeepData_2" -e')
59        self.runCmd('type summary add --summary-string "Level 3" "DeepData_3"')
60        self.runCmd('type summary add --summary-string "Level 4" "DeepData_4"')
61        self.runCmd('type summary add --summary-string "Level 5" "DeepData_5"')
62
63        # Default case, just print out summaries
64        self.expect(
65            "frame variable",
66            substrs=[
67                "(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        )
76
77        # Skip the default (should be 1) levels of summaries
78        self.expect(
79            "frame variable --no-summary-depth",
80            substrs=[
81                "(DeepData_1) data1 = {",
82                "m_child1 = 0x",
83                "}",
84                "(DeepData_2) data2 = {",
85                "m_child1 = Level 3",
86                "m_child2 = Level 3",
87                "m_child3 = Level 3",
88                "m_child4 = Level 3",
89                "}",
90            ],
91        )
92
93        # Now skip 2 levels of summaries
94        self.expect(
95            "frame variable --no-summary-depth=2",
96            substrs=[
97                "(DeepData_1) data1 = {",
98                "m_child1 = 0x",
99                "}",
100                "(DeepData_2) data2 = {",
101                "m_child1 = {",
102                "m_child1 = 0x",
103                "Level 4",
104                "m_child2 = {",
105                "m_child3 = {",
106                "}",
107            ],
108        )
109
110        # Check that no "Level 3" comes out
111        self.expect(
112            "frame variable data1.m_child1 --no-summary-depth=2",
113            matching=False,
114            substrs=["Level 3"],
115        )
116
117        # Now expand a pointer with 2 level of skipped summaries
118        self.expect(
119            "frame variable data1.m_child1 --no-summary-depth=2",
120            substrs=["(DeepData_2 *) data1.m_child1 = 0x"],
121        )
122
123        # Deref and expand said pointer
124        self.expect(
125            "frame variable *data1.m_child1 --no-summary-depth=2",
126            substrs=[
127                "(DeepData_2) *data1.m_child1 = {",
128                "m_child2 = {",
129                "m_child1 = 0x",
130                "Level 4",
131                "}",
132            ],
133        )
134
135        # Expand an expression, skipping 2 layers of summaries
136        self.expect(
137            "frame variable data1.m_child1->m_child2 --no-summary-depth=2",
138            substrs=[
139                "(DeepData_3) data1.m_child1->m_child2 = {",
140                "m_child2 = {",
141                "m_child1 = Level 5",
142                "m_child2 = Level 5",
143                "m_child3 = Level 5",
144                "}",
145            ],
146        )
147
148        # Expand same expression, skipping only 1 layer of summaries
149        self.expect(
150            "frame variable data1.m_child1->m_child2 --no-summary-depth=1",
151            substrs=[
152                "(DeepData_3) data1.m_child1->m_child2 = {",
153                "m_child1 = 0x",
154                "Level 4",
155                "m_child2 = Level 4",
156                "}",
157            ],
158        )
159
160        # Expand same expression, skipping 3 layers of summaries
161        self.expect(
162            "frame variable data1.m_child1->m_child2 --show-types --no-summary-depth=3",
163            substrs=[
164                "(DeepData_3) data1.m_child1->m_child2 = {",
165                'm_some_text = "Just a test"',
166                "m_child2 = {",
167                'm_some_text = "Just a test"',
168            ],
169        )
170
171        # Change summary and expand, first without --no-summary-depth then with
172        # --no-summary-depth
173        self.runCmd('type summary add --summary-string "${var.m_some_text}" DeepData_5')
174
175        self.expect(
176            "fr var data2.m_child4.m_child2.m_child2",
177            substrs=['(DeepData_5) data2.m_child4.m_child2.m_child2 = "Just a test"'],
178        )
179
180        self.expect(
181            "fr var data2.m_child4.m_child2.m_child2 --no-summary-depth",
182            substrs=[
183                "(DeepData_5) data2.m_child4.m_child2.m_child2 = {",
184                'm_some_text = "Just a test"',
185                "}",
186            ],
187        )
188