[lldb-dap] Migrate all DAP variables test.#208215
Open
da-viper wants to merge 1 commit into
Open
Conversation
migrate TestDAP_variables and TestDAP_variables_children
|
@llvm/pr-subscribers-lldb Author: Ebuka Ezike (da-viper) Changesmigrate TestDAP_variables and TestDAP_variables_children. Patch is 77.51 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/208215.diff 3 Files Affected:
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb_dap/session_helpers.py b/lldb/packages/Python/lldbsuite/test/tools/lldb_dap/session_helpers.py
index 34eb33f03c450..35a2d6c2f281a 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb_dap/session_helpers.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb_dap/session_helpers.py
@@ -1578,7 +1578,9 @@ def get_variables(
count=count,
format=format,
)
- response = self.send_request(args).result()
+ response = self.send_request(args).result(
+ f"failed to get variables for reference: {variablesReference}"
+ )
return response.body.variables
def thread_context_from(self, thread_ref: int | StoppedEvent) -> ThreadContext:
diff --git a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
index 66c8d7f720aef..3fb47323efffa 100644
--- a/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
+++ b/lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py
@@ -3,401 +3,277 @@
"""
import os
-
-import lldbdap_testcase
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-
-
-def make_buffer_verify_dict(start_idx, count, offset=0):
- verify_dict = {}
- for i in range(start_idx, start_idx + count):
- verify_dict["[%i]" % (i)] = {"type": "int", "value": str(i + offset)}
- return verify_dict
-
-
-class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase):
+from typing import List, Optional
+
+from lldbsuite.test import lldbplatformutil
+from lldbsuite.test.decorators import (
+ no_debug_info_test,
+ skipIfAsan,
+ skipIfWindows,
+ skipUnlessDarwin,
+)
+from lldbsuite.test.lldbtest import line_number
+from lldbsuite.test.tools.lldb_dap.dap_types import (
+ EvaluateContext,
+ LaunchArgs,
+ VariablesArgs,
+)
+from lldbsuite.test.tools.lldb_dap.lldb_dap_testcase import DAPTestCaseBase
+from lldbsuite.test.tools.lldb_dap.session_helpers import ExpectEval, ExpectVar
+
+
+def make_expected_buffer(start_idx, count, offset=0):
+ return {
+ f"[{i}]": ExpectVar(type="int", value=str(i + offset))
+ for i in range(start_idx, start_idx + count)
+ }
+
+
+class TestDAP_variables(DAPTestCaseBase):
SHARED_BUILD_TESTCASE = False
- def verify_values(self, verify_dict, actual, varref_dict=None, expression=None):
- if "equals" in verify_dict:
- verify = verify_dict["equals"]
- for key in verify:
- verify_value = verify[key]
- actual_value = actual[key]
- self.assertEqual(
- verify_value,
- actual_value,
- '"%s" keys don\'t match (%s != %s) from:\n%s'
- % (key, actual_value, verify_value, actual),
- )
- if "startswith" in verify_dict:
- verify = verify_dict["startswith"]
- for key in verify:
- verify_value = verify[key]
- actual_value = actual[key]
- startswith = actual_value.startswith(verify_value)
- self.assertTrue(
- startswith,
- ('"%s" value "%s" doesn\'t start with "%s")')
- % (key, actual_value, verify_value),
- )
- if "matches" in verify_dict:
- verify = verify_dict["matches"]
- for key in verify:
- verify_value = verify[key]
- actual_value = actual[key]
- self.assertRegex(
- actual_value,
- verify_value,
- ('"%s" value "%s" doesn\'t match pattern "%s")')
- % (key, actual_value, verify_value),
- )
- if "contains" in verify_dict:
- verify = verify_dict["contains"]
- for key in verify:
- contains_array = verify[key]
- actual_value = actual[key]
- self.assertIsInstance(contains_array, list)
- for verify_value in contains_array:
- self.assertIn(verify_value, actual_value)
- if "missing" in verify_dict:
- missing = verify_dict["missing"]
- for key in missing:
- self.assertNotIn(
- key, actual, 'key "%s" is not expected in %s' % (key, actual)
- )
- isReadOnly = verify_dict.get("readOnly", False)
- attributes = actual.get("presentationHint", {}).get("attributes", [])
- self.assertEqual(
- isReadOnly, "readOnly" in attributes, "%s %s" % (verify_dict, actual)
- )
- hasVariablesReference = "variablesReference" in actual
- varRef = None
- if hasVariablesReference:
- # Remember variable references in case we want to test further
- # by using the evaluate name.
- varRef = actual["variablesReference"]
- if varRef != 0 and varref_dict is not None:
- if expression is None:
- evaluateName = actual["evaluateName"]
- else:
- evaluateName = expression
- varref_dict[evaluateName] = varRef
- if (
- "hasVariablesReference" in verify_dict
- and verify_dict["hasVariablesReference"]
- ):
- self.assertTrue(hasVariablesReference, "verify variable reference")
- if "children" in verify_dict:
- self.assertTrue(
- hasVariablesReference and varRef is not None and varRef != 0,
- ("children verify values specified for " "variable without children"),
- )
-
- response = self.dap_server.request_variables(varRef)
- self.verify_variables(
- verify_dict["children"], response["body"]["variables"], varref_dict
- )
-
- def verify_variables(self, verify_dict, variables, varref_dict=None):
- self.assertGreaterEqual(
- len(variables),
- 1,
- f"No variables to verify, verify_dict={json.dumps(verify_dict, indent=4)}",
- )
- for variable in variables:
- name = variable["name"]
- if not name.startswith("std::"):
- self.assertIn(
- name, verify_dict, 'variable "%s" in verify dictionary' % (name)
- )
- self.verify_values(verify_dict[name], variable, varref_dict)
-
- def darwin_dwarf_missing_obj(self, initCommands):
+ def darwin_dwarf_missing_obj(self, initCommands: Optional[List[str]]):
self.build(debug_info="dwarf")
program = self.getBuildArtifact("a.out")
main_obj = self.getBuildArtifact("main.o")
self.assertTrue(os.path.exists(main_obj))
+
# Delete the main.o file that contains the debug info so we force an
- # error when we run to main and try to get variables
+ # error when we run to main and try to get variables.
os.unlink(main_obj)
-
- self.create_debug_adapter()
self.assertTrue(os.path.exists(program), "executable must exist")
- self.launch(program, initCommands=initCommands)
+ session = self.create_session()
+ with session.configure(
+ LaunchArgs(program=program, initCommands=initCommands)
+ ) as ctx:
+ breakpoint_ids = session.resolve_function_breakpoints(["main"])
+ self.assertEqual(len(breakpoint_ids), 1, "expect one breakpoint")
- functions = ["main"]
- breakpoint_ids = self.set_function_breakpoints(functions)
- self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint")
- self.continue_to_breakpoints(breakpoint_ids)
+ stop_event = session.verify_stopped_on_breakpoint(
+ breakpoint_ids, after=ctx.process_event
+ )
+ thread_id = self.expect_not_none(stop_event.body.threadId)
+ frame = session.thread_context_from(thread_id).top_frame()
- resp = self.dap_server.get_local_variables()
- self.assertFalse(resp["success"], "Expected to fail")
+ var_args = VariablesArgs(variablesReference=frame.locals.variablesReference)
+ error_response = session.send_request(var_args).error()
+ error_body = self.expect_not_none(error_response.body)
+ error_message = self.expect_not_none(error_body.error)
self.assertEqual(
f'debug map object file "{main_obj}" containing debug info does not exist, debug info will not be loaded',
- resp["body"]["error"]["format"],
+ error_message.format,
)
- self.assertTrue(resp["body"]["error"]["showUser"])
+ self.assertTrue(error_message.showUser)
def do_test_scopes_variables_setVariable_evaluate(
self, enableAutoVariableSummaries: bool
):
- """
- Tests the "scopes", "variables", "setVariable", and "evaluate" packets.
- """
+ """Tests the "scopes", "variables", "setVariable", and "evaluate" packets."""
program = self.getBuildArtifact("a.out")
- self.build_and_launch(
- program, enableAutoVariableSummaries=enableAutoVariableSummaries
- )
+ session = self.build_and_create_session()
source = "main.cpp"
breakpoint1_line = line_number(source, "// breakpoint 1")
- lines = [breakpoint1_line]
- # Set breakpoint in the thread function so we can step the threads
- breakpoint_ids = self.set_source_breakpoints(source, lines)
- self.assertEqual(
- len(breakpoint_ids), len(lines), "expect correct number of breakpoints"
+ breakpoint2_line = line_number(source, "// breakpoint 2")
+ breakpoint3_line = line_number(source, "// breakpoint 3")
+
+ launch_args = LaunchArgs(
+ program=program, enableAutoVariableSummaries=enableAutoVariableSummaries
)
- self.continue_to_breakpoints(breakpoint_ids)
- locals = self.dap_server.get_local_variables()
- globals = self.dap_server.get_global_variables()
- buffer_children = make_buffer_verify_dict(0, 16)
- verify_locals = {
- "argc": {
- "equals": {
- "type": "int",
- "value": "1",
- },
- },
- "argv": {
- "equals": {"type": "const char **"},
- "startswith": {"value": "0x"},
- "hasVariablesReference": True,
- },
- "pt": {
- "equals": {
- "type": "PointType",
- },
- "hasVariablesReference": True,
- "children": {
- "x": {"equals": {"type": "int", "value": "11"}},
- "y": {"equals": {"type": "int", "value": "22"}},
- "buffer": {"children": buffer_children, "readOnly": True},
+ with session.configure(launch_args) as ctx:
+ breakpoint_ids = session.resolve_source_breakpoints(
+ source, [breakpoint1_line, breakpoint2_line, breakpoint3_line]
+ )
+
+ bp1, bp2, bp3 = breakpoint_ids
+ stop_event = session.verify_stopped_on_breakpoint(bp1, after=ctx.process_event)
+ thread_id = self.expect_not_none(stop_event.body.threadId)
+ frame = session.top_frame_from(thread_id)
+ local_vars = session.get_variables(frame.locals.variablesReference)
+ global_vars = session.get_variables(frame.globals.variablesReference)
+
+ buffer_children = make_expected_buffer(0, 16)
+ expect_locals = {
+ "argc": ExpectVar(type="int", value="1"),
+ "argv": ExpectVar(type="const char **", startswith="0x", has_var_ref=True),
+ "pt": ExpectVar(
+ type="PointType",
+ has_var_ref=True,
+ read_only=True,
+ children={
+ "x": ExpectVar(type="int", value="11"),
+ "y": ExpectVar(type="int", value="22"),
+ "buffer": ExpectVar(read_only=True, children=buffer_children),
},
- "readOnly": True,
- },
- "valid_str": {},
- "malformed_str": {},
- "x": {"equals": {"type": "int"}},
+ ),
+ "valid_str": ExpectVar(),
+ "malformed_str": ExpectVar(),
+ "x": ExpectVar(type="int"),
}
- verify_globals = {
- "s_local": {"equals": {"type": "float", "value": "2.25"}},
+ s_global = ExpectVar(type="int", value="234")
+ g_global = ExpectVar(type="int", value="123")
+ expect_globals = {
+ "s_local": ExpectVar(type="float", value="2.25"),
}
- s_global = {"equals": {"type": "int", "value": "234"}}
- g_global = {"equals": {"type": "int", "value": "123"}}
if lldbplatformutil.getHostPlatform() == "windows":
- verify_globals["::s_global"] = s_global
- verify_globals["g_global"] = g_global
+ expect_globals["::s_global"] = s_global
+ expect_globals["g_global"] = g_global
else:
- verify_globals["s_global"] = s_global
- verify_globals["::g_global"] = g_global
+ expect_globals["s_global"] = s_global
+ expect_globals["::g_global"] = g_global
+
+ session.verify_variables(local_vars, expect_locals)
+ session.verify_variables(global_vars, expect_globals)
+
+ pt_var = frame.locals["pt"]
+ pt_buffer = pt_var["buffer"]
- varref_dict = {}
- self.verify_variables(verify_locals, locals, varref_dict)
- self.verify_variables(verify_globals, globals, varref_dict)
- # pprint.PrettyPrinter(indent=4).pprint(varref_dict)
# We need to test the functionality of the "variables" request as it
# has optional parameters like "start" and "count" to limit the number
- # of variables that are fetched
- varRef = varref_dict["pt.buffer"]
- response = self.dap_server.request_variables(varRef)
- self.verify_variables(buffer_children, response["body"]["variables"])
- # Verify setting start=0 in the arguments still gets all children
- response = self.dap_server.request_variables(varRef, start=0)
- self.verify_variables(buffer_children, response["body"]["variables"])
- # Verify setting count=0 in the arguments still gets all children.
- # If count is zero, it means to get all children.
- response = self.dap_server.request_variables(varRef, count=0)
- self.verify_variables(buffer_children, response["body"]["variables"])
- # Verify setting count to a value that is too large in the arguments
- # still gets all children, and no more
- response = self.dap_server.request_variables(varRef, count=1000)
- self.verify_variables(buffer_children, response["body"]["variables"])
- # Verify setting the start index and count gets only the children we
- # want
- response = self.dap_server.request_variables(varRef, start=5, count=5)
- self.verify_variables(
- make_buffer_verify_dict(5, 5), response["body"]["variables"]
- )
- # Verify setting the start index to a value that is out of range
- # results in an empty list
- response = self.dap_server.request_variables(varRef, start=32, count=1)
+ # of variables that are fetched.
+ var_ref = pt_buffer.variablesReference
+ children = session.get_variables(var_ref)
+ session.verify_variables(children, buffer_children)
+ # start=0 still gets all children.
+ children = session.get_variables(var_ref, start=0)
+ session.verify_variables(children, buffer_children)
+ # count=0 gets all children.
+ children = session.get_variables(var_ref, count=0)
+ session.verify_variables(children, buffer_children)
+ # An oversized count gets all children, no more.
+ children = session.get_variables(var_ref, count=1000)
+ session.verify_variables(children, buffer_children)
+ # start and count gets only the children we want.
+ children = session.get_variables(var_ref, start=5, count=5)
+ session.verify_variables(children, make_expected_buffer(5, 5))
+ # An out-of-range start gets an empty list.
+ children = session.get_variables(var_ref, start=32, count=1)
self.assertEqual(
- len(response["body"]["variables"]),
- 0,
- "verify we get no variable back for invalid start",
+ len(children), 0, "verify we get no variables back for an invalid start"
)
- # Test evaluate
+ # Test evaluate.
+ if enableAutoVariableSummaries:
+ pt_summary = "{x:11, y:22, buffer:{...}}"
+ buf_summary = "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}"
+ else:
+ pt_summary = "PointType"
+ buf_summary = "int[16]"
+
expressions = {
- "pt.x": {
- "equals": {"result": "11", "type": "int"},
- "hasVariablesReference": False,
- },
- "pt.buffer[2]": {
- "equals": {"result": "2", "type": "int"},
- "hasVariablesReference": False,
- },
- "pt": {
- "equals": {"type": "PointType"},
- "startswith": {
- "result": (
- "{x:11, y:22, buffer:{...}}"
- if enableAutoVariableSummaries
- else "PointType"
- )
- },
- "hasVariablesReference": True,
- },
- "pt.buffer": {
- "equals": {"type": "int[16]"},
- "startswith": {
- "result": (
- "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}"
- if enableAutoVariableSummaries
- else "int[16]"
- )
- },
- "hasVariablesReference": True,
- },
- "argv": {
- "equals": {"type": "const char **"},
- "startswith": {"result": "0x"},
- "hasVariablesReference": True,
- },
- "argv[0]": {
- "equals": {"type": "const char *"},
- "startswith": {"result": "0x"},
- "hasVariablesReference": True,
- },
- "2+3": {
- "equals": {"result": "5", "type": "int"},
- "hasVariablesReference": False,
- },
+ "pt.x": ExpectEval(type="int", result="11", has_var_ref=False),
+ "pt.buffer[2]": ExpectEval(type="int", result="2", has_var_ref=False),
+ "pt": ExpectEval(type="PointType", startswith=pt_summary, has_var_ref=True),
+ "pt.buffer": ExpectEval(
+ type="int[16]",
+ startswith=buf_summary,
+ has_var_ref=True,
+ ),
+ "argv": ExpectEval(type="const char **", startswith="0x", has_var_ref=True),
+ "argv[0]": ExpectEval(
+ type="const char *", startswith="0x", has_var_ref=True
+ ),
+ "2+3": ExpectEval(type="int", result="5", has_var_ref=False),
}
- for expression in expressions:
- response = self.dap_server.request_evaluate(expression)
- self.verify_values(expressions[expression], response["body"])
+ for expression, expected in expressions.items():
+ expr_result = frame.evaluate(expression)
+ session.verify_evaluate(expr_result, expected)
- # Test setting variables
- self.set_local("argc", 123)
- argc = self.get_local_as_int("argc")
- self.assertEqual(argc, 123, "verify argc was set to 123 (123 != %i)" % (argc))
+ # Test setting variables.
+ self.expect_success(frame.locals.set("argc", 123))
+ argc = frame.locals["argc"].value_as_int
+ self.assertEqual(argc, 123, f"verify argc was set to 123 (123 != {argc})")
- self.set_local("argv", 0x1234)
- argv = self.get_local_as_int("argv")
+ ...
[truncated]
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
migrate TestDAP_variables and TestDAP_variables_children.