generated from coulomb/repo-seed
Verify the git backend's fold reads the durable log into CoordinationState with unchanged semantics, and that read-your-writes holds across separate handles and separate OS processes against the same space ref (one test spawns a real subprocess that appends, then reads it back). Cross-process fold equals the in-memory fold for the same event sequence (derived = f(log)). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
84 lines
3.2 KiB
Python
84 lines
3.2 KiB
Python
"""Cross-process read-your-writes over the git log + fold parity (SHARD-WP-0009 T3).
|
|
|
|
The git backend's value over the in-memory double is that the totally ordered log is durable and
|
|
shared: a write by one process/handle is immediately visible to another opening the same ref, and
|
|
the derived fold is identical to the in-memory fold of the same event sequence (derived = f(log)).
|
|
"""
|
|
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import textwrap
|
|
from pathlib import Path
|
|
|
|
from shard_wiki.coordination import (
|
|
DecisionLog,
|
|
EventType,
|
|
GitEventStore,
|
|
InMemoryEventStore,
|
|
)
|
|
|
|
_SRC = str(Path(__file__).resolve().parents[1] / "src")
|
|
|
|
|
|
def test_new_handle_sees_prior_writes(tmp_path):
|
|
repo = tmp_path / "coord"
|
|
writer = DecisionLog(GitEventStore(repo))
|
|
writer.append("s", EventType.ALIAS_SET, {"alias": "Home", "target": "shardA:Index"})
|
|
writer.append("s", EventType.BINDING_MADE, {"members": ["a", "b"]})
|
|
# A second, independent handle on the same repo — read-your-writes across handles.
|
|
reader = DecisionLog(GitEventStore(repo))
|
|
assert [e.seq for e in reader.events("s")] == [0, 1]
|
|
assert reader.fold("s").resolve_alias("Home") == "shardA:Index"
|
|
|
|
|
|
def test_append_in_separate_process_is_visible(tmp_path):
|
|
repo = tmp_path / "coord"
|
|
# Seed from this process so the repo exists.
|
|
DecisionLog(GitEventStore(repo)).append(
|
|
"s", EventType.ALIAS_SET, {"alias": "A", "target": "x:1"}
|
|
)
|
|
child = textwrap.dedent(
|
|
f"""
|
|
from shard_wiki.coordination import DecisionLog, EventType, GitEventStore
|
|
log = DecisionLog(GitEventStore({str(repo)!r}))
|
|
log.append("s", EventType.ALIAS_SET, {{"alias": "B", "target": "x:2"}})
|
|
"""
|
|
)
|
|
result = subprocess.run(
|
|
[sys.executable, "-c", child],
|
|
capture_output=True,
|
|
text=True,
|
|
env={"PYTHONPATH": _SRC, "PATH": os.environ.get("PATH", "")},
|
|
)
|
|
assert result.returncode == 0, result.stderr
|
|
# This process, with a fresh handle, sees the child's append in order.
|
|
reader = DecisionLog(GitEventStore(repo))
|
|
assert [e.payload["alias"] for e in reader.events("s")] == ["A", "B"]
|
|
assert [e.seq for e in reader.events("s")] == [0, 1]
|
|
|
|
|
|
def test_cross_process_fold_equals_in_memory_fold(tmp_path):
|
|
sequence = [
|
|
(EventType.ALIAS_SET, {"alias": "Home", "target": "shardA:Index"}),
|
|
(EventType.BINDING_MADE, {"members": ["a", "b"]}),
|
|
(EventType.BINDING_MADE, {"members": ["b", "c"]}),
|
|
(EventType.PAGE_FORKED, {"source": "p", "fork": "q"}),
|
|
(EventType.ALIAS_SET, {"alias": "Home", "target": "shardB:Main"}),
|
|
]
|
|
mem = DecisionLog(InMemoryEventStore())
|
|
for typ, payload in sequence:
|
|
mem.append("s", typ, payload)
|
|
|
|
repo = tmp_path / "coord"
|
|
DecisionLog(GitEventStore(repo)) # init repo
|
|
for typ, payload in sequence:
|
|
# Each append from a fresh handle to simulate distinct writers over time.
|
|
DecisionLog(GitEventStore(repo)).append("s", typ, payload)
|
|
|
|
git_state = DecisionLog(GitEventStore(repo)).fold("s")
|
|
mem_state = mem.fold("s")
|
|
assert git_state.aliases == mem_state.aliases
|
|
assert git_state.equivalence_groups == mem_state.equivalence_groups
|
|
assert git_state.equivalent_to("a") == frozenset({"a", "b", "c"})
|