gabriel / muse public

test_plumbing_verify_pack.py file-level

at sha256:6 · View file ↗ · Intel ↗

History
1 files
1 commits
0 hotspots
0 🧊 dead
0 💥 blast risk
sha256:0 test: validate staging push and MP workflow for aaronrene · · Jul 7, 2026
1 """Comprehensive tests for muse plumbing verify-pack.
2
3 Coverage:
4 - Unit: TypedDict schemas, _Failure, _VerifyPackResult, _StatResult
5 - Integration: JSON/text formats, --stat, --quiet, --no-local, --file, --json shorthand
6 - Verification: object integrity, snapshot consistency, commit consistency
7 - Security: ANSI sanitization, format error → stderr, no tracebacks, invalid object IDs
8 - Stress: 500-object bundle, 200 sequential verifications, large object hashing
9 """
10
11 from __future__ import annotations
12
13 import datetime
14 import hashlib
15 import io
16 import json
17 import pathlib
18 import uuid
19
20 import msgpack
21 import pytest
22 from tests.cli_test_helper import CliRunner, InvokeResult
23
24 from muse.cli.commands.plumbing.verify_pack import (
25 _Failure,
26 _StatResult,
27 _VerifyPackResult,
28 _FORMAT_CHOICES,
29 )
30 from muse.core.store import CommitRecord, SnapshotRecord, write_commit, write_snapshot
31 from muse.core._types import Manifest
32 from typing import TypedDict
33
34 runner = CliRunner()
35
36
37 # ---------------------------------------------------------------------------
38 # Bundle TypedDicts (mirror the plumbing contract shape)
39 # ---------------------------------------------------------------------------
40
41 class _ObjectEntry(TypedDict):
42 object_id: str
43 content: bytes
44
45
46 class _SnapshotEntry(TypedDict, total=False):
47 snapshot_id: str
48 manifest: Manifest
49
50
51 class _CommitEntry(TypedDict):
52 commit_id: str
53 snapshot_id: str
54
55
56 type _EnvMap = dict[str, str]
57 type _CommitEntryDict = dict[str, str]
58 type _BadObjectEntry = dict[str, str | bytes]
59 type _BundleDict = dict[str, list[_ObjectEntry] | list[_SnapshotEntry] | list[_CommitEntry]]
60
61
62 # ---------------------------------------------------------------------------
63 # Helpers
64 # ---------------------------------------------------------------------------
65
66 def _init_repo(path: pathlib.Path) -> pathlib.Path:
67 muse = path / ".muse"
68 (muse / "commits").mkdir(parents=True, exist_ok=True)
69 (muse / "snapshots").mkdir(parents=True, exist_ok=True)
70 (muse / "objects" / "ab").mkdir(parents=True, exist_ok=True)
71 (muse / "refs" / "heads").mkdir(parents=True, exist_ok=True)
72 (muse / "HEAD").write_text("ref: refs/heads/main", encoding="utf-8")
73 (muse / "repo.json").write_text(
74 json.dumps({"repo_id": "test-repo", "domain": "generic"}), encoding="utf-8"
75 )
76 return path
77
78
79 def _env(repo: pathlib.Path) -> _EnvMap:
80 return {"MUSE_REPO_ROOT": str(repo)}
81
82
83 def _sha(data: bytes) -> str:
84 return hashlib.sha256(data).hexdigest()
85
86
87 def _good_obj(data: bytes = b"hello world") -> _ObjectEntry:
88 return _ObjectEntry(object_id=_sha(data), content=data)
89
90
91 def _bad_hash_obj(data: bytes = b"hello world") -> _ObjectEntry:
92 return _ObjectEntry(object_id="a" * 64, content=data)
93
94
95 def _make_bundle(
96 objects: list[_ObjectEntry] | None = None,
97 snapshots: list[_SnapshotEntry] | None = None,
98 commits: list[_CommitEntry] | None = None,
99 ) -> bytes:
100 bundle: _BundleDict = {
101 "objects": objects or [],
102 "snapshots": snapshots or [],
103 "commits": commits or [],
104 }
105 return msgpack.packb(bundle, use_bin_type=True)
106
107
108 def _vp(
109 tmp_path: pathlib.Path,
110 args: list[str],
111 stdin: bytes | None = None,
112 ) -> InvokeResult:
113 """Invoke verify-pack against a freshly initialised repo in tmp_path."""
114 from muse.cli.app import main as cli
115 _init_repo(tmp_path)
116 return runner.invoke(
117 cli,
118 ["verify-pack"] + args,
119 env=_env(tmp_path),
120 input=stdin,
121 )
122
123
124 # ---------------------------------------------------------------------------
125 # Unit: schemas
126 # ---------------------------------------------------------------------------
127
128 class TestSchemas:
129 def test_failure_fields(self) -> None:
130 f: _Failure = {"kind": "object", "id": "abc", "error": "hash mismatch"}
131 assert f["kind"] == "object"
132 assert f["id"] == "abc"
133 assert f["error"] == "hash mismatch"
134
135 def test_verify_pack_result_fields(self) -> None:
136 r: _VerifyPackResult = {
137 "objects_checked": 3,
138 "snapshots_checked": 2,
139 "commits_checked": 1,
140 "all_ok": True,
141 "failures": [],
142 }
143 assert r["all_ok"] is True
144 assert isinstance(r["failures"], list)
145
146 def test_stat_result_fields(self) -> None:
147 s: _StatResult = {"objects": 10, "snapshots": 5, "commits": 3}
148 assert s["objects"] == 10
149
150 def test_format_choices(self) -> None:
151 assert "json" in _FORMAT_CHOICES
152 assert "text" in _FORMAT_CHOICES
153
154
155 # ---------------------------------------------------------------------------
156 # Integration: JSON output — clean bundles
157 # ---------------------------------------------------------------------------
158
159 class TestJsonOutputClean:
160 def test_empty_bundle(self, tmp_path: pathlib.Path) -> None:
161 bf = tmp_path / "b.muse"
162 bf.write_bytes(_make_bundle())
163 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
164 assert r.exit_code == 0
165 d = json.loads(r.output)
166 assert d["all_ok"] is True
167 assert d["failures"] == []
168 assert d["objects_checked"] == 0
169 assert d["snapshots_checked"] == 0
170 assert d["commits_checked"] == 0
171
172 def test_single_good_object(self, tmp_path: pathlib.Path) -> None:
173 bf = tmp_path / "b.muse"
174 bf.write_bytes(_make_bundle([_good_obj()]))
175 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
176 assert r.exit_code == 0
177 d = json.loads(r.output)
178 assert d["all_ok"] is True
179 assert d["objects_checked"] == 1
180
181 def test_json_shorthand(self, tmp_path: pathlib.Path) -> None:
182 bf = tmp_path / "b.muse"
183 bf.write_bytes(_make_bundle())
184 r = _vp(tmp_path, ["--file", str(bf), "--json", "--no-local"])
185 assert r.exit_code == 0
186 json.loads(r.output) # must be valid JSON
187
188 def test_multiple_good_objects(self, tmp_path: pathlib.Path) -> None:
189 objs = [_good_obj(f"content-{i}".encode()) for i in range(10)]
190 bf = tmp_path / "b.muse"
191 bf.write_bytes(_make_bundle(objs))
192 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
193 assert r.exit_code == 0
194 d = json.loads(r.output)
195 assert d["objects_checked"] == 10
196 assert d["all_ok"] is True
197
198
199 # ---------------------------------------------------------------------------
200 # Integration: JSON output — hash integrity failures
201 # ---------------------------------------------------------------------------
202
203 class TestObjectIntegrity:
204 def test_bad_hash_detected(self, tmp_path: pathlib.Path) -> None:
205 bf = tmp_path / "b.muse"
206 bf.write_bytes(_make_bundle([_bad_hash_obj()]))
207 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
208 assert r.exit_code != 0
209 d = json.loads(r.output)
210 assert d["all_ok"] is False
211 assert d["failures"][0]["kind"] == "object"
212 assert "hash mismatch" in d["failures"][0]["error"]
213
214 def test_mix_good_and_bad(self, tmp_path: pathlib.Path) -> None:
215 objs = [_good_obj(b"good"), _bad_hash_obj(b"bad")]
216 bf = tmp_path / "b.muse"
217 bf.write_bytes(_make_bundle(objs))
218 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
219 assert r.exit_code != 0
220 d = json.loads(r.output)
221 assert d["objects_checked"] == 2
222 assert len(d["failures"]) == 1
223
224 def test_invalid_object_id_format(self, tmp_path: pathlib.Path) -> None:
225 """Bundle with non-hex object ID should report a specific format error."""
226 bad: _BadObjectEntry = {
227 "object_id": "\x1b[31mmalicious\x1b[0m" + "a" * 55,
228 "content": b"data",
229 }
230 bf = tmp_path / "b.muse"
231 bf.write_bytes(_make_bundle([bad]))
232 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
233 assert r.exit_code != 0
234 d = json.loads(r.output)
235 assert d["all_ok"] is False
236 assert "not a valid" in d["failures"][0]["error"].lower() or "sha-256" in d["failures"][0]["error"].lower()
237
238 def test_entry_not_dict(self, tmp_path: pathlib.Path) -> None:
239 bundle = {
240 "objects": ["not-a-dict"],
241 "snapshots": [],
242 "commits": [],
243 }
244 bf = tmp_path / "b.muse"
245 bf.write_bytes(msgpack.packb(bundle, use_bin_type=True))
246 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
247 d = json.loads(r.output)
248 assert d["all_ok"] is False
249 assert "not a dict" in d["failures"][0]["error"]
250
251 def test_missing_content_field(self, tmp_path: pathlib.Path) -> None:
252 entry: _CommitEntryDict = {"object_id": "a" * 64} # no content
253 bf = tmp_path / "b.muse"
254 bf.write_bytes(_make_bundle([entry]))
255 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
256 d = json.loads(r.output)
257 assert d["all_ok"] is False
258
259 def test_empty_object_passes(self, tmp_path: pathlib.Path) -> None:
260 """An empty bytes object is valid — its SHA-256 is known."""
261 obj = _good_obj(b"")
262 bf = tmp_path / "b.muse"
263 bf.write_bytes(_make_bundle([obj]))
264 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
265 d = json.loads(r.output)
266 assert d["all_ok"] is True
267
268 def test_binary_object_passes(self, tmp_path: pathlib.Path) -> None:
269 obj = _good_obj(bytes(range(256)))
270 bf = tmp_path / "b.muse"
271 bf.write_bytes(_make_bundle([obj]))
272 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
273 d = json.loads(r.output)
274 assert d["all_ok"] is True
275
276
277 # ---------------------------------------------------------------------------
278 # Integration: snapshot consistency
279 # ---------------------------------------------------------------------------
280
281 class TestSnapshotConsistency:
282 def _snap_entry(self, snap_id: str, manifest: Manifest) -> _SnapshotEntry:
283 return _SnapshotEntry(snapshot_id=snap_id, manifest=manifest)
284
285 def test_snapshot_with_all_objects_present(self, tmp_path: pathlib.Path) -> None:
286 obj = _good_obj(b"snap-obj")
287 snap = self._snap_entry(_sha(b"snap"), {"file.txt": obj["object_id"]})
288 bf = tmp_path / "b.muse"
289 bf.write_bytes(_make_bundle(objects=[obj], snapshots=[snap]))
290 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
291 d = json.loads(r.output)
292 assert d["all_ok"] is True
293 assert d["snapshots_checked"] == 1
294
295 def test_snapshot_missing_object_fails(self, tmp_path: pathlib.Path) -> None:
296 missing_oid = "b" * 64
297 snap = self._snap_entry(_sha(b"snap"), {"file.txt": missing_oid})
298 bf = tmp_path / "b.muse"
299 bf.write_bytes(_make_bundle(snapshots=[snap]))
300 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
301 d = json.loads(r.output)
302 assert d["all_ok"] is False
303 assert d["failures"][0]["kind"] == "snapshot"
304 assert "missing object" in d["failures"][0]["error"]
305
306 def test_snapshot_entry_not_dict(self, tmp_path: pathlib.Path) -> None:
307 bundle = {
308 "objects": [],
309 "snapshots": ["bad"],
310 "commits": [],
311 }
312 bf = tmp_path / "b.muse"
313 bf.write_bytes(msgpack.packb(bundle, use_bin_type=True))
314 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
315 d = json.loads(r.output)
316 assert d["all_ok"] is False
317
318 def test_skip_local_check_allows_missing(self, tmp_path: pathlib.Path) -> None:
319 """--no-local should NOT check the local store; missing objects pass."""
320 # With --no-local, snapshot references a missing object but no local check.
321 missing_oid = "c" * 64
322 snap = self._snap_entry(_sha(b"snap"), {"f.txt": missing_oid})
323 bf = tmp_path / "b.muse"
324 bf.write_bytes(_make_bundle(snapshots=[snap]))
325 # Without --no-local, this fails (missing locally).
326 r_fail = _vp(tmp_path, ["--file", str(bf)])
327 assert r_fail.exit_code != 0
328 # With --no-local, this fails too (not in bundle either).
329 r_nol = _vp(tmp_path, ["--file", str(bf), "--no-local"])
330 assert r_nol.exit_code != 0
331
332
333 # ---------------------------------------------------------------------------
334 # Integration: commit consistency
335 # ---------------------------------------------------------------------------
336
337 class TestCommitConsistency:
338 def _commit_entry(self, commit_id: str, snapshot_id: str) -> _CommitEntryDict:
339 return {"commit_id": commit_id, "snapshot_id": snapshot_id}
340
341 def test_commit_with_bundled_snapshot(self, tmp_path: pathlib.Path) -> None:
342 snap_id = _sha(b"snap-data")
343 snap = {"snapshot_id": snap_id, "manifest": {}}
344 commit = self._commit_entry(_sha(b"c1"), snap_id)
345 bf = tmp_path / "b.muse"
346 bf.write_bytes(_make_bundle(snapshots=[snap], commits=[commit]))
347 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
348 d = json.loads(r.output)
349 assert d["all_ok"] is True
350 assert d["commits_checked"] == 1
351
352 def test_commit_missing_snapshot_fails(self, tmp_path: pathlib.Path) -> None:
353 # Default (local store enabled): snapshot not in bundle → failure
354 commit = self._commit_entry(_sha(b"c1"), "d" * 64)
355 bf = tmp_path / "b.muse"
356 bf.write_bytes(_make_bundle(commits=[commit]))
357 r = _vp(tmp_path, ["--file", str(bf)]) # local check on by default
358 d = json.loads(r.output)
359 assert d["all_ok"] is False
360 assert d["failures"][0]["kind"] == "commit"
361
362 def test_commit_entry_not_dict(self, tmp_path: pathlib.Path) -> None:
363 bundle = {
364 "objects": [],
365 "snapshots": [],
366 "commits": [42],
367 }
368 bf = tmp_path / "b.muse"
369 bf.write_bytes(msgpack.packb(bundle, use_bin_type=True))
370 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
371 d = json.loads(r.output)
372 assert d["all_ok"] is False
373
374
375 # ---------------------------------------------------------------------------
376 # Integration: text format
377 # ---------------------------------------------------------------------------
378
379 class TestTextFormat:
380 def test_text_format_clean(self, tmp_path: pathlib.Path) -> None:
381 bf = tmp_path / "b.muse"
382 bf.write_bytes(_make_bundle())
383 r = _vp(tmp_path, ["--file", str(bf), "--format", "text", "--no-local"])
384 assert r.exit_code == 0
385 assert "all_ok=True" in r.output
386
387 def test_text_format_failure_shows_fail(self, tmp_path: pathlib.Path) -> None:
388 bf = tmp_path / "b.muse"
389 bf.write_bytes(_make_bundle([_bad_hash_obj()]))
390 r = _vp(tmp_path, ["--file", str(bf), "--format", "text", "--no-local"])
391 assert r.exit_code != 0
392 assert "FAIL" in r.output
393
394 def test_text_format_counts(self, tmp_path: pathlib.Path) -> None:
395 objs = [_good_obj(f"x{i}".encode()) for i in range(5)]
396 bf = tmp_path / "b.muse"
397 bf.write_bytes(_make_bundle(objs))
398 r = _vp(tmp_path, ["--file", str(bf), "--format", "text", "--no-local"])
399 assert "objects=5" in r.output
400
401
402 # ---------------------------------------------------------------------------
403 # Integration: --stat fast-path
404 # ---------------------------------------------------------------------------
405
406 class TestStatMode:
407 def test_stat_json(self, tmp_path: pathlib.Path) -> None:
408 objs = [_good_obj(f"s{i}".encode()) for i in range(7)]
409 bf = tmp_path / "b.muse"
410 bf.write_bytes(_make_bundle(objs))
411 r = _vp(tmp_path, ["--file", str(bf), "--stat"])
412 assert r.exit_code == 0
413 d = json.loads(r.output)
414 assert d["objects"] == 7
415 assert d["snapshots"] == 0
416 assert d["commits"] == 0
417
418 def test_stat_text(self, tmp_path: pathlib.Path) -> None:
419 bf = tmp_path / "b.muse"
420 bf.write_bytes(_make_bundle())
421 r = _vp(tmp_path, ["--file", str(bf), "--stat", "--format", "text"])
422 assert r.exit_code == 0
423 assert "objects=0" in r.output
424
425 def test_stat_does_not_verify_hashes(self, tmp_path: pathlib.Path) -> None:
426 """--stat exits 0 even with a corrupted bundle hash."""
427 bf = tmp_path / "b.muse"
428 bf.write_bytes(_make_bundle([_bad_hash_obj()]))
429 r = _vp(tmp_path, ["--file", str(bf), "--stat"])
430 assert r.exit_code == 0 # no hashing — passes
431 d = json.loads(r.output)
432 assert d["objects"] == 1
433
434 def test_stat_counts_all_sections(self, tmp_path: pathlib.Path) -> None:
435 snap_id = _sha(b"s")
436 snap = {"snapshot_id": snap_id, "manifest": {}}
437 commit = {"commit_id": _sha(b"c"), "snapshot_id": snap_id}
438 objs = [_good_obj(b"obj")]
439 bf = tmp_path / "b.muse"
440 bf.write_bytes(_make_bundle(objs, [snap], [commit]))
441 r = _vp(tmp_path, ["--file", str(bf), "--stat"])
442 d = json.loads(r.output)
443 assert d["objects"] == 1
444 assert d["snapshots"] == 1
445 assert d["commits"] == 1
446
447
448 # ---------------------------------------------------------------------------
449 # Integration: --quiet
450 # ---------------------------------------------------------------------------
451
452 class TestQuietMode:
453 def test_quiet_clean_exits_zero_no_output(self, tmp_path: pathlib.Path) -> None:
454 bf = tmp_path / "b.muse"
455 bf.write_bytes(_make_bundle())
456 r = _vp(tmp_path, ["--file", str(bf), "--quiet", "--no-local"])
457 assert r.exit_code == 0
458 assert r.output.strip() == ""
459
460 def test_quiet_failure_exits_nonzero_no_output(self, tmp_path: pathlib.Path) -> None:
461 bf = tmp_path / "b.muse"
462 bf.write_bytes(_make_bundle([_bad_hash_obj()]))
463 r = _vp(tmp_path, ["--file", str(bf), "-q", "--no-local"])
464 assert r.exit_code != 0
465 assert r.output.strip() == ""
466
467
468 # ---------------------------------------------------------------------------
469 # Integration: malformed input
470 # ---------------------------------------------------------------------------
471
472 class TestMalformedInput:
473 def test_malformed_msgpack(self, tmp_path: pathlib.Path) -> None:
474 bf = tmp_path / "b.muse"
475 bf.write_bytes(b"\xff\xff NOT VALID MSGPACK")
476 r = _vp(tmp_path, ["--file", str(bf)])
477 assert r.exit_code != 0
478
479 def test_msgpack_scalar(self, tmp_path: pathlib.Path) -> None:
480 """msgpack-encoded scalar (not a map) must error cleanly."""
481 bf = tmp_path / "b.muse"
482 bf.write_bytes(msgpack.packb(42))
483 r = _vp(tmp_path, ["--file", str(bf)])
484 assert r.exit_code != 0
485 assert "error" in r.stderr.lower() or r.exit_code != 0
486
487 def test_missing_file(self, tmp_path: pathlib.Path) -> None:
488 r = _vp(tmp_path, ["--file", str(tmp_path / "nonexistent.muse")])
489 assert r.exit_code != 0
490
491 def test_objects_not_a_list(self, tmp_path: pathlib.Path) -> None:
492 bundle = {"objects": "bad", "snapshots": [], "commits": []}
493 bf = tmp_path / "b.muse"
494 bf.write_bytes(msgpack.packb(bundle, use_bin_type=True))
495 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
496 assert r.exit_code != 0
497 # Error goes to stderr
498 assert "objects" in r.stderr.lower()
499
500 def test_snapshots_not_a_list(self, tmp_path: pathlib.Path) -> None:
501 bundle = {"objects": [], "snapshots": 99, "commits": []}
502 bf = tmp_path / "b.muse"
503 bf.write_bytes(msgpack.packb(bundle, use_bin_type=True))
504 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
505 assert r.exit_code != 0
506 assert "snapshots" in r.stderr.lower()
507
508 def test_commits_not_a_list(self, tmp_path: pathlib.Path) -> None:
509 bundle = {"objects": [], "snapshots": [], "commits": True}
510 bf = tmp_path / "b.muse"
511 bf.write_bytes(msgpack.packb(bundle, use_bin_type=True))
512 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
513 assert r.exit_code != 0
514 assert "commits" in r.stderr.lower()
515
516
517 # ---------------------------------------------------------------------------
518 # Security
519 # ---------------------------------------------------------------------------
520
521 class TestSecurity:
522 def test_format_error_to_stderr(self, tmp_path: pathlib.Path) -> None:
523 bf = tmp_path / "b.muse"
524 bf.write_bytes(_make_bundle())
525 r = _vp(tmp_path, ["--file", str(bf), "--format", "xml"])
526 assert r.exit_code != 0
527 assert r.stdout_bytes == b""
528 assert "error" in r.stderr.lower()
529
530 def test_ansi_in_object_id_sanitized_in_text(self, tmp_path: pathlib.Path) -> None:
531 """ANSI in a bundle object_id must not leak to text output."""
532 ansi_oid = "\x1b[31m" + "a" * 58 + "\x1b[0m"
533 bad: _BadObjectEntry = {"object_id": ansi_oid, "content": b"data"}
534 bf = tmp_path / "b.muse"
535 bf.write_bytes(_make_bundle([bad]))
536 r = _vp(tmp_path, ["--file", str(bf), "--format", "text", "--no-local"])
537 # ANSI escape sequences must not appear in text output
538 assert "\x1b" not in r.output
539
540 def test_no_traceback_on_invalid_format(self, tmp_path: pathlib.Path) -> None:
541 bf = tmp_path / "b.muse"
542 bf.write_bytes(_make_bundle())
543 r = _vp(tmp_path, ["--file", str(bf), "--format", "yaml"])
544 assert "Traceback" not in r.output
545 assert "Traceback" not in r.stderr
546
547 def test_no_traceback_on_corrupt_bundle(self, tmp_path: pathlib.Path) -> None:
548 bf = tmp_path / "b.muse"
549 bf.write_bytes(b"\x00\x01\x02garbage")
550 r = _vp(tmp_path, ["--file", str(bf)])
551 assert "Traceback" not in r.output
552 assert "Traceback" not in r.stderr
553
554 def test_json_output_encodes_ansi_safely(self, tmp_path: pathlib.Path) -> None:
555 """JSON output must encode ANSI characters, never emit raw escape sequences."""
556 ansi_oid = "\x1b[31m" + "a" * 58 + "\x1b[0m"
557 bad: _BadObjectEntry = {"object_id": ansi_oid, "content": b"data"}
558 bf = tmp_path / "b.muse"
559 bf.write_bytes(_make_bundle([bad]))
560 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
561 # JSON output must not contain raw ANSI sequences
562 assert "\x1b" not in r.output
563 # But should still be parseable JSON
564 d = json.loads(r.output)
565 assert d["all_ok"] is False
566
567 def test_path_traversal_in_bundle_file(self, tmp_path: pathlib.Path) -> None:
568 """Referencing a path-traversal bundle file must fail cleanly."""
569 r = _vp(tmp_path, ["--file", "/etc/shadow"])
570 assert r.exit_code != 0
571 assert "Traceback" not in r.output
572
573 def test_deeply_nested_msgpack(self, tmp_path: pathlib.Path) -> None:
574 """Deeply nested msgpack should not crash (msgpack raises StackError)."""
575 # Build raw msgpack bytes: 2000 × fixmap(1){"x": …} + nil
576 # Avoids Python-level dict recursion; msgpack may raise StackError on unpack.
577 packed = b"\x81\xa1x" * 2000 + b"\xc0"
578 bf = tmp_path / "b.muse"
579 bf.write_bytes(packed)
580 r = _vp(tmp_path, ["--file", str(bf)])
581 # Either parses or errors — must never traceback
582 assert "Traceback" not in r.output
583 assert "Traceback" not in r.stderr
584
585
586 # ---------------------------------------------------------------------------
587 # Stress
588 # ---------------------------------------------------------------------------
589
590 class TestStress:
591 def test_500_object_bundle(self, tmp_path: pathlib.Path) -> None:
592 objs = [_good_obj(f"stress-object-{i:05d}".encode()) for i in range(500)]
593 bf = tmp_path / "b.muse"
594 bf.write_bytes(_make_bundle(objs))
595 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
596 assert r.exit_code == 0
597 d = json.loads(r.output)
598 assert d["objects_checked"] == 500
599 assert d["all_ok"] is True
600
601 def test_500_object_bundle_one_corrupt(self, tmp_path: pathlib.Path) -> None:
602 objs = [_good_obj(f"stress-{i}".encode()) for i in range(499)]
603 objs.append(_bad_hash_obj(b"corrupt"))
604 bf = tmp_path / "b.muse"
605 bf.write_bytes(_make_bundle(objs))
606 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
607 assert r.exit_code != 0
608 d = json.loads(r.output)
609 assert d["objects_checked"] == 500
610 assert d["all_ok"] is False
611
612 def test_200_sequential_verifications(self, tmp_path: pathlib.Path) -> None:
613 bf = tmp_path / "b.muse"
614 bf.write_bytes(_make_bundle([_good_obj(b"seq")]))
615 for _ in range(200):
616 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
617 assert r.exit_code == 0
618
619 def test_large_object_hashing(self, tmp_path: pathlib.Path) -> None:
620 """1 MiB object should hash correctly without memory issues."""
621 large_data = b"X" * (1024 * 1024)
622 obj = _good_obj(large_data)
623 bf = tmp_path / "b.muse"
624 bf.write_bytes(_make_bundle([obj]))
625 r = _vp(tmp_path, ["--file", str(bf), "--no-local"])
626 assert r.exit_code == 0
627 d = json.loads(r.output)
628 assert d["all_ok"] is True
629
630 def test_stat_on_large_bundle(self, tmp_path: pathlib.Path) -> None:
631 """--stat on a 500-object bundle must complete quickly."""
632 objs = [_good_obj(f"big-{i}".encode()) for i in range(500)]
633 bf = tmp_path / "b.muse"
634 bf.write_bytes(_make_bundle(objs))
635 r = _vp(tmp_path, ["--file", str(bf), "--stat"])
636 assert r.exit_code == 0
637 d = json.loads(r.output)
638 assert d["objects"] == 500