gabriel / musehub public
test_musehub_muse_cli.py python
99 lines 4.2 KB
7923a405 test(supercharge): comprehensive test suite overhaul — all 11 points Gabriel Cardona <gabriel@tellurstori.com> 6d ago
1 """Unit tests for muse_cli snapshot hashing utilities.
2
3 muse_cli/snapshot.py provides deterministic ID functions used by test
4 fixtures across the suite — yet it had no tests of its own. These
5 tests lock down the hashing contract so that any accidental change to
6 the algorithm is immediately caught.
7 """
8 from __future__ import annotations
9
10 import hashlib
11
12 import pytest
13
14 from musehub.muse_cli.snapshot import compute_commit_id, compute_snapshot_id
15
16
17 class TestComputeSnapshotId:
18 def test_empty_manifest_is_deterministic(self) -> None:
19 result = compute_snapshot_id({})
20 assert isinstance(result, str)
21 assert len(result) == 64 # SHA-256 hex
22
23 def test_single_entry(self) -> None:
24 result = compute_snapshot_id({"tracks/bass.mid": "sha256:abc"})
25 assert len(result) == 64
26
27 def test_same_manifest_same_id(self) -> None:
28 manifest = {"a": "1", "b": "2"}
29 assert compute_snapshot_id(manifest) == compute_snapshot_id(manifest)
30
31 def test_insertion_order_does_not_matter(self) -> None:
32 m1 = {"a": "1", "b": "2"}
33 m2 = {"b": "2", "a": "1"}
34 assert compute_snapshot_id(m1) == compute_snapshot_id(m2)
35
36 def test_different_manifests_different_ids(self) -> None:
37 assert compute_snapshot_id({"a": "1"}) != compute_snapshot_id({"a": "2"})
38 assert compute_snapshot_id({"a": "1"}) != compute_snapshot_id({"b": "1"})
39
40 def test_known_value(self) -> None:
41 """Regression: algorithm must not change without updating this test."""
42 manifest = {"tracks/piano.mid": "sha256:deadbeef"}
43 parts = sorted(f"{k}:{v}" for k, v in manifest.items())
44 payload = "|".join(parts).encode()
45 expected = hashlib.sha256(payload).hexdigest()
46 assert compute_snapshot_id(manifest) == expected
47
48 def test_multiple_entries_sorted(self) -> None:
49 m = {"z/file": "oid-z", "a/file": "oid-a", "m/file": "oid-m"}
50 result = compute_snapshot_id(m)
51 # Manually compute expected value
52 parts = sorted(f"{k}:{v}" for k, v in m.items())
53 expected = hashlib.sha256("|".join(parts).encode()).hexdigest()
54 assert result == expected
55
56
57 class TestComputeCommitId:
58 def test_returns_sha256_hex(self) -> None:
59 cid = compute_commit_id([], "snap-id", "init", "2026-01-01T00:00:00+00:00")
60 assert len(cid) == 64
61
62 def test_deterministic(self) -> None:
63 kwargs = dict(
64 parent_ids=["p1", "p2"],
65 snapshot_id="snap-abc",
66 message="feat: add piano",
67 committed_at_iso="2026-03-01T12:00:00+00:00",
68 )
69 assert compute_commit_id(**kwargs) == compute_commit_id(**kwargs)
70
71 def test_parent_order_does_not_matter(self) -> None:
72 base = dict(snapshot_id="s", message="m", committed_at_iso="2026-01-01T00:00:00")
73 id1 = compute_commit_id(parent_ids=["a", "b"], **base)
74 id2 = compute_commit_id(parent_ids=["b", "a"], **base)
75 assert id1 == id2
76
77 def test_different_messages_different_ids(self) -> None:
78 base = dict(parent_ids=[], snapshot_id="s", committed_at_iso="2026-01-01T00:00:00")
79 assert compute_commit_id(message="msg-1", **base) != compute_commit_id(message="msg-2", **base)
80
81 def test_different_timestamps_different_ids(self) -> None:
82 base = dict(parent_ids=[], snapshot_id="s", message="m")
83 t1 = compute_commit_id(committed_at_iso="2026-01-01T00:00:00", **base)
84 t2 = compute_commit_id(committed_at_iso="2026-01-02T00:00:00", **base)
85 assert t1 != t2
86
87 def test_different_snapshots_different_ids(self) -> None:
88 base = dict(parent_ids=[], message="m", committed_at_iso="2026-01-01T00:00:00")
89 assert compute_commit_id(snapshot_id="s1", **base) != compute_commit_id(snapshot_id="s2", **base)
90
91 def test_known_value(self) -> None:
92 """Regression: algorithm must not change without updating this test."""
93 parents = ["parent-a", "parent-b"]
94 snap = "snapshot-xyz"
95 msg = "feat: add groove"
96 ts = "2026-01-01T00:00:00+00:00"
97 parts = ["|".join(sorted(parents)), snap, msg, ts]
98 expected = hashlib.sha256("|".join(parts).encode()).hexdigest()
99 assert compute_commit_id(parent_ids=parents, snapshot_id=snap, message=msg, committed_at_iso=ts) == expected