test: deps-accept — iteration 15's gate (Task 4)
scripts/deps-accept.sh: 8 checks over local file:// remotes built at run time (network-free) — cold fetch + lock + use <dep>/<dep>/sub + app-entry- wins (the dep's fn main returns 99 and must never run), offline rebuild with the remote deleted, lock-beats-moved-tag, --update-deps refresh, cache/lock drift WO-E106, transitive refusal, WO-E107 collision, missing-rev manifest shape. `just deps-accept` wired. 8/0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
edf67d532a
commit
5d5d7f61ab
2 changed files with 172 additions and 0 deletions
7
justfile
7
justfile
|
|
@ -28,6 +28,13 @@ wovm-test:
|
|||
dist:
|
||||
./scripts/mkdist.sh
|
||||
|
||||
# deps-accept: iteration 15's gate — wo.toml [deps] + git fetch + wo.lock,
|
||||
# proven against local file:// remotes built at run time (network-free):
|
||||
# cold fetch, offline rebuild, lock-beats-moved-tag, --update-deps, drift/
|
||||
# transitive/collision diagnostics, dep-main-never-entry, manifest shape.
|
||||
deps-accept:
|
||||
./scripts/deps-accept.sh
|
||||
|
||||
# install-accept: extract the dist tarball to a temp prefix, PATH it, and prove
|
||||
# `woc version` + a from-scratch project build+run (self-located wovm) + the
|
||||
# wo-constraint refusal all work — the "tarball install actually works" gate.
|
||||
|
|
|
|||
165
scripts/deps-accept.sh
Executable file
165
scripts/deps-accept.sh
Executable file
|
|
@ -0,0 +1,165 @@
|
|||
#!/usr/bin/env bash
|
||||
# scripts/deps-accept.sh — iteration 15's acceptance gate: wo.toml [deps] +
|
||||
# git fetch + wo.lock, proven against local file:// remotes built at run time
|
||||
# (network-free). One check per spec behavior, log-watcher-accept style.
|
||||
set -uo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
WOC="$ROOT/compiler/_build/default/bin/woc"
|
||||
WOVM="$ROOT/runtime/wovm"
|
||||
|
||||
pass=0
|
||||
fail=0
|
||||
ok() { echo "ok $1"; pass=$((pass + 1)); }
|
||||
bad() { echo "FAIL $1 -- $2"; fail=$((fail + 1)); }
|
||||
|
||||
if [[ ! -x "$WOC" || ! -x "$WOVM" ]]; then
|
||||
echo "deps-accept: build woc and wovm first (just woc-build; just wovm-build)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
W="$(mktemp -d "${TMPDIR:-/tmp}/deps-accept.XXXXXX")"
|
||||
cleanup() { [[ -n "${DEPS_ACCEPT_KEEP:-}" ]] && echo "kept $W" || rm -rf "$W"; }
|
||||
trap cleanup EXIT
|
||||
G() { git -C "$1" -c user.email=t@t -c user.name=t "${@:2}"; }
|
||||
|
||||
# ---- the framework remote: a real git repo with a tag ----
|
||||
mkdir -p "$W/fwsrc/strutil"
|
||||
cat > "$W/fwsrc/wo.toml" <<'EOF'
|
||||
name = "niceframework"
|
||||
version = "0.1.0"
|
||||
EOF
|
||||
cat > "$W/fwsrc/greet.wo" <<'EOF'
|
||||
pub fn greeting(who: Text) -> Text {
|
||||
return "hello, " .. who
|
||||
}
|
||||
fn main(args: multi Text) -> Int {
|
||||
return 99
|
||||
}
|
||||
EOF
|
||||
cat > "$W/fwsrc/strutil/shout.wo" <<'EOF'
|
||||
pub fn quiet(t: Text) -> Text {
|
||||
return to_lower(t)
|
||||
}
|
||||
EOF
|
||||
git -C "$W/fwsrc" init -q
|
||||
G "$W/fwsrc" add -A
|
||||
G "$W/fwsrc" commit -qm one
|
||||
G "$W/fwsrc" tag v0.1.0
|
||||
|
||||
# ---- the consuming app ----
|
||||
mkdir -p "$W/app"
|
||||
cat > "$W/app/wo.toml" <<EOF
|
||||
name = "app"
|
||||
version = "0.1.0"
|
||||
[build]
|
||||
runtime = "$WOVM"
|
||||
[deps]
|
||||
niceframework = { git = "file://$W/fwsrc", rev = "v0.1.0" }
|
||||
EOF
|
||||
cat > "$W/app/main.wo" <<'EOF'
|
||||
use niceframework
|
||||
use niceframework/strutil
|
||||
|
||||
fn main(args: multi Text) -> Int {
|
||||
print(greeting("web"));
|
||||
print(quiet("QUIET"));
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
|
||||
# ---- 1. cold fetch + lock + build + run (dep main must NOT be the entry:
|
||||
# the dep's main returns 99; the app's prints and returns 0) ----
|
||||
out="$(cd /tmp && "$WOC" "$W/app" 2>&1 && "$W/app/target/app")"
|
||||
rc=$?
|
||||
if [[ $rc -eq 0 && "$out" == "hello, web
|
||||
quiet" && -f "$W/app/wo.lock" ]]; then
|
||||
ok "cold fetch + lock + use <dep> and <dep>/sub + app entry wins"
|
||||
else
|
||||
bad "cold build" "rc=$rc out=$(printf '%s' "$out" | tr '\n' '|')"
|
||||
fi
|
||||
locked_sha="$(awk '!/^#/ {print $2}' "$W/app/wo.lock")"
|
||||
|
||||
# ---- 2. offline rebuild: remote removed, lock + cache satisfy ----
|
||||
mv "$W/fwsrc" "$W/fwsrc.hidden"
|
||||
rm -rf "$W/app/target"
|
||||
if "$WOC" "$W/app" >/dev/null 2>&1 && [[ "$("$W/app/target/app")" == "hello, web
|
||||
quiet" ]]; then
|
||||
ok "offline rebuild (remote deleted, lock satisfied)"
|
||||
else
|
||||
bad "offline rebuild" "failed with the remote gone"
|
||||
fi
|
||||
mv "$W/fwsrc.hidden" "$W/fwsrc"
|
||||
|
||||
# ---- 3. moved tag: cold cache + lock -> rebuilt at the LOCKED sha ----
|
||||
G "$W/fwsrc" commit -qm two --allow-empty
|
||||
G "$W/fwsrc" tag -f v0.1.0 >/dev/null 2>&1
|
||||
rm -rf "$W/app/.wo-deps"
|
||||
"$WOC" "$W/app" >/dev/null 2>&1
|
||||
now_sha="$(git -C "$W/app/.wo-deps/niceframework" rev-parse HEAD 2>/dev/null)"
|
||||
if [[ "$now_sha" == "$locked_sha" ]]; then
|
||||
ok "moved tag: lock wins (checkout pinned to the locked SHA)"
|
||||
else
|
||||
bad "moved tag" "expected $locked_sha got $now_sha"
|
||||
fi
|
||||
|
||||
# ---- 4. --update-deps follows the tag and rewrites the lock ----
|
||||
"$WOC" --update-deps "$W/app" >/dev/null 2>&1
|
||||
new_lock="$(awk '!/^#/ {print $2}' "$W/app/wo.lock")"
|
||||
tag_sha="$(git -C "$W/fwsrc" rev-parse v0.1.0)"
|
||||
if [[ "$new_lock" == "$tag_sha" && "$new_lock" != "$locked_sha" ]]; then
|
||||
ok "--update-deps refreshes the lock to the moved tag"
|
||||
else
|
||||
bad "--update-deps" "lock=$new_lock tag=$tag_sha"
|
||||
fi
|
||||
|
||||
# ---- 5. cache/lock drift is a named diagnostic ----
|
||||
G "$W/app/.wo-deps/niceframework" commit -qm local --allow-empty
|
||||
out="$("$WOC" "$W/app" 2>&1)"
|
||||
if [[ "$out" == *"WO-E106"* && "$out" == *"lock drift"* ]]; then
|
||||
ok "cache/lock drift diagnosed (WO-E106)"
|
||||
else
|
||||
bad "drift" "$(printf '%s' "$out" | head -1)"
|
||||
fi
|
||||
git -C "$W/app/.wo-deps/niceframework" reset -q --hard HEAD~1
|
||||
|
||||
# ---- 6. transitive [deps] refused ----
|
||||
printf '[deps]\nx = { git = "file:///nowhere", rev = "v1" }\n' >> "$W/fwsrc/wo.toml"
|
||||
G "$W/fwsrc" commit -qam trans
|
||||
G "$W/fwsrc" tag -f v0.1.0 >/dev/null 2>&1
|
||||
rm -rf "$W/app/.wo-deps" "$W/app/wo.lock"
|
||||
out="$("$WOC" "$W/app" 2>&1)"
|
||||
if [[ "$out" == *"WO-E106"* && "$out" == *"transitive"* ]]; then
|
||||
ok "transitive [deps] refused (flat-only)"
|
||||
else
|
||||
bad "transitive" "$(printf '%s' "$out" | head -1)"
|
||||
fi
|
||||
G "$W/fwsrc" revert --no-edit HEAD >/dev/null 2>&1
|
||||
G "$W/fwsrc" tag -f v0.1.0 >/dev/null 2>&1
|
||||
|
||||
# ---- 7. dep name colliding with a local module directory ----
|
||||
mkdir -p "$W/app/niceframework"
|
||||
touch "$W/app/niceframework/x.wo"
|
||||
rm -rf "$W/app/.wo-deps" "$W/app/wo.lock"
|
||||
out="$("$WOC" "$W/app" 2>&1)"
|
||||
if [[ "$out" == *"WO-E107"* ]]; then
|
||||
ok "dep/local module-name collision diagnosed (WO-E107)"
|
||||
else
|
||||
bad "collision" "$(printf '%s' "$out" | head -1)"
|
||||
fi
|
||||
rm -rf "$W/app/niceframework"
|
||||
|
||||
# ---- 8. manifest shape: a dep without `rev` is refused at parse ----
|
||||
mkdir -p "$W/norev"
|
||||
printf 'name = "norev"\n[deps]\nfw = { git = "file:///x" }\n' > "$W/norev/wo.toml"
|
||||
printf 'fn main(args: multi Text) -> Int { return 0 }\n' > "$W/norev/main.wo"
|
||||
out="$("$WOC" "$W/norev" 2>&1)"
|
||||
if [[ "$out" == *"needs both"* ]]; then
|
||||
ok "missing rev refused at manifest parse"
|
||||
else
|
||||
bad "missing rev" "$(printf '%s' "$out" | head -1)"
|
||||
fi
|
||||
|
||||
echo
|
||||
printf 'deps-accept: %d checks, %d failures\n' "$((pass + fail))" "$fail"
|
||||
[[ $fail -eq 0 ]]
|
||||
Loading…
Reference in a new issue