169 lines
5.5 KiB
Bash
Executable File
169 lines
5.5 KiB
Bash
Executable File
#!/bin/bash
|
|
set -uo pipefail
|
|
|
|
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
|
SCRIPT="$PROJECT_ROOT/run.command"
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
run_test() {
|
|
local name="$1"
|
|
shift
|
|
if ("$@"); then
|
|
printf 'PASS %s\n' "$name"
|
|
PASS=$((PASS + 1))
|
|
else
|
|
printf 'FAIL %s\n' "$name"
|
|
FAIL=$((FAIL + 1))
|
|
fi
|
|
}
|
|
|
|
test_resolves_root_when_sourced_elsewhere() (
|
|
[ -r "$SCRIPT" ] || return 1
|
|
cd /tmp || return 1
|
|
source "$SCRIPT"
|
|
[ "$ROOT_DIR" = "$PROJECT_ROOT" ]
|
|
[ -z "$BACKEND_PID" ]
|
|
[ -z "$NGROK_PID" ]
|
|
)
|
|
|
|
test_reuses_healthy_backend() (
|
|
source "$SCRIPT"
|
|
declare -F ensure_backend >/dev/null || return 1
|
|
backend_is_healthy() { return 0; }
|
|
port_listener_pid() { printf '4242\n'; }
|
|
start_backend() { return 77; }
|
|
ensure_backend
|
|
[ -z "$BACKEND_PID" ]
|
|
)
|
|
|
|
test_rejects_unhealthy_port_without_killing_owner() (
|
|
source "$SCRIPT"
|
|
declare -F ensure_backend >/dev/null || return 1
|
|
sleep 30 &
|
|
local external_pid=$!
|
|
trap "kill '$external_pid' 2>/dev/null || true" EXIT
|
|
backend_is_healthy() { return 1; }
|
|
port_listener_pid() { printf '%s\n' "$external_pid"; }
|
|
if ensure_backend; then return 1; fi
|
|
kill -0 "$external_pid" 2>/dev/null || return 1
|
|
kill "$external_pid" 2>/dev/null || true
|
|
wait "$external_pid" 2>/dev/null || true
|
|
trap - EXIT
|
|
)
|
|
|
|
test_cleanup_stops_owned_pid_only() (
|
|
source "$SCRIPT"
|
|
declare -F cleanup >/dev/null || return 1
|
|
local ready="${TMPDIR:-/tmp}/run-command-owned-ready-$$"
|
|
rm -f "$ready"
|
|
python3 -c 'import signal,sys,time; signal.signal(signal.SIGTERM, lambda *_: sys.exit(0)); open(sys.argv[1], "w").close(); time.sleep(30)' "$ready" &
|
|
BACKEND_PID=$!
|
|
local attempt=0
|
|
while [ ! -e "$ready" ] && [ "$attempt" -lt 50 ]; do
|
|
sleep 0.02
|
|
attempt=$((attempt + 1))
|
|
done
|
|
[ -e "$ready" ] || return 1
|
|
sleep 30 &
|
|
local external_pid=$!
|
|
cleanup
|
|
if kill -0 "$BACKEND_PID" 2>/dev/null; then return 1; fi
|
|
kill -0 "$external_pid" 2>/dev/null || return 1
|
|
kill "$external_pid" 2>/dev/null || true
|
|
wait "$external_pid" 2>/dev/null || true
|
|
rm -f "$ready"
|
|
)
|
|
|
|
test_reuses_healthy_ngrok() (
|
|
source "$SCRIPT"
|
|
declare -F ensure_ngrok >/dev/null || return 1
|
|
ngrok_is_healthy() { return 0; }
|
|
port_listener_pid() { printf '5252\n'; }
|
|
start_ngrok() { return 78; }
|
|
ensure_ngrok
|
|
[ -z "$NGROK_PID" ]
|
|
)
|
|
|
|
test_no_open_mode_skips_browser() (
|
|
source "$SCRIPT"
|
|
declare -F maybe_open_browser >/dev/null || return 1
|
|
local marker="${TMPDIR:-/tmp}/run-command-open-$$"
|
|
rm -f "$marker"
|
|
open() { : > "$marker"; }
|
|
ERP_RUN_NO_OPEN=1
|
|
maybe_open_browser
|
|
[ ! -e "$marker" ]
|
|
)
|
|
|
|
test_main_runs_steps_in_order() (
|
|
source "$SCRIPT"
|
|
local events="${TMPDIR:-/tmp}/run-command-events-$$"
|
|
: > "$events"
|
|
preflight() { printf 'preflight\n' >> "$events"; }
|
|
ensure_backend() { printf 'backend\n' >> "$events"; }
|
|
ensure_ngrok() { printf 'ngrok\n' >> "$events"; }
|
|
wait_for_public() { printf 'public\n' >> "$events"; }
|
|
maybe_open_browser() { printf 'open\n' >> "$events"; }
|
|
monitor_services() { printf 'monitor\n' >> "$events"; }
|
|
main
|
|
[ "$(tr '\n' ' ' < "$events")" = 'preflight backend ngrok public open monitor ' ]
|
|
)
|
|
|
|
test_postgres_profile_is_forwarded_to_backend() (
|
|
local tmp="${TMPDIR:-/tmp}/run-command-postgres-$$"
|
|
mkdir -p "$tmp/backend" "$tmp/log"
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
: > "$tmp/backend/app.jar"
|
|
printf '%s\n' \
|
|
'#!/bin/bash' \
|
|
'if [ "${1:-}" = "-version" ]; then printf '\''openjdk version "17.0.12"\n'\'' >&2; exit 0; fi' \
|
|
'printf '\''%s\n'\'' "$@" > "$MOCK_JAVA_ARGS"' > "$tmp/java"
|
|
chmod +x "$tmp/java"
|
|
export MOCK_JAVA_ARGS="$tmp/args"
|
|
ERP_RUN_BACKEND_DIR="$tmp/backend" ERP_RUN_JAVA_BIN="$tmp/java" \
|
|
ERP_RUN_JAR_PATH="$tmp/backend/app.jar" ERP_RUN_LOG_DIR="$tmp/log" \
|
|
ERP_RUN_PROFILE=postgres source "$SCRIPT"
|
|
start_backend
|
|
wait "$BACKEND_PID"
|
|
grep -Fqx -- '--spring.profiles.active=postgres' "$tmp/args"
|
|
grep -Fqx -- '--server.port=8091' "$tmp/args"
|
|
)
|
|
|
|
test_ngrok_uses_configured_endpoint_and_api_port() (
|
|
source "$SCRIPT"
|
|
local tmp="${TMPDIR:-/tmp}/run-command-ngrok-config-$$"
|
|
mkdir -p "$tmp"
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
printf '%s\n' \
|
|
'#!/bin/bash' \
|
|
'printf '\''%s\n'\'' "$@" > "$MOCK_NGROK_ARGS"' > "$tmp/ngrok"
|
|
chmod +x "$tmp/ngrok"
|
|
printf 'version: "3"\n' > "$tmp/base.yml"
|
|
export MOCK_NGROK_ARGS="$tmp/args"
|
|
NGROK_BIN="$tmp/ngrok"
|
|
NGROK_BASE_CONFIG="$tmp/base.yml"
|
|
NGROK_RUNTIME_CONFIG="$tmp/runtime.yml"
|
|
NGROK_LOG="$tmp/ngrok.log"
|
|
NGROK_API_PORT=4141
|
|
BACKEND_PORT=8191
|
|
PUBLIC_URL=https://example.ngrok.app
|
|
start_ngrok
|
|
wait "$NGROK_PID"
|
|
grep -Fqx -- '--url=https://example.ngrok.app' "$tmp/args" || return 1
|
|
grep -Fqx -- '8191' "$tmp/args" || return 1
|
|
grep -Fq -- ' web_addr: "127.0.0.1:4141"' "$tmp/runtime.yml"
|
|
)
|
|
|
|
run_test 'resolves project root when sourced elsewhere' test_resolves_root_when_sourced_elsewhere
|
|
run_test 'reuses a healthy backend' test_reuses_healthy_backend
|
|
run_test 'rejects a foreign 8091 listener without killing it' test_rejects_unhealthy_port_without_killing_owner
|
|
run_test 'cleanup stops owned PID only' test_cleanup_stops_owned_pid_only
|
|
run_test 'reuses a healthy ngrok tunnel' test_reuses_healthy_ngrok
|
|
run_test 'no-open mode skips browser launch' test_no_open_mode_skips_browser
|
|
run_test 'main orchestrates steps in order' test_main_runs_steps_in_order
|
|
run_test 'PostgreSQL profile is forwarded to the backend' test_postgres_profile_is_forwarded_to_backend
|
|
run_test 'ngrok uses the configured endpoint and API port' test_ngrok_uses_configured_endpoint_and_api_port
|
|
printf 'RESULT pass=%s fail=%s\n' "$PASS" "$FAIL"
|
|
[ "$FAIL" -eq 0 ]
|