init: llm-wiki-haness 하네스 설계
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
RUNTIME = ROOT / "harness/runtime"
|
||||
sys.path.insert(0, str(RUNTIME))
|
||||
import contract_projection # noqa: E402
|
||||
import fs_transaction # noqa: E402
|
||||
import typed_contract_check # noqa: E402
|
||||
|
||||
|
||||
class ContractProjectionTest(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.tempdir = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.tempdir.cleanup)
|
||||
self.root = Path(self.tempdir.name)
|
||||
(self.root / "harness/source").mkdir(parents=True)
|
||||
shutil.copy2(ROOT / "harness/source/typed-contracts.json", self.root / "harness/source/typed-contracts.json")
|
||||
(self.root / "raw/project-notes").mkdir(parents=True)
|
||||
branches = self.root / "raw/branch-notes"
|
||||
branches.mkdir(parents=True)
|
||||
(self.root / "schemas").mkdir()
|
||||
(self.root / "schemas/a.json").write_text("{}\n", encoding="utf-8")
|
||||
(self.root / "raw/project-notes/demo.md").write_text(
|
||||
"""---
|
||||
title: demo
|
||||
---
|
||||
<!-- section-id: artifact-registry -->
|
||||
## Artifact Registry
|
||||
| Artifact ID | Revision | Name | Schema Owner | Producer | Consumers | Schema Ref | Status |
|
||||
|---|---:|---|---|---|---|---|---|
|
||||
| `ART-DEMO-A-001` | 1 | `a.json` | `feature-owner-contract` | `feature-owner-contract` | `feature-consumer-one`, `feature-consumer-two` | `schemas/a.json` | active |
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
(branches / "feature-owner-contract.md").write_text("---\ntitle: owner\n---\n# owner\n", encoding="utf-8")
|
||||
for slug in ("feature-consumer-one", "feature-consumer-two"):
|
||||
(branches / f"{slug}.md").write_text(
|
||||
f"---\ntitle: {slug}\nimports: [ART-DEMO-A-001@1]\n---\n# {slug}\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
def test_all_consumer_projections_are_one_transaction_and_idempotent(self) -> None:
|
||||
updates, result = contract_projection.build_updates(self.root)
|
||||
self.assertEqual(result["status"], "DRIFT")
|
||||
self.assertEqual(len(updates), 2)
|
||||
with mock.patch.object(contract_projection, "replace_many") as replace:
|
||||
code = contract_projection.main(["--root", str(self.root), "--write"])
|
||||
self.assertEqual(code, 0)
|
||||
replace.assert_called_once()
|
||||
self.assertEqual(len(replace.call_args.args[0]), 2)
|
||||
|
||||
fs_transaction.replace_many({path: text.encode("utf-8") for path, text in updates.items()})
|
||||
second, current = contract_projection.build_updates(self.root)
|
||||
self.assertEqual((second, current["status"]), ({}, "CURRENT"))
|
||||
self.assertEqual(typed_contract_check.check(self.root)["status"], "PASS")
|
||||
|
||||
def test_mid_commit_failure_restores_every_consumer(self) -> None:
|
||||
updates, _result = contract_projection.build_updates(self.root)
|
||||
before = {path: path.read_bytes() for path in updates}
|
||||
original = fs_transaction.os.replace
|
||||
calls = 0
|
||||
|
||||
def fail_second(source: object, target: object) -> None:
|
||||
nonlocal calls
|
||||
calls += 1
|
||||
if calls == 2:
|
||||
raise OSError("injected projection failure")
|
||||
original(source, target)
|
||||
|
||||
with mock.patch.object(fs_transaction.os, "replace", side_effect=fail_second):
|
||||
with self.assertRaises(fs_transaction.TransactionError):
|
||||
fs_transaction.replace_many({path: text.encode("utf-8") for path, text in updates.items()})
|
||||
self.assertEqual({path: path.read_bytes() for path in updates}, before)
|
||||
|
||||
def test_manual_projection_edit_reports_artifact_drift(self) -> None:
|
||||
updates, _result = contract_projection.build_updates(self.root)
|
||||
fs_transaction.replace_many({path: text.encode("utf-8") for path, text in updates.items()})
|
||||
target = self.root / "raw/branch-notes/feature-consumer-one.md"
|
||||
target.write_text(target.read_text(encoding="utf-8").replace("a.json", "other.json"), encoding="utf-8")
|
||||
result = typed_contract_check.check(self.root)
|
||||
self.assertIn("ARTIFACT_PROJECTION_DRIFT", {item["code"] for item in result["findings"]})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user