mirror of
https://oauth2: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@github.com/m1ngsama/TNT.git
synced 2026-06-26 04:34:38 +08:00
test: stabilize stress test runner
This commit is contained in:
parent
fa16beb7a6
commit
998da4288f
6 changed files with 128 additions and 33 deletions
6
Makefile
6
Makefile
|
|
@ -31,7 +31,7 @@ MANDIR ?= $(PREFIX)/share/man
|
|||
SYSTEMD_UNIT_DIR ?= $(PREFIX)/lib/systemd/system
|
||||
CI_TEST_PORT ?= $(if $(PORT),$(PORT),2222)
|
||||
|
||||
.PHONY: all clean install install-systemd uninstall uninstall-systemd debug release release-check release-check-strict asan valgrind check test test-advisory ci-test unit-test integration-test anonymous-access-test connection-limit-test security-test info
|
||||
.PHONY: all clean install install-systemd uninstall uninstall-systemd debug release release-check release-check-strict asan valgrind check test test-advisory ci-test unit-test integration-test anonymous-access-test connection-limit-test security-test stress-test info
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
|
|
@ -125,6 +125,10 @@ security-test: all
|
|||
@echo "Running security feature tests..."
|
||||
@cd tests && PORT=$${PORT:-13600} ./test_security_features.sh
|
||||
|
||||
stress-test: all
|
||||
@echo "Running stress tests..."
|
||||
@cd tests && PORT=$${PORT:-2222} ./test_stress.sh $${CLIENTS:-10} $${DURATION:-30}
|
||||
|
||||
ci-test:
|
||||
@$(MAKE) test PORT=$(CI_TEST_PORT)
|
||||
@$(MAKE) anonymous-access-test PORT=$$(($(CI_TEST_PORT) + 5))
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ make test-advisory # run integration tests as advisory checks
|
|||
make anonymous-access-test # verify default anonymous login behavior
|
||||
make connection-limit-test # verify per-IP concurrency and rate limits
|
||||
make security-test # run security feature checks
|
||||
make stress-test # run configurable concurrent-client stress test
|
||||
make ci-test # run the same checks as GitHub Actions
|
||||
|
||||
# Individual tests
|
||||
|
|
@ -220,7 +221,7 @@ cd tests
|
|||
- Basic functionality: 3 tests
|
||||
- Anonymous access: 2 tests
|
||||
- Security features: 12 tests
|
||||
- Stress test: concurrent connections
|
||||
- Stress test: configurable concurrent clients (`CLIENTS=20 DURATION=60 make stress-test`)
|
||||
|
||||
### Dependencies
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@
|
|||
- Anonymous access checks now use isolated state, wait for real SSH health,
|
||||
avoid external `timeout` helpers, and run through `make anonymous-access-test`
|
||||
as part of `make ci-test`.
|
||||
- Stress testing now uses isolated state, waits for real SSH health, avoids
|
||||
external `timeout` helpers, and is available through `make stress-test`.
|
||||
- Refreshed README and quick-reference module maps to match the current
|
||||
`cli_text`, `help_text`, `support_text`, i18n, exec, and rate-limit modules.
|
||||
- NORMAL mode now opens at the latest visible messages instead of the oldest
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ make test-advisory # Run integration tests as advisory checks
|
|||
make anonymous-access-test # Verify default anonymous login behavior
|
||||
make connection-limit-test # Verify per-IP concurrency and rate limits
|
||||
make security-test # Run security feature checks
|
||||
make stress-test # Run configurable concurrent-client stress test
|
||||
make ci-test # Run the same checks as GitHub Actions
|
||||
|
||||
# Individual tests
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ TEST
|
|||
make anonymous-access-test default anonymous login checks
|
||||
make connection-limit-test per-IP concurrency/rate-limit checks
|
||||
make security-test security feature checks
|
||||
make stress-test concurrent-client stress test
|
||||
make ci-test same checks as GitHub Actions
|
||||
|
||||
DEBUG
|
||||
|
|
|
|||
|
|
@ -1,56 +1,142 @@
|
|||
#!/bin/sh
|
||||
# Stress test for TNT server
|
||||
# Usage: ./test_stress.sh [num_clients]
|
||||
# Lightweight concurrent-client stress test for TNT.
|
||||
# Usage: ./test_stress.sh [num_clients] [duration_seconds]
|
||||
|
||||
PORT=${PORT:-2222}
|
||||
CLIENTS=${1:-10}
|
||||
DURATION=${2:-30}
|
||||
BIN="../tnt"
|
||||
PASS=0
|
||||
FAIL=0
|
||||
STATE_DIR=$(mktemp -d "${TMPDIR:-/tmp}/tnt-stress-test.XXXXXX")
|
||||
SERVER_PID=""
|
||||
CLIENT_PIDS=""
|
||||
|
||||
cleanup() {
|
||||
for pid in $CLIENT_PIDS; do
|
||||
kill "$pid" 2>/dev/null || true
|
||||
wait "$pid" 2>/dev/null || true
|
||||
done
|
||||
if [ -n "$SERVER_PID" ]; then
|
||||
kill "$SERVER_PID" 2>/dev/null || true
|
||||
wait "$SERVER_PID" 2>/dev/null || true
|
||||
fi
|
||||
rm -rf "$STATE_DIR"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
if [ ! -f "$BIN" ]; then
|
||||
echo "Error: Binary $BIN not found."
|
||||
echo "Error: Binary $BIN not found. Run make first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Detect timeout command
|
||||
TIMEOUT_CMD="timeout"
|
||||
if command -v gtimeout >/dev/null 2>&1; then
|
||||
TIMEOUT_CMD="gtimeout"
|
||||
case "$CLIENTS" in
|
||||
''|*[!0-9]*)
|
||||
echo "Error: num_clients must be a positive integer"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$DURATION" in
|
||||
''|*[!0-9]*)
|
||||
echo "Error: duration_seconds must be a positive integer"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$CLIENTS" -lt 1 ] || [ "$DURATION" -lt 1 ]; then
|
||||
echo "Error: num_clients and duration_seconds must be positive"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
echo "Starting TNT server on port $PORT..."
|
||||
TNT_RATE_LIMIT=0 TNT_MAX_CONN_PER_IP=$CLIENTS $BIN -p $PORT &
|
||||
SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -p $PORT"
|
||||
|
||||
wait_for_health() {
|
||||
out=""
|
||||
for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
|
||||
if [ -n "$SERVER_PID" ] && ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
return 1
|
||||
fi
|
||||
out=$(ssh -n $SSH_OPTS localhost health 2>/dev/null || true)
|
||||
[ "$out" = "ok" ] && return 0
|
||||
sleep 1
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "=== TNT Stress Test ==="
|
||||
echo "clients=$CLIENTS duration=${DURATION}s port=$PORT"
|
||||
|
||||
MAX_CONN_PER_IP=$((CLIENTS + 5))
|
||||
TNT_LANG=zh TNT_RATE_LIMIT=0 TNT_MAX_CONN_PER_IP=$MAX_CONN_PER_IP \
|
||||
"$BIN" -p "$PORT" -d "$STATE_DIR" >"$STATE_DIR/server.log" 2>&1 &
|
||||
SERVER_PID=$!
|
||||
sleep 2
|
||||
|
||||
if ! kill -0 $SERVER_PID 2>/dev/null; then
|
||||
echo "Server failed to start"
|
||||
if wait_for_health; then
|
||||
echo "✓ server started"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo "✗ server failed to start"
|
||||
sed -n '1,120p' "$STATE_DIR/server.log"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Spawning $CLIENTS clients for ${DURATION}s..."
|
||||
for i in $(seq 1 "$CLIENTS"); do
|
||||
script="$STATE_DIR/client-$i.expect"
|
||||
log="$STATE_DIR/client-$i.log"
|
||||
ready="$STATE_DIR/client-$i.ready"
|
||||
|
||||
for i in $(seq 1 $CLIENTS); do
|
||||
(
|
||||
sleep $((i % 5))
|
||||
echo "test user $i" | $TIMEOUT_CMD $DURATION ssh -o StrictHostKeyChecking=no \
|
||||
-o UserKnownHostsFile=/dev/null -p $PORT localhost \
|
||||
>/dev/null 2>&1
|
||||
) &
|
||||
cat >"$script" <<EOF
|
||||
set timeout [expr {$DURATION + 15}]
|
||||
spawn ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p $PORT stress$i@localhost
|
||||
expect "请输入用户名"
|
||||
send -- "stress$i\r"
|
||||
exec touch "$ready"
|
||||
sleep $DURATION
|
||||
send -- "\003"
|
||||
expect eof
|
||||
EOF
|
||||
|
||||
expect "$script" >"$log" 2>&1 &
|
||||
CLIENT_PIDS="$CLIENT_PIDS $!"
|
||||
done
|
||||
|
||||
echo "Running stress test..."
|
||||
sleep $DURATION
|
||||
ready_count=0
|
||||
for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
|
||||
ready_count=$(find "$STATE_DIR" -name 'client-*.ready' -type f | wc -l | tr -d ' ')
|
||||
[ "$ready_count" = "$CLIENTS" ] && break
|
||||
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "Cleaning up..."
|
||||
kill $SERVER_PID 2>/dev/null
|
||||
wait
|
||||
|
||||
echo "Stress test complete"
|
||||
if kill -0 $SERVER_PID 2>/dev/null; then
|
||||
echo "WARNING: tnt process still running"
|
||||
if [ "$ready_count" = "$CLIENTS" ]; then
|
||||
echo "✓ all clients reached chat"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo "Server shutdown confirmed."
|
||||
echo "✗ only $ready_count/$CLIENTS clients reached chat"
|
||||
sed -n '1,160p' "$STATE_DIR/server.log"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
|
||||
exit 0
|
||||
for pid in $CLIENT_PIDS; do
|
||||
wait "$pid" 2>/dev/null || FAIL=$((FAIL + 1))
|
||||
done
|
||||
CLIENT_PIDS=""
|
||||
|
||||
if kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
echo "✓ server survived concurrent clients"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo "✗ server exited during stress test"
|
||||
sed -n '1,160p' "$STATE_DIR/server.log"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "PASSED: $PASS"
|
||||
echo "FAILED: $FAIL"
|
||||
[ "$FAIL" -eq 0 ] && echo "All tests passed" || echo "Some tests failed"
|
||||
exit "$FAIL"
|
||||
|
|
|
|||
Loading…
Reference in a new issue