From 157394267336e0c13133dd6a8f1f66bdcd9686fc Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 27 Oct 2026 10:15:10 +0000 Subject: [PATCH] test: ledger comparator compares labels exactly and numbers with NaN-equality same_summary applied np.array_equal(equal_nan=True) to string metadata ('last_base_step'), a TypeError on the first D/B vs B/B ledger compare. Numbers (bool/int/float/complex) still compare exactly with equal shapes and NaN-equality; other values (window labels) compare by dtype and value. New host test: a summary with string metadata equals itself, and changing the window label, an integer, a nested float, a scalar or a NaN-bearing array is detected in both directions. No assertion removed, no tolerance. Co-Authored-By: Claude Opus 5.5 --- .../multigrid/test_refinement_blocked_base.py | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/validation/multigrid/test_refinement_blocked_base.py b/tests/validation/multigrid/test_refinement_blocked_base.py index 1fafa99..5ecf3ae 100644 --- a/tests/validation/multigrid/test_refinement_blocked_base.py +++ b/tests/validation/multigrid/test_refinement_blocked_base.py @@ -362,10 +362,24 @@ def same_summary(a, b): return a.keys() == b.keys() and all(same_summary(a[k], b[k]) for k in a) if isinstance(a, (list, tuple)): return len(a) == len(b) and all(same_summary(x, y) for x, y in zip(a, b)) - return np.array_equal(np.asarray(a), np.asarray(b), equal_nan=True) + a, b = np.asarray(a), np.asarray(b) + if a.dtype.kind in "biufc" and b.dtype.kind in "biufc": + return a.shape == b.shape and np.array_equal(a, b, equal_nan=True) + return a.dtype == b.dtype and np.array_equal(a, b) # labels such as the window name class DenseBlockedRouteCPU(unittest.TestCase): + def test_same_summary_compares_labels_and_every_number(self): + ledger = {"window": "last_base_step", "time_start": 3, "total": {"force": [1.0, -2.0], + "torque": 0.5}, "aperture": {"force": np.array([np.nan, 1.0])}} + self.assertTrue(same_summary(ledger, replace_value(ledger, ()))) + for path, value in ((("window",), "last_substep"), (("time_start",), 4), + (("total", "force"), [1.0, -2.000001]), (("total", "torque"), 0.25), + (("aperture", "force"), np.array([0.0, 1.0]))): + with self.subTest(path=path): + self.assertFalse(same_summary(ledger, replace_value(ledger, path, value))) + self.assertFalse(same_summary(replace_value(ledger, path, value), ledger)) + def test_route_capability_matrix(self): context = Mock(activate=Mock(side_effect=AssertionError("CUDA reached"))) periodic = config("periodic") @@ -389,6 +403,14 @@ class DenseBlockedRouteCPU(unittest.TestCase): context.activate.assert_not_called() +def replace_value(tree, path, value=None): + """Deep copy of a nested dict with the item at ``path`` replaced (no change for ()).""" + if isinstance(tree, dict): + return {k: (value if path == (k,) else replace_value(v, path[1:], value) if path[:1] == (k,) + else replace_value(v, (), None)) for k, v in tree.items()} + return np.array(tree, copy=True) if isinstance(tree, np.ndarray) else tree + + class DenseBlockedRouteParity(unittest.TestCase): """D/D vs D/B vs B/B, unshifted SRT, one circle or one velocity Jet; see module docstring."""