test: versioned reader for DFG Re20 result.json (schema 1 and 2)
read_result() returns cases/provenance for the old bare-list receipts and
the new schema-2 object, and rejects unknown schemas. Existing evidence
(e.g. 70f6617) and its digest scripts stay valid for schema 1; queue and
digest scripts must use read_result(...)['cases'] for new receipts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2220cdd157
commit
c33af7a66d
3 files changed
+35
-1
No files matched your search
@@ -48,5 +48,7 @@ The uniform D80 control separates method error from refinement error. `--plan` w
|
|||||||
(per case: lattice parameters, every sample, window ranges, status, verdict).
|
(per case: lattice parameters, every sample, window ranges, status, verdict).
|
||||||
Receipts: `plan.json` and `result.json` carry `schema` 2 and `provenance` (HEAD, src tree,
|
Receipts: `plan.json` and `result.json` carry `schema` 2 and `provenance` (HEAD, src tree,
|
||||||
runner hash; clean checkout required, refused if it changes during the run). Receipts
|
runner hash; clean checkout required, refused if it changes during the run). Receipts
|
||||||
written before this (schema 1, e.g. evidence 70f6617) are a bare list of cases.
|
written before this (schema 1, e.g. evidence 70f6617) are a bare list of cases. Read both
|
||||||
|
with `run_dfg_re20.read_result(path)` (`["cases"][0]` replaces the old `[0]`); existing
|
||||||
|
evidence scripts stay valid for schema-1 receipts and need this reader for new ones.
|
||||||
Host contract tests: `tests/unit/test_dfg_re20.py`.
|
Host contract tests: `tests/unit/test_dfg_re20.py`.
|
||||||
@@ -85,6 +85,23 @@ class Re20Provenance(unittest.TestCase):
|
|||||||
self.assertFalse(record["checkout_dirty"])
|
self.assertFalse(record["checkout_dirty"])
|
||||||
self.assertEqual(v.RESULT_SCHEMA, 2)
|
self.assertEqual(v.RESULT_SCHEMA, 2)
|
||||||
|
|
||||||
|
def test_reader_accepts_both_schemas_and_rejects_unknown(self):
|
||||||
|
import json
|
||||||
|
import tempfile
|
||||||
|
from pathlib import Path
|
||||||
|
case = dict(case="refined", status="NOT_STEADY", verdict=None, rows=[])
|
||||||
|
with tempfile.TemporaryDirectory() as d:
|
||||||
|
old, new, bad = Path(d, "old.json"), Path(d, "new.json"), Path(d, "bad.json")
|
||||||
|
old.write_text(json.dumps([case]))
|
||||||
|
new.write_text(json.dumps(dict(schema=2, provenance=dict(src_tree="a" * 40),
|
||||||
|
cases=[case])))
|
||||||
|
bad.write_text(json.dumps(dict(schema=3, cases=[case])))
|
||||||
|
self.assertEqual(v.read_result(old), dict(schema=1, provenance=None, cases=[case]))
|
||||||
|
self.assertEqual(v.read_result(new)["cases"][0], case)
|
||||||
|
self.assertEqual(v.read_result(new)["provenance"]["src_tree"], "a" * 40)
|
||||||
|
with self.assertRaisesRegex(ValueError, "unknown DFG Re20 result schema"):
|
||||||
|
v.read_result(bad)
|
||||||
|
|
||||||
def test_dirty_checkout_is_refused(self):
|
def test_dirty_checkout_is_refused(self):
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
with patch("source_provenance.subprocess.check_output",
|
with patch("source_provenance.subprocess.check_output",
|
||||||
|
|||||||
@@ -108,6 +108,21 @@ def summarize(rows):
|
|||||||
verdict=inside)
|
verdict=inside)
|
||||||
|
|
||||||
|
|
||||||
|
def read_result(path):
|
||||||
|
"""Cases and provenance from a result.json of either schema.
|
||||||
|
|
||||||
|
Schema 1 (receipts before RESULT_SCHEMA=2, e.g. evidence 70f6617) is a bare list of
|
||||||
|
cases without provenance; schema 2 is {schema, provenance, cases}. Readers that
|
||||||
|
indexed [0] on schema 1 must use read_result(path)["cases"][0].
|
||||||
|
"""
|
||||||
|
data = json.loads(Path(path).read_text())
|
||||||
|
if isinstance(data, list):
|
||||||
|
return dict(schema=1, provenance=None, cases=data)
|
||||||
|
if not isinstance(data, dict) or data.get("schema") != RESULT_SCHEMA:
|
||||||
|
raise ValueError(f"unknown DFG Re20 result schema: {data.get('schema') if isinstance(data, dict) else type(data).__name__}")
|
||||||
|
return dict(schema=RESULT_SCHEMA, provenance=data["provenance"], cases=data["cases"])
|
||||||
|
|
||||||
|
|
||||||
def healthy(row):
|
def healthy(row):
|
||||||
return row["max_mach"] <= 0.2 and row["rho_min"] >= 0.5 and row["rho_max"] <= 1.5
|
return row["max_mach"] <= 0.2 and row["rho_min"] >= 0.5 and row["rho_max"] <= 1.5
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user