mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-30 08:36:55 +09:00
EL9/Fedora containers ship without diffutils and openSUSE Leap without tar, which failed 4 of the 7 cross-distro unit jobs: - files_identical() in stubs.sh: cmp when available, sha256sum (coreutils, everywhere) otherwise - the two tarball-fixture tests skip cleanly when tar is absent (harness's existing skip convention; proven on the other distros) - the t16/t16r assertion lists are now && chains: bash suppresses set -e inside an if-condition subshell, so sequential statements only gated on the LAST one — the cmp-less EL9 run proved it by passing t16r vacuously while cmp exited 127 Verified in the actual images: rockylinux:9 65p/0f/0s, opensuse/leap:15.5 61p/0f/4s (was 63p/2f and 61p/2f). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
138 lines
5.3 KiB
Bash
138 lines
5.3 KiB
Bash
# shellcheck shell=bash
|
|
#
|
|
# scripts/test/stubs.sh — shared PATH-stub factories for the shell test harness.
|
|
#
|
|
# Source this from a test suite, then call the factories to materialise
|
|
# executable stubs inside a per-test bin directory that gets PATH-prepended.
|
|
# Two families live here:
|
|
#
|
|
# * generic: make_stub_ok / make_stub_exit — the exit-0/exit-N one-liners
|
|
# every suite used to re-implement inline.
|
|
# * failing: make_stub_systemctl_exit5, make_stub_docker_fail,
|
|
# make_stub_docker_empty, make_stub_curl_fail22,
|
|
# make_stub_curl_ratelimited, make_stub_sleep_noop — the
|
|
# degenerate tool behaviours a fresh or broken box presents.
|
|
#
|
|
# make_fresh_box_fixture builds the EMPTIEST valid world a fresh ServerKit
|
|
# install presents to observation/discovery functions (zero apps, zero
|
|
# containers, no optional confs, dead network, empty state) — the exact state
|
|
# that killed the 2026-07-02 production update.
|
|
#
|
|
# Keep this file bash-3-portable and shellcheck-clean: CI runs
|
|
# `shellcheck --severity=error` and `bash -n` on scripts/test/*.sh across a
|
|
# 7-distro matrix.
|
|
|
|
# files_identical <a> <b> — byte-equality that works on minimal CI images:
|
|
# EL9/Fedora containers ship without diffutils (`cmp`), so fall back to a
|
|
# checksum compare (sha256sum is coreutils, present everywhere we run).
|
|
files_identical() {
|
|
[ -f "$1" ] && [ -f "$2" ] || return 1
|
|
if command -v cmp >/dev/null 2>&1; then
|
|
cmp -s "$1" "$2"
|
|
else
|
|
[ "$(sha256sum < "$1")" = "$(sha256sum < "$2")" ]
|
|
fi
|
|
}
|
|
|
|
# make_stub_exit <bindir> <code> <name...> — each <name> becomes a stub that
|
|
# ignores its arguments and exits <code>.
|
|
make_stub_exit() {
|
|
local dir="$1" code="$2" name
|
|
shift 2
|
|
for name in "$@"; do
|
|
printf '#!/usr/bin/env bash\nexit %s\n' "$code" > "$dir/$name"
|
|
chmod +x "$dir/$name"
|
|
done
|
|
}
|
|
|
|
# make_stub_ok <bindir> <name...> — happy no-op stubs (exit 0).
|
|
make_stub_ok() {
|
|
local dir="$1"
|
|
shift
|
|
make_stub_exit "$dir" 0 "$@"
|
|
}
|
|
|
|
# systemctl on a box where the queried/stopped unit is not loaded: systemd
|
|
# answers with exit 5 ("unit not loaded") — what `systemctl stop serverkit`
|
|
# returns on a fresh install before the unit exists.
|
|
make_stub_systemctl_exit5() {
|
|
make_stub_exit "$1" 5 systemctl
|
|
}
|
|
|
|
# docker present but broken/unreachable: every invocation fails (daemon down,
|
|
# permission denied, ...).
|
|
make_stub_docker_fail() {
|
|
make_stub_exit "$1" 1 docker
|
|
}
|
|
|
|
# docker installed and the daemon healthy, but the box runs ZERO containers:
|
|
# `docker ps ...` prints nothing and succeeds; everything else (inspect, tag,
|
|
# cp, compose, ...) fails because nothing exists to operate on.
|
|
make_stub_docker_empty() {
|
|
cat > "$1/docker" <<'DOCKER_EOF'
|
|
#!/usr/bin/env bash
|
|
case "${1:-}" in
|
|
ps) exit 0 ;;
|
|
*) exit 1 ;;
|
|
esac
|
|
DOCKER_EOF
|
|
chmod +x "$1/docker"
|
|
}
|
|
|
|
# curl with the network dead (or every URL 404ing under -f): exit 22, the code
|
|
# `curl -f` uses for HTTP errors and the shape `curl -sf` callers must survive.
|
|
make_stub_curl_fail22() {
|
|
make_stub_exit "$1" 22 curl
|
|
}
|
|
|
|
# curl hitting the GitHub API's unauthenticated rate limit: HTTP 403 whose
|
|
# JSON error body is delivered with exit 0 (the no--f shape) — the nastiest
|
|
# case for code that greps tag_name out of whatever curl printed.
|
|
make_stub_curl_ratelimited() {
|
|
cat > "$1/curl" <<'CURL_EOF'
|
|
#!/usr/bin/env bash
|
|
out=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-o) out="$2"; shift 2 ;;
|
|
*) shift ;;
|
|
esac
|
|
done
|
|
body='{"message":"API rate limit exceeded for 203.0.113.7.","documentation_url":"https://docs.github.com/rest/overview/resources-in-the-rest-api#rate-limiting"}'
|
|
if [ -n "$out" ]; then printf '%s\n' "$body" > "$out"; else printf '%s\n' "$body"; fi
|
|
exit 0
|
|
CURL_EOF
|
|
chmod +x "$1/curl"
|
|
}
|
|
|
|
# sleep that returns immediately — keeps retry/poll loops (quick_health,
|
|
# await_health) sub-second inside fixtures where the probe can never succeed.
|
|
make_stub_sleep_noop() {
|
|
make_stub_exit "$1" 0 sleep
|
|
}
|
|
|
|
# make_fresh_box_fixture <root> — lay out the degenerate fresh-box world:
|
|
# <root>/bin PATH-prepend stubs: systemctl exit 5,
|
|
# docker with zero containers, curl
|
|
# exit 22, instant sleep
|
|
# <root>/etc/nginx/serverkit-locations EMPTY (zero managed apps — the
|
|
# default state of every fresh install)
|
|
# <root>/etc/nginx no serverkit.conf, no nginx.conf
|
|
# <root>/etc/serverkit no ssl-mode / panel-domain, and an
|
|
# EMPTY install-state.json
|
|
# <root>/etc/os-release minimal Ubuntu-ish identity
|
|
# <root>/opt exists, but /opt/serverkit does NOT
|
|
# <root>/var/backups, <root>/var/log empty
|
|
make_fresh_box_fixture() {
|
|
local root="$1"
|
|
mkdir -p "$root/bin" "$root/etc/nginx/serverkit-locations" \
|
|
"$root/etc/serverkit" "$root/opt" "$root/var/backups" "$root/var/log"
|
|
: > "$root/etc/serverkit/install-state.json"
|
|
printf 'ID=ubuntu\nID_LIKE=debian\nPRETTY_NAME="Ubuntu 24.04 LTS"\n' \
|
|
> "$root/etc/os-release"
|
|
make_stub_systemctl_exit5 "$root/bin"
|
|
make_stub_docker_empty "$root/bin"
|
|
make_stub_curl_fail22 "$root/bin"
|
|
make_stub_sleep_noop "$root/bin"
|
|
}
|