gabriel / muse public
test_fetch_mpack_command_wiring.py python
192 lines 7.5 KB
Raw
sha256:ff478cfdcdd4b7fd6de89cb68896601a981f945634463275ec333bd20ca36402 Merge branch 'dev' into main Human 21 days ago
1 """TDD — Phase 4: fetch_mpack wired into clone and pull commands (issue #47).
2
3 All clone and pull paths must call transport.fetch_mpack exclusively.
4
5 Tests:
6 CW0 clone (depth=None) calls fetch_mpack.
7 CW1 clone --depth 1 also calls fetch_mpack.
8 CW2 pull calls fetch_mpack.
9 """
10 from __future__ import annotations
11
12 import argparse
13 import contextlib
14 import pathlib
15 from typing import TYPE_CHECKING, Callable
16 from unittest.mock import MagicMock, patch
17
18 import pytest
19
20 from muse.core.types import blob_id, fake_id
21
22 if TYPE_CHECKING:
23 from muse.core.transport import SigningIdentity
24
25 _FetchResult = dict[str, str | list[str] | int] # transport fetch response
26 _KwVal = str | int | bool | None
27
28 # ── helpers ───────────────────────────────────────────────────────────────────
29
30 _COMMIT_ID = fake_id("commit-1")
31 _SNAP_ID = fake_id("snap-1")
32 _REPO_ID = fake_id("repo-1")
33
34 _FETCH_RESULT = {
35 "repo_id": _REPO_ID,
36 "domain": "code",
37 "default_branch": "main",
38 "branch_heads": {"main": _COMMIT_ID},
39 "commits": [],
40 "snapshots": [],
41 "blobs_received": 0,
42 "shallow_commits": [],
43 }
44
45 _APPLY_RESULT = {
46 "commits_written": 1,
47 "snapshots_written": 1,
48 "blobs_written": 0,
49 "blobs_skipped": 0,
50 }
51
52 _REMOTE_INFO = {
53 "repo_id": _REPO_ID,
54 "domain": "code",
55 "default_branch": "main",
56 "branch_heads": {"main": _COMMIT_ID},
57 "object_count": 1,
58 "size_bytes": 100,
59 }
60
61
62 def _make_transport() -> MagicMock:
63 """Transport mock: fetch_mpack returns _FETCH_RESULT."""
64 t = MagicMock()
65 t.fetch_remote_info.return_value = _REMOTE_INFO
66 t.fetch_mpack.return_value = _FETCH_RESULT
67 return t
68
69
70 def _clone_patches(t: MagicMock) -> list[contextlib.AbstractContextManager[MagicMock]]:
71 return [
72 patch("muse.cli.commands.clone.get_signing_identity", return_value=None),
73 patch("muse.cli.commands.clone.make_transport", return_value=t),
74 patch("muse.cli.commands.clone.apply_mpack", return_value=_APPLY_RESULT),
75 patch("muse.cli.commands.clone.set_remote"),
76 patch("muse.cli.commands.clone.set_remote_head"),
77 patch("muse.cli.commands.clone.set_upstream"),
78 patch("muse.cli.commands.clone.apply_manifest"),
79 patch("muse.cli.commands.clone.read_commit", return_value=MagicMock(snapshot_id=_SNAP_ID)),
80 patch("muse.cli.commands.clone.read_snapshot", return_value=MagicMock(manifest={})),
81 ]
82
83
84 # ══════════════════════════════════════════════════════════════════════════════
85 # CW0 — clone (depth=None) calls fetch_mpack
86 # ══════════════════════════════════════════════════════════════════════════════
87
88 def test_cw0_clone_full_calls_fetch_mpack(tmp_path: pathlib.Path) -> None:
89 """Full clone (no --depth) must call transport.fetch_mpack, not fetch_presign_or_stream."""
90 from muse.cli.commands.clone import run
91
92 t = _make_transport()
93 args = argparse.Namespace(
94 url="https://hub.example.com/gabriel/repo",
95 directory=str(tmp_path / "cloned"),
96 branch=None,
97 depth=None,
98 dry_run=False,
99 no_checkout=False,
100 json_out=False,
101 )
102
103 patches = _clone_patches(t)
104 with patches[0], patches[1], patches[2], patches[3], patches[4], patches[5], patches[6], patches[7], patches[8]:
105 run(args)
106
107 t.fetch_mpack.assert_called_once()
108
109
110 # ══════════════════════════════════════════════════════════════════════════════
111 # CW1 — clone --depth 1 calls fetch_mpack (presign-only policy)
112 # ══════════════════════════════════════════════════════════════════════════════
113
114 def test_cw1_clone_shallow_calls_fetch_mpack(tmp_path: pathlib.Path) -> None:
115 """--depth clone must call transport.fetch_mpack — presign-only policy, no stream path."""
116 from muse.cli.commands.clone import run
117
118 t = _make_transport()
119 args = argparse.Namespace(
120 url="https://hub.example.com/gabriel/repo",
121 directory=str(tmp_path / "cloned"),
122 branch=None,
123 depth=1,
124 dry_run=False,
125 no_checkout=False,
126 json_out=False,
127 )
128
129 patches = _clone_patches(t)
130 with patches[0], patches[1], patches[2], patches[3], patches[4], patches[5], patches[6], patches[7], patches[8]:
131 run(args)
132
133 t.fetch_mpack.assert_called_once()
134
135
136 # ══════════════════════════════════════════════════════════════════════════════
137 # CW2 — pull calls fetch_mpack
138 # ══════════════════════════════════════════════════════════════════════════════
139
140 def test_cw2_pull_calls_fetch_mpack(tmp_path: pathlib.Path) -> None:
141 """pull must call transport.fetch_mpack, not fetch_presign_or_stream."""
142 import argparse
143 from muse.cli.commands.pull import run
144
145 def _fetch_mpack(
146 url: str,
147 signing: "SigningIdentity | None",
148 *,
149 want: str,
150 have: list[str],
151 on_object: Callable[[str, bytes], None] | None = None,
152 **kw: _KwVal,
153 ) -> _FetchResult:
154 return _FETCH_RESULT
155
156 t = MagicMock()
157 t.fetch_remote_info.return_value = _REMOTE_INFO
158 t.fetch_mpack.side_effect = _fetch_mpack
159
160 args = argparse.Namespace(
161 remote="origin",
162 branch_flag=None,
163 branch_pos=None,
164 no_merge=False,
165 ff_only=False,
166 dry_run=False,
167 message=None,
168 json_out=False,
169 )
170
171 with (
172 patch("muse.cli.commands.pull.require_repo", return_value=tmp_path),
173 patch("muse.cli.commands.pull.get_remote", return_value="https://hub.example.com"),
174 patch("muse.cli.commands.pull.get_signing_identity", return_value=None),
175 patch("muse.cli.commands.pull.read_current_branch", return_value="main"),
176 patch("muse.cli.commands.pull.get_upstream", return_value=None),
177 patch("muse.cli.commands.pull.make_transport", return_value=t),
178 patch("muse.cli.commands.pull.get_remote_head", return_value=None), # not up-to-date
179 patch("muse.cli.commands.pull.get_head_commit_id", return_value=None),
180 patch("muse.cli.commands.pull.get_all_commits", return_value=[]),
181 patch("muse.cli.commands.pull.apply_mpack", return_value=_APPLY_RESULT),
182 patch("muse.cli.commands.pull.set_remote_head"),
183 patch("muse.cli.commands.pull.apply_manifest"),
184 patch("muse.cli.commands.pull.read_commit", return_value=MagicMock(snapshot_id=_SNAP_ID)),
185 patch("muse.cli.commands.pull.read_snapshot", return_value=MagicMock(manifest={})),
186 ):
187 try:
188 run(args)
189 except SystemExit:
190 pass # exit after pull is OK — we only care which transport method was called
191
192 t.fetch_mpack.assert_called_once()
File History 1 commit
sha256:ff478cfdcdd4b7fd6de89cb68896601a981f945634463275ec333bd20ca36402 Merge branch 'dev' into main Human 21 days ago