14 cases: RELEASE validation (valid/invalid/missing), tag consistency, status on empty state, fault-injected refusal with no pointer + single valid refusal log line, healthy activation, pointer fields, repeat activation append-only log, rollback-without-previous refusal. Harness fix learned the hard way: restore RELEASE from backup inline after the missing-file case (mv-back restored the mutated file); single exit trap self-heals the repo state. Closes #12
99 lines
3.9 KiB
Bash
Executable File
99 lines
3.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Sandboxed selftests for the release layer.
|
|
#
|
|
# Fast cases (version validation) need no Docker. State-machine cases
|
|
# (status/activate/refusal) run against a sandboxed config and therefore
|
|
# require the Docker daemon; they are skipped when it is unavailable.
|
|
set -uo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
|
|
SANDBOX="$(mktemp -d)"
|
|
RELEASE_BACKUP="$(mktemp)"
|
|
cp RELEASE "$RELEASE_BACKUP"
|
|
# One exit trap: the repo RELEASE is ALWAYS restored from the backup,
|
|
# regardless of how the test run ends.
|
|
trap 'cp "$RELEASE_BACKUP" RELEASE 2>/dev/null; rm -rf "$SANDBOX" "$RELEASE_BACKUP"' EXIT
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
expect_exit() {
|
|
local name="$1" expected="$2"
|
|
shift 3
|
|
local rc
|
|
"$@" >/dev/null 2>&1
|
|
rc=$?
|
|
if [ "$rc" -eq "$expected" ]; then
|
|
PASS=$((PASS+1)); echo "ok $name (exit $rc)"
|
|
else
|
|
FAIL=$((FAIL+1)); echo "FAIL $name (exit $rc, expected $expected)"
|
|
fi
|
|
}
|
|
|
|
check() {
|
|
if [ "$2" = "0" ]; then PASS=$((PASS+1)); echo "ok $1"; else FAIL=$((FAIL+1)); echo "FAIL $1"; fi
|
|
}
|
|
|
|
# ---------- fast: release identity ----------
|
|
expect_exit "valid RELEASE resolves" 0 -- bash -c 'source scripts/common.sh && load_release'
|
|
|
|
printf 'garbage\n' > RELEASE
|
|
expect_exit "invalid RELEASE exits 1" 1 -- bash -c 'source scripts/common.sh && load_release'
|
|
|
|
mv RELEASE "$SANDBOX/RELEASE.hidden"
|
|
expect_exit "missing RELEASE exits 1" 1 -- bash -c 'source scripts/common.sh && load_release'
|
|
cp "$RELEASE_BACKUP" RELEASE
|
|
|
|
bash -c 'source scripts/common.sh && load_release' >/dev/null 2>&1
|
|
bash -c 'source scripts/common.sh && load_release && case "$MOSAIC_IMAGE_TAG" in mosaic-poc-agent:*-r'"$(cat RELEASE)"') exit 0;; *) exit 1;; esac' >/dev/null 2>&1
|
|
check "valid RELEASE leaves image tag consistent with version" $?
|
|
|
|
# ---------- sandboxed state machine (Docker required) ----------
|
|
if docker info >/dev/null 2>&1; then
|
|
mkdir -p "$SANDBOX/data"
|
|
cat > "$SANDBOX/config.json" <<EOF
|
|
{"configVersion":1,"environment":"development","dataRoot":"$SANDBOX/data","execution":{"backend":"docker","provider":"zai","model":"glm-5.3-flash"}}
|
|
EOF
|
|
export MOSAIC_CONFIG="$SANDBOX/config.json"
|
|
|
|
expect_exit "status safe on empty state" 0 -- scripts/release.sh status
|
|
[ ! -e "$SANDBOX/data/state/active.json" ] \
|
|
&& check "status created no pointer" 0 || check "status created no pointer" 1
|
|
|
|
expect_exit "fault-injected activation refuses" 1 -- scripts/release.sh activate --fault-injection
|
|
[ ! -e "$SANDBOX/data/state/active.json" ] \
|
|
&& check "refused activation wrote no pointer" 0 || check "refused activation wrote no pointer" 1
|
|
if [ -f "$SANDBOX/data/state/activation-log.jsonl" ]; then
|
|
node -e '
|
|
const fs = require("fs");
|
|
const lines = fs.readFileSync(process.argv[1], "utf8").split("\n").filter(Boolean);
|
|
if (lines.length !== 1) process.exit(1);
|
|
const e = JSON.parse(lines[0]);
|
|
process.exit(e.event === "refused" && e.release && e.imageTag && e.at ? 0 : 1);
|
|
' "$SANDBOX/data/state/activation-log.jsonl"
|
|
check "refusal logged exactly once with valid fields" $?
|
|
else
|
|
check "refusal logged exactly once with valid fields" 1
|
|
fi
|
|
|
|
expect_exit "healthy activation succeeds" 0 -- scripts/release.sh activate
|
|
node -e '
|
|
const fs = require("fs");
|
|
const p = JSON.parse(fs.readFileSync(process.argv[1], "utf8"));
|
|
process.exit(p.pointerVersion === 1 && p.release && p.imageTag && p.activatedAt ? 0 : 1);
|
|
' "$SANDBOX/data/state/active.json"
|
|
check "pointer written with valid fields" $?
|
|
|
|
expect_exit "repeat activation succeeds (log grows)" 0 -- scripts/release.sh activate
|
|
LINES=$(grep -c '' "$SANDBOX/data/state/activation-log.jsonl")
|
|
[ "$LINES" -ge 3 ] && check "log is append-only across activations" 0 || check "log is append-only across activations" 1
|
|
|
|
expect_exit "rollback without previous refuses" 1 -- scripts/release.sh rollback
|
|
else
|
|
echo "skip state-machine cases (docker daemon unavailable)"
|
|
fi
|
|
|
|
echo
|
|
echo "selftest: $PASS passed, $FAIL failed"
|
|
[ "$FAIL" -eq 0 ]
|