#!/usr/bin/env python3 """Tests of the reference side's corrections: `python conformance/test_ref.py`. - ref.py compares a big-endian VL sequence by the file's values even though h5py returns them byte-swapped (and records that it corrected them); - ref_bugs.py confirms an object only when its reads disagree. """ import json import os import subprocess import sys import tempfile import unittest import h5py import numpy as np HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, HERE) import ref_bugs # noqa: E402 def ref_objects(path): out = subprocess.run([sys.executable, os.path.join(HERE, "ref.py"), path], capture_output=True, text=True, check=True).stdout return {o["path"]: o for o in json.loads(out)["objects"]} class BigEndianVlen(unittest.TestCase): def test_be_vlen_compared_by_file_values(self): with tempfile.TemporaryDirectory() as d: path = os.path.join(d, "v.h5") with h5py.File(path, "w") as f: for name, order in (("be", ">"), ("le", "<")): t = np.dtype(order + "f4") ds = f.create_dataset(name, (2,), dtype=h5py.vlen_dtype(t)) ds[0] = np.array([1.0, 2.0], dtype=t) ds[1] = np.array([3.0], dtype=t) u = np.dtype(order + "u8") f.attrs.create(name, [np.array([1, 2], dtype=u), np.array([42], dtype=u)], dtype=h5py.vlen_dtype(u)) objs = ref_objects(path) be, le = objs["/be"], objs["/le"] # Same values, so the same canonical hash whatever the file's byte order. self.assertEqual(be["hash"], le["hash"]) self.assertEqual(objs["/"]["attrs"]["be"]["hash"], objs["/"]["attrs"]["le"]["hash"]) self.assertNotIn("ref_fix", le) # And the correction is recorded wherever h5py needed it. import ref if ref.be_vlen_bug(): self.assertEqual(be.get("ref_fix"), ["h5py-be-vlen"]) self.assertEqual(objs["/"]["attrs"]["be"].get("ref_fix"), ["h5py-be-vlen"]) class RefBugsConfirmation(unittest.TestCase): def run_check(self, outcomes): seq = iter(outcomes) saved = ref_bugs.read_once ref_bugs.read_once = lambda *a: next(seq) try: key = next(iter(ref_bugs.READ_BUGS)) with tempfile.TemporaryDirectory() as d: p = os.path.join(d, key[0]) os.makedirs(os.path.dirname(p)) open(p, "wb").close() return ref_bugs.check(d, key) finally: ref_bugs.read_once = saved def test_stable_values_are_not_confirmed(self): r = self.run_check(["values a"] * len(ref_bugs.RUNS)) self.assertFalse(r["confirmed"]) def test_changing_values_are_confirmed(self): r = self.run_check(["values a"] * (len(ref_bugs.RUNS) - 1) + ["values b"]) self.assertTrue(r["confirmed"]) r = self.run_check(["values a"] * (len(ref_bugs.RUNS) - 1) + ["error filter failed"]) self.assertTrue(r["confirmed"]) def test_errors_only_are_not_confirmed(self): # h5py cannot read it at all: nothing it reads, nothing to excuse. r = self.run_check(["error x"] * (len(ref_bugs.RUNS) - 1) + ["error y"]) self.assertFalse(r["confirmed"]) def test_missing_file_is_not_confirmed(self): key = next(iter(ref_bugs.READ_BUGS)) with tempfile.TemporaryDirectory() as d: self.assertFalse(ref_bugs.check(d, key)["confirmed"]) if __name__ == "__main__": unittest.main()