swift-nio/IntegrationTests/tests_01_http/defines.sh

204 lines
5.4 KiB
Bash

#!/bin/bash
##===----------------------------------------------------------------------===##
##
## This source file is part of the SwiftNIO open source project
##
## Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
## Licensed under Apache License v2.0
##
## See LICENSE.txt for license information
## See CONTRIBUTORS.txt for the list of SwiftNIO project authors
##
## SPDX-License-Identifier: Apache-2.0
##
##===----------------------------------------------------------------------===##
function server_lsof() {
lsof -a -d 0-1024 -p "$1"
}
function get_number_of_open_fds_for_pid() {
server_lsof "$1" >&2
server_lsof "$1" | wc -l
}
# pid, expected_number_of_fds
function assert_number_of_open_fds_for_pid_equals() {
local pid expected actual
pid="$1"
expected="$2"
for f in $(seq 50); do
sleep 0.2
actual=$(get_number_of_open_fds_for_pid "$pid")
echo "try $f, actually having $actual open fds, expecting $expected"
if [[ "$expected" == "$actual" ]]; then
break
fi
done
server_lsof "$pid"
assert_equal "$expected" "$actual" "wrong number of open fds"
}
function do_netstat() {
pf="$1"
netstat_options=()
case "$(uname -s)" in
Linux)
netstat_options+=( "-A" "$pf" -p )
;;
Darwin)
netstat_options+=( "-f" "$pf" -v )
;;
*)
fail "Unknown OS $(uname -s)"
;;
esac
netstat -an "${netstat_options[@]}"
}
function create_token() {
mktemp "$tmp/server_token_XXXXXX"
}
function start_server() {
local extra_args=''
if [[ "$1" == "--disable-half-closure" ]]; then
extra_args="$1"
shift
fi
local token="$1"
local type="unix"
local port="$tmp/port.sock"
local tmp_server_pid
local curl_port=80
maybe_host=""
maybe_nio_host=""
if [[ "${2:-uds}" == "tcp" ]]; then
type="inet"
port="0"
maybe_host="localhost"
maybe_nio_host="127.0.0.1"
fi
mkdir "$tmp/htdocs"
swift build
"$(swift build --show-bin-path)/NIOHTTP1Server" $extra_args $maybe_nio_host "$port" "$tmp/htdocs" &
tmp_server_pid=$!
case "$type" in
inet)
# TCP mode, need to wait until we found a port that we can curl
worked=false
for f in $(seq 20); do
server_lsof "$tmp_server_pid"
port=$(server_lsof "$tmp_server_pid" | grep -Eo 'TCP .*:[0-9]+ ' | grep -Eo '[0-9]{4,5} ' | tr -d ' ' || true)
curl_port="$port"
if [[ -n "$port" ]] && curl --ipv4 "http://$maybe_host:$curl_port/dynamic/pid"; then
worked=true
break
else
server_lsof "$tmp_server_pid"
sleep 0.1 # wait for the socket to be bound
fi
done
"$worked" || fail "Could not reach server 2s after lauching..."
;;
unix)
# Unix Domain Socket, wait for the file to appear
for f in $(seq 30); do if [[ -S "$port" ]]; then break; else sleep 0.1; fi; done
;;
*)
fail "Unknown server type '$type'"
;;
esac
echo "port: $port"
echo "curl port: $curl_port"
echo "local token_port; local token_htdocs; local token_pid;" >> "$token"
echo " token_port='$port'; token_htdocs='$tmp/htdocs'; token_pid='$!';" >> "$token"
echo " token_type='$type'; token_server_ip='$maybe_nio_host'" >> "$token"
tmp_server_pid=$(get_server_pid "$token")
echo "local token_open_fds" >> "$token"
echo "token_open_fds='$(get_number_of_open_fds_for_pid "$tmp_server_pid")'" >> "$token"
local curl_host=${maybe_host:-localhost}
do_curl "$token" "http://$curl_host:$curl_port/dynamic/pid"
}
function get_htdocs() {
source "$1"
echo "$token_htdocs"
}
function get_socket() {
source "$1"
echo "$token_port"
}
function stop_server() {
source "$1"
sleep 0.5 # just to make sure all the fds could be closed
if command -v lsof > /dev/null 2> /dev/null; then
do_netstat "$token_type"
assert_number_of_open_fds_for_pid_equals "$token_pid" "$token_open_fds"
fi
kill -0 "$token_pid" # assert server is still running
###kill -INT "$token_pid" # tell server to shut down gracefully
kill "$token_pid" # tell server to shut down gracefully
for f in $(seq 20); do
if ! kill -0 "$token_pid" 2> /dev/null; then
break # good, dead
fi
ps auxw | grep "$token_pid" || true
sleep 0.1
done
if kill -0 "$token_pid" 2> /dev/null; then
fail "server $token_pid still running"
fi
}
function get_server_pid() {
source "$1"
echo "$token_pid"
}
function get_server_port() {
source "$1"
echo "$token_port"
}
function get_server_ip() {
source "$1"
echo "$token_server_ip"
}
function do_curl() {
source "$1"
shift
case "$token_type" in
inet)
curl -v --ipv4 "$@"
;;
unix)
curl --unix-socket "$token_port" -v "$@"
;;
*)
fail "Unknown type '$token_type'"
;;
esac
}
_new_nc=false
if nc -h 2>&1 | grep -- -N | grep -q EOF; then
# this is a new kind of 'nc' that doesn't automatically shut down
# the input socket after EOF. But we rely on that behaviour.
_new_nc=true
fi
function do_nc() {
if "$_new_nc"; then
nc -N "$@"
else
nc "$@"
fi
}