Files
clang-p2996/lldb/test/API/tools/lldb-vscode/evaluate/TestVSCode_evaluate.py
Walter Erquinigo 89a81ec205 [lldb-vscode] Display a more descriptive summary for containers and pointers (#65514)
We've been displaying types and addresses for containers, but that's not
very useful information. A better approach is to compose the summary of
containers with the summary of a few of its children.

Not only that, we can dereference simple pointers and references to get
the summary of the pointer variable, which is also better than just
showing an anddress.

And in the rare case where the user wants to inspect the raw address,
they can always use the debug console for that.

For the record, this is very similar to what the CodeLLDB extension
does, and it seems to give a better experience.

An example of the new output:
<img width="494" alt="Screenshot 2023-09-06 at 2 24 27 PM"
src="https://github.com/llvm/llvm-project/assets/1613874/588659b8-421a-4865-8d67-ce4b6182c4f9">

And this is the 
<img width="476" alt="Screenshot 2023-09-06 at 2 46 30 PM"
src="https://github.com/llvm/llvm-project/assets/1613874/5768a52e-a773-449d-9aab-1b2fb2a98035">
old output:
2023-09-06 17:13:27 -04:00

168 lines
6.4 KiB
Python

"""
Test lldb-vscode completions request
"""
import lldbvscode_testcase
import vscode
from lldbsuite.test import lldbutil
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
class TestVSCode_variables(lldbvscode_testcase.VSCodeTestCaseBase):
def assertEvaluate(self, expression, regex):
self.assertRegexpMatches(
self.vscode.request_evaluate(expression, context=self.context)["body"][
"result"
],
regex,
)
def assertEvaluateFailure(self, expression):
self.assertNotIn(
"result",
self.vscode.request_evaluate(expression, context=self.context)["body"],
)
def isExpressionParsedExpected(self):
return self.context != "hover"
def run_test_evaluate_expressions(self, context=None):
"""
Tests the evaluate expression request at different breakpoints
"""
self.context = context
program = self.getBuildArtifact("a.out")
self.build_and_launch(program)
source = "main.cpp"
self.set_source_breakpoints(
source,
[
line_number(source, "// breakpoint 1"),
line_number(source, "// breakpoint 2"),
line_number(source, "// breakpoint 3"),
line_number(source, "// breakpoint 4"),
line_number(source, "// breakpoint 5"),
line_number(source, "// breakpoint 6"),
line_number(source, "// breakpoint 7"),
],
)
self.continue_to_next_stop()
# Expressions at breakpoint 1, which is in main
self.assertEvaluate("var1", "20")
self.assertEvaluate("var2", "21")
self.assertEvaluate("static_int", "42")
self.assertEvaluate("non_static_int", "43")
self.assertEvaluate("struct1", "{foo:15}")
self.assertEvaluate("struct1.foo", "15")
self.assertEvaluate("struct2->foo", "16")
self.assertEvaluateFailure("var") # local variable of a_function
self.assertEvaluateFailure("my_struct") # type name
self.assertEvaluateFailure("int") # type name
self.assertEvaluateFailure("foo") # member of my_struct
if self.isExpressionParsedExpected():
self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
self.assertEvaluate("a_function(1)", "1")
self.assertEvaluate("var2 + struct1.foo", "36")
self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
self.assertEvaluate("foo_var", "44")
else:
self.assertEvaluateFailure("a_function")
self.assertEvaluateFailure("a_function(1)")
self.assertEvaluateFailure("var2 + struct1.foo")
self.assertEvaluateFailure("foo_func")
self.assertEvaluateFailure("foo_var")
# Expressions at breakpoint 2, which is an anonymous block
self.continue_to_next_stop()
self.assertEvaluate("var1", "20")
self.assertEvaluate("var2", "2") # different variable with the same name
self.assertEvaluate("static_int", "42")
self.assertEvaluate(
"non_static_int", "10"
) # different variable with the same name
self.assertEvaluate("struct1", "{foo:15}")
self.assertEvaluate("struct1.foo", "15")
self.assertEvaluate("struct2->foo", "16")
if self.isExpressionParsedExpected():
self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
self.assertEvaluate("a_function(1)", "1")
self.assertEvaluate("var2 + struct1.foo", "17")
self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
self.assertEvaluate("foo_var", "44")
else:
self.assertEvaluateFailure("a_function")
self.assertEvaluateFailure("a_function(1)")
self.assertEvaluateFailure("var2 + struct1.foo")
self.assertEvaluateFailure("foo_func")
self.assertEvaluateFailure("foo_var")
# Expressions at breakpoint 3, which is inside a_function
self.continue_to_next_stop()
self.assertEvaluate("var", "42")
self.assertEvaluate("static_int", "42")
self.assertEvaluate("non_static_int", "43")
self.assertEvaluateFailure("var1")
self.assertEvaluateFailure("var2")
self.assertEvaluateFailure("struct1")
self.assertEvaluateFailure("struct1.foo")
self.assertEvaluateFailure("struct2->foo")
self.assertEvaluateFailure("var2 + struct1.foo")
if self.isExpressionParsedExpected():
self.assertEvaluate("a_function", "0x.*a.out`a_function.*")
self.assertEvaluate("a_function(1)", "1")
self.assertEvaluate("var + 1", "43")
self.assertEvaluate("foo_func", "0x.*a.out`foo_func.*")
self.assertEvaluate("foo_var", "44")
else:
self.assertEvaluateFailure("a_function")
self.assertEvaluateFailure("a_function(1)")
self.assertEvaluateFailure("var + 1")
self.assertEvaluateFailure("foo_func")
self.assertEvaluateFailure("foo_var")
# Now we check that values are updated after stepping
self.continue_to_next_stop()
self.assertEvaluate("my_vec", "size=2")
self.continue_to_next_stop()
self.assertEvaluate("my_vec", "size=3")
self.assertEvaluate("my_map", "size=2")
self.continue_to_next_stop()
self.assertEvaluate("my_map", "size=3")
self.assertEvaluate("my_bool_vec", "size=1")
self.continue_to_next_stop()
self.assertEvaluate("my_bool_vec", "size=2")
@skipIfWindows
@skipIfRemote
def test_generic_evaluate_expressions(self):
# Tests context-less expression evaluations
self.run_test_evaluate_expressions()
@skipIfWindows
@skipIfRemote
def test_repl_evaluate_expressions(self):
# Tests expression evaluations that are triggered from the Debug Console
self.run_test_evaluate_expressions("repl")
@skipIfWindows
@skipIfRemote
def test_watch_evaluate_expressions(self):
# Tests expression evaluations that are triggered from a watch expression
self.run_test_evaluate_expressions("watch")
@skipIfWindows
@skipIfRemote
def test_hover_evaluate_expressions(self):
# Tests expression evaluations that are triggered when hovering on the editor
self.run_test_evaluate_expressions("hover")