gabriel / muse public
test_snapshot_delta.py python
184 lines 6.7 KB
Raw
sha256:81ae324db5ad375fbfe4834c6fcb378312cafad3cc92dec5d3e5c427306621a2 fix: remove commit_exists filter from have anchors — server… Sonnet 4.6 patch 21 days ago
1 """Tests for snapshot delta encoding/decoding pure functions.
2
3 compute_snapshot_delta(base, new) -> (added_or_modified, removed)
4 apply_snapshot_delta(base, added, removed) -> full manifest
5
6 Test plan:
7 A. Identity — delta against self is empty
8 B. Add one file
9 C. Modify one file (same path, new hash)
10 D. Remove one file
11 E. Mixed — add + modify + remove in one delta
12 F. Roundtrip — apply(compute(base, new), base) == new
13 G. Delta is smaller than full manifest for typical commits
14 H. Empty base manifest (first commit ever)
15 I. Empty new manifest (all files deleted)
16 """
17 from __future__ import annotations
18
19 from muse.core.types import Manifest, NULL_LONG_ID, long_id
20
21
22 def _make_manifest(n: int, prefix: str = "src/file") -> Manifest:
23 """Build a deterministic {path: sha256_hex} manifest with n entries."""
24 return {
25 f"{prefix}_{i}.py": long_id(f"{'a' * 60}{i:04d}")
26 for i in range(n)
27 }
28
29
30 # ---------------------------------------------------------------------------
31 # A. Identity
32 # ---------------------------------------------------------------------------
33
34 def test_delta_identity_is_empty() -> None:
35 from muse.core.mpack import compute_snapshot_delta
36 m = _make_manifest(100)
37 added, removed = compute_snapshot_delta(m, m)
38 assert added == {}
39 assert removed == []
40
41
42 # ---------------------------------------------------------------------------
43 # B. Add one file
44 # ---------------------------------------------------------------------------
45
46 def test_delta_upsert_one_file() -> None:
47 from muse.core.mpack import compute_snapshot_delta
48 base = _make_manifest(10)
49 new = dict(base)
50 new["src/new_file.py"] = long_id("b" * 64)
51 added, removed = compute_snapshot_delta(base, new)
52 assert added == {"src/new_file.py": long_id("b" * 64)}
53 assert removed == []
54
55
56 # ---------------------------------------------------------------------------
57 # C. Modify one file
58 # ---------------------------------------------------------------------------
59
60 def test_delta_modify_one_file() -> None:
61 from muse.core.mpack import compute_snapshot_delta
62 base = _make_manifest(10)
63 new = dict(base)
64 existing_path = "src/file_5.py"
65 new[existing_path] = long_id("c" * 64)
66 added, removed = compute_snapshot_delta(base, new)
67 assert added == {existing_path: long_id("c" * 64)}
68 assert removed == []
69
70
71 # ---------------------------------------------------------------------------
72 # D. Remove one file
73 # ---------------------------------------------------------------------------
74
75 def test_delta_remove_one_file() -> None:
76 from muse.core.mpack import compute_snapshot_delta
77 base = _make_manifest(10)
78 new = dict(base)
79 del new["src/file_3.py"]
80 added, removed = compute_snapshot_delta(base, new)
81 assert added == {}
82 assert "src/file_3.py" in removed
83
84
85 # ---------------------------------------------------------------------------
86 # E. Mixed
87 # ---------------------------------------------------------------------------
88
89 def test_delta_mixed_operations() -> None:
90 from muse.core.mpack import compute_snapshot_delta
91 base = _make_manifest(10)
92 new = dict(base)
93 new["src/file_0.py"] = long_id("d" * 64) # modify
94 del new["src/file_9.py"] # remove
95 new["src/brand_new.py"] = long_id("e" * 64) # add
96 added, removed = compute_snapshot_delta(base, new)
97 assert "src/file_0.py" in added
98 assert added["src/file_0.py"] == long_id("d" * 64)
99 assert "src/brand_new.py" in added
100 assert "src/file_9.py" in removed
101 assert len(added) == 2
102 assert len(removed) == 1
103
104
105 # ---------------------------------------------------------------------------
106 # F. Roundtrip
107 # ---------------------------------------------------------------------------
108
109 def test_delta_roundtrip() -> None:
110 from muse.core.mpack import compute_snapshot_delta, apply_snapshot_delta
111 base = _make_manifest(200)
112 # Simulate a typical code commit: 3 files changed, 1 added, 1 deleted
113 new = dict(base)
114 new["src/file_10.py"] = long_id("f" * 64)
115 new["src/file_20.py"] = NULL_LONG_ID
116 new["src/file_30.py"] = long_id("1" * 64)
117 new["src/new_feature.py"] = long_id("2" * 64)
118 del new["src/file_199.py"]
119
120 added, removed = compute_snapshot_delta(base, new)
121 reconstructed = apply_snapshot_delta(base, added, removed)
122 assert reconstructed == new
123
124
125 def test_delta_roundtrip_large_repo() -> None:
126 from muse.core.mpack import compute_snapshot_delta, apply_snapshot_delta
127 base = _make_manifest(1071) # muse repo scale
128 new = dict(base)
129 # typical commit: 2 files changed
130 new["src/file_500.py"] = long_id("a" * 63 + "1")
131 new["src/file_501.py"] = long_id("a" * 63 + "2")
132
133 added, removed = compute_snapshot_delta(base, new)
134 reconstructed = apply_snapshot_delta(base, added, removed)
135 assert reconstructed == new
136
137
138 # ---------------------------------------------------------------------------
139 # G. Delta size vs full manifest size
140 # ---------------------------------------------------------------------------
141
142 def test_delta_smaller_than_full_for_typical_commit() -> None:
143 import json as _json
144 from muse.core.mpack import compute_snapshot_delta
145 base = _make_manifest(1071) # muse repo scale
146 new = dict(base)
147 # Change 3 files
148 for i in [100, 200, 300]:
149 new[f"src/file_{i}.py"] = long_id("9" * 64)
150
151 added, removed = compute_snapshot_delta(base, new)
152 delta_bytes = len(_json.dumps({"added": added, "removed": removed}).encode())
153 full_bytes = len(_json.dumps(new).encode())
154 assert delta_bytes < full_bytes, (
155 f"delta ({delta_bytes}B) should be smaller than full manifest ({full_bytes}B)"
156 )
157
158
159 # ---------------------------------------------------------------------------
160 # H. Empty base (first commit)
161 # ---------------------------------------------------------------------------
162
163 def test_delta_from_empty_base() -> None:
164 from muse.core.mpack import compute_snapshot_delta, apply_snapshot_delta
165 base: dict[str, str] = {}
166 new = _make_manifest(10)
167 added, removed = compute_snapshot_delta(base, new)
168 assert added == new
169 assert removed == []
170 assert apply_snapshot_delta(base, added, removed) == new
171
172
173 # ---------------------------------------------------------------------------
174 # I. Empty new manifest (all files deleted)
175 # ---------------------------------------------------------------------------
176
177 def test_delta_to_empty_manifest() -> None:
178 from muse.core.mpack import compute_snapshot_delta, apply_snapshot_delta
179 base = _make_manifest(5)
180 new: dict[str, str] = {}
181 added, removed = compute_snapshot_delta(base, new)
182 assert added == {}
183 assert set(removed) == set(base.keys())
184 assert apply_snapshot_delta(base, added, removed) == {}
File History 5 commits
sha256:81ae324db5ad375fbfe4834c6fcb378312cafad3cc92dec5d3e5c427306621a2 fix: remove commit_exists filter from have anchors — server… Sonnet 4.6 patch 21 days ago
sha256:36c3cb3e76619d4c30a6d9bf81b5ec4ff148e30dcfed913e3114ca7b43b81c7e fix: rename objects→blobs in push client and all stale test… Sonnet 4.6 patch 22 days ago
sha256:fb19dc03703eb3fc11d016ea19f619eebfab7bde2acf247346dc0f032e65ff19 fix(push): step 0 log shows full /refs URL instead of misle… Sonnet 4.6 patch 23 days ago
sha256:c06a9b9b9fee26c68ea725b44d54b2c0a171301ce9de746d5b656617b4463a9a fix: repair four test failures from post-migration audit Sonnet 4.6 patch 29 days ago
sha256:1900655993c83c4107067375548a7be823e471d2515830842f1a12cba4bd3cdf fix: unified object store migration — idempotent writes, JS… Sonnet 4.6 minor 29 days ago