[llvm-branch-commits] [llvm] [Dexter] Add support for aggregate expects in the debugger (PR #202545)

Orlando Cazalet-Hyams via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Jun 15 03:25:15 PDT 2026


================
@@ -6,33 +6,198 @@
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 """Utilities for matching debugger output to script expected values."""
 
-from typing import Any, Dict, List, Union
+from collections import Counter, OrderedDict
+from enum import Enum, IntEnum
+from typing import Any, Dict, List, Optional, Set, Tuple, Union
 
 from dex.dextIR import ValueIR
 from dex.test_script.Nodes import Expect, Value
 
 
+def get_expected_value_set(
+    expected, prepend_tuple: Tuple = ()
+) -> Dict[Tuple[str], int]:
+    """For the given "expected" taken directly from the script YAML, returns the set of all actual expected
+    values, using tuples to represent nested expected values, and mapping each result to the number of times that it
+    appears in the set (giving a count). For example, the expected values of:
+    ```
+    !value foo:
+    - 4
+    - 6
+    - x: 5
+      y: 10
+    - x: 5
+      y: 20
+    ```
+    Would be represented by the dict:
+    ```
+    {
+      (4,): 1,
+      (6,): 1,
+      ("x", 5): 2,
+      ("y", 10): 1,
+      ("y", 20): 1,
+    }
+    ```
+    """
+    result: Dict[Tuple, int] = Counter()
+    if isinstance(expected, list):
+        for ev in expected:
+            result.update(get_expected_value_set(ev, prepend_tuple))
+    elif isinstance(expected, dict):
+        for sub_expect, sub_expected in expected.items():
+            next_prepend = prepend_tuple + (str(sub_expect),)
+            result.update(get_expected_value_set(sub_expected, next_prepend))
+    else:
+        result[prepend_tuple + (str(expected),)] += 1
+    return result
+
+
+class MatchResult(IntEnum):
+    FALSE = 0
+    PARTIAL = 1
+    TRUE = 2
+
+
 class DebuggerExpectMatch:
     """Class that represents the match between a particular expected value for an Expect node and the actual debugger
-    output corresponding to the watched value for that node."""
+    output corresponding to the watched value for that node.
+    `actual_result` is None if `actual` or `expect.get_variable_result(actual)` is None,
+    Otherwise, if `expected` is a dict, then `actual_result` is a dict[str, DebuggerExpectMatch],
+    Otherwise, `actual_result` is a str.
+    """
 
-    def __init__(self, expect: Expect, expected, actual: ValueIR):
+    def __init__(self, expect: Expect, expected, actual: Optional[ValueIR]):
         self.expect = expect
         self.expected = expected
         self.actual = actual
-        self.actual_result = self.expect.get_variable_result(self.actual)
-        self.match_result = (
-            self.expected is not None and str(self.expected) == self.actual_result
+        self.actual_result, self.match_result = self._get_actual_result()
+        self.match_distance = self._get_match_distance()
+
+    def _get_actual_result(
+        self,
+    ) -> Tuple[Union[str, Dict[str, "DebuggerExpectMatch"], None], MatchResult]:
+        if isinstance(self.expected, dict):
+            sub_expect_results: Dict[str, DebuggerExpectMatch] = OrderedDict()
+            for sub_expect, sub_expected in self.expected.items():
+                value = (
+                    None
+                    if self.actual is None
+                    else next(
+                        (
+                            sub_value
+                            for sub_value in self.actual.sub_values
----------------
OCHyams wrote:

Are the recursive sub_values flattened in `actual.sub_values`?

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


More information about the llvm-branch-commits mailing list