Files
bot-bottle/tests/integration/test_orphan_cleanup.sh
T

75 lines
2.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Integration: the cleanup primitives the start-flow trap depends on
# are idempotent. The original orphan-network bug was a trap-ordering
# issue (cleanup_all installed AFTER networks were created); the fix
# moved the install earlier. The trap is only safe if the helpers it
# calls — network_remove, pipelock_stop — are no-ops against
# already-missing or never-existed resources. We test that here.
#
# (The full end-to-end "cli.sh dies mid-run, networks gone" flow needs
# a TTY and is documented as a manual verification step in tests/README.md.)
TEST_NAME="orphan_cleanup"
. "$(dirname "$0")/../lib/common.sh"
# shellcheck source=../../lib/log.sh
. "${REPO_ROOT}/lib/log.sh"
# shellcheck source=../../lib/docker.sh
. "${REPO_ROOT}/lib/docker.sh"
# shellcheck source=../../lib/network.sh
. "${REPO_ROOT}/lib/network.sh"
# shellcheck source=../../lib/pipelock.sh
. "${REPO_ROOT}/lib/pipelock.sh"
skip_test_if_no_docker
slug="cb-test-orphan-$$"
internal_name=""
egress_name=""
cleanup() {
for n in "$internal_name" "$egress_name"; do
[ -n "$n" ] && docker network rm "$n" >/dev/null 2>&1 || true
done
}
trap cleanup EXIT
# 1. network_remove against a name that doesn't exist returns 0
# (the trap can call it eagerly without crashing on the first run
# where the network was never created).
assert_exit_zero "network_remove: missing network is a no-op" \
network_remove "claude-bottle-net-${slug}-does-not-exist"
# 2. Create both networks the way cli.sh does, then remove them with
# network_remove. Both should succeed and the networks should be
# gone afterwards.
internal_name="$(network_create_internal "$slug")"
egress_name="$(network_create_egress "$slug")"
assert_match "$(docker network ls --format '{{.Name}}')" "^${internal_name}$" \
"internal network was created"
assert_match "$(docker network ls --format '{{.Name}}')" "^${egress_name}$" \
"egress network was created"
assert_exit_zero "network_remove: removes existing internal network" \
network_remove "$internal_name"
assert_exit_zero "network_remove: removes existing egress network" \
network_remove "$egress_name"
nets_after="$(docker network ls --format '{{.Name}}')"
assert_not_contains "$nets_after" "$internal_name" "internal network gone after removal"
assert_not_contains "$nets_after" "$egress_name" "egress network gone after removal"
# 3. Removing a second time is still safe — the trap may run after a
# clean exit, where the resources are already gone.
assert_exit_zero "network_remove: idempotent on already-removed internal" \
network_remove "$internal_name"
assert_exit_zero "network_remove: idempotent on already-removed egress" \
network_remove "$egress_name"
# 4. pipelock_stop against a slug whose sidecar was never started must
# also be a no-op — same reason.
assert_exit_zero "pipelock_stop: missing sidecar is a no-op" \
pipelock_stop "missing-${slug}"
test_summary