llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Ebuka Ezike (da-viper) <details> <summary>Changes</summary> migrate 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: - (modified) lldb/packages/Python/lldbsuite/test/tools/lldb_dap/session_helpers.py (+3-1) - (modified) lldb/test/API/tools/lldb-dap/variables/TestDAP_variables.py (+613-846) - (modified) lldb/test/API/tools/lldb-dap/variables/children/TestDAP_variables_children.py (+54-68) ``````````diff 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] `````````` </details> https://github.com/llvm/llvm-project/pull/208215 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
