[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