Files
lda-wf/tests/wf_contract_manifest/test_io.py
T

95 lines
2.8 KiB
Python

from __future__ import annotations
import math
from collections.abc import Mapping
from pathlib import Path
from typing import Any
import pytest
import wf_contract_manifest.io as manifest_io
from wf_contract_manifest import (
ManifestDriftError,
canonical_manifest_json,
check_manifest,
manifest_from_openrpc,
write_manifest,
)
from .fixtures import synthetic_openrpc_document
def _manifest():
return manifest_from_openrpc(synthetic_openrpc_document())
def _reverse_mapping_insertions(value: Any) -> Any:
if isinstance(value, Mapping):
return {
key: _reverse_mapping_insertions(child)
for key, child in reversed(list(value.items()))
}
if isinstance(value, list):
return [_reverse_mapping_insertions(item) for item in value]
return value
def test_canonical_json_is_stable_utf8_text_with_trailing_newline() -> None:
first = canonical_manifest_json(_manifest())
second = canonical_manifest_json(_manifest())
assert first == second
assert first.endswith("\n")
assert ' "manifest_version": 1' in first
assert "\\u" not in first
def test_canonical_json_ignores_recursive_mapping_insertion_order() -> None:
manifest = _manifest()
reordered = _reverse_mapping_insertions(manifest)
assert canonical_manifest_json(manifest).encode("utf-8") == (
canonical_manifest_json(reordered).encode("utf-8")
)
@pytest.mark.parametrize("value", [math.nan, math.inf, -math.inf])
def test_canonical_json_rejects_non_finite_numbers(value: float) -> None:
manifest = _manifest()
manifest["components"]["schemas"]["FreeJson"] = {"const": value}
with pytest.raises(ValueError, match="manifest is not canonically serializable"):
canonical_manifest_json(manifest)
def test_write_and_check_round_trip(tmp_path: Path) -> None:
path = tmp_path / "workflow-api.manifest.json"
assert write_manifest(_manifest(), path) == path
check_manifest(_manifest(), path)
assert path.read_bytes() == canonical_manifest_json(_manifest()).encode("utf-8")
def test_default_write_refuses_to_target_a_non_checkout_parent(
monkeypatch: pytest.MonkeyPatch,
) -> None:
missing_marker = manifest_io.REPOSITORY_ROOT / "missing-pyproject.toml"
monkeypatch.setattr(manifest_io, "REPOSITORY_MARKER", missing_marker)
with pytest.raises(RuntimeError, match="repository checkout"):
write_manifest(_manifest())
def test_check_reports_drift_without_mutating_the_file(tmp_path: Path) -> None:
path = tmp_path / "workflow-api.manifest.json"
path.write_text("stale\n", encoding="utf-8")
before = path.read_bytes()
with pytest.raises(
ManifestDriftError, match="python -m wf_contract_manifest write"
):
check_manifest(_manifest(), path)
assert path.read_bytes() == before