Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions scripts/smoke-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ they stage the release fixture, start the fixture server, and sandbox
HOME/TEMP/agent-config destinations. Called bare, the download/checksum/
install-script phases (12-13) SKIP for lack of a fixture server, and the run
mutates the REAL profile — the venue-parity contract forbids that in any venue.
The daemon runtime and cache are private to the run either way: every product
process is started under a CBM_RUNTIME_DIR/CBM_CACHE_DIR this harness owns.

Arguments:
<binary-path> product binary to smoke
Expand All @@ -41,6 +43,15 @@ if [ -n "$SMOKE_MODE" ] && [ "$SMOKE_MODE" != "--agent-config-only" ]; then
fi
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")/.." && pwd)"

# Every product process below — the phases, the install/update E2E and the
# daemon retirements — must reach a daemon rendezvous this run owns. Only
# CBM_RUNTIME_DIR moves that rendezvous; the wrappers' HOME/TMPDIR/CBM_CACHE_DIR
# sandbox does not, so without this the retirements land on the operator's live
# account daemon (#1691, #1696).
# shellcheck source=test-runtime.sh
source "$REPO_ROOT/scripts/test-runtime.sh"
cbm_test_runtime_init

smoke_mktemp_file() {
if [ -n "${SMOKE_TEMP_ROOT:-}" ]; then
mktemp "$SMOKE_TEMP_ROOT/cbm-smoke.XXXXXX"
Expand Down Expand Up @@ -100,8 +111,8 @@ copy_smoke_binary() {
cp "$BINARY" "$destination"
}

# Retire the shared account daemon (if one is running) and wait until it
# reports not-running. Install/uninstall flows leave an ephemeral daemon
# Retire this run's private account daemon (if one is running) and wait until
# it reports not-running. Install/uninstall flows leave an ephemeral daemon
# draining asynchronously whose mapped generation backing and open logs
# block rm on Windows (POSIX rm doesn't care) — so every cleanup of a
# fixture HOME that received an install, and the final cache removal, must
Expand Down Expand Up @@ -149,7 +160,7 @@ CODEX_LIFECYCLE_HOME=""
if command -v cygpath &>/dev/null; then
TMPDIR=$(cygpath -m "$TMPDIR")
fi
trap 'smoke_rmtree "$TMPDIR" "${DRYRUN_HOME:-}" "${CODEX_LIFECYCLE_HOME:-}"' EXIT
trap 'smoke_rmtree "$TMPDIR" "${DRYRUN_HOME:-}" "${CODEX_LIFECYCLE_HOME:-}"; cbm_test_runtime_cleanup "$BINARY"' EXIT

CLI_STDERR=$(smoke_mktemp_file)
# 10 of the cli call sites assign directly (VAR=$(cli ...)). Under
Expand Down
3 changes: 3 additions & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@ bash "$ROOT/tests/test_release_gate_chain_contract.sh"
echo "=== Step 0t: test runtime isolation contract (#1691) ==="
bash "$ROOT/tests/test_runtime_isolation_contract.sh"

echo "=== Step 0t2: smoke harness runtime isolation contract (#1696) ==="
bash "$ROOT/tests/test_smoke_runtime_isolation_contract.sh"

echo "=== Step 0u: shell line-ending contract ==="
bash "$ROOT/tests/test_shell_line_endings.sh"

Expand Down
82 changes: 82 additions & 0 deletions tests/test_smoke_runtime_isolation_contract.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env bash
set -euo pipefail

# Runtime-isolation contract for the smoke harness (#1696, follow-up to #1691).
#
# scripts/smoke-test.sh is the process that actually starts the product during
# a smoke run, and it retires "the account daemon" seven times through
# `daemon stop`. Its wrappers sandbox HOME/XDG/TMPDIR and CBM_CACHE_DIR, but
# only CBM_RUNTIME_DIR moves the daemon rendezvous (docs/CONFIGURATION.md), so
# without a private runtime every one of those stops lands on the operator's
# live daemon. Drive the harness with an environment-probe fixture and require
# that no product process ever receives the caller's runtime or cache.

ROOT="$(cd "$(dirname "$0")/.." && pwd)"
WORKDIR="$(mktemp -d)"
trap 'rm -rf "$WORKDIR"' EXIT

fail() {
echo "FAIL: $*" >&2
exit 1
}

normalize_path() {
local path=${1%$'\r'}
if command -v cygpath >/dev/null 2>&1; then
cygpath -u "$path" 2>/dev/null && return 0
fi
printf '%s\n' "${path//\\//}"
}

ENV_PROBE="$WORKDIR/environment-probe"
cat > "$ENV_PROBE" <<'EOF'
#!/usr/bin/env bash
printf '%s\t%s\n' "${CBM_CACHE_DIR-}" "${CBM_RUNTIME_DIR-}" >> "$CBM_SMOKE_ENV_PROBE"
case "${1-}" in
--version) echo "v0.0.0-probe"; exit 0 ;;
daemon) [[ "${2-}" == status ]] && exit 1; exit 0 ;;
esac
echo '{}'
exit 0
EOF
chmod +x "$ENV_PROBE"

CALLER_CACHE="$WORKDIR/caller-cache"
CALLER_RUNTIME="$WORKDIR/caller-runtime"
ENV_LOG="$WORKDIR/environment.log"
mkdir -p "$CALLER_CACHE" "$CALLER_RUNTIME"

# The fixture answers nothing beyond --version, so the smoke fails early; only
# the environment it handed to the product is under test here.
CBM_CACHE_DIR="$CALLER_CACHE" \
CBM_RUNTIME_DIR="$CALLER_RUNTIME" \
CBM_SMOKE_ENV_PROBE="$ENV_LOG" \
"$ROOT/scripts/smoke-test.sh" "$ENV_PROBE" > "$WORKDIR/smoke.out" 2>&1 || true

[[ -s "$ENV_LOG" ]] || fail "smoke-test did not execute the environment-probe fixture"

CALLER_CACHE_NORMALIZED=$(normalize_path "$CALLER_CACHE")
CALLER_RUNTIME_NORMALIZED=$(normalize_path "$CALLER_RUNTIME")
private_root=""
while IFS=$'\t' read -r child_cache_raw child_runtime_raw; do
child_cache=$(normalize_path "$child_cache_raw")
child_runtime=$(normalize_path "$child_runtime_raw")
if [[ -z "$child_runtime" || "$child_runtime" == "$CALLER_RUNTIME_NORMALIZED" ]]; then
fail "smoke-test exposed the caller CBM_RUNTIME_DIR to a product process"
fi
if [[ -z "$child_cache" || "$child_cache" == "$CALLER_CACHE_NORMALIZED" ]]; then
fail "smoke-test exposed the caller CBM_CACHE_DIR to a product process"
fi
if [[ "${child_runtime%/*}" != "${child_cache%/*}" ||
"${child_runtime##*/}" != "runtime" || "${child_cache##*/}" != "cache" ]]; then
fail "smoke runtime/cache were not isolated beneath one private root"
fi
if [[ -n "$private_root" && "$private_root" != "${child_runtime%/*}" ]]; then
fail "smoke-test switched private roots mid-run"
fi
private_root="${child_runtime%/*}"
done < "$ENV_LOG"

[[ ! -e "$private_root" ]] || fail "smoke-test left its private root behind: $private_root"

echo "PASS: smoke harness isolates its daemon runtime and cache from the caller"
Loading