gabriel / musehub public
pull_test.py python
178 lines 5.5 KB
Raw
sha256:7d6dd8f4a89e2d1fef2d84f6e65feaff51385d382f466766b7f690a22ec18e32 fix: fall back to DB ancestry check when mpack-only fast-fo… Sonnet 4.6 patch 6 days ago
1 """Pull verb atomic tests against localhost.
2
3 Builds a source repo with real muse commits, pushes to local hub,
4 then exercises clone + incremental pull roundtrips.
5
6 Tests:
7 PL0: clone-equivalent — pull 100 commits into an empty local repo
8 PL1: +1 commit incremental
9 PL2: +10 commits incremental
10 PL3: +100 commits incremental
11
12 Usage:
13 python3 scripts/pull_test.py
14 """
15 from __future__ import annotations
16
17 import json
18 import os
19 import shutil
20 import subprocess
21 import sys
22 import time
23
24 MUSE = "muse"
25 LOCAL_HUB = "https://localhost:1337"
26 TIMING_REPO_URL = f"{LOCAL_HUB}/gabriel/timing-test"
27
28
29 def run(cmd: list[str], cwd: str | None = None, check: bool = True) -> subprocess.CompletedProcess:
30 return subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, check=check)
31
32
33 def m(args: list[str], cwd: str, check: bool = True) -> subprocess.CompletedProcess:
34 return run([MUSE] + args, cwd=cwd, check=check)
35
36
37 def mj(args: list[str], cwd: str) -> dict:
38 r = m(args + ["--json"], cwd=cwd)
39 return json.loads(r.stdout)
40
41
42 def fresh_pull_target(path: str) -> str:
43 if os.path.exists(path):
44 shutil.rmtree(path)
45 os.makedirs(path)
46 m(["init"], cwd=path)
47 # Use remote add first; fall back to set-url if it already exists.
48 r = run([MUSE, "remote", "add", "local", TIMING_REPO_URL], cwd=path, check=False)
49 if r.returncode != 0:
50 run([MUSE, "remote", "set-url", "local", TIMING_REPO_URL], cwd=path, check=False)
51 return path
52
53
54 def local_commit_count(repo: str) -> int:
55 try:
56 return len(mj(["log"], cwd=repo).get("commits", []))
57 except Exception:
58 return -1
59
60
61 def timed_pull(repo: str, branch: str = "main") -> dict:
62 t0 = time.perf_counter()
63 r = run([MUSE, "pull", "local", branch], cwd=repo, check=False)
64 elapsed = round((time.perf_counter() - t0) * 1000, 1)
65 ok = r.returncode == 0
66 err = None
67 if not ok:
68 output = r.stdout + r.stderr
69 for line in output.splitlines():
70 if "❌" in line or "Error" in line or "failed" in line.lower():
71 err = line.strip()
72 break
73 if not err:
74 err = (r.stdout + r.stderr).strip()[:200]
75 return {"ok": ok, "t_total": elapsed, "error": err}
76
77
78 def fmt(label: str, r: dict, extra: str = "") -> str:
79 ok = "✅" if r["ok"] else "❌"
80 err = f" ERROR: {r['error']}" if r.get("error") else ""
81 return (
82 f" {label:42s}"
83 f" total={str(r['t_total']):>8}ms"
84 f" {ok}{extra}{err}"
85 )
86
87
88 def _add_commits(src: str, n: int) -> bool:
89 existing = local_commit_count(src)
90 for i in range(n):
91 idx = existing + i
92 obj_file = os.path.join(src, f"obj_{idx:04d}.dat")
93 with open(obj_file, "wb") as f:
94 f.write(os.urandom(512))
95 m(["code", "add", f"obj_{idx:04d}.dat"], cwd=src)
96 m(["commit", "-m", f"pull test commit {idx}",
97 "--agent-id", "wire-test", "--model-id", "n/a"], cwd=src)
98 r = run([MUSE, "push", "local", "main", "--force"], cwd=src, check=False)
99 return r.returncode == 0
100
101
102 def build_source_repo(path: str, n_commits: int) -> bool:
103 if os.path.exists(path):
104 shutil.rmtree(path)
105 os.makedirs(path)
106 m(["init"], cwd=path)
107 r = run([MUSE, "remote", "add", "local", TIMING_REPO_URL], cwd=path, check=False)
108 if r.returncode != 0:
109 run([MUSE, "remote", "set-url", "local", TIMING_REPO_URL], cwd=path, check=False)
110
111 for i in range(n_commits):
112 obj_file = os.path.join(path, f"obj_{i:04d}.dat")
113 with open(obj_file, "wb") as f:
114 f.write(os.urandom(512))
115 m(["code", "add", f"obj_{i:04d}.dat"], cwd=path)
116 m(["commit", "-m", f"pull test commit {i}",
117 "--agent-id", "wire-test", "--model-id", "n/a"], cwd=path)
118
119 r = run([MUSE, "push", "local", "main", "--force"], cwd=path, check=False)
120 return r.returncode == 0
121
122
123 def ensure_hub_repo() -> None:
124 tmp = "/tmp/pull-hub-probe"
125 if os.path.exists(tmp):
126 shutil.rmtree(tmp)
127 os.makedirs(tmp)
128 m(["init"], cwd=tmp)
129 run([MUSE, "-C", tmp, "hub", "repo", "create",
130 "--name", "timing-test", "--visibility", "public", "--json"], check=False)
131
132
133 def main() -> None:
134 print(f"\n── Pull atomic tests → {LOCAL_HUB} ──")
135 print(f" {'label':42s} {'total':>12} status")
136 print(" " + "-" * 85)
137
138 ensure_hub_repo()
139
140 src = "/tmp/pull-local-src"
141 print(f" building source repo (100 commits)… ", end="", flush=True)
142 ok_build = build_source_repo(src, 100)
143 print("done" if ok_build else "FAILED")
144 if not ok_build:
145 print("❌ source repo push failed — stopping.")
146 return
147
148 target = "/tmp/pull-local-target"
149 fresh_pull_target(target)
150
151 r0 = timed_pull(target)
152 n0 = local_commit_count(target)
153 print(fmt("PL0: empty→100c+100o (M clone)", r0, f" [{n0}c local]"))
154 sys.stdout.flush()
155 if not r0["ok"]:
156 print(f"\n❌ PL0 failed — stopping.\n {r0['error']}")
157 return
158
159 _add_commits(src, 1)
160 r1 = timed_pull(target)
161 print(fmt("PL1: +1c+1o incremental (XS)", r1, f" [{local_commit_count(target)}c local]"))
162 sys.stdout.flush()
163
164 _add_commits(src, 10)
165 r2 = timed_pull(target)
166 print(fmt("PL2: +10c+10o incremental (XS→S)", r2, f" [{local_commit_count(target)}c local]"))
167 sys.stdout.flush()
168
169 _add_commits(src, 100)
170 r3 = timed_pull(target)
171 print(fmt("PL3: +100c+100o incremental (M)", r3, f" [{local_commit_count(target)}c local]"))
172 sys.stdout.flush()
173
174 print()
175
176
177 if __name__ == "__main__":
178 main()
File History 1 commit
sha256:7d6dd8f4a89e2d1fef2d84f6e65feaff51385d382f466766b7f690a22ec18e32 fix: fall back to DB ancestry check when mpack-only fast-fo… Sonnet 4.6 patch 6 days ago