xref: /llvm-project/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py (revision c658d07c4f8210555473c5721e1302f00f9fd25b)
1"""
2Test lldb-dap completions request
3"""
4
5import re
6
7import lldbdap_testcase
8import dap_server
9from lldbsuite.test import lldbutil
10from lldbsuite.test.decorators import *
11from lldbsuite.test.lldbtest import *
12
13
14class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
15    def assertEvaluate(self, expression, regex):
16        self.assertRegex(
17            self.dap_server.request_evaluate(expression, context=self.context)["body"][
18                "result"
19            ],
20            regex,
21        )
22
23    def assertEvaluateFailure(self, expression):
24        self.assertNotIn(
25            "result",
26            self.dap_server.request_evaluate(expression, context=self.context)["body"],
27        )
28
29    def isResultExpandedDescription(self):
30        return self.context == "repl"
31
32    def isExpressionParsedExpected(self):
33        return self.context != "hover"
34
35    def run_test_evaluate_expressions(
36        self, context=None, enableAutoVariableSummaries=False
37    ):
38        """
39        Tests the evaluate expression request at different breakpoints
40        """
41        self.context = context
42        program = self.getBuildArtifact("a.out")
43        self.build_and_launch(
44            program, enableAutoVariableSummaries=enableAutoVariableSummaries
45        )
46        source = "main.cpp"
47        self.set_source_breakpoints(
48            source,
49            [
50                line_number(source, "// breakpoint 1"),
51                line_number(source, "// breakpoint 2"),
52                line_number(source, "// breakpoint 3"),
53                line_number(source, "// breakpoint 4"),
54                line_number(source, "// breakpoint 5"),
55                line_number(source, "// breakpoint 6"),
56                line_number(source, "// breakpoint 7"),
57                line_number(source, "// breakpoint 8"),
58            ],
59        )
60        self.continue_to_next_stop()
61
62        # Expressions at breakpoint 1, which is in main
63        self.assertEvaluate("var1", "20")
64        # Empty expression should equate to the previous expression.
65        if context == "repl":
66            self.assertEvaluate("", "20")
67        else:
68            self.assertEvaluateFailure("")
69        self.assertEvaluate("var2", "21")
70        if context == "repl":
71            self.assertEvaluate("", "21")
72            self.assertEvaluate("", "21")
73        self.assertEvaluate("static_int", "42")
74        self.assertEvaluate("non_static_int", "43")
75        self.assertEvaluate("struct1.foo", "15")
76        self.assertEvaluate("struct2->foo", "16")
77
78        if self.isResultExpandedDescription():
79            self.assertEvaluate(
80                "struct1",
81                r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
82            )
83            self.assertEvaluate("struct2", r"\(my_struct \*\) (struct2|\$\d+) = 0x.*")
84            self.assertEvaluate(
85                "struct3", r"\(my_struct \*\) (struct3|\$\d+) = nullptr"
86            )
87        else:
88            self.assertEvaluate(
89                "struct1",
90                (
91                    re.escape("{foo:15}")
92                    if enableAutoVariableSummaries
93                    else "my_struct @ 0x"
94                ),
95            )
96            self.assertEvaluate(
97                "struct2", "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*"
98            )
99            self.assertEvaluate("struct3", "0x.*0")
100
101        if context == "repl":
102            # In the repl context expressions may be interpreted as lldb
103            # commands since no variables have the same name as the command.
104            self.assertEvaluate("list", r"\(lldb\) list\n.*")
105        else:
106            self.assertEvaluateFailure("list")  # local variable of a_function
107
108        self.assertEvaluateFailure("my_struct")  # type name
109        self.assertEvaluateFailure("int")  # type name
110        self.assertEvaluateFailure("foo")  # member of my_struct
111
112        if self.isExpressionParsedExpected():
113            self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
114            self.assertEvaluate("a_function(1)", "1")
115            self.assertEvaluate("var2 + struct1.foo", "36")
116            self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
117            self.assertEvaluate("foo_var", "44")
118        else:
119            self.assertEvaluateFailure("a_function")
120            self.assertEvaluateFailure("a_function(1)")
121            self.assertEvaluateFailure("var2 + struct1.foo")
122            self.assertEvaluateFailure("foo_func")
123            self.assertEvaluateFailure("foo_var")
124
125        # Expressions at breakpoint 2, which is an anonymous block
126        self.continue_to_next_stop()
127        self.assertEvaluate("var1", "20")
128        self.assertEvaluate("var2", "2")  # different variable with the same name
129        self.assertEvaluate("static_int", "42")
130        self.assertEvaluate(
131            "non_static_int", "10"
132        )  # different variable with the same name
133        if self.isResultExpandedDescription():
134            self.assertEvaluate(
135                "struct1",
136                r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
137            )
138        else:
139            self.assertEvaluate(
140                "struct1",
141                (
142                    re.escape("{foo:15}")
143                    if enableAutoVariableSummaries
144                    else "my_struct @ 0x"
145                ),
146            )
147        self.assertEvaluate("struct1.foo", "15")
148        self.assertEvaluate("struct2->foo", "16")
149
150        if self.isExpressionParsedExpected():
151            self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
152            self.assertEvaluate("a_function(1)", "1")
153            self.assertEvaluate("var2 + struct1.foo", "17")
154            self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
155            self.assertEvaluate("foo_var", "44")
156        else:
157            self.assertEvaluateFailure("a_function")
158            self.assertEvaluateFailure("a_function(1)")
159            self.assertEvaluateFailure("var2 + struct1.foo")
160            self.assertEvaluateFailure("foo_func")
161            self.assertEvaluateFailure("foo_var")
162
163        # Expressions at breakpoint 3, which is inside a_function
164        self.continue_to_next_stop()
165        self.assertEvaluate("list", "42")
166        self.assertEvaluate("static_int", "42")
167        self.assertEvaluate("non_static_int", "43")
168
169        self.assertEvaluateFailure("var1")
170        self.assertEvaluateFailure("var2")
171        self.assertEvaluateFailure("struct1")
172        self.assertEvaluateFailure("struct1.foo")
173        self.assertEvaluateFailure("struct2->foo")
174        self.assertEvaluateFailure("var2 + struct1.foo")
175
176        if self.isExpressionParsedExpected():
177            self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
178            self.assertEvaluate("a_function(1)", "1")
179            self.assertEvaluate("list + 1", "43")
180            self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
181            self.assertEvaluate("foo_var", "44")
182        else:
183            self.assertEvaluateFailure("a_function")
184            self.assertEvaluateFailure("a_function(1)")
185            self.assertEvaluateFailure("list + 1")
186            self.assertEvaluateFailure("foo_func")
187            self.assertEvaluateFailure("foo_var")
188
189        # Now we check that values are updated after stepping
190        self.continue_to_next_stop()
191        self.assertEvaluate("my_vec", "size=2")
192        self.continue_to_next_stop()
193        self.assertEvaluate("my_vec", "size=3")
194
195        self.assertEvaluate("my_map", "size=2")
196        self.continue_to_next_stop()
197        self.assertEvaluate("my_map", "size=3")
198
199        self.assertEvaluate("my_bool_vec", "size=1")
200        self.continue_to_next_stop()
201        self.assertEvaluate("my_bool_vec", "size=2")
202
203        # Test memory read, especially with 'empty' repeat commands.
204        if context == "repl":
205            self.continue_to_next_stop()
206            self.assertEvaluate("memory read -c 1 &my_ints", ".* 05 .*\n")
207            self.assertEvaluate("", ".* 0a .*\n")
208            self.assertEvaluate("", ".* 0f .*\n")
209            self.assertEvaluate("", ".* 14 .*\n")
210            self.assertEvaluate("", ".* 19 .*\n")
211
212    @skipIfWindows
213    def test_generic_evaluate_expressions(self):
214        # Tests context-less expression evaluations
215        self.run_test_evaluate_expressions(enableAutoVariableSummaries=False)
216
217    @skipIfWindows
218    def test_repl_evaluate_expressions(self):
219        # Tests expression evaluations that are triggered from the Debug Console
220        self.run_test_evaluate_expressions("repl", enableAutoVariableSummaries=False)
221
222    @skipIfWindows
223    def test_watch_evaluate_expressions(self):
224        # Tests expression evaluations that are triggered from a watch expression
225        self.run_test_evaluate_expressions("watch", enableAutoVariableSummaries=True)
226
227    @skipIfWindows
228    def test_hover_evaluate_expressions(self):
229        # Tests expression evaluations that are triggered when hovering on the editor
230        self.run_test_evaluate_expressions("hover", enableAutoVariableSummaries=False)
231
232    @skipIfWindows
233    def test_variable_evaluate_expressions(self):
234        # Tests expression evaluations that are triggered in the variable explorer
235        self.run_test_evaluate_expressions("variable", enableAutoVariableSummaries=True)
236