AtlatestRepositorysigil-http
sigil-http / tree / test / integrationrun-starvation-test.sh
1
#!/usr/bin/env bash2
# Integration test for the server-loop drain starvation fix.3
#4
# Proves that a sibling socket io-waiter is serviced promptly while the HTTP5
# server has a connected (half-open) client. Before the fix, the server-loop6
# `drain` busy-spins process-connections while >=1 client is connected; the7
# async scheduler only polls socket io-waiters when its run-queue is empty,8
# so the sibling's first read starves (observed as multi-second to9
# multi-minute first-event delays for outbound sockets in real apps). After10
# the fix the drain suspends on the scheduler (await-readable-any), the run11
# queue empties, and the sibling io-waiter is serviced within milliseconds.12
#13
# Same ceremony as run-streaming-tests.sh: a loose `sigil <file>` run would14
# resolve imports from the RELEASED sigil-http (and the interpreter's async15
# path is not faithful to compiled scheduling anyway), so we build an16
# ephemeral bundle and run the compiled binary. The probe is self-contained17
# (exit 0 = serviced promptly, 1 = starved/degraded, 2 = harness failure).18
#19
# Unlike run-streaming-tests.sh, this repo's http modules are VENDORED into20
# the bundle (copied verbatim from src/) instead of pulled as a `from-path`21
# package: combining a from-path sigil-http with a from-path/redirected22
# sigil monorepo (needed while the `await-readable-any` scheduler primitive23
# is unreleased) makes the from-path package build silently produce nothing.24
# Vendoring sidesteps that while still compiling this repo's actual25
# server.sgl bytes.26
#27
# SIGIL_MONOREPO_PATH: when set, sigil-run/sigil-stdlib resolve from that28
# local sigil checkout (for testing against an unreleased runtime); when29
# unset, they resolve from the released monorepo (from-git).30
#31
# Requires: a working `sigil` toolchain, network on first run (dep fetch).32
# Run from anywhere:33
# test/integration/run-starvation-test.sh35
set -u37
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"38
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"39
PROBE_SRC="$SCRIPT_DIR/starvation-probe-main.sgl"41
APP_DIR="$(mktemp -d /tmp/starvation-probe-app.XXXXXX)"42
BIN="$APP_DIR/build/dev/bin/starvation-probe"44
cleanup() {45
rm -rf "$APP_DIR"46
}47
trap cleanup EXIT49
echo "=== server-loop drain starvation probe ==="51
mkdir -p "$APP_DIR/src/starvation-probe" "$APP_DIR/src/sigil/http"52
cp "$PROBE_SRC" "$APP_DIR/src/starvation-probe/main.sgl"53
# Vendor this repo's http modules (the code under test) into the bundle.54
for m in server request response mime; do55
cp "$REPO_ROOT/src/sigil/http/$m.sgl" "$APP_DIR/src/sigil/http/$m.sgl"56
done58
if [ -n "${SIGIL_MONOREPO_PATH:-}" ]; then59
MONOREPO_DEPS="(from-path dir: \"$SIGIL_MONOREPO_PATH\" package: \"sigil-run\")60
(from-path dir: \"$SIGIL_MONOREPO_PATH\" package: \"sigil-stdlib\")"61
else62
MONOREPO_DEPS="(from-git url: \"codeberg:sigil/sigil\" package: \"sigil-run\" version: \"^0.17\")63
(from-git url: \"codeberg:sigil/sigil\" package: \"sigil-stdlib\" version: \"^0.17\")"64
fi66
cat > "$APP_DIR/package.sgl" <<EOF67
(package68
name: "starvation-probe"69
version: "0.1.0"70
sigil: "^0.17"71
description: "Ephemeral integration bundle for the drain starvation fix"72
entry: '(starvation-probe main)73
bundle-name: "starvation-probe"74
configs: (list75
(config name: 'dev output-dir: "build/dev" static?: #f debug?: #t optimize: 0 bundle?: #t))76
dependencies: (list77
$MONOREPO_DEPS78
(from-git url: "codeberg:sigil/sigil-json" version: "^0.16"))80
tasks: (list81
(task82
name: 'build83
description: "Compile probe + vendored http modules"84
steps: (list85
(compile-sigil-modules sources: "src/**/*.sgl")))))86
EOF88
echo "--- building probe bundle ($APP_DIR) ---"89
(cd "$APP_DIR" \90
&& sigil deps install >"$APP_DIR/deps.log" 2>&1 \91
&& sigil build starvation-probe) || {92
echo "FAIL: probe build failed; deps log:"93
tail -20 "$APP_DIR/deps.log" 2>/dev/null94
exit 295
}96
if [ ! -x "$BIN" ]; then97
echo "FAIL: probe binary missing after build"98
exit 299
fi101
echo "--- running probe (watchdog-bounded; ~10-20s) ---"102
"$BIN"103
RC=$?105
if [ "$RC" -eq 0 ]; then106
echo "PASS: sibling io-waiter serviced promptly while a client was connected"107
else108
echo "FAIL: probe exit $RC (1 = starved/degraded, 2 = harness failure)"109
fi110
exit "$RC"