gabriel / muse public
test_push_pack_origin.py python
205 lines 6.7 KB
Raw
sha256:660fcac1df3ab28f61862e961890bd2ca8b754fa0242079d93ca1e25037ec8a6 chore(tests): add docstring to tests/__init__.py so rc14 tr… Human 26 days ago
1 """Tests for pack_origin URL rewriting in _push_objects_as_packs.
2
3 Covers:
4 - URL origin replacement (scheme + host replaced, path preserved)
5 - No-op when pack_origin is absent
6 - Different scheme rewriting (http → https)
7 - Empty object-list produces no pack uploads
8 """
9 from __future__ import annotations
10
11 import pathlib
12 import unittest.mock
13
14 import hashlib
15
16 import pytest
17
18 from muse.cli.commands.push import _push_objects_as_packs
19 from muse.core.object_store import write_object
20 from muse.core.pack import ObjectsChunkResponse
21
22
23 # ---------------------------------------------------------------------------
24 # Helpers
25 # ---------------------------------------------------------------------------
26
27
28 def _make_transport(captured_urls: list[str]) -> unittest.mock.MagicMock:
29 """Build a mock transport that records the URL passed to push_object_pack."""
30 transport = unittest.mock.MagicMock()
31
32 def _push_pack(url: str, signing: object, pack: list[object]) -> ObjectsChunkResponse:
33 captured_urls.append(url)
34 return ObjectsChunkResponse(stored=len(pack), skipped=0)
35
36 transport.push_object_pack.side_effect = _push_pack
37 return transport
38
39
40 def _write_obj(root: pathlib.Path, content: bytes) -> str:
41 """Write content to the object store and return its real SHA-256 OID."""
42 oid = hashlib.sha256(content).hexdigest()
43 write_object(root, oid, content)
44 return oid
45
46
47 # ---------------------------------------------------------------------------
48 # pack_origin URL rewriting
49 # ---------------------------------------------------------------------------
50
51
52 class TestPackOriginUrlRewriting:
53 def test_origin_replaced_path_preserved(self, tmp_path: pathlib.Path) -> None:
54 """pack_origin replaces scheme+host; /{owner}/{slug} path is kept intact."""
55 urls: list[str] = []
56 transport = _make_transport(urls)
57 oid = _write_obj(tmp_path, b"test-object-a")
58
59 _push_objects_as_packs(
60 transport,
61 "http://localhost:10003/gabriel/muse",
62 None,
63 [oid],
64 tmp_path,
65 pack_origin="https://worker.example.workers.dev",
66 )
67
68 assert len(urls) == 1
69 assert urls[0] == "https://worker.example.workers.dev/gabriel/muse"
70
71 def test_https_hub_replaced_with_worker_origin(self, tmp_path: pathlib.Path) -> None:
72 """HTTPS musehub.ai origin is replaced with the worker origin."""
73 urls: list[str] = []
74 transport = _make_transport(urls)
75 oid = _write_obj(tmp_path, b"test-object-b")
76
77 _push_objects_as_packs(
78 transport,
79 "https://musehub.ai/gabriel/muse",
80 None,
81 [oid],
82 tmp_path,
83 pack_origin="https://worker.example.workers.dev",
84 )
85
86 assert urls[0] == "https://worker.example.workers.dev/gabriel/muse"
87
88 def test_no_pack_origin_uses_hub_url_unchanged(self, tmp_path: pathlib.Path) -> None:
89 """Without pack_origin the original URL is passed to push_object_pack."""
90 urls: list[str] = []
91 transport = _make_transport(urls)
92 oid = _write_obj(tmp_path, b"test-object-c")
93
94 _push_objects_as_packs(
95 transport,
96 "https://musehub.ai/gabriel/muse",
97 None,
98 [oid],
99 tmp_path,
100 )
101
102 assert urls[0] == "https://musehub.ai/gabriel/muse"
103
104 def test_http_to_https_scheme_swap(self, tmp_path: pathlib.Path) -> None:
105 """HTTP localhost URL is rewritten to HTTPS worker URL."""
106 urls: list[str] = []
107 transport = _make_transport(urls)
108 oid = _write_obj(tmp_path, b"test-object-d")
109
110 _push_objects_as_packs(
111 transport,
112 "http://localhost:10003/org/repo",
113 None,
114 [oid],
115 tmp_path,
116 pack_origin="https://worker.example.workers.dev",
117 )
118
119 assert urls[0] == "https://worker.example.workers.dev/org/repo"
120
121 def test_empty_object_list_no_pack_calls(self, tmp_path: pathlib.Path) -> None:
122 """Zero objects produces zero push_object_pack calls regardless of pack_origin."""
123 urls: list[str] = []
124 transport = _make_transport(urls)
125
126 stored, skipped = _push_objects_as_packs(
127 transport,
128 "https://musehub.ai/gabriel/muse",
129 None,
130 [],
131 tmp_path,
132 pack_origin="https://worker.example.workers.dev",
133 )
134
135 assert urls == []
136 assert stored == 0
137 assert skipped == 0
138
139 def test_pack_origin_does_not_append_extra_path(self, tmp_path: pathlib.Path) -> None:
140 """The worker origin must not accumulate path segments from both URLs."""
141 urls: list[str] = []
142 transport = _make_transport(urls)
143 oid = _write_obj(tmp_path, b"test-object-e")
144
145 _push_objects_as_packs(
146 transport,
147 "https://musehub.ai/gabriel/muse",
148 None,
149 [oid],
150 tmp_path,
151 pack_origin="https://different-worker.dev",
152 )
153
154 # Must be exactly worker origin + hub path, no duplication
155 assert urls[0] == "https://different-worker.dev/gabriel/muse"
156 assert urls[0].count("/gabriel/muse") == 1
157
158 def test_multiple_packs_all_use_worker_url(self, tmp_path: pathlib.Path) -> None:
159 """All packs in a multi-pack upload use the worker origin."""
160 urls: list[str] = []
161 transport = _make_transport(urls)
162
163 oids = []
164 for i in range(5):
165 oid = _write_obj(tmp_path, f"multi-pack-content-{i}".encode())
166 oids.append(oid)
167
168 _push_objects_as_packs(
169 transport,
170 "https://musehub.ai/gabriel/muse",
171 None,
172 oids,
173 tmp_path,
174 pack_origin="https://worker.example.workers.dev",
175 )
176
177 assert len(urls) >= 1
178 for url in urls:
179 assert url.startswith("https://worker.example.workers.dev")
180 assert "/gabriel/muse" in url
181
182 def test_stored_and_skipped_totals_accumulated(self, tmp_path: pathlib.Path) -> None:
183 """Return value is (total_stored, total_skipped) summed across all packs."""
184 transport = unittest.mock.MagicMock()
185
186 def _push_pack(url: str, signing: object, pack: list[object]) -> ObjectsChunkResponse:
187 return ObjectsChunkResponse(stored=len(pack), skipped=0)
188
189 transport.push_object_pack.side_effect = _push_pack
190
191 oids = []
192 for i in range(3):
193 oid = _write_obj(tmp_path, f"accumulate-content-{i}".encode())
194 oids.append(oid)
195
196 stored, skipped = _push_objects_as_packs(
197 transport,
198 "https://musehub.ai/gabriel/muse",
199 None,
200 oids,
201 tmp_path,
202 )
203
204 assert stored == 3
205 assert skipped == 0
File History 2 commits
sha256:660fcac1df3ab28f61862e961890bd2ca8b754fa0242079d93ca1e25037ec8a6 chore(tests): add docstring to tests/__init__.py so rc14 tr… Human 26 days ago
sha256:d8316ffae901be06347e16ab55be11868eb519dd16ade3e8aa16a99e662f7e62 baseline: rc14 re-baseline after rc3 store corruption recovery Human patch 26 days ago