generated from coulomb/repo-seed
test(coordination): cross-process read-your-writes + fold parity (WP-0009 T3)
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>
This commit is contained in:
83
tests/test_cross_process_fold.py
Normal file
83
tests/test_cross_process_fold.py
Normal file
@@ -0,0 +1,83 @@
|
||||
"""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"})
|
||||
Reference in New Issue
Block a user