cgcardona / muse public
test_stress_store_provenance.py python
418 lines 14.8 KB
119290fc Add mission-critical stress test suite (9 new files, 1716 tests total) (#76) Gabriel Cardona <cgcardona@gmail.com> 1d ago
1 """Stress tests for CommitRecord, SnapshotRecord, TagRecord, and provenance fields.
2
3 Covers:
4 - CommitRecord round-trip through to_dict/from_dict for all format versions.
5 - format_version evolution: missing fields default correctly when reading old records.
6 - reviewed_by (ORSet semantics): list preserved, sorted, deduplicated via overwrite_commit.
7 - test_runs (GCounter semantics): monotonically increases via overwrite_commit.
8 - agent_id / model_id / toolchain_id / prompt_hash / signature fields.
9 - SnapshotRecord round-trip with large manifests.
10 - TagRecord round-trip.
11 - get_head_commit_id on empty branch returns None.
12 - write_commit is idempotent (won't overwrite).
13 - overwrite_commit updates the persisted record correctly.
14 - read_commit for absent commit returns None.
15 - list_commits and list_branches.
16 - list_tags returns all tags.
17 """
18 from __future__ import annotations
19
20 import datetime
21 import pathlib
22
23 import pytest
24
25 from muse.core.crdts.or_set import ORSet
26 from muse.domain import SemVerBump
27 from muse.core.store import (
28 CommitDict,
29 CommitRecord,
30 SnapshotRecord,
31 TagRecord,
32 get_all_commits,
33 get_all_tags,
34 get_head_commit_id,
35 overwrite_commit,
36 read_commit,
37 read_snapshot,
38 write_commit,
39 write_snapshot,
40 write_tag,
41 )
42
43
44 # ---------------------------------------------------------------------------
45 # Fixtures
46 # ---------------------------------------------------------------------------
47
48
49 @pytest.fixture
50 def repo(tmp_path: pathlib.Path) -> pathlib.Path:
51 muse = tmp_path / ".muse"
52 (muse / "commits").mkdir(parents=True)
53 (muse / "snapshots").mkdir(parents=True)
54 (muse / "tags").mkdir(parents=True)
55 (muse / "refs" / "heads").mkdir(parents=True)
56 return tmp_path
57
58
59 def _now() -> datetime.datetime:
60 return datetime.datetime.now(datetime.timezone.utc)
61
62
63 def _commit(
64 cid: str = "abc1234",
65 branch: str = "main",
66 parent: str | None = None,
67 ) -> CommitRecord:
68 return CommitRecord(
69 commit_id=cid,
70 repo_id="test-repo",
71 branch=branch,
72 snapshot_id=f"snap-{cid}",
73 message=f"commit {cid}",
74 committed_at=_now(),
75 parent_commit_id=parent,
76 )
77
78
79 # ===========================================================================
80 # CommitRecord round-trip
81 # ===========================================================================
82
83
84 class TestCommitRecordRoundTrip:
85 def test_minimal_round_trip(self) -> None:
86 c = _commit()
87 restored = CommitRecord.from_dict(c.to_dict())
88 assert restored.commit_id == c.commit_id
89 assert restored.branch == c.branch
90 assert restored.message == c.message
91
92 def test_all_provenance_fields_preserved(self) -> None:
93 c = CommitRecord(
94 commit_id="prov123",
95 repo_id="repo",
96 branch="main",
97 snapshot_id="snap",
98 message="provenance commit",
99 committed_at=_now(),
100 agent_id="claude-v4",
101 model_id="claude-3-5-sonnet",
102 toolchain_id="muse-cli-1.0",
103 prompt_hash="abc" * 10 + "ab",
104 signature="sig-" + "x" * 60,
105 signer_key_id="key-001",
106 )
107 d = c.to_dict()
108 restored = CommitRecord.from_dict(d)
109 assert restored.agent_id == "claude-v4"
110 assert restored.model_id == "claude-3-5-sonnet"
111 assert restored.toolchain_id == "muse-cli-1.0"
112 assert restored.signature == c.signature
113 assert restored.signer_key_id == "key-001"
114
115 def test_crdt_fields_preserved(self) -> None:
116 c = CommitRecord(
117 commit_id="crdt123",
118 repo_id="repo",
119 branch="main",
120 snapshot_id="snap",
121 message="crdt",
122 committed_at=_now(),
123 reviewed_by=["alice", "bob", "charlie"],
124 test_runs=42,
125 )
126 d = c.to_dict()
127 restored = CommitRecord.from_dict(d)
128 assert sorted(restored.reviewed_by) == ["alice", "bob", "charlie"]
129 assert restored.test_runs == 42
130
131 def test_format_version_5_is_default(self) -> None:
132 c = _commit()
133 assert c.format_version == 5
134
135 def test_format_version_persisted(self) -> None:
136 c = _commit()
137 assert CommitRecord.from_dict(c.to_dict()).format_version == 5
138
139 def test_sem_ver_bump_preserved(self) -> None:
140 bumps: tuple[SemVerBump, ...] = ("none", "patch", "minor", "major")
141 for bump in bumps:
142 c = CommitRecord(
143 commit_id="sv",
144 repo_id="r",
145 branch="main",
146 snapshot_id="s",
147 message="m",
148 committed_at=_now(),
149 sem_ver_bump=bump,
150 )
151 assert CommitRecord.from_dict(c.to_dict()).sem_ver_bump == bump
152
153 def test_breaking_changes_preserved(self) -> None:
154 c = CommitRecord(
155 commit_id="bc",
156 repo_id="r",
157 branch="main",
158 snapshot_id="s",
159 message="m",
160 committed_at=_now(),
161 breaking_changes=["removed `old_api`", "renamed `foo` → `bar`"],
162 )
163 restored = CommitRecord.from_dict(c.to_dict())
164 assert restored.breaking_changes == ["removed `old_api`", "renamed `foo` → `bar`"]
165
166 def test_parent_ids_preserved(self) -> None:
167 c = CommitRecord(
168 commit_id="merge",
169 repo_id="r",
170 branch="main",
171 snapshot_id="s",
172 message="m",
173 committed_at=_now(),
174 parent_commit_id="parent-1",
175 parent2_commit_id="parent-2",
176 )
177 restored = CommitRecord.from_dict(c.to_dict())
178 assert restored.parent_commit_id == "parent-1"
179 assert restored.parent2_commit_id == "parent-2"
180
181 def test_missing_crdt_fields_default_correctly(self) -> None:
182 """Simulates reading an older commit that lacks reviewed_by / test_runs."""
183 minimal: CommitDict = {
184 "commit_id": "old",
185 "repo_id": "r",
186 "branch": "main",
187 "snapshot_id": "snap",
188 "message": "old commit",
189 "committed_at": _now().isoformat(),
190 }
191 restored = CommitRecord.from_dict(minimal)
192 assert restored.reviewed_by == []
193 assert restored.test_runs == 0
194 assert restored.format_version == 1
195
196 def test_committed_at_timezone_aware(self) -> None:
197 c = _commit()
198 restored = CommitRecord.from_dict(c.to_dict())
199 assert restored.committed_at.tzinfo is not None
200
201
202 # ===========================================================================
203 # CommitRecord persistence
204 # ===========================================================================
205
206
207 class TestCommitPersistence:
208 def test_write_and_read_back(self, repo: pathlib.Path) -> None:
209 c = _commit("id001")
210 write_commit(repo, c)
211 restored = read_commit(repo, "id001")
212 assert restored is not None
213 assert restored.commit_id == "id001"
214
215 def test_write_is_idempotent(self, repo: pathlib.Path) -> None:
216 c = CommitRecord(
217 commit_id="id002", repo_id="test-repo", branch="main",
218 snapshot_id="snap-id002", message="original", committed_at=_now(),
219 )
220 write_commit(repo, c)
221 # Second write with a different message — original must be kept.
222 c2 = CommitRecord(
223 commit_id="id002", repo_id="test-repo", branch="main",
224 snapshot_id="snap-id002", message="overwritten-attempt", committed_at=_now(),
225 )
226 write_commit(repo, c2)
227 restored = read_commit(repo, "id002")
228 assert restored is not None
229 assert restored.message == "original"
230
231 def test_read_absent_commit_returns_none(self, repo: pathlib.Path) -> None:
232 assert read_commit(repo, "does-not-exist") is None
233
234 def test_overwrite_commit_updates_reviewed_by(self, repo: pathlib.Path) -> None:
235 c = _commit("id003")
236 write_commit(repo, c)
237 # Simulate ORSet merge: add reviewer.
238 updated = read_commit(repo, "id003")
239 assert updated is not None
240 updated.reviewed_by = ["agent-x", "human-bob"]
241 overwrite_commit(repo, updated)
242 restored = read_commit(repo, "id003")
243 assert restored is not None
244 assert "agent-x" in restored.reviewed_by
245 assert "human-bob" in restored.reviewed_by
246
247 def test_overwrite_commit_updates_test_runs(self, repo: pathlib.Path) -> None:
248 c = _commit("id004")
249 write_commit(repo, c)
250 for expected in range(1, 6):
251 rec = read_commit(repo, "id004")
252 assert rec is not None
253 rec.test_runs += 1
254 overwrite_commit(repo, rec)
255 after = read_commit(repo, "id004")
256 assert after is not None
257 assert after.test_runs == expected
258
259 def test_list_commits_returns_all_written(self, repo: pathlib.Path) -> None:
260 ids = [f"c{i:04d}" for i in range(20)]
261 for cid in ids:
262 write_commit(repo, _commit(cid))
263 found = {c.commit_id for c in get_all_commits(repo)}
264 for cid in ids:
265 assert cid in found
266
267 def test_many_commits_all_retrievable(self, repo: pathlib.Path) -> None:
268 for i in range(100):
269 write_commit(repo, _commit(f"stress-{i:04d}"))
270 for i in range(100):
271 assert read_commit(repo, f"stress-{i:04d}") is not None
272
273
274 # ===========================================================================
275 # SnapshotRecord
276 # ===========================================================================
277
278
279 class TestSnapshotRecordRoundTrip:
280 def test_minimal_round_trip(self) -> None:
281 s = SnapshotRecord(snapshot_id="snap-1", manifest={"f.mid": "hash1"})
282 restored = SnapshotRecord.from_dict(s.to_dict())
283 assert restored.snapshot_id == "snap-1"
284 assert restored.manifest == {"f.mid": "hash1"}
285
286 def test_large_manifest(self) -> None:
287 manifest = {f"track_{i:04d}.mid": f"hash-{i:064d}" for i in range(500)}
288 s = SnapshotRecord(snapshot_id="big-snap", manifest=manifest)
289 restored = SnapshotRecord.from_dict(s.to_dict())
290 assert len(restored.manifest) == 500
291 assert restored.manifest["track_0000.mid"] == f"hash-{0:064d}"
292
293 def test_write_and_read_back(self, repo: pathlib.Path) -> None:
294 s = SnapshotRecord(snapshot_id="snap-rw", manifest={"a.mid": "h1", "b.mid": "h2"})
295 write_snapshot(repo, s)
296 restored = read_snapshot(repo, "snap-rw")
297 assert restored is not None
298 assert restored.manifest == {"a.mid": "h1", "b.mid": "h2"}
299
300 def test_empty_manifest_round_trip(self) -> None:
301 s = SnapshotRecord(snapshot_id="empty-snap", manifest={})
302 restored = SnapshotRecord.from_dict(s.to_dict())
303 assert restored.manifest == {}
304
305
306 # ===========================================================================
307 # TagRecord
308 # ===========================================================================
309
310
311 class TestTagRecord:
312 def test_round_trip(self) -> None:
313 t = TagRecord(
314 tag_id="tag-001",
315 repo_id="repo",
316 commit_id="abc123",
317 tag="v1.0.0",
318 )
319 restored = TagRecord.from_dict(t.to_dict())
320 assert restored.tag_id == "tag-001"
321 assert restored.tag == "v1.0.0"
322 assert restored.commit_id == "abc123"
323
324 def test_write_and_list(self, repo: pathlib.Path) -> None:
325 for i in range(10):
326 write_tag(repo, TagRecord(
327 tag_id=f"tag-{i:04d}",
328 repo_id="repo",
329 commit_id=f"commit-{i:04d}",
330 tag=f"v{i}.0.0",
331 ))
332 tags = get_all_tags(repo, "repo")
333 assert len(tags) == 10
334
335 def test_created_at_preserved(self) -> None:
336 ts = datetime.datetime(2025, 6, 15, 12, 0, 0, tzinfo=datetime.timezone.utc)
337 t = TagRecord(tag_id="t", repo_id="r", commit_id="c", tag="v1", created_at=ts)
338 restored = TagRecord.from_dict(t.to_dict())
339 assert abs((restored.created_at - ts).total_seconds()) < 1.0
340
341
342 # ===========================================================================
343 # get_head_commit_id
344 # ===========================================================================
345
346
347 class TestGetHeadCommitId:
348 def test_empty_branch_returns_none(self, repo: pathlib.Path) -> None:
349 assert get_head_commit_id(repo, "nonexistent-branch") is None
350
351 def test_returns_id_after_writing_head_ref(self, repo: pathlib.Path) -> None:
352 ref_path = repo / ".muse" / "refs" / "heads" / "main"
353 ref_path.write_text("abc1234\n")
354 assert get_head_commit_id(repo, "main") == "abc1234"
355
356 def test_strips_whitespace(self, repo: pathlib.Path) -> None:
357 ref_path = repo / ".muse" / "refs" / "heads" / "feature"
358 ref_path.write_text(" deadbeef \n")
359 assert get_head_commit_id(repo, "feature") == "deadbeef"
360
361
362 # ===========================================================================
363 # CRDT semantics on CommitRecord fields
364 # ===========================================================================
365
366
367 class TestCRDTAnnotationSemantics:
368 def test_reviewed_by_orset_union_semantics(self, repo: pathlib.Path) -> None:
369 """ORSet union: multiple overwrite_commit calls accumulate reviewers."""
370 c = _commit("crdt-or-001")
371 write_commit(repo, c)
372
373 # Agent 1 adds their name.
374 rec = read_commit(repo, "crdt-or-001")
375 assert rec is not None
376 s, tok1 = ORSet().add("agent-alpha")
377 rec.reviewed_by = list(s.elements())
378 overwrite_commit(repo, rec)
379
380 # Agent 2 independently adds their name.
381 rec2 = read_commit(repo, "crdt-or-001")
382 assert rec2 is not None
383 s2 = ORSet()
384 for name in rec2.reviewed_by:
385 s2, _ = s2.add(name)
386 s2, tok2 = s2.add("agent-beta")
387 rec2.reviewed_by = sorted(s2.elements())
388 overwrite_commit(repo, rec2)
389
390 final = read_commit(repo, "crdt-or-001")
391 assert final is not None
392 assert "agent-alpha" in final.reviewed_by
393 assert "agent-beta" in final.reviewed_by
394
395 def test_test_runs_gcounter_monotone(self, repo: pathlib.Path) -> None:
396 """GCounter: test_runs must never decrease."""
397 c = _commit("crdt-gc-001")
398 write_commit(repo, c)
399 prev = 0
400 for _ in range(50):
401 rec = read_commit(repo, "crdt-gc-001")
402 assert rec is not None
403 rec.test_runs += 1
404 overwrite_commit(repo, rec)
405 current = read_commit(repo, "crdt-gc-001")
406 assert current is not None
407 assert current.test_runs >= prev
408 prev = current.test_runs
409 assert prev == 50
410
411 def test_all_provenance_fields_default_to_empty_string(self) -> None:
412 c = _commit()
413 assert c.agent_id == ""
414 assert c.model_id == ""
415 assert c.toolchain_id == ""
416 assert c.prompt_hash == ""
417 assert c.signature == ""
418 assert c.signer_key_id == ""