#!/bin/sh # Tests for nox-mesh-host-rollback. # # It runs on a machine where the host will not start, which is the one moment nobody can afford # it to be wrong — and the one moment it is hardest to debug. So it is tested here, against a # real filesystem, with a stub package manager that records what it was asked to do. set -eu cd "$(dirname "$0")" SCRIPT="$PWD/nox-mesh-host-rollback" PASS=0; FAIL=0 setup() { WORK="$(mktemp -d)" export MESH_HOST_STATE_DIR="$WORK/state" export MESH_HOST_PKG_CACHE="$WORK/cache" export MESH_HOST_PACKAGE="nox-mesh-host" mkdir -p "$MESH_HOST_STATE_DIR" "$MESH_HOST_PKG_CACHE" "$WORK/bin" # Stubs on PATH. Not mocks of the script's own logic — the boundary is real commands, and # these record the calls so a test can assert what the script asked the machine to do. cat > "$WORK/bin/pacman" <<'STUB' #!/bin/sh echo "$@" >> "$MESH_HOST_STATE_DIR/pacman.calls" [ -n "${STUB_PACMAN_FAILS:-}" ] && exit 1 exit 0 STUB cat > "$WORK/bin/systemctl" <<'STUB' #!/bin/sh echo "$@" >> "$MESH_HOST_STATE_DIR/systemctl.calls" exit 0 STUB chmod +x "$WORK/bin/pacman" "$WORK/bin/systemctl" PATH="$WORK/bin:$PATH"; export PATH unset STUB_PACMAN_FAILS || true } check() { # name, condition-description, actual, expected if [ "$3" = "$4" ]; then PASS=$((PASS+1)); printf ' ok %s\n' "$1" else FAIL=$((FAIL+1)); printf ' FAIL %s\n %s\n got: %s\n expected: %s\n' "$1" "$2" "$3" "$4"; fi } # --- a normal rollback --------------------------------------------------------------------- setup echo "1.4.2" > "$MESH_HOST_STATE_DIR/known-good" touch "$MESH_HOST_PKG_CACHE/nox-mesh-host-1.4.2-1-x86_64.pkg.tar.zst" "$SCRIPT" >/dev/null 2>&1 check "installs the known-good version" "pacman is asked to install the cached package" \ "$(grep -c 'nox-mesh-host-1.4.2' "$MESH_HOST_STATE_DIR/pacman.calls" 2>/dev/null || echo 0)" "1" # It installs and stops. The launcher execs the host next, and starting it here would run two # (novox/hq ADR 0005). check "does not start anything itself" "the launcher owns starting" \ "$([ -f "$MESH_HOST_STATE_DIR/systemctl.calls" ] && echo started || echo not-started)" "not-started" check "records that it rolled back" "the attempted marker holds the version" \ "$(cat "$MESH_HOST_STATE_DIR/rollback-attempted" 2>/dev/null || echo MISSING)" "1.4.2" # --- it rolls back only once --------------------------------------------------------------- setup echo "1.4.2" > "$MESH_HOST_STATE_DIR/known-good" echo "1.4.2" > "$MESH_HOST_STATE_DIR/rollback-attempted" touch "$MESH_HOST_PKG_CACHE/nox-mesh-host-1.4.2-1-x86_64.pkg.tar.zst" "$SCRIPT" >/dev/null 2>&1 check "does not roll back twice" "a second failure is the machine, not the binary" \ "$([ -f "$MESH_HOST_STATE_DIR/pacman.calls" ] && echo called || echo not-called)" "not-called" # --- nothing to roll back to --------------------------------------------------------------- setup set +e; "$SCRIPT" >/dev/null 2>&1; RC=$?; set -e check "no known-good: does nothing" "a host that never reconciled has no version to return to" \ "$([ -f "$MESH_HOST_STATE_DIR/pacman.calls" ] && echo called || echo not-called)" "not-called" # The exit code is asserted from a real run, not from a literal. An earlier version of this # compared "0" to "0" and could not fail — which hid an injected fault that made the script die # here instead of returning cleanly. check "no known-good: exits zero" "an installation failure is not a rollback failure" "$RC" "0" setup printf ' \n' > "$MESH_HOST_STATE_DIR/known-good" "$SCRIPT" >/dev/null 2>&1 check "blank known-good: refuses to guess" "installing nothing and reporting success is the fault this prevents" \ "$([ -f "$MESH_HOST_STATE_DIR/pacman.calls" ] && echo called || echo not-called)" "not-called" # --- the cache was cleaned ------------------------------------------------------------------ setup echo "1.4.2" > "$MESH_HOST_STATE_DIR/known-good" set +e; "$SCRIPT" >/dev/null 2>&1; RC=$?; set -e check "missing package: fails loudly" "cannot roll back, and says so rather than reporting success" "$RC" "1" # --- the package manager refuses ------------------------------------------------------------- setup echo "1.4.2" > "$MESH_HOST_STATE_DIR/known-good" touch "$MESH_HOST_PKG_CACHE/nox-mesh-host-1.4.2-1-x86_64.pkg.tar.zst" STUB_PACMAN_FAILS=1 ; export STUB_PACMAN_FAILS set +e; "$SCRIPT" >/dev/null 2>&1; RC=$?; set -e check "pacman fails: exits non-zero" "a failed rollback is a failure the launcher must see" "$RC" "1" printf '\nrollback: %d passed, %d failed\n' "$PASS" "$FAIL" [ "$FAIL" -eq 0 ]