cgcardona / muse public
test_music_plugin.py python
143 lines 5.1 KB
9ee9c39c refactor: rename music→midi domain, strip all 5-dim backward compat Gabriel Cardona <gabriel@tellurstori.com> 1d ago
1 """Tests for muse.plugins.midi.plugin — the MuseDomainPlugin reference implementation."""
2 from __future__ import annotations
3
4 import pathlib
5
6 import pytest
7
8 from muse.domain import DriftReport, MergeResult, MuseDomainPlugin, SnapshotManifest
9 from muse.plugins.midi.plugin import MidiPlugin, content_hash, plugin
10
11
12 def _snap(files: dict[str, str]) -> SnapshotManifest:
13 return SnapshotManifest(files=files, domain="midi")
14
15
16 class TestProtocolConformance:
17 def test_plugin_satisfies_protocol(self) -> None:
18 assert isinstance(plugin, MuseDomainPlugin)
19
20 def test_module_singleton_is_music_plugin(self) -> None:
21 assert isinstance(plugin, MidiPlugin)
22
23
24 class TestSnapshot:
25 def test_from_dict_passthrough(self) -> None:
26 snap = SnapshotManifest(files={"a.mid": "h1"}, domain="midi")
27 assert plugin.snapshot(snap) is snap
28
29 def test_from_workdir(self, tmp_path: pathlib.Path) -> None:
30 workdir = tmp_path / "muse-work"
31 workdir.mkdir()
32 (workdir / "beat.mid").write_bytes(b"drums")
33 snap = plugin.snapshot(workdir)
34 assert "files" in snap
35 assert "beat.mid" in snap["files"]
36 assert snap["domain"] == "midi"
37
38 def test_empty_workdir(self, tmp_path: pathlib.Path) -> None:
39 workdir = tmp_path / "muse-work"
40 workdir.mkdir()
41 snap = plugin.snapshot(workdir)
42 assert snap["files"] == {}
43
44
45 class TestDiff:
46 """diff() returns a StructuredDelta with typed ops — not the old DeltaManifest."""
47
48 def test_no_change_empty_ops(self) -> None:
49 snap = _snap({"a.mid": "h1"})
50 delta = plugin.diff(snap, snap)
51 assert delta["ops"] == []
52
53 def test_no_change_summary(self) -> None:
54 snap = _snap({"a.mid": "h1"})
55 delta = plugin.diff(snap, snap)
56 assert delta["summary"] == "no changes"
57
58 def test_added_file_produces_insert_op(self) -> None:
59 base = _snap({})
60 target = _snap({"new.mid": "h1"})
61 delta = plugin.diff(base, target)
62 insert_ops = [op for op in delta["ops"] if op["op"] == "insert"]
63 assert any(op["address"] == "new.mid" for op in insert_ops)
64
65 def test_removed_file_produces_delete_op(self) -> None:
66 base = _snap({"old.mid": "h1"})
67 target = _snap({})
68 delta = plugin.diff(base, target)
69 delete_ops = [op for op in delta["ops"] if op["op"] == "delete"]
70 assert any(op["address"] == "old.mid" for op in delete_ops)
71
72 def test_modified_file_produces_replace_or_patch_op(self) -> None:
73 base = _snap({"f.mid": "old"})
74 target = _snap({"f.mid": "new"})
75 delta = plugin.diff(base, target)
76 changed_ops = [op for op in delta["ops"] if op["op"] in ("replace", "patch")]
77 assert any(op["address"] == "f.mid" for op in changed_ops)
78
79 def test_domain_is_music(self) -> None:
80 snap = _snap({"a.mid": "h"})
81 delta = plugin.diff(snap, snap)
82 assert delta["domain"] == "midi"
83
84
85 class TestMerge:
86 def test_clean_merge(self) -> None:
87 base = _snap({"a.mid": "h0", "b.mid": "h0"})
88 left = _snap({"a.mid": "h_left", "b.mid": "h0"})
89 right = _snap({"a.mid": "h0", "b.mid": "h_right"})
90 result = plugin.merge(base, left, right)
91 assert isinstance(result, MergeResult)
92 assert result.is_clean
93 assert result.merged["files"]["a.mid"] == "h_left"
94 assert result.merged["files"]["b.mid"] == "h_right"
95
96 def test_conflict_detected(self) -> None:
97 base = _snap({"a.mid": "h0"})
98 left = _snap({"a.mid": "h_left"})
99 right = _snap({"a.mid": "h_right"})
100 result = plugin.merge(base, left, right)
101 assert not result.is_clean
102 assert result.conflicts == ["a.mid"]
103
104 def test_both_delete_same_file(self) -> None:
105 base = _snap({"a.mid": "h0", "b.mid": "h0"})
106 left = _snap({"b.mid": "h0"})
107 right = _snap({"b.mid": "h0"})
108 result = plugin.merge(base, left, right)
109 assert result.is_clean
110 assert "a.mid" not in result.merged["files"]
111
112
113 class TestDrift:
114 def test_no_drift(self) -> None:
115 snap = _snap({"a.mid": "h1"})
116 report = plugin.drift(snap, snap)
117 assert isinstance(report, DriftReport)
118 assert not report.has_drift
119
120 def test_has_drift_on_addition(self) -> None:
121 committed = _snap({"a.mid": "h1"})
122 live = _snap({"a.mid": "h1", "b.mid": "h2"})
123 report = plugin.drift(committed, live)
124 assert report.has_drift
125 assert "added" in report.summary
126
127 def test_drift_delta_is_structured(self) -> None:
128 snap = _snap({"a.mid": "h1"})
129 report = plugin.drift(snap, snap)
130 assert "ops" in report.delta
131 assert "summary" in report.delta
132 assert "domain" in report.delta
133
134
135 class TestContentHash:
136 def test_deterministic(self) -> None:
137 snap = SnapshotManifest(files={"a.mid": "h1"}, domain="midi")
138 assert content_hash(snap) == content_hash(snap)
139
140 def test_different_content_different_hash(self) -> None:
141 a = SnapshotManifest(files={"a.mid": "h1"}, domain="midi")
142 b = SnapshotManifest(files={"a.mid": "h2"}, domain="midi")
143 assert content_hash(a) != content_hash(b)