AtlatestRepositorysigil-http
sigil-http / tree / test / integrationrun-timeout-tests.sh
1
#!/usr/bin/env bash2
# Live positive controls for the blocking-segment bounds.3
#4
# Every in-suite test of those bounds asserts a FAILURE: a stalled peer must5
# give up on time. None of them would notice if the bounds broke every6
# SUCCESSFUL request, because a client that could no longer complete a TLS7
# handshake at all would satisfy all of them. This script supplies the other8
# direction: real servers, bounds armed, requests must still work, and9
# bodies must still arrive intact through the new partial-write loop.10
#11
# Usage:12
# test/integration/run-timeout-tests.sh [--redirects FILE]13
#14
# While sigil-tls 0.16.5 is unreleased, pass the local redirect:15
# test/integration/run-timeout-tests.sh --redirects tls-redirects.sgl16
#17
# Requires python3 and openssl. A MISSING TOOL IS A HARD FAILURE HERE, never18
# a skip: a harness that quietly stops testing what it claims to test is the19
# exact failure class these bounds exist to eliminate.21
set -u23
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"24
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"26
REDIRECTS=""27
if [ "${1:-}" = "--redirects" ]; then28
REDIRECTS="$2"29
fi31
fail() { echo "FAIL: $*" >&2; exit 2; }33
command -v python3 >/dev/null 2>&1 || fail "python3 not found"34
command -v sigil >/dev/null 2>&1 || fail "sigil not found"36
# openssl is frequently absent from a bare PATH on this host even though it37
# is present in the store. Look, then fail loudly rather than degrading.38
OPENSSL="$(command -v openssl 2>/dev/null || true)"39
if [ -z "$OPENSSL" ]; then40
for candidate in /gnu/store/*openssl*/bin/openssl; do41
if [ -x "$candidate" ]; then OPENSSL="$candidate"; break; fi42
done43
fi44
[ -n "$OPENSSL" ] || fail "openssl not found on PATH or in /gnu/store; cannot generate a test certificate"46
WORK="$(mktemp -d /tmp/sigil-http-timeout-tests.XXXXXX)"47
SERVER_PID=""48
cleanup() {49
[ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null50
rm -rf "$WORK"51
}52
trap cleanup EXIT54
echo "=== live timeout positive controls ==="56
"$OPENSSL" req -x509 -newkey rsa:2048 -nodes -days 2 \57
-keyout "$WORK/key.pem" -out "$WORK/cert.pem" -subj "/CN=localhost" \58
>/dev/null 2>&1 || fail "certificate generation failed"60
# Two free ports, chosen by the kernel so concurrent runs cannot collide.61
read -r HTTP_PORT TLS_PORT DRIP_PORT <<EOF62
$(python3 - <<'PY'63
import socket64
socks = [socket.socket() for _ in range(3)]65
for s in socks:66
s.bind(("127.0.0.1", 0))67
ports = [s.getsockname()[1] for s in socks]68
for s in socks:69
s.close()70
print(ports[0], ports[1], ports[2])71
PY72
)73
EOF74
[ -n "${HTTP_PORT:-}" ] && [ -n "${TLS_PORT:-}" ] && [ -n "${DRIP_PORT:-}" ] \75
|| fail "could not allocate ports"77
python3 "$SCRIPT_DIR/timeout-servers.py" "$HTTP_PORT" "$TLS_PORT" \78
"$WORK/cert.pem" "$WORK/key.pem" "$DRIP_PORT" >"$WORK/servers.log" 2>&1 &79
SERVER_PID=$!81
# Wait for the servers' own readiness line rather than sleeping a guess.82
for _ in $(seq 1 100); do83
grep -q "SERVERS READY" "$WORK/servers.log" 2>/dev/null && break84
sleep 0.185
done86
grep -q "SERVERS READY" "$WORK/servers.log" 2>/dev/null \87
|| { cat "$WORK/servers.log" >&2; fail "servers did not come up"; }89
echo "servers up: http=$HTTP_PORT tls=$TLS_PORT drip=$DRIP_PORT"91
# The certificate is self-signed, so verification is off for this run only.92
export SIGIL_TLS_INSECURE=193
export SIGIL_HTTP_TEST_HTTP_PORT="$HTTP_PORT"94
export SIGIL_HTTP_TEST_TLS_PORT="$TLS_PORT"95
export SIGIL_HTTP_TEST_DRIP_PORT="$DRIP_PORT"97
cd "$REPO_ROOT" || fail "cannot enter $REPO_ROOT"99
if [ -n "$REDIRECTS" ]; then100
sigil test --redirects "$REDIRECTS" test/integration/live-timeouts-main.sgl \101
2>&1 | tee "$WORK/test.log"102
else103
sigil test test/integration/live-timeouts-main.sgl 2>&1 | tee "$WORK/test.log"104
fi106
# COVERAGE ASSERTION. `sigil test` exits 0 for a run that executed nothing,107
# so the exit status alone cannot distinguish "all passed" from "no tests108
# found". Name the controls that must have run.109
for required in \110
"plain http with NO timeout arguments still works" \111
"https with NO timeout arguments still works" \112
"https with the handshake bound ARMED still completes a real handshake" \113
"plain http with both bounds armed still works" \114
"a POST body still arrives intact through the bounded write loop" \115
"a POST body still arrives intact over TLS" \116
"a partial write resumes at the right offset" \117
"the handshake bound fires against a DRIPPING peer, not just a silent one" \118
"tls-connect/status reports connected for a live peer" \119
"http-fetch-bytes still returns the body byte-for-byte"120
do121
grep -qF "$required" "$WORK/test.log" \122
|| fail "expected control did not run: $required"123
done125
grep -q "All tests passed" "$WORK/test.log" || fail "live positive controls failed"127
echo "=== live timeout positive controls: PASS ==="