diff --git a/tests/lifecycle/bats/use-quadlet-backends-install.bats b/tests/lifecycle/bats/use-quadlet-backends-install.bats index cbb23298..4730e478 100644 --- a/tests/lifecycle/bats/use-quadlet-backends-install.bats +++ b/tests/lifecycle/bats/use-quadlet-backends-install.bats @@ -50,6 +50,22 @@ backend_quadlet_units() { done } +# A unit file on disk does NOT imply the app should be running: an +# explicitly user-stopped app keeps its .container file (e.g. the inactive +# half of the bitcoin-core/bitcoin-knots multi-version pair), and its +# .service being inactive / container absent is the CORRECT state. The +# orchestrator persists that intent in user-stopped.json; honour it here so +# the active-state assertions below don't false-fail on stopped-on-purpose +# apps (gate tests 123/124, .228 2026-07-09). +USER_STOPPED_FILE="${ARCHY_DATA_DIR:-/var/lib/archipelago}/user-stopped.json" + +is_user_stopped() { + local name="$1" + [[ -r "$USER_STOPPED_FILE" ]] || return 1 + jq -e --arg n "$name" --arg s "${name#archy-}" \ + 'index($n) != null or index($s) != null' "$USER_STOPPED_FILE" >/dev/null 2>&1 +} + # Read the cgroup path of a running container's main process. For # rootless podman the conmon-run target lands the container's pid1 in # the cgroup that owns its supervising .service. @@ -127,6 +143,7 @@ require_quadlet_backends() { require_quadlet_backends while read -r name; do [[ -z "$name" ]] && continue + is_user_stopped "$name" && continue run systemctl --user is-active "$name.service" [[ "$status" -eq 0 ]] || fail "$name.service is '$output' — expected 'active'" done < <(backend_quadlet_units) @@ -136,6 +153,7 @@ require_quadlet_backends() { require_quadlet_backends while read -r name; do [[ -z "$name" ]] && continue + is_user_stopped "$name" && continue run sh -c "podman inspect --format '{{.State.Running}}' '$name'" [[ "$status" -eq 0 ]] || fail "$name not present in podman" [[ "$output" == "true" ]] || fail "$name container exists but not running (state=$output)"