← Files Canonical Memory VerifierARCHIVED FILE
tests/test_cmverify.py
9.45 KB · Sep 30, 2026 · 23:13 UTC
from __future__ import annotations
import importlib.util
import json
import os
import subprocess
import sys
import unittest
from pathlib import Path
from unittest import mock
ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / "skills" / "verify-canonical-memory" / "scripts" / "cmverify.py"
SCHEMA = ROOT / "skills" / "verify-canonical-memory" / "references" / "bundle.schema.json"
INDEX = ROOT / "fixtures" / "fixture-index.json"
DATA = ROOT / "tests" / "data"
SPEC = importlib.util.spec_from_file_location("cmverify_candidate", SCRIPT)
assert SPEC is not None and SPEC.loader is not None
CMV = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(CMV)
class CanonicalMemoryVerifierTests(unittest.TestCase):
def cli(self, *args: str) -> tuple[int, dict]:
env = dict(os.environ)
env["PYTHONDONTWRITEBYTECODE"] = "1"
completed = subprocess.run(
[sys.executable, str(SCRIPT), *args],
cwd=ROOT,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=False,
)
self.assertEqual(completed.stderr, "")
return completed.returncode, json.loads(completed.stdout)
def test_schema_document_is_strict_json(self) -> None:
schema = json.loads(SCHEMA.read_text(encoding="utf-8"))
self.assertEqual(schema["$defs"]["claim"]["properties"]["approval_eligible"]["const"], False)
def test_every_declared_fixture_has_expected_result(self) -> None:
rows = json.loads(INDEX.read_text(encoding="utf-8"))["fixtures"]
self.assertGreaterEqual(len(rows), 8)
for row in rows:
with self.subTest(row=row["fixture"]):
code, output = self.cli("verify", f"fixtures/{row['fixture']}")
self.assertEqual(output["status"], row["expected_status"])
self.assertEqual(code, 0 if row["expected_status"] == "VERIFIED" else 2)
actual_codes = {item["code"] for item in output.get("errors", [])}
self.assertTrue(set(row["required_error_codes"]).issubset(actual_codes))
def test_projection_uses_only_the_superseding_head(self) -> None:
code, output = self.cli("project", "fixtures/valid/supersession-chain")
self.assertEqual(code, 0)
self.assertEqual([item["claim_id"] for item in output["projection"]], ["clm_target_new"])
self.assertIs(output["projection"][0]["approval_eligible"], False)
def test_trace_reaches_final_head_and_source_level_evidence(self) -> None:
code, output = self.cli(
"trace",
"fixtures/valid/supersession-chain",
"clm_target_old",
)
self.assertEqual(code, 0)
trace = output["trace"]
self.assertEqual(trace["final_head_claim_id"], "clm_target_new")
self.assertEqual(len(trace["sources"]), 2)
self.assertTrue(all(item["approval_eligible"] is False for item in trace["claims"]))
def test_trace_missing_claim_fails_closed(self) -> None:
code, output = self.cli("trace", "fixtures/valid/basic", "clm_missing")
self.assertEqual(code, 2)
self.assertEqual(output["errors"][0]["code"], "CMV_CLAIM_NOT_FOUND")
def test_authority_demo_requires_live_host_approval(self) -> None:
code, output = self.cli("demo", "authority-replay")
self.assertEqual(code, 0)
self.assertEqual(output["demo"]["live_approval"], "REQUIRED_FROM_HOST_CONTROL_PLANE")
remembered = output["demo"]["remembered_authority"]
self.assertEqual(len(remembered), 1)
self.assertIs(remembered[0]["approval_eligible"], False)
def test_output_is_byte_deterministic_and_path_free(self) -> None:
first = subprocess.check_output(
[sys.executable, str(SCRIPT), "verify", "fixtures/valid/basic"],
cwd=ROOT,
)
second = subprocess.check_output(
[sys.executable, str(SCRIPT), "verify", "fixtures/valid/basic"],
cwd=ROOT,
)
self.assertEqual(first, second)
self.assertNotIn(str(ROOT).encode("utf-8"), first)
self.assertNotIn(b"fixtures/valid/basic", first)
def test_manifest_whitespace_does_not_change_semantic_digest(self) -> None:
original = CMV.validate_bundle(ROOT / "fixtures" / "valid" / "basic")
reformatted = CMV.validate_bundle(DATA / "basic-pretty")
self.assertEqual(original["digests"], reformatted["digests"])
def test_duplicate_json_key_is_rejected(self) -> None:
result = CMV.validate_bundle(DATA / "duplicate-json-key")
self.assertEqual(result["status"], "INVALID")
self.assertEqual(result["errors"][0]["code"], "CMV_INVALID_JSON")
def test_undeclared_source_file_is_rejected(self) -> None:
result = CMV.validate_bundle(DATA / "undeclared-file")
codes = {item["code"] for item in result["errors"]}
self.assertIn("CMV_UNDECLARED_FILE", codes)
def test_cli_usage_error_is_json(self) -> None:
code, output = self.cli("verify")
self.assertEqual(code, 64)
self.assertEqual(output["status"], "INVALID")
def test_cli_usage_error_does_not_echo_arguments(self) -> None:
sensitive_argument = str(ROOT / "private" / "secret.txt")
code, output = self.cli(
"verify",
"fixtures/valid/basic",
sensitive_argument,
)
self.assertEqual(code, 64)
self.assertEqual(output["errors"][0]["detail"], "invalid command-line arguments")
serialized = json.dumps(output, ensure_ascii=False)
self.assertNotIn(sensitive_argument, serialized)
self.assertNotIn(str(ROOT), serialized)
def test_maximum_acyclic_graph_does_not_recurse(self) -> None:
claims = {
f"clm_node_{index:04d}": {"key": "long.chain"}
for index in range(CMV.MAX_RECORDS)
}
edges = [
{
"superseded_claim_id": f"clm_node_{index:04d}",
"superseding_claim_id": f"clm_node_{index + 1:04d}",
}
for index in range(CMV.MAX_RECORDS - 1)
]
self.assertFalse(CMV._detect_cycle(edges, claims))
edges.append(
{
"superseded_claim_id": f"clm_node_{CMV.MAX_RECORDS - 1:04d}",
"superseding_claim_id": "clm_node_0000",
}
)
self.assertTrue(CMV._detect_cycle(edges, claims))
def test_cli_writes_utf8_independently_of_console_encoding(self) -> None:
env = dict(os.environ)
env["PYTHONDONTWRITEBYTECODE"] = "1"
env["PYTHONIOENCODING"] = "latin-1"
completed = subprocess.run(
[
sys.executable,
str(SCRIPT),
"project",
"tests/data/unicode",
],
cwd=ROOT,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
check=False,
)
self.assertEqual(completed.returncode, 0)
self.assertEqual(completed.stderr, b"")
self.assertIn(b"caf\xc3\xa9", completed.stdout)
self.assertEqual(json.loads(completed.stdout.decode("utf-8"))["status"], "VERIFIED")
def test_string_limits_use_json_schema_code_points(self) -> None:
self.assertTrue(CMV._bounded_string("é" * CMV.MAX_VALUE_BYTES, 1, CMV.MAX_VALUE_BYTES))
self.assertFalse(
CMV._bounded_string("é" * (CMV.MAX_VALUE_BYTES + 1), 1, CMV.MAX_VALUE_BYTES)
)
def test_directory_inventory_stops_at_bound(self) -> None:
class FakeEntry:
def __init__(self, index: int) -> None:
self.path = str(ROOT / f"synthetic-{index}")
class FakeScandir:
def __enter__(self):
return iter(
FakeEntry(index)
for index in range(CMV.MAX_DIRECTORY_ENTRIES + 1)
)
def __exit__(self, exc_type, exc_value, traceback):
return False
with mock.patch.object(CMV.os, "scandir", return_value=FakeScandir()):
entries, error = CMV._bounded_directory_entries(
ROOT, CMV.MAX_DIRECTORY_ENTRIES
)
self.assertEqual(len(entries), CMV.MAX_DIRECTORY_ENTRIES)
self.assertEqual(error, "directory entry limit exceeded")
def test_unsafe_source_path_forms_are_rejected(self) -> None:
for value in (
"../outside.txt",
"sources/../outside.txt",
"sources\\outside.txt",
"C:/outside.txt",
"sources/nested/outside.txt",
"sources/file.txt:stream",
):
with self.subTest(value=value):
self.assertFalse(CMV._matches(value, "source_path"))
def test_name_normalization_is_casefolded_nfc(self) -> None:
self.assertEqual(
CMV._normal_name("sources/Évidence.txt"),
CMV._normal_name("SOURCES/E\u0301VIDENCE.TXT"),
)
def test_reparse_sources_directory_fails_closed(self) -> None:
original = CMV._is_reparse
def fake_is_reparse(path: Path) -> bool:
return path.name == "sources" or original(path)
with mock.patch.object(CMV, "_is_reparse", side_effect=fake_is_reparse):
result = CMV.validate_bundle(ROOT / "fixtures" / "valid" / "basic")
self.assertEqual(result["status"], "INVALID")
self.assertIn(
"CMV_NONREGULAR_PATH",
{item["code"] for item in result["errors"]},
)
if __name__ == "__main__":
unittest.main()
SHA-256: 336b76a21770c655d455df7a6ae5e764b0ce268c3e44540d773ad7dd5385011f