返回 CodeWhale
dev-cache.test.sh
根目录 / scripts / dev-cache.test.sh
1 #!/bin/sh
2 # Hermetic tests for scripts/dev-cache.sh. No cargo compile, no cache
3 # deletion. Exercises portable defaults, overrides, missing-sccache
4 # fallback, incremental gating, and new-vs-existing worktree policy.
5 set -eu
6
7 repo_root=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
8 DEV_CACHE=$repo_root/scripts/dev-cache.sh
9 DEV_CARGO=$repo_root/scripts/dev-cargo.sh
10
11 fail=0
12 pass=0
13
14 ok() {
15 pass=$((pass + 1))
16 printf 'ok - %s\n' "$1"
17 }
18
19 bad() {
20 fail=$((fail + 1))
21 printf 'FAIL - %s\n' "$1"
22 if [ -n "${2:-}" ]; then
23 printf '%s\n' "$2" | sed 's/^/ /'
24 fi
25 }
26
27 work=$(mktemp -d "${TMPDIR:-/tmp}/codewhale-dev-cache.XXXXXX")
28 cleanup() { rm -rf "$work"; }
29 trap cleanup EXIT INT HUP TERM
30
31 HOME_DIR=$work/home
32 mkdir -p "$HOME_DIR"
33 FAKEBIN=$work/bin
34 mkdir -p "$FAKEBIN"
35 NEW_WT=$work/new-wt
36 OLD_WT=$work/old-wt
37 mkdir -p "$NEW_WT" "$OLD_WT/target"
38
39 # cargo/rustc/sccache are injected per case. Keep the base PATH hermetic.
40 BASE_PATH=$FAKEBIN:/usr/bin:/bin
41
42 run_apply() {
43 env -i \
44 PATH="$BASE_PATH" \
45 HOME="$HOME_DIR" \
46 CODEWHALE_DEV_CACHE_QUIET=1 \
47 DEV_CACHE="$DEV_CACHE" \
48 "$@" \
49 /bin/sh -c '
50 set -eu
51 . "$DEV_CACHE"
52 codewhale_dev_cache_apply
53 codewhale_dev_cache_status
54 ' # shellcheck disable=SC2016 -- $DEV_CACHE expands in the child.
55 }
56
57 contains() {
58 printf '%s' "$1" | grep -qF -- "$2"
59 }
60
61 # 1. Portable default root is $HOME/.cache/codewhale, never a desk path.
62 out=$(run_apply CODEWHALE_DEV_CACHE=0 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT")
63 if contains "$out" "cache_root=$HOME_DIR/.cache/codewhale"; then
64 ok "default cache root is HOME/.cache/codewhale"
65 else
66 bad "default cache root is HOME/.cache/codewhale" "$out"
67 fi
68 if printf '%s\n' "$out" | grep -v '^repo_root=' | grep -qF /Volumes/VIXinSSD; then
69 bad "default paths must not mention /Volumes/VIXinSSD" "$out"
70 else
71 ok "default paths do not mention /Volumes/VIXinSSD"
72 fi
73 if grep -E '/Users/hunterbown|/Volumes/VIXinSSD' "$DEV_CACHE" "$DEV_CARGO" >/dev/null; then
74 bad "helper source must not hard-code a desk path"
75 else
76 ok "helper source has no desk-local absolute paths"
77 fi
78
79 # 2. XDG_CACHE_HOME and CODEWHALE_CACHE_ROOT win in that documented order.
80 out=$(run_apply CODEWHALE_DEV_CACHE=0 XDG_CACHE_HOME="$work/xdg")
81 if contains "$out" "cache_root=$work/xdg/codewhale"; then
82 ok "XDG_CACHE_HOME/codewhale is the default when set"
83 else
84 bad "XDG_CACHE_HOME/codewhale is the default when set" "$out"
85 fi
86 out=$(run_apply CODEWHALE_DEV_CACHE=0 \
87 XDG_CACHE_HOME="$work/xdg" \
88 CODEWHALE_CACHE_ROOT="$work/explicit-root")
89 if contains "$out" "cache_root=$work/explicit-root"; then
90 ok "CODEWHALE_CACHE_ROOT overrides XDG and HOME"
91 else
92 bad "CODEWHALE_CACHE_ROOT overrides XDG and HOME" "$out"
93 fi
94
95 # 3. Disabled mode leaves Cargo/sccache vars alone.
96 out=$(run_apply CODEWHALE_DEV_CACHE=0)
97 if contains "$out" "mode=disabled" \
98 && contains "$out" "CARGO_BUILD_BUILD_DIR=<unset>" \
99 && contains "$out" "RUSTC_WRAPPER=<unset>"; then
100 ok "CODEWHALE_DEV_CACHE=0 does not set cargo or sccache vars"
101 else
102 bad "CODEWHALE_DEV_CACHE=0 does not set cargo or sccache vars" "$out"
103 fi
104
105 # 4. New worktree (no ./target) gets isolated build-dir with the cargo template.
106 out=$(run_apply \
107 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
108 CODEWHALE_CACHE_ROOT="$work/cache")
109 if contains "$out" "mode=isolated-build-dir" \
110 && contains "$out" "CARGO_BUILD_BUILD_DIR=$work/cache/build/{workspace-path-hash}"; then
111 ok "new worktree uses isolated build-dir template"
112 else
113 bad "new worktree uses isolated build-dir template" "$out"
114 fi
115 if contains "$out" "CARGO_INCREMENTAL=<unset>"; then
116 ok "isolated default does not turn incremental off"
117 else
118 bad "isolated default does not turn incremental off" "$out"
119 fi
120 if contains "$out" "sccache=skipped-incremental"; then
121 ok "sccache stays off while incremental is on"
122 else
123 bad "sccache stays off while incremental is on" "$out"
124 fi
125
126 # 5. A stub or leftover ./target does not abandon isolation (Cargo still
127 # writes CACHEDIR.TAG under ./target when build-dir is split).
128 out=$(run_apply \
129 CODEWHALE_DEV_CACHE_REPO_ROOT="$OLD_WT" \
130 CODEWHALE_CACHE_ROOT="$work/cache")
131 if contains "$out" "mode=isolated-build-dir" \
132 && contains "$out" "CARGO_BUILD_BUILD_DIR=$work/cache/build/{workspace-path-hash}"; then
133 ok "existing ./target does not abandon isolated build-dir"
134 else
135 bad "existing ./target does not abandon isolated build-dir" "$out"
136 fi
137
138 # 6. CODEWHALE_DEV_CACHE=local keeps ./target.
139 out=$(run_apply \
140 CODEWHALE_DEV_CACHE=local \
141 CODEWHALE_DEV_CACHE_REPO_ROOT="$OLD_WT" \
142 CODEWHALE_CACHE_ROOT="$work/cache")
143 if contains "$out" "mode=existing-target" \
144 && contains "$out" "CARGO_BUILD_BUILD_DIR=<unset>"; then
145 ok "CODEWHALE_DEV_CACHE=local keeps ./target"
146 else
147 bad "CODEWHALE_DEV_CACHE=local keeps ./target" "$out"
148 fi
149
150 # 7. Already-set CARGO_TARGET_DIR / CARGO_BUILD_BUILD_DIR are respected.
151 out=$(run_apply \
152 CODEWHALE_DEV_CACHE=1 \
153 CARGO_TARGET_DIR="$work/user-target" \
154 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT")
155 if contains "$out" "mode=inherited-target-dir" \
156 && contains "$out" "CARGO_TARGET_DIR=$work/user-target" \
157 && contains "$out" "CARGO_BUILD_BUILD_DIR=<unset>"; then
158 ok "existing CARGO_TARGET_DIR is not overwritten"
159 else
160 bad "existing CARGO_TARGET_DIR is not overwritten" "$out"
161 fi
162 out=$(run_apply \
163 CARGO_BUILD_BUILD_DIR="$work/user-build" \
164 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT")
165 if contains "$out" "mode=inherited-build-dir" \
166 && contains "$out" "CARGO_BUILD_BUILD_DIR=$work/user-build"; then
167 ok "existing CARGO_BUILD_BUILD_DIR is not overwritten"
168 else
169 bad "existing CARGO_BUILD_BUILD_DIR is not overwritten" "$out"
170 fi
171
172 # 8. Missing sccache is a fallback, not a failure, even when requested.
173 out=$(run_apply \
174 CODEWHALE_SCCACHE=1 \
175 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
176 CODEWHALE_CACHE_ROOT="$work/cache")
177 if contains "$out" "sccache=not-found" \
178 && contains "$out" "RUSTC_WRAPPER=<unset>" \
179 && contains "$out" "CARGO_INCREMENTAL=0"; then
180 ok "missing sccache falls back without setting RUSTC_WRAPPER"
181 else
182 bad "missing sccache falls back without setting RUSTC_WRAPPER" "$out"
183 fi
184
185 # 9. sccache wraps only when incremental is off and the binary exists.
186 printf '%s\n' '#!/bin/sh' 'exit 0' >"$FAKEBIN/sccache"
187 chmod +x "$FAKEBIN/sccache"
188
189 out=$(run_apply \
190 CARGO_INCREMENTAL=0 \
191 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
192 CODEWHALE_CACHE_ROOT="$work/cache" \
193 CODEWHALE_RUSTC_COMMIT=abc123deadbeef)
194 if contains "$out" "sccache=enabled" \
195 && contains "$out" "RUSTC_WRAPPER=$FAKEBIN/sccache" \
196 && contains "$out" "SCCACHE_DIR=$work/cache/sccache/abc123deadbeef"; then
197 ok "sccache wraps rustc when incremental is off"
198 else
199 bad "sccache wraps rustc when incremental is off" "$out"
200 fi
201
202 out=$(run_apply \
203 CARGO_INCREMENTAL=1 \
204 CODEWHALE_SCCACHE=1 \
205 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
206 CODEWHALE_CACHE_ROOT="$work/cache")
207 if contains "$out" "sccache=skipped-incremental" \
208 && contains "$out" "RUSTC_WRAPPER=<unset>" \
209 && contains "$out" "CARGO_INCREMENTAL=1"; then
210 ok "explicit incremental=1 wins over CODEWHALE_SCCACHE=1"
211 else
212 bad "explicit incremental=1 wins over CODEWHALE_SCCACHE=1" "$out"
213 fi
214
215 out=$(run_apply \
216 CODEWHALE_SCCACHE=1 \
217 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
218 CODEWHALE_CACHE_ROOT="$work/cache" \
219 CODEWHALE_RUSTC_COMMIT=abc123deadbeef)
220 if contains "$out" "sccache=enabled" \
221 && contains "$out" "CARGO_INCREMENTAL=0"; then
222 ok "CODEWHALE_SCCACHE=1 requests incremental=0 and wraps"
223 else
224 bad "CODEWHALE_SCCACHE=1 requests incremental=0 and wraps" "$out"
225 fi
226
227 out=$(run_apply \
228 RUSTC_WRAPPER=/usr/bin/true \
229 CARGO_INCREMENTAL=0 \
230 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT")
231 if contains "$out" "sccache=external-wrapper" \
232 && contains "$out" "RUSTC_WRAPPER=/usr/bin/true"; then
233 ok "existing RUSTC_WRAPPER is left alone"
234 else
235 bad "existing RUSTC_WRAPPER is left alone" "$out"
236 fi
237
238 # 10. Cargo older than 1.91 falls back to a per-workspace CARGO_TARGET_DIR.
239 printf '%s\n' '#!/bin/sh' 'echo "cargo 1.88.0 (test)"' >"$FAKEBIN/cargo"
240 chmod +x "$FAKEBIN/cargo"
241 out=$(run_apply \
242 CODEWHALE_DEV_CACHE=1 \
243 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
244 CODEWHALE_CACHE_ROOT="$work/cache")
245 if contains "$out" "legacy-target-dir" \
246 && contains "$out" "CARGO_BUILD_BUILD_DIR=<unset>" \
247 && contains "$out" "CARGO_TARGET_DIR=$work/cache/target/"; then
248 ok "cargo 1.88 falls back to an isolated CARGO_TARGET_DIR"
249 else
250 bad "cargo 1.88 falls back to an isolated CARGO_TARGET_DIR" "$out"
251 fi
252 rm -f "$FAKEBIN/cargo"
253
254 # 11. CLI self-check passes for a new worktree with portable HOME.
255 cli_out=$(
256 env -i \
257 PATH="$BASE_PATH" \
258 HOME="$HOME_DIR" \
259 PWD="$NEW_WT" \
260 CODEWHALE_DEV_CACHE_QUIET=1 \
261 CODEWHALE_DEV_CACHE_REPO_ROOT="$NEW_WT" \
262 CODEWHALE_CACHE_ROOT="$work/cache" \
263 /bin/sh "$DEV_CACHE" --self-check
264 ) || cli_rc=$?
265 cli_rc=${cli_rc:-0}
266 if [ "$cli_rc" -eq 0 ] && contains "$cli_out" "dev-cache: self-check ok"; then
267 ok "CLI --self-check passes on a new worktree"
268 else
269 bad "CLI --self-check passes on a new worktree" "$cli_out"
270 fi
271
272 # 12. Two worktree paths produce different legacy fingerprints.
273 # shellcheck source=scripts/dev-cache.sh
274 . "$DEV_CACHE"
275 fp_a=$(codewhale_dev_cache_path_fingerprint "$NEW_WT")
276 fp_b=$(codewhale_dev_cache_path_fingerprint "$OLD_WT")
277 if [ -n "$fp_a" ] && [ -n "$fp_b" ] && [ "$fp_a" != "$fp_b" ]; then
278 ok "path fingerprints differ across worktrees"
279 else
280 bad "path fingerprints differ across worktrees" "a=$fp_a b=$fp_b"
281 fi
282
283 # 13. dev-cargo.sh --status is the same helper.
284 if /bin/sh "$DEV_CARGO" --help | grep -q 'dev-cache'; then
285 ok "dev-cargo.sh --help delegates to the cache helper"
286 else
287 bad "dev-cargo.sh --help delegates to the cache helper"
288 fi
289
290 if [ "$fail" -eq 0 ]; then
291 printf 'dev-cache.test.sh: all %s checks passed\n' "$pass"
292 exit 0
293 fi
294 printf 'dev-cache.test.sh: %s/%s checks failed\n' "$fail" "$((pass + fail))" >&2
295 exit 1
296
296 lines BASH