gabriel / musehub public
test_wire_snapshot_delta.py python
232 lines 7.4 KB
Raw
sha256:a34090cc4a394a78bd72cbbe34b08cc59525141e19135b6c0ab154f10611b9ef debug(push/stream): instrument O-frame decode path with INF… Sonnet 4.6 patch 121 days ago
1 """TDD — snapshot delta reconstruction on the server side.
2
3 Tests that wire_push_stream correctly:
4 A. Accepts C frames with snapshot_deltas and reconstructs full snapshots
5 B. Rejects a delta whose base_id is not in the stream cache
6 C. Delta + full snapshot in same C frame both stored correctly
7 D. Chain of deltas reconstructs all snapshots correctly
8 E. WireSnapshotDelta model rejects invalid snapshot_id / base_id
9 F. reconstruct_snapshot_delta returns correct WireSnapshot
10 G. reconstruct_snapshot_delta raises WireFrameError for missing base
11 """
12 from __future__ import annotations
13
14 import msgpack
15
16 from muse.core.types import blob_id, fake_id, long_id
17 from musehub.types.json_types import StrDict
18 import pytest
19
20 _SNAP_A = fake_id("snap-a")
21 _SNAP_B = fake_id("snap-b")
22 _SNAP_C = fake_id("snap-c")
23 _SNAP_0 = fake_id("snap-0")
24 _OBJ_F = fake_id("obj-f")
25 _OBJ_9 = fake_id("obj-9")
26
27
28 # ---------------------------------------------------------------------------
29 # Helpers
30 # ---------------------------------------------------------------------------
31
32 def _sha256_manifest(manifest: StrDict) -> str:
33 raw = msgpack.packb(sorted(manifest.items()), use_bin_type=True)
34 return blob_id(raw)
35
36
37 def _make_manifest(n: int) -> StrDict:
38 return {f"src/file_{i}.py": fake_id(f"file-{i}") for i in range(n)}
39
40
41 def _snap_id(manifest: StrDict) -> str:
42 return _sha256_manifest(manifest)
43
44
45 # ---------------------------------------------------------------------------
46 # E. WireSnapshotDelta model validation
47 # ---------------------------------------------------------------------------
48
49 def test_wire_snapshot_delta_valid() -> None:
50 from musehub.models.wire import WireSnapshotDelta
51 delta = WireSnapshotDelta(
52 snapshot_id=_SNAP_A,
53 base_id=_SNAP_B,
54 added={"src/foo.py": long_id("c" * 64)},
55 removed=["src/old.py"],
56 directories=[],
57 created_at="2026-04-23T00:00:00+00:00",
58 )
59 assert delta.snapshot_id == _SNAP_A
60 assert delta.base_id == _SNAP_B
61
62
63 def test_wire_snapshot_delta_invalid_snapshot_id() -> None:
64 from musehub.models.wire import WireSnapshotDelta
65 import pydantic
66 with pytest.raises(pydantic.ValidationError):
67 WireSnapshotDelta(
68 snapshot_id="not-a-valid-id",
69 base_id=_SNAP_B,
70 )
71
72
73 def test_wire_snapshot_delta_invalid_base_id() -> None:
74 from musehub.models.wire import WireSnapshotDelta
75 import pydantic
76 with pytest.raises(pydantic.ValidationError):
77 WireSnapshotDelta(
78 snapshot_id=_SNAP_A,
79 base_id="bare-hex-no-prefix",
80 )
81
82
83 # ---------------------------------------------------------------------------
84 # F. reconstruct_snapshot_delta returns correct WireSnapshot
85 # ---------------------------------------------------------------------------
86
87 def test_reconstruct_snapshot_delta_basic() -> None:
88 from musehub.services.musehub_wire import reconstruct_snapshot_delta
89 from musehub.models.wire import WireSnapshotDelta
90
91 base_manifest = _make_manifest(50)
92 base_id = _SNAP_B
93
94 new_manifest = dict(base_manifest)
95 new_manifest["src/file_5.py"] = _OBJ_F
96 del new_manifest["src/file_10.py"]
97 snap_id = _SNAP_A
98
99 delta = WireSnapshotDelta(
100 snapshot_id=snap_id,
101 base_id=base_id,
102 added={"src/file_5.py": _OBJ_F},
103 removed=["src/file_10.py"],
104 directories=[],
105 created_at="2026-04-23T00:00:00+00:00",
106 )
107
108 cache = {base_id: base_manifest}
109 result = reconstruct_snapshot_delta(delta, cache)
110
111 assert result.snapshot_id == snap_id
112 assert result.manifest["src/file_5.py"] == _OBJ_F
113 assert "src/file_10.py" not in result.manifest
114 assert len(result.manifest) == len(base_manifest) - 1 # file_10 removed, file_5 modified (same count)
115
116
117 def test_reconstruct_snapshot_delta_add_only() -> None:
118 from musehub.services.musehub_wire import reconstruct_snapshot_delta
119 from musehub.models.wire import WireSnapshotDelta
120
121 base_manifest = _make_manifest(10)
122 base_id = _SNAP_B
123 snap_id = _SNAP_A
124
125 new_file = "src/brand_new.py"
126 new_hash = _OBJ_9
127
128 delta = WireSnapshotDelta(
129 snapshot_id=snap_id,
130 base_id=base_id,
131 added={new_file: new_hash},
132 removed=[],
133 directories=[],
134 created_at="",
135 )
136
137 cache = {base_id: base_manifest}
138 result = reconstruct_snapshot_delta(delta, cache)
139 assert result.manifest[new_file] == new_hash
140 assert len(result.manifest) == len(base_manifest) + 1
141
142
143 # ---------------------------------------------------------------------------
144 # G. reconstruct_snapshot_delta raises WireFrameError for missing base
145 # ---------------------------------------------------------------------------
146
147 def test_reconstruct_snapshot_delta_missing_base_raises() -> None:
148 from musehub.services.musehub_wire import reconstruct_snapshot_delta
149 from musehub.models.wire import WireSnapshotDelta
150 from muse.core.mpack import WireFrameError
151
152 delta = WireSnapshotDelta(
153 snapshot_id=_SNAP_A,
154 base_id=_SNAP_B,
155 added={},
156 removed=[],
157 directories=[],
158 created_at="",
159 )
160
161 with pytest.raises(WireFrameError, match="base snapshot"):
162 reconstruct_snapshot_delta(delta, manifest_cache={})
163
164
165 # ---------------------------------------------------------------------------
166 # A. Chain reconstruction — multiple deltas in sequence
167 # ---------------------------------------------------------------------------
168
169 def test_delta_chain_reconstruction() -> None:
170 """Build a 5-snapshot delta chain manually and verify each reconstructs."""
171 from musehub.services.musehub_wire import reconstruct_snapshot_delta
172 from musehub.models.wire import WireSnapshotDelta
173
174 base_manifest = _make_manifest(100)
175 base_id = _SNAP_0
176
177 cache: dict[str, dict] = {base_id: base_manifest}
178 expected_manifests: dict[str, dict] = {}
179
180 prev_id = base_id
181 prev_manifest = base_manifest
182
183 for i in range(5):
184 new_manifest = dict(prev_manifest)
185 changed_path = f"src/file_{i * 10}.py"
186 new_hash = long_id("c" * 63 + str(i))
187 new_manifest[changed_path] = new_hash
188 snap_id = long_id("d" * 63 + str(i))
189
190 delta = WireSnapshotDelta(
191 snapshot_id=snap_id,
192 base_id=prev_id,
193 added={changed_path: new_hash},
194 removed=[],
195 directories=[],
196 created_at="",
197 )
198 result = reconstruct_snapshot_delta(delta, cache)
199 cache[snap_id] = dict(result.manifest)
200 expected_manifests[snap_id] = new_manifest
201
202 prev_id = snap_id
203 prev_manifest = new_manifest
204
205 for snap_id, expected in expected_manifests.items():
206 assert cache[snap_id] == expected, f"Mismatch at {snap_id[:16]}"
207
208
209 # ---------------------------------------------------------------------------
210 # B. Empty delta (no-op commit) reconstructs to identical manifest
211 # ---------------------------------------------------------------------------
212
213 def test_empty_delta_is_identity() -> None:
214 from musehub.services.musehub_wire import reconstruct_snapshot_delta
215 from musehub.models.wire import WireSnapshotDelta
216
217 base_manifest = _make_manifest(20)
218 base_id = _SNAP_B
219 snap_id = _SNAP_A
220
221 delta = WireSnapshotDelta(
222 snapshot_id=snap_id,
223 base_id=base_id,
224 added={},
225 removed=[],
226 directories=[],
227 created_at="",
228 )
229
230 cache = {base_id: base_manifest}
231 result = reconstruct_snapshot_delta(delta, cache)
232 assert result.manifest == base_manifest
File History 1 commit
sha256:a34090cc4a394a78bd72cbbe34b08cc59525141e19135b6c0ab154f10611b9ef debug(push/stream): instrument O-frame decode path with INF… Sonnet 4.6 patch 121 days ago