"""Conformance runner tests: pass/fail accounting and tamper detection.""" from __future__ import annotations import pytest from fpcf import runner, vectors as fpcf_vectors from fpcf.errors import ConformanceError from helpers import ( DEFAULT_SEED, load_json, manifest_entries, report_counts, tamper_body, valid_single_ops, write_json, ) def _fresh_suite(tmp_path): out = tmp_path / "vectors" fpcf_vectors.generate_vectors(out, seed=DEFAULT_SEED) return out def test_pristine_suite_passes_completely(tmp_path): out = _fresh_suite(tmp_path) report = runner.run_vectors(out) total, passed, failed = report_counts(report) manifest = load_json(out / "manifest.json") assert total == len(manifest_entries(manifest)) assert failed == 0 assert passed == total > 0 def test_tampered_valid_vector_is_caught(tmp_path): out = _fresh_suite(tmp_path) manifest = load_json(out / "manifest.json") entry, op = valid_single_ops(out, manifest)[0] write_json(out / entry["file"], tamper_body(op)) report = runner.run_vectors(out) total, passed, failed = report_counts(report) assert failed >= 1 assert passed < total def test_swapped_expectation_is_caught(tmp_path): """Flipping an expected-valid entry to expected-invalid must fail: the vector still verifies, so the runner's expectation is not met.""" out = _fresh_suite(tmp_path) manifest = load_json(out / "manifest.json") flipped = False for entry in manifest_entries(manifest): if entry["expect"] == "valid": entry["expect"] = "invalid" entry["error"] = "ERR_SIG_INVALID" flipped = True break assert flipped write_json(out / "manifest.json", manifest) report = runner.run_vectors(out) _, _, failed = report_counts(report) assert failed >= 1 def test_missing_vector_file_is_an_error(tmp_path): out = _fresh_suite(tmp_path) manifest = load_json(out / "manifest.json") entry = manifest_entries(manifest)[0] (out / entry["file"]).unlink() # The runner may either raise a ConformanceError for a structurally # broken suite, or record the vector as a failure; both are conforming. try: report = runner.run_vectors(out) except ConformanceError: return _, _, failed = report_counts(report) assert failed >= 1 def test_missing_manifest_is_an_error(tmp_path): out = _fresh_suite(tmp_path) (out / "manifest.json").unlink() with pytest.raises(ConformanceError): runner.run_vectors(out) def test_report_results_name_each_vector(tmp_path): out = _fresh_suite(tmp_path) report = runner.run_vectors(out) results = report["results"] if isinstance(report, dict) else report.results manifest = load_json(out / "manifest.json") expected_names = {e["name"] for e in manifest_entries(manifest)} result_names = set() for r in results: name = r["name"] if isinstance(r, dict) else r.name result_names.add(name) assert result_names == expected_names