AtlatestRepositorysigil-http

sigil-http / tree / test / integrationrun-timeout-tests.sh

1#!/usr/bin/env bash
2# Live positive controls for the blocking-segment bounds.
3#
4# Every in-suite test of those bounds asserts a FAILURE: a stalled peer must
5# give up on time. None of them would notice if the bounds broke every
6# SUCCESSFUL request, because a client that could no longer complete a TLS
7# handshake at all would satisfy all of them. This script supplies the other
8# direction: real servers, bounds armed, requests must still work, and
9# bodies must still arrive intact through the new partial-write loop.
11# Usage:
12# test/integration/run-timeout-tests.sh [--redirects FILE]
14# While sigil-tls 0.16.5 is unreleased, pass the local redirect:
15# test/integration/run-timeout-tests.sh --redirects tls-redirects.sgl
17# Requires python3 and openssl. A MISSING TOOL IS A HARD FAILURE HERE, never
18# a skip: a harness that quietly stops testing what it claims to test is the
19# exact failure class these bounds exist to eliminate.
21set -u
23SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
24REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
26REDIRECTS=""
27if [ "${1:-}" = "--redirects" ]; then
28 REDIRECTS="$2"
29fi
31fail() { echo "FAIL: $*" >&2; exit 2; }
33command -v python3 >/dev/null 2>&1 || fail "python3 not found"
34command -v sigil >/dev/null 2>&1 || fail "sigil not found"
36# openssl is frequently absent from a bare PATH on this host even though it
37# is present in the store. Look, then fail loudly rather than degrading.
38OPENSSL="$(command -v openssl 2>/dev/null || true)"
39if [ -z "$OPENSSL" ]; then
40 for candidate in /gnu/store/*openssl*/bin/openssl; do
41 if [ -x "$candidate" ]; then OPENSSL="$candidate"; break; fi
42 done
43fi
44[ -n "$OPENSSL" ] || fail "openssl not found on PATH or in /gnu/store; cannot generate a test certificate"
46WORK="$(mktemp -d /tmp/sigil-http-timeout-tests.XXXXXX)"
47SERVER_PID=""
48cleanup() {
49 [ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null
50 rm -rf "$WORK"
52trap cleanup EXIT
54echo "=== 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.
61read -r HTTP_PORT TLS_PORT DRIP_PORT <<EOF
62$(python3 - <<'PY'
63import socket
64socks = [socket.socket() for _ in range(3)]
65for s in socks:
66 s.bind(("127.0.0.1", 0))
67ports = [s.getsockname()[1] for s in socks]
68for s in socks:
69 s.close()
70print(ports[0], ports[1], ports[2])
71PY
73EOF
74[ -n "${HTTP_PORT:-}" ] && [ -n "${TLS_PORT:-}" ] && [ -n "${DRIP_PORT:-}" ] \
75 || fail "could not allocate ports"
77python3 "$SCRIPT_DIR/timeout-servers.py" "$HTTP_PORT" "$TLS_PORT" \
78 "$WORK/cert.pem" "$WORK/key.pem" "$DRIP_PORT" >"$WORK/servers.log" 2>&1 &
79SERVER_PID=$!
81# Wait for the servers' own readiness line rather than sleeping a guess.
82for _ in $(seq 1 100); do
83 grep -q "SERVERS READY" "$WORK/servers.log" 2>/dev/null && break
84 sleep 0.1
85done
86grep -q "SERVERS READY" "$WORK/servers.log" 2>/dev/null \
87 || { cat "$WORK/servers.log" >&2; fail "servers did not come up"; }
89echo "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.
92export SIGIL_TLS_INSECURE=1
93export SIGIL_HTTP_TEST_HTTP_PORT="$HTTP_PORT"
94export SIGIL_HTTP_TEST_TLS_PORT="$TLS_PORT"
95export SIGIL_HTTP_TEST_DRIP_PORT="$DRIP_PORT"
97cd "$REPO_ROOT" || fail "cannot enter $REPO_ROOT"
99if [ -n "$REDIRECTS" ]; then
100 sigil test --redirects "$REDIRECTS" test/integration/live-timeouts-main.sgl \
101 2>&1 | tee "$WORK/test.log"
102else
103 sigil test test/integration/live-timeouts-main.sgl 2>&1 | tee "$WORK/test.log"
104fi
106# COVERAGE ASSERTION. `sigil test` exits 0 for a run that executed nothing,
107# so the exit status alone cannot distinguish "all passed" from "no tests
108# found". Name the controls that must have run.
109for 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"
120do
121 grep -qF "$required" "$WORK/test.log" \
122 || fail "expected control did not run: $required"
123done
125grep -q "All tests passed" "$WORK/test.log" || fail "live positive controls failed"
127echo "=== live timeout positive controls: PASS ==="