#!/usr/bin/env bash # Inspected control plane only. No compilation/fallback and no host test execution. set -euo pipefail CONTROL=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) [[ $# == 0 && ${ARCHY_TEST_ISOLATOR:-} == podman && ${ARCHY_TEST_TERMINAL_FIXTURE:-} == 1 ]] || exit 2 [[ ${ARCHY_TEST_CLOUD_COMPILE_ONLY:-0} == 0 && -z ${ARCHY_TEST_ARTIFACT_EXPORT:-} && -z ${ARCHY_TEST_CLOUD_FIXTURE_CONTAINER:-} ]] || exit 2 [[ ${ARCHY_TEST_PACKAGE:-archipelago} == archipelago ]] || exit 2 REPO=$(realpath -e "${ARCHY_TEST_REPO:?Exact source export required}") [[ -d "$REPO/core" && ! -e "$REPO/.git" && ! -L "$REPO/.git" ]] || exit 2 image=${ARCHY_TEST_IMAGE:?Immutable compiler identity required} runtime_image=${ARCHY_TEST_TERMINAL_RUNTIME_IMAGE:?Immutable tmux/browser runtime required} [[ "$image" =~ ^(sha256:)?[a-f0-9]{64}$ && "$runtime_image" =~ ^(sha256:)?[a-f0-9]{64}$ ]] || exit 2 reuse=$(realpath -e "${ARCHY_TEST_REUSE_ARTIFACT:?Precompiled exact artifact required; no Cargo fallback}") out=$(realpath -e "${ARCHY_TEST_EVIDENCE_DIR:?Existing empty receipt directory required}") [[ -d "$out" && -z $(find "$out" -mindepth 1 -maxdepth 1 -print -quit) ]] || exit 2 podman image exists "$runtime_image" # Inherited image volumes must not introduce undeclared writable storage. volumes=$(podman image inspect "$runtime_image" --format '{{json .Config.Volumes}}') [[ "$volumes" == null || "$volumes" == '{}' ]] || exit 2 mkdir "$out/screenshots" artifacts=$(mktemp -d /tmp/archy-terminal-test.XXXXXXXX) cleanup() { local status=$? cid exists trap - EXIT INT TERM set +e if [[ -s "$artifacts/runtime.cid" ]]; then cid=$(<"$artifacts/runtime.cid") if [[ "$cid" =~ ^[a-f0-9]{64}$ ]]; then printf '%s\n' "$cid" > "$out/owned.id" timeout --kill-after=2s 10s podman rm -f "$cid" > "$out/cleanup.log" 2>&1 || status=1 podman container exists "$cid"; exists=$? [[ "$exists" == 1 ]] || status=1 else status=1; fi fi podman ps -aq --no-trunc | sort > "$out/containers.after" || status=1 cmp "$out/containers.before" "$out/containers.after" || status=1 rm -rf -- "$artifacts" || status=1 printf '%s\n' "$status" > "$out/outer.exit" exit "$status" } trap cleanup EXIT trap 'exit 143' TERM trap 'exit 130' INT podman ps -aq --no-trunc | sort > "$out/containers.before" : > "$artifacts/test-binary" : > "$artifacts/empty-resolv.conf" : > "$artifacts/host-only-canary" python3 "$CONTROL/scripts/cloud-test-artifact.py" reuse "$REPO" "$image" "$runtime_image" "$artifacts/test-binary" "$reuse" v1 chmod 0500 "$artifacts/test-binary" sha256sum "$artifacts/test-binary" | cut -d' ' -f1 > "$out/binary.sha256" host_netns=$(readlink /proc/self/ns/net) host_pidns=$(readlink /proc/self/ns/pid) host_ipcns=$(readlink /proc/self/ns/ipc) podman create --cidfile "$artifacts/runtime.cid" --name "archy-terminal-execute-${artifacts##*.}" --pull=never \ --network=none --pid=private --ipc=private --no-hosts --http-proxy=false \ --log-driver=none --timeout=120 --cpus=2 --memory=3g --memory-swap=3g --pids-limit=256 \ --ulimit fsize=1073741824:1073741824 --cap-drop=all --security-opt=no-new-privileges --read-only \ --tmpfs /tmp:rw,notmpcopyup,size=128m --tmpfs /root:rw,notmpcopyup,size=16m --tmpfs /run:rw,notmpcopyup,size=16m \ --tmpfs /var/lib/archipelago:rw,notmpcopyup,size=64m --tmpfs /var/lib/containers:rw,notmpcopyup,size=16m \ --volume "$REPO:/workspace:ro" --volume "$artifacts/test-binary:/test-binary:ro" \ --volume "$artifacts/empty-resolv.conf:/etc/resolv.conf:ro" --volume "$out/screenshots:/out:rw" \ --env HOME=/root --env ARCHY_TEST_ISOLATED=1 --env "ARCHY_TEST_HOST_CANARY=$artifacts/host-only-canary" \ --workdir /workspace/core --entrypoint /bin/sh "$runtime_image" -ec ' [ "$(readlink /proc/self/ns/net)" != "$1" ] || { echo "Host network namespace leaked"; exit 2; } [ "$(readlink /proc/self/ns/pid)" != "$2" ] || { echo "Host PID namespace leaked"; exit 2; } [ "$(readlink /proc/self/ns/ipc)" != "$3" ] || { echo "Host IPC namespace leaked"; exit 2; } target=api::handler::terminal_transport_tests::actual_handler_private_tmux_history_and_reconnect /test-binary --list --ignored --exact "$target" > /tmp/test-list grep -Fx "$target: test" /tmp/test-list [ "$(grep -c ": test$" /tmp/test-list)" = 1 ] exec /test-binary --test-threads=1 --ignored --exact "$target" --nocapture ' terminal-netns "$host_netns" "$host_pidns" "$host_ipcns" > "$out/create.log" 2>&1 cid=$(<"$artifacts/runtime.cid") [[ "$cid" =~ ^[a-f0-9]{64}$ ]] || exit 2 podman inspect "$cid" > "$out/container.inspect.json" date -u +%FT%TZ > "$out/start" set +e timeout --signal=TERM --kill-after=10s 140s podman start --attach "$cid" 2>&1 | python3 "$CONTROL/scripts/limit-test-output.py" | tee "$out/runtime.log" result=$? set -e printf '%s\n' "$result" > "$out/test.exit" date -u +%FT%TZ > "$out/end" [[ "$result" == 0 ]] || exit "$result" grep -F 'test result: ok. 1 passed; 0 failed; 0 ignored;' "$out/runtime.log" >/dev/null