cgcardona / muse public
test_core_snapshot.py python
140 lines 5.2 KB
1d9234e8 Replace Maestro-coupled tests with new architecture test suite Gabriel Cardona <gabriel@tellurstori.com> 3d ago
1 """Tests for muse.core.snapshot — content-addressed snapshot computation."""
2 from __future__ import annotations
3
4 import pathlib
5
6 import pytest
7
8 from muse.core.snapshot import (
9 build_snapshot_manifest,
10 compute_commit_id,
11 compute_snapshot_id,
12 diff_workdir_vs_snapshot,
13 hash_file,
14 )
15
16
17 @pytest.fixture
18 def workdir(tmp_path: pathlib.Path) -> pathlib.Path:
19 d = tmp_path / "muse-work"
20 d.mkdir()
21 return d
22
23
24 class TestHashFile:
25 def test_consistent(self, tmp_path: pathlib.Path) -> None:
26 f = tmp_path / "file.mid"
27 f.write_bytes(b"hello world")
28 assert hash_file(f) == hash_file(f)
29
30 def test_different_content_different_hash(self, tmp_path: pathlib.Path) -> None:
31 a = tmp_path / "a.mid"
32 b = tmp_path / "b.mid"
33 a.write_bytes(b"aaa")
34 b.write_bytes(b"bbb")
35 assert hash_file(a) != hash_file(b)
36
37 def test_known_hash(self, tmp_path: pathlib.Path) -> None:
38 import hashlib
39 content = b"muse"
40 f = tmp_path / "f.mid"
41 f.write_bytes(content)
42 expected = hashlib.sha256(content).hexdigest()
43 assert hash_file(f) == expected
44
45
46 class TestBuildSnapshotManifest:
47 def test_empty_workdir(self, workdir: pathlib.Path) -> None:
48 assert build_snapshot_manifest(workdir) == {}
49
50 def test_single_file(self, workdir: pathlib.Path) -> None:
51 (workdir / "beat.mid").write_bytes(b"drums")
52 manifest = build_snapshot_manifest(workdir)
53 assert "beat.mid" in manifest
54 assert len(manifest["beat.mid"]) == 64 # sha256 hex
55
56 def test_nested_file(self, workdir: pathlib.Path) -> None:
57 (workdir / "tracks").mkdir()
58 (workdir / "tracks" / "bass.mid").write_bytes(b"bass")
59 manifest = build_snapshot_manifest(workdir)
60 assert "tracks/bass.mid" in manifest
61
62 def test_hidden_files_excluded(self, workdir: pathlib.Path) -> None:
63 (workdir / ".DS_Store").write_bytes(b"junk")
64 (workdir / "beat.mid").write_bytes(b"drums")
65 manifest = build_snapshot_manifest(workdir)
66 assert ".DS_Store" not in manifest
67 assert "beat.mid" in manifest
68
69 def test_deterministic_order(self, workdir: pathlib.Path) -> None:
70 for name in ["c.mid", "a.mid", "b.mid"]:
71 (workdir / name).write_bytes(name.encode())
72 m1 = build_snapshot_manifest(workdir)
73 m2 = build_snapshot_manifest(workdir)
74 assert m1 == m2
75
76
77 class TestComputeSnapshotId:
78 def test_empty_manifest(self) -> None:
79 sid = compute_snapshot_id({})
80 assert len(sid) == 64
81
82 def test_deterministic(self) -> None:
83 manifest = {"a.mid": "hash1", "b.mid": "hash2"}
84 assert compute_snapshot_id(manifest) == compute_snapshot_id(manifest)
85
86 def test_order_independent(self) -> None:
87 m1 = {"a.mid": "h1", "b.mid": "h2"}
88 m2 = {"b.mid": "h2", "a.mid": "h1"}
89 assert compute_snapshot_id(m1) == compute_snapshot_id(m2)
90
91 def test_different_content_different_id(self) -> None:
92 m1 = {"a.mid": "h1"}
93 m2 = {"a.mid": "h2"}
94 assert compute_snapshot_id(m1) != compute_snapshot_id(m2)
95
96
97 class TestComputeCommitId:
98 def test_deterministic(self) -> None:
99 kwargs = dict(parent_ids=["p1"], snapshot_id="s1", message="msg", committed_at_iso="2026-01-01T00:00:00+00:00")
100 assert compute_commit_id(**kwargs) == compute_commit_id(**kwargs)
101
102 def test_parent_order_independent(self) -> None:
103 a = compute_commit_id(parent_ids=["p1", "p2"], snapshot_id="s1", message="m", committed_at_iso="t")
104 b = compute_commit_id(parent_ids=["p2", "p1"], snapshot_id="s1", message="m", committed_at_iso="t")
105 assert a == b
106
107 def test_different_messages_different_ids(self) -> None:
108 a = compute_commit_id(parent_ids=[], snapshot_id="s1", message="msg1", committed_at_iso="t")
109 b = compute_commit_id(parent_ids=[], snapshot_id="s1", message="msg2", committed_at_iso="t")
110 assert a != b
111
112
113 class TestDiffWorkdirVsSnapshot:
114 def test_new_repo_all_untracked(self, workdir: pathlib.Path) -> None:
115 (workdir / "beat.mid").write_bytes(b"x")
116 added, modified, deleted, untracked = diff_workdir_vs_snapshot(workdir, {})
117 assert added == set()
118 assert untracked == {"beat.mid"}
119
120 def test_added_file(self, workdir: pathlib.Path) -> None:
121 (workdir / "beat.mid").write_bytes(b"x")
122 last = {"other.mid": "abc"}
123 added, modified, deleted, untracked = diff_workdir_vs_snapshot(workdir, last)
124 assert "beat.mid" in added
125 assert "other.mid" in deleted
126
127 def test_modified_file(self, workdir: pathlib.Path) -> None:
128 f = workdir / "beat.mid"
129 f.write_bytes(b"new content")
130 last = {"beat.mid": "oldhash"}
131 added, modified, deleted, untracked = diff_workdir_vs_snapshot(workdir, last)
132 assert "beat.mid" in modified
133
134 def test_clean_workdir(self, workdir: pathlib.Path) -> None:
135 f = workdir / "beat.mid"
136 f.write_bytes(b"content")
137 from muse.core.snapshot import hash_file
138 h = hash_file(f)
139 added, modified, deleted, untracked = diff_workdir_vs_snapshot(workdir, {"beat.mid": h})
140 assert not added and not modified and not deleted and not untracked