[Lldb-commits] [lldb] [lldb-dap] Mirgate TestDAP_evaluate. (PR #212282)

via lldb-commits lldb-commits at lists.llvm.org
Mon Jul 27 08:50:55 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Ebuka Ezike (da-viper)

<details>
<summary>Changes</summary>

rewrite the `assertEvaluate` and `assertEvaluateFailure` helpers to use the already existing `session.verify_evaluate` function. THe helpers are now inlined functions.

---

Patch is 34.37 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/212282.diff


1 Files Affected:

- (modified) lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py (+304-431) 


``````````diff
diff --git a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
index 556168e5adfa8..7c3f698a2db2c 100644
--- a/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
+++ b/lldb/test/API/tools/lldb-dap/evaluate/TestDAP_evaluate.py
@@ -2,500 +2,373 @@
 Test lldb-dap evaluate request
 """
 
-import re
+from typing import Optional
 
-import lldbdap_testcase
 from lldbsuite.test.decorators import skipIfWindows
 from lldbsuite.test.lldbtest import line_number
-from typing import TypedDict, Optional
+from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase
+from lldbsuite.test.tools.lldb_dap.session_helpers import ExpectEval, FrameContext
+from lldbsuite.test.tools.lldb_dap.types import EvaluateContext, LaunchArgs, ValueFormat
 
 
-class EvaluateResponseBody(TypedDict, total=False):
-    result: str
-    variablesReference: int
-    type: Optional[str]
-    memoryReference: Optional[str]
-    valueLocationReference: Optional[int]
+class TestDAP_evaluate(DAPTestCaseBase):
+    # The frame that `assert_eval*` functions calls evaluate in.
+    _eval_frame: Optional[FrameContext] = None
 
+    def set_evaluation_frame(self, frame: Optional[FrameContext]):
+        """Set the frame that `assert_eval*` functions calls evaluate in."""
+        self._eval_frame = frame
 
-class TestDAP_evaluate(lldbdap_testcase.DAPTestCaseBase):
-    def assertEvaluate(
+    def run_evaluate_expressions(
         self,
-        expression,
-        result: str,
-        want_type="",
-        want_varref=False,
-        want_memref=True,
-        want_locref=False,
-        frame_index: Optional[int] = 0,
-        is_hex=None,
+        context: Optional[EvaluateContext] = None,
+        enableAutoVariableSummaries: bool = False,
     ):
-        resp = self.dap_server.request_evaluate(
-            expression, context=self.context, is_hex=is_hex, frameIndex=frame_index
+        self.set_evaluation_frame(None)
+        is_result_expanded = context == "repl"
+        is_result_brief = context == "clipboard"
+        is_result_summary = (
+            not is_result_expanded
+            and not is_result_brief
+            and enableAutoVariableSummaries
         )
-        self.assertTrue(
-            resp["success"],
-            f"Failed to evaluate expression {expression!r} in frame {frame_index}",
-        )
-        body: EvaluateResponseBody = resp["body"]
-        self.assertRegex(
-            body["result"],
-            result,
-            f"Unexpected 'result' for expression {expression!r} in response body {body}",
-        )
-        if want_varref:
-            self.assertNotEqual(
-                body["variablesReference"],
-                0,
-                f"Unexpected 'variablesReference' for expression {expression!r} in response body {body}",
-            )
-        else:
-            self.assertEqual(
-                body["variablesReference"],
-                0,
-                f"Unexpected 'variablesReference' for expression {expression!r} in response body {body}",
-            )
-        if want_type:
-            self.assertEqual(
-                body["type"],
-                want_type,
-                f"Unexpected 'type' for expression {expression!r} in response body {body}",
-            )
-        if want_memref:
-            self.assertIn(
-                "memoryReference",
-                body,
-                f"Unexpected 'memoryReference' for expression {expression!r} in response body {body}",
-            )
-        if want_locref:
-            self.assertIn(
-                "valueLocationReference",
-                body,
-                f"Unexpected 'valueLocationReference' for expression {expression!r} in response body {body}",
-            )
-
-    def assertEvaluateFailure(self, expression):
-        response = self.dap_server.request_evaluate(expression, context=self.context)
-        self.assertFalse(
-            response["success"],
-            f"Expression:'{expression}' should fail in {self.context} context, got {response!r}",
-        )
-        self.assertNotIn(
-            "result",
-            response["body"],
-        )
-
-    def isResultExpandedDescription(self):
-        return self.context == "repl"
+        context_parses_expressions = context != "hover"
+        session = self.build_and_create_session()
 
-    def isResultShortDescription(self):
-        return self.context == "clipboard"
+        def assert_eval(expression: str, matches: str, *, as_hex=False, **expects):
+            fmt = ValueFormat(hex=True) if as_hex else None
+            if eval_frame := self._eval_frame:
+                body = eval_frame.evaluate(expression, context=context, format=fmt)
+            else:
+                body = session.evaluate(expression, context=context, format=fmt)
+            expects.setdefault("has_mem_ref", True)
+            session.verify_evaluate(body, ExpectEval(matches=matches, **expects))
+            return body
 
-    def isExpressionParsedExpected(self):
-        return self.context != "hover"
+        def assert_eval_fails(expression: str):
+            frame_id = self._eval_frame.id if self._eval_frame else None
+            session.do_evaluate(expression, frameId=frame_id, context=context).error(
+                f"expected {expression!r} to fail using {context=!r} in {frame_id=!r}"
+            )
 
-    def run_test_evaluate_expressions(
-        self, context=None, enableAutoVariableSummaries=False
-    ):
-        """
-        Tests the evaluate expression request at different breakpoints
-        """
-        self.context = context
-        program = self.getBuildArtifact("a.out")
-        self.build_and_launch(
-            program,
-            enableAutoVariableSummaries=enableAutoVariableSummaries,
-        )
         source = "main.cpp"
+        program = self.getBuildArtifact("a.out")
         breakpoint_lines = [
-            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"),
-            line_number(source, "// breakpoint 8"),
+            line_number(source, f"// breakpoint 1"),
+            line_number(source, f"// breakpoint 2"),
+            line_number(source, f"// breakpoint 3"),
+            line_number(source, f"// breakpoint 4"),
+            line_number(source, f"// breakpoint 5"),
+            line_number(source, f"// breakpoint 6"),
+            line_number(source, f"// breakpoint 7"),
+            line_number(source, f"// breakpoint 8"),
         ]
-        breakpoint_ids = self.set_source_breakpoints(source, breakpoint_lines)
 
-        self.assertEqual(
-            len(breakpoint_ids),
-            len(breakpoint_lines),
-            "Did not resolve all the breakpoints.",
+        launch = LaunchArgs(
+            program, enableAutoVariableSummaries=enableAutoVariableSummaries
         )
-        breakpoint_1 = breakpoint_ids[0]
-        breakpoint_2 = breakpoint_ids[1]
-        breakpoint_3 = breakpoint_ids[2]
-        breakpoint_4 = breakpoint_ids[3]
-        breakpoint_5 = breakpoint_ids[4]
-        breakpoint_6 = breakpoint_ids[5]
-        breakpoint_7 = breakpoint_ids[6]
-        breakpoint_8 = breakpoint_ids[7]
-        self.continue_to_breakpoint(breakpoint_1)
-
-        # Expressions at breakpoint 1, which is in main
-        self.assertEvaluate("var1", "20", want_type="int")
-        # Empty expression should equate to the previous expression.
+        with session.configure(launch) as cfg:
+            bp_ids = session.resolve_source_breakpoints(source, breakpoint_lines)
+        bp1, bp2, bp3, bp4, bp5, bp6, bp7, bp8 = bp_ids
+
+        # Expression at breakpoint 1: In main.
+        stop_event = session.verify_stopped_on_breakpoint(bp1, after=cfg.process_event)
+        main_frames = session.thread_context_from(stop_event).frames(levels=2)
+        main_frame, caller_frame = main_frames[0], main_frames[1]
+        self.set_evaluation_frame(main_frame)
+
+        assert_eval("var1", "20", type="int")
+
+        # In repl context, an empty expression repeats the previous expression.
         if context == "repl":
-            self.assertEvaluate("", "20")
+            assert_eval("", "20")
         else:
-            self.assertEvaluateFailure("")
-        self.assertEvaluate("var2", "21", want_type="int")
+            assert_eval_fails("")
+
+        assert_eval("var2", "21", type="int")
         if context == "repl":
-            self.assertEvaluate("", "21", want_type="int")
-            self.assertEvaluate("", "21", want_type="int")
-        self.assertEvaluate("static_int", "0x0000002a", want_type="int", is_hex=True)
-        self.assertEvaluate(
-            "non_static_int", "0x0000002b", want_type="int", is_hex=True
-        )
-        self.assertEvaluate("struct1.foo", "0x0000000f", want_type="int", is_hex=True)
-        self.assertEvaluate("struct2->foo", "0x00000010", want_type="int", is_hex=True)
-        self.assertEvaluate("static_int", "42", want_type="int")
-        self.assertEvaluate("non_static_int", "43", want_type="int")
-        self.assertEvaluate("struct1.foo", "15", want_type="int")
-        self.assertEvaluate("struct2->foo", "16", want_type="int")
-
-        if self.isResultExpandedDescription():
-            self.assertEvaluate(
-                "struct1",
-                r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
-                want_type="my_struct",
-                want_varref=True,
-            )
-            self.assertEvaluate(
-                "struct2",
-                r"\(my_struct \*\) (struct2|\$\d+) = 0x.*",
-                want_type="my_struct *",
-                want_varref=True,
-            )
-            self.assertEvaluate(
-                "struct3",
-                r"\(my_struct \*\) (struct3|\$\d+) = nullptr",
-                want_type="my_struct *",
-                want_varref=True,
-            )
-        elif self.isResultShortDescription():
-            self.assertEvaluate(
-                "struct1",
-                "(foo = 15)",
-                want_type="my_struct",
-                want_varref=True,
-            )
-            self.assertEvaluate(
-                "struct2",
-                r"0x.*",
-                want_type="my_struct *",
-                want_varref=True,
-            )
-            self.assertEvaluate(
-                "struct3",
-                "nullptr",
-                want_type="my_struct *",
-                want_varref=True,
-            )
+            assert_eval("", "21", type="int")
+            assert_eval("", "21", type="int")
+
+        # Verify hex and decimal formatting.
+        assert_eval("static_int", "0x0000002a", type="int", as_hex=True)
+        assert_eval("static_int", "42", type="int")
+        assert_eval("non_static_int", "0x0000002b", type="int", as_hex=True)
+        assert_eval("non_static_int", "43", type="int")
+        assert_eval("struct1.foo", "0x0000000f", type="int", as_hex=True)
+        assert_eval("struct1.foo", "15", type="int")
+        assert_eval("struct2->foo", "0x00000010", type="int", as_hex=True)
+        assert_eval("struct2->foo", "16", type="int")
+
+        if is_result_expanded:
+            struct1_match = r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)"
+        elif is_result_brief:
+            struct1_match = r"\(foo = 15\)"
+        elif is_result_summary:
+            struct1_match = r"\{foo:15\}"
         else:
-            self.assertEvaluate(
-                "struct1",
-                (re.escape("{foo:15}") if enableAutoVariableSummaries else "my_struct"),
-                want_varref=True,
-            )
-            self.assertEvaluate(
-                "struct2",
-                "0x.* {foo:16}" if enableAutoVariableSummaries else "0x.*",
-                want_varref=True,
-                want_type="my_struct *",
-            )
-            self.assertEvaluate(
-                "struct3", "0x.*0", want_varref=True, want_type="my_struct *"
-            )
+            struct1_match = "my_struct"
+        assert_eval("struct1", struct1_match, type="my_struct", has_var_ref=True)
 
-        if context == "repl" or context is None:
+        if is_result_expanded:
+            struct2_match = r"\(my_struct \*\) (struct2|\$\d+) = 0x.*"
+        elif is_result_summary:
+            struct2_match = r"0x.* \{foo:16\}"
+        else:
+            struct2_match = r"0x.*"
+        assert_eval("struct2", struct2_match, type="my_struct *", has_var_ref=True)
+
+        if is_result_expanded:
+            struct3_match = r"\(my_struct \*\) (struct3|\$\d+) = nullptr"
+        elif is_result_brief:
+            struct3_match = "nullptr"
+        else:
+            struct3_match = r"0x.*0"
+        assert_eval("struct3", struct3_match, type="my_struct *", has_var_ref=True)
+
+        if context in ("repl", None):
             # In repl or unknown context expressions may be interpreted as lldb
             # commands since no variables have the same name as the command.
-            self.assertEvaluate("list", r".*", want_memref=False)
-            # Changing the frame index should not make a difference
-            self.assertEvaluate(
-                "version", r".*lldb.+", want_memref=False, frame_index=1
-            )
-
+            eval_body = main_frame.evaluate("list")
+            session.verify_evaluate(eval_body, matches=r".*", has_mem_ref=False)
+            # Changing the frame should not make a difference.
+            eval_body = caller_frame.evaluate("version")
+            session.verify_evaluate(eval_body, matches=r".*lldb.+", has_mem_ref=False)
         else:
-            self.assertEvaluateFailure("list")  # local variable of a_function
+            assert_eval_fails("list")  # local variable of a_function.
+            assert_eval_fails("version")
 
-        self.assertEvaluateFailure("my_struct")  # type name
-        self.assertEvaluateFailure("int")  # type name
-        self.assertEvaluateFailure("foo")  # member of my_struct
+        # Identifiers and variables not in scope should fail.
+        assert_eval_fails("my_struct")  # struct name.
+        assert_eval_fails("int")  # type name.
+        assert_eval_fails("foo")  # member variable of my_struct.
 
-        if self.isExpressionParsedExpected():
-            self.assertEvaluate(
+        if context_parses_expressions:
+            assert_eval(
                 "a_function",
-                "0x.*a.out`a_function.*",
-                want_type="int (*)(int)",
-                want_varref=True,
-                want_memref=False,
-                want_locref=True,
-            )
-            self.assertEvaluate(
-                "a_function(1)", "1", want_memref=False, want_type="int"
-            )
-            self.assertEvaluate("var2 + struct1.foo", "36", want_memref=False)
-            self.assertEvaluate(
+                r"0x.*a.out`a_function.*",
+                type="int (*)(int)",
+                has_var_ref=True,
+                has_mem_ref=False,
+                has_loc_ref=True,
+            )
+            assert_eval("a_function(1)", "1", type="int", has_mem_ref=False)
+            assert_eval("var2 + struct1.foo", "36", has_mem_ref=False)
+            assert_eval(
                 "foo_func",
-                "0x.*a.out`foo_func.*",
-                want_type="int (*)()",
-                want_varref=True,
-                want_memref=False,
-                want_locref=True,
+                r"0x.*a.out`foo_func.*",
+                type="int (*)()",
+                has_var_ref=True,
+                has_mem_ref=False,
+                has_loc_ref=True,
             )
-            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("(float) var2")
-            self.assertEvaluate("foo_var", "44")
-
-        # Expressions at breakpoint 2, which is an anonymous block
-        self.continue_to_breakpoint(breakpoint_2)
-        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
-        if self.isResultExpandedDescription():
-            self.assertEvaluate(
-                "struct1",
-                r"\(my_struct\) (struct1|\$\d+) = \(foo = 15\)",
-                want_type="my_struct",
-                want_varref=True,
-            )
-        elif self.isResultShortDescription():
-            self.assertEvaluate(
-                "struct1",
-                "(foo = 15)",
-                want_type="my_struct",
-                want_varref=True,
-            )
-        else:
-            self.assertEvaluate(
-                "struct1",
-                (re.escape("{foo:15}") if enableAutoVariableSummaries else "my_struct"),
-                want_type="my_struct",
-                want_varref=True,
-            )
-        self.assertEvaluate("struct1.foo", "15")
-        self.assertEvaluate("struct2->foo", "16")
-
-        if self.isExpressionParsedExpected():
-            self.assertEvaluate(
+            assert_eval_fails("a_function")
+            assert_eval_fails("a_function(1)")
+            assert_eval_fails("var2 + struct1.foo")
+            assert_eval_fails("foo_func")
+            assert_eval_fails("(float) var2")
+
+        # foo_var is a global variable and should evaluate.
+        assert_eval("foo_var", "44")
+
+        # Expressions at breakpoint 2: In an anonymous block.
+        stop_event = session.continue_to_breakpoint(bp2)
+        self.set_evaluation_frame(session.top_frame_from(stop_event))
+
+        assert_eval("var1", "20")
+        assert_eval("var2", "2")  # shadowed variable.
+        assert_eval("static_int", "42")
+        assert_eval("non_static_int", "10")  # shadowed variable.
+        assert_eval("struct1", struct1_match, type="my_struct", has_var_ref=True)
+        assert_eval("struct1.foo", "15")
+        assert_eval("struct2->foo", "16")
+
+        if context_parses_expressions:
+            assert_eval(
                 "a_function",
-                "0x.*a.out`a_function.*",
-                want_type="int (*)(int)",
-                want_varref=True,
-                want_memref=False,
-                want_locref=True,
-            )
-            self.assertEvaluate("a_function(1)", "1", want_memref=False)
-            self.assertEvaluate("var2 + struct1.foo", "17", want_memref=False)
-            self.assertEvaluate(
-                "foo_func", "0x.*a.out`foo_func.*", want_varref=True, want_memref=False
+                r"0x.*a.out`a_function.*",
+                type="int (*)(int)",
+                has_var_ref=True,
+                has_mem_ref=False,
+                has_loc_ref=True,
+            )
+            assert_eval("a_function(1)", "1", has_mem_ref=False)
+            assert_eval("var2 + struct1.foo", "17", has_mem_ref=False)
+            assert_eval(
+                "foo_func",
+                r"0x.*a.out`foo_func.*",
+                has_var_ref=True,
+                has_mem_ref=False,
             )
-            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.assertEvaluate("foo_var", "44")
-
-        # Expressions at breakpoint 3, which is inside a_function
-        self.continue_to_breakpoint(breakpoint_3)
-        self.assertEvaluate("list", "42")
-        self.assertEvaluate("static_int", "42")
-        self.assertEvaluate("non_static_int", "43")
-        # variable from a different frame
-        self.assertEvaluate("var1", "20", frame_index=1)
-
-        if self.isExpressionParsedExp...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/212282


More information about the lldb-commits mailing list