Browse code

Add t_server_null test suite

Change-Id: I1b54da258c7d15551b6c3de7522a0d19afdb66de
Signed-off-by: Samuli Seppänen <samuli.seppanen@gmail.com>
Acked-by: Frank Lichtenheld <frank@lichtenheld.com>
Message-Id: <20240613081422.139493-1-frank@lichtenheld.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg28750.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Samuli Seppänen authored on 2024/06/13 17:14:22
Showing 10 changed files
... ...
@@ -55,6 +55,7 @@ vendor/dist
55 55
 
56 56
 tests/t_client.sh
57 57
 tests/t_client-*-20??????-??????/
58
+tests/t_server_null.rc
58 59
 t_client.rc
59 60
 t_client_ips.rc
60 61
 tests/unit_tests/**/*_testdriver
61 62
new file mode 100644
... ...
@@ -0,0 +1,147 @@
0
+Notes for the --dev null test suite
1
+===================================
2
+
3
+Introduction
4
+------------
5
+
6
+The *--dev null test suite* is primary targeted at testing client connections
7
+to the "just compiled" version of OpenVPN. The name is derived from "null"
8
+device type in OpenVPN. In particular, when *--dev null --ifconfig-noexec* is
9
+used in OpenVPN client configuration one does not need to run OpenVPN with root
10
+privileges because interface, routing, etc. configuration is not done at all.
11
+This is still enough to ensure that the OpenVPN client can connect to a server
12
+instance.
13
+
14
+The main features of the test suite:
15
+
16
+* Parallelized for fairly high performance
17
+* Mostly operating-system agnostic
18
+* Tested on Fedora Linux 38/39/40 and FreeBSD 14
19
+* POSIX-compliant
20
+* Tested and known to work with Bash, Dash, Ksh, Yash and FreeBSD's default /bin/sh
21
+* Uses the sample certificates and keys
22
+* Supports running multiple servers and clients
23
+* Supports running servers directly as root and with sudo
24
+* Supports using different OpenVPN client versions
25
+
26
+  * The "current" (just compiled) version
27
+  * Any other OpenVPN versions that is present on the filesystem
28
+
29
+* Support testing for success as well as failure
30
+* Test cases (client configurations) and server setups (server configurations) are stored in a configuration file, i.e. data and code have been separated
31
+* Configuration file format is nearly identical to t_client.rc configuration
32
+* Supports a set of default tests, overriding default test settings and adding local tests
33
+
34
+Prerequisites
35
+-------------
36
+
37
+Running the test suite requires the following:
38
+
39
+* *bash* for running the tests
40
+* root-level privileges for launching the servers
41
+
42
+  * run as root
43
+  * a privilege escalation tool (sudo, doas, su) and the permission to become root
44
+
45
+Technical implementation
46
+------------------------
47
+
48
+The test suite is completely parallelized to allow running a large number of
49
+server and client combinations quickly.
50
+
51
+A normal test run looks like this:
52
+
53
+#. Server instances start
54
+#. Brief wait
55
+#. Client instances start
56
+#. Tests run
57
+#. Client instances stop
58
+#. Brief wait
59
+#. Server instances stop
60
+
61
+The tests suite is launched via "make check":
62
+
63
+* make check
64
+
65
+  * t_server_null.sh
66
+
67
+    * t_server_null_server.sh
68
+
69
+      * Launches the compiled OpenVPN server instances as root (if necessary with sudo or su) in the background. The servers are killed using their management interface once all clients have exited.
70
+
71
+    * t_server_null_client.sh
72
+
73
+      * Waits until servers have launched. Then launch all clients, wait for them to exit and then check test results by parsing the client log files. Each client kills itself after some delay using an "--up" script.
74
+
75
+Note that "make check" moves on once *t_server_null_client.sh* has exited. At
76
+that point *t_server_null_server.sh* is still running, because it exists only
77
+after waiting a few seconds for more client connections to potentially appear.
78
+This is a feature and not a bug, but means that launching "make check" runs too
79
+quickly might cause test failures or unexpected behavior such as leftover
80
+OpenVPN server processes.
81
+
82
+Configuration
83
+-------------
84
+
85
+The test suite reads its configuration from two files:
86
+
87
+* *tests/t_server_null_defaults.rc:* default test configuration that should work on any system
88
+* *tests/t_server_null.rc:* a local configuration file; can be used to add additional tests or override settings from the default test configuration. Must be present or tests will be skipped, but can be an empty file.
89
+
90
+The configuration syntax is very similar to *t_client.rc*. New server instances can be
91
+defined like this::
92
+
93
+  SERVER_NAME_5="t_server_null_server-11195_udp"
94
+  SERVER_MGMT_PORT_5="11195"
95
+  SERVER_EXEC_5="${SERVER_EXEC}"
96
+  SERVER_CONF_5="${SERVER_CONF_BASE} --lport 11195 --proto udp --management 127.0.0.1 ${SERVER_MGMT_PORT_5}"
97
+
98
+In this case the server instance identifier is **5**. Variables such as
99
+*SERVER_EXEC* and *SERVER_CONF_BASE* are defined in
100
+*t_server_null_defaults.rc*. To enable this server instance add it to the
101
+server list::
102
+
103
+  TEST_SERVER_LIST="1 2 5"
104
+
105
+The client instances are added similarly::
106
+
107
+  TEST_NAME_9="t_server_null_client.sh-openvpn_current_udp_custom"
108
+  SHOULD_PASS_9="yes"
109
+  CLIENT_EXEC_9="${CLIENT_EXEC}"
110
+  CLIENT_CONF_9="${CLIENT_CONF_BASE} --remote 127.0.0.1 1194 udp --proto udp"
111
+
112
+In this case the test identifier is **9**. *CLIENT_EXEC* and *CLIENT_CONF_BASE*
113
+are defined in *t_server_null_defaults.rc*. The variable *SHOULD_PASS*
114
+determines that this particular test is supposed to succeed and not fail.  To
115
+enable this client instance add it to the test list::
116
+
117
+  TEST_RUN_LIST="1 2 5 9"
118
+
119
+Stress-testing the --dev null test suite
120
+----------------------------------------
121
+
122
+It is very easy to introduce subtle, difficult to debug issues to the --dev
123
+null tests when you make changes to it. These issues can be difficult to spot:
124
+based on practical experience a bad change can make the test failure rate go
125
+from 0% (normal) to anywhere between 1% and 20%. You can spot these issues with
126
+the provided stress-test script, *t_server_null_stress.sh*. It calls *make check*
127
+over and over again in a loop and when failures occur it saves the output under
128
+*tests/make-check*.
129
+
130
+To follow the test flow on Linux you can run this while stress-testing::
131
+
132
+    watch -n 0.5 "ps aux|grep -E '(openvpn|t_server_null_server.sh)'|grep -vE '(suppress|grep|tail)'"
133
+
134
+Regarding privilege escalation
135
+------------------------------
136
+
137
+The --dev null test servers need to be launched as root. Either run the tests
138
+as root directly, or configure a privilege escalation tool of your choice in
139
+*t_server_null.rc*. For example, to use sudo::
140
+
141
+    SUDO_EXEC=`which sudo`
142
+    RUN_SUDO="${SUDO_EXEC} -E"
143
+
144
+If you do stress-testing with *t_server_null_stress.sh* make sure your
145
+privilege escalation authorization does not time out: if it does, then a
146
+reauthorization prompt will interrupt your tests.
... ...
@@ -15,10 +15,10 @@ MAINTAINERCLEANFILES = \
15 15
 SUBDIRS = unit_tests
16 16
 
17 17
 AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING) System Tests'
18
-LOG_DRIVER = $(SHELL) $(top_srcdir)/forked-test-driver
18
+SH_LOG_DRIVER = $(SHELL) $(top_srcdir)/forked-test-driver
19 19
 
20 20
 if !WIN32
21
-test_scripts = t_client.sh t_lpback.sh t_cltsrv.sh
21
+test_scripts = t_client.sh t_lpback.sh t_cltsrv.sh t_server_null.sh
22 22
 
23 23
 check_PROGRAMS = ntlm_support
24 24
 if HAVE_SITNL
... ...
@@ -27,6 +27,7 @@ endif
27 27
 endif
28 28
 
29 29
 TESTS_ENVIRONMENT = top_srcdir="$(top_srcdir)"
30
+TEST_EXTENSIONS = .sh
30 31
 TESTS = $(test_scripts)
31 32
 
32 33
 dist_noinst_SCRIPTS = \
... ...
@@ -34,8 +35,14 @@ dist_noinst_SCRIPTS = \
34 34
 	t_cltsrv-down.sh \
35 35
 	t_lpback.sh \
36 36
 	t_net.sh \
37
+	t_server_null.sh \
38
+	t_server_null_client.sh \
39
+	t_server_null_server.sh \
40
+	t_server_null_default.rc \
37 41
 	update_t_client_ips.sh
38 42
 
43
+t_client.log: t_server_null.log
44
+
39 45
 dist_noinst_DATA = \
40 46
 	t_client.rc-sample
41 47
 
42 48
new file mode 100755
... ...
@@ -0,0 +1,11 @@
0
+#!/bin/sh
1
+#
2
+# Stop the parent process (openvpn) gracefully after a small delay
3
+
4
+# Determine the OpenVPN PID from its pid file. This works reliably even when
5
+# the OpenVPN process is backgrounded for parallel tests.
6
+MY_PPID=`cat $pid`
7
+
8
+# Allow OpenVPN to finish initializing while waiting in the background and then
9
+# killing the process gracefully.
10
+(sleep 5 ; kill -15 $MY_PPID) &
0 11
new file mode 100644
... ...
@@ -0,0 +1,15 @@
0
+# Uncomment to run tests with sudo
1
+#SUDO_EXEC=`which sudo`
2
+#RUN_SUDO="${SUDO_EXEC} -E"
3
+
4
+TEST_RUN_LIST="1 2 3 10 11"
5
+
6
+TEST_NAME_10="t_server_null_client.sh-openvpn_2_6_8_udp"
7
+SHOULD_PASS_10="yes"
8
+CLIENT_EXEC_10="/usr/sbin/openvpn"
9
+CLIENT_CONF_10="${CLIENT_CONF_BASE} --remote 127.0.0.1 1194 udp --proto udp"
10
+
11
+TEST_NAME_11="t_server_null_client.sh-openvpn_2_6_8_tcp"
12
+SHOULD_PASS_11="yes"
13
+CLIENT_EXEC_11="/usr/sbin/openvpn"
14
+CLIENT_CONF_11="${CLIENT_CONF_BASE} --remote 127.0.0.1 1195 tcp --proto tcp"
0 15
new file mode 100755
... ...
@@ -0,0 +1,72 @@
0
+#!/usr/bin/env sh
1
+#
2
+TSERVER_NULL_SKIP_RC="${TSERVER_NULL_SKIP_RC:-77}"
3
+
4
+if ! [ -r "./t_server_null.rc" ] ; then
5
+    echo "${0}: cannot find './t_server_null.rc. SKIPPING TEST.'" >&2
6
+    exit "${TSERVER_NULL_SKIP_RC}"
7
+fi
8
+
9
+. ./t_server_null.rc
10
+
11
+if KILL_EXEC=$(which kill); then
12
+    export KILL_EXEC
13
+else
14
+    echo "${0}: kill not found in \$PATH" >&2
15
+    exit "${TSERVER_NULL_SKIP_RC}"
16
+fi
17
+
18
+# Ensure PREFER_KSU is in a known state
19
+PREFER_KSU="${PREFER_KSU:-0}"
20
+
21
+# make sure we have permissions to run ifconfig/route from OpenVPN
22
+# can't use "id -u" here - doesn't work on Solaris
23
+ID=$(id)
24
+if expr "$ID" : "uid=0" >/dev/null
25
+then :
26
+else
27
+    if [ "${PREFER_KSU}" -eq 1 ];
28
+    then
29
+        # Check if we have a valid kerberos ticket
30
+        if klist -l 1>/dev/null 2>/dev/null; then
31
+            RUN_SUDO="ksu -q -e"
32
+        else
33
+            # No kerberos ticket found, skip ksu and fallback to RUN_SUDO
34
+            PREFER_KSU=0
35
+            echo "${0}: No Kerberos ticket available.  Will not use ksu."
36
+        fi
37
+    fi
38
+
39
+    if [ -z "$RUN_SUDO" ]
40
+    then
41
+        echo "${0}: this test must run be as root, or RUN_SUDO=... " >&2
42
+        echo "      must be set correctly in 't_server_null.rc'. SKIP." >&2
43
+        exit "${TSERVER_NULL_SKIP_RC}"
44
+    else
45
+	# Run a no-op command with privilege escalation (e.g. sudo) so that
46
+	# we (hopefully) do not have to ask the users password during the test.
47
+	if $RUN_SUDO "${KILL_EXEC}" -0 $$
48
+	then
49
+	    echo "${0}: $RUN_SUDO $KILL_EXEC -0 succeeded, good."
50
+	else
51
+	    echo "${0}: $RUN_SUDO $KILL_EXEC -0 failed, cannot go on. SKIP." >&2
52
+	    exit "${TSERVER_NULL_SKIP_RC}"
53
+	fi
54
+    fi
55
+fi
56
+
57
+srcdir="${srcdir:-.}"
58
+
59
+if [ -z "${RUN_SUDO}" ]; then
60
+    "${srcdir}/t_server_null_server.sh" &
61
+else
62
+    $RUN_SUDO "${srcdir}/t_server_null_server.sh" &
63
+fi
64
+
65
+"${srcdir}/t_server_null_client.sh"
66
+
67
+# When running make jobs in parallel ("make -j<x> check") we need to ensure
68
+# that this script does not exit before all --dev null servers are dead and
69
+# their network interfaces are gone. Otherwise t_client.sh will fail because
70
+# pre and post ifconfig output does not match.
71
+wait
0 72
new file mode 100755
... ...
@@ -0,0 +1,136 @@
0
+#!/usr/bin/env sh
1
+
2
+launch_client() {
3
+    test_name=$1
4
+    log="${test_name}.log"
5
+    pid="${test_name}.pid"
6
+    client_exec=$2
7
+    client_conf=$3
8
+
9
+    # Ensure that old log and pid files are gone
10
+    rm -f "${log}" "${pid}"
11
+
12
+    "${client_exec}" \
13
+        $client_conf \
14
+        --writepid "${pid}" \
15
+        --setenv pid $pid \
16
+        --log "${log}" &
17
+}
18
+
19
+wait_for_results() {
20
+    tests_running="yes"
21
+
22
+    # Wait a bit to allow an OpenVPN client process to create a pidfile to
23
+    # prevent exiting too early
24
+    sleep 1
25
+
26
+    while [ "${tests_running}" = "yes" ]; do
27
+        tests_running="no"
28
+        for t in $test_names; do
29
+            if [ -f "${t}.pid" ]; then
30
+                tests_running="yes"
31
+            fi
32
+        done
33
+
34
+        if [ "${tests_running}" = "yes" ]; then
35
+            echo "Clients still running"
36
+            sleep 1
37
+        fi
38
+    done
39
+}
40
+
41
+get_client_test_result() {
42
+    test_name=$1
43
+    should_pass=$2
44
+    log="${test_name}.log"
45
+
46
+    grep "Initialization Sequence Completed" "${log}" > /dev/null
47
+    exit_code=$?
48
+
49
+    if [ $exit_code -eq 0 ] && [ "${should_pass}" = "yes" ]; then
50
+        echo "PASS ${test_name}"
51
+    elif [ $exit_code -eq 1 ] && [ "${should_pass}" = "no" ]; then
52
+        echo "PASS ${test_name} (test failure)"
53
+    elif [ $exit_code -eq 0 ] && [ "${should_pass}" = "no" ]; then
54
+        echo "FAIL ${test_name} (test failure)"
55
+        cat "${log}"
56
+        retval=1
57
+    elif [ $exit_code -eq 1 ] && [ "${should_pass}" = "yes" ]; then
58
+        echo "FAIL ${test_name}"
59
+        cat "${log}"
60
+        retval=1
61
+    fi
62
+}
63
+
64
+# Load basic/default tests
65
+. ${srcdir}/t_server_null_default.rc || exit 1
66
+
67
+# Load additional local tests, if any
68
+test -r ./t_server_null.rc && . ./t_server_null.rc
69
+
70
+# Return value for the entire test suite. Gets set to 1 if any test fails.
71
+export retval=0
72
+
73
+# Wait until servers are up. This check is based on the presence of processes
74
+# matching the PIDs in each servers PID files
75
+count=0
76
+server_max_wait=15
77
+while [ $count -lt $server_max_wait ]; do
78
+    server_pids=""
79
+    server_count=$(set|grep 'SERVER_NAME_'|wc -l)
80
+
81
+    # We need to trim single-quotes because some shells return quoted values
82
+    # and some don't. Using "set -o posix" which would resolve this problem is
83
+    # not supported in all shells.
84
+    for i in `set|grep 'SERVER_NAME_'|cut -d "=" -f 2|tr -d "[\']"`; do
85
+        server_pid=$(cat $i.pid 2> /dev/null)
86
+        server_pids="${server_pids} ${server_pid}"
87
+    done
88
+
89
+    servers_up=$(ps -p $server_pids 2>/dev/null|sed '1d'|wc -l)
90
+
91
+    echo "OpenVPN test servers up: ${servers_up}/${server_count}"
92
+
93
+    if [ $servers_up -ge $server_count ]; then
94
+        retval=0
95
+        break
96
+    else
97
+        count=$(( count + 1))
98
+        sleep 1
99
+    fi
100
+
101
+    if [ $count -eq $server_max_wait ]; then
102
+        retval=1
103
+    fi
104
+done
105
+
106
+# Wait a while to let server processes to settle down
107
+sleep 1
108
+
109
+# Launch OpenVPN clients. While at it, construct a list of test names. The list
110
+# is used later to determine when all OpenVPN clients have exited and it is
111
+# safe to check the test results.
112
+test_names=""
113
+for SUF in $TEST_RUN_LIST
114
+do
115
+    eval test_name=\"\$TEST_NAME_$SUF\"
116
+    eval client_exec=\"\$CLIENT_EXEC_$SUF\"
117
+    eval client_conf=\"\$CLIENT_CONF_$SUF\"
118
+
119
+    test_names="${test_names} ${test_name}"
120
+    (launch_client "${test_name}" "${client_exec}" "${client_conf}")
121
+done
122
+
123
+# Wait until all OpenVPN clients have exited
124
+(wait_for_results)
125
+
126
+# Check test results
127
+for SUF in $TEST_RUN_LIST
128
+do
129
+    eval test_name=\"\$TEST_NAME_$SUF\"
130
+    eval should_pass=\"\$SHOULD_PASS_$SUF\"
131
+
132
+    (get_client_test_result "${test_name}" "${should_pass}")
133
+done
134
+
135
+exit $retval
0 136
new file mode 100755
... ...
@@ -0,0 +1,66 @@
0
+# Notes regarding --dev null server and client configurations:
1
+#
2
+# The t_server_null_server.sh exits when all client pid files have gone
3
+# missing. That is the most reliable and fastest way to detect client
4
+# disconnections in the "everything runs on localhost" context. Checking server
5
+# status files for client connections works, but introduces long delays as
6
+# --explicit-exit-notify does not seem to work on all client configurations.
7
+# This means that, by default, there is about 1 minute delay before the server
8
+# purges clients that have already exited and have not reported back.
9
+#
10
+srcdir="${srcdir:-.}"
11
+top_builddir="${top_builddir:-..}"
12
+sample_keys="${srcdir}/../sample/sample-keys"
13
+
14
+DH="${sample_keys}/dh2048.pem"
15
+CA="${sample_keys}/ca.crt"
16
+CLIENT_CERT="${sample_keys}/client.crt"
17
+CLIENT_KEY="${sample_keys}/client.key"
18
+SERVER_CERT="${sample_keys}/server.crt"
19
+SERVER_KEY="${sample_keys}/server.key"
20
+TA="${sample_keys}/ta.key"
21
+
22
+# Test server configurations
23
+MAX_CLIENTS="10"
24
+CLIENT_MATCH="Test-Client"
25
+SERVER_EXEC="${top_builddir}/src/openvpn/openvpn"
26
+SERVER_BASE_OPTS="--daemon --local 127.0.0.1 --dev tun --topology subnet --server 10.29.41.0 255.255.255.0 --max-clients $MAX_CLIENTS --persist-tun --verb 3"
27
+SERVER_CIPHER_OPTS=""
28
+SERVER_CERT_OPTS="--ca ${CA} --dh ${DH} --cert ${SERVER_CERT} --key ${SERVER_KEY} --tls-auth ${TA} 0"
29
+SERVER_CONF_BASE="${SERVER_BASE_OPTS} ${SERVER_CIPHER_OPTS} ${SERVER_CERT_OPTS}"
30
+
31
+TEST_SERVER_LIST="1 2"
32
+
33
+SERVER_NAME_1="t_server_null_server-1194_udp"
34
+SERVER_MGMT_PORT_1="11194"
35
+SERVER_EXEC_1="${SERVER_EXEC}"
36
+SERVER_CONF_1="${SERVER_CONF_BASE} --lport 1194 --proto udp --management 127.0.0.1 ${SERVER_MGMT_PORT_1}"
37
+
38
+SERVER_NAME_2="t_server_null_server-1195_tcp"
39
+SERVER_MGMT_PORT_2="11195"
40
+SERVER_EXEC_2="${SERVER_EXEC}"
41
+SERVER_CONF_2="${SERVER_CONF_BASE} --lport 1195 --proto tcp --management 127.0.0.1 ${SERVER_MGMT_PORT_2}"
42
+
43
+# Test client configurations
44
+CLIENT_EXEC="${top_builddir}/src/openvpn/openvpn"
45
+CLIENT_BASE_OPTS="--client --dev null --ifconfig-noexec --nobind --remote-cert-tls server --persist-tun --verb 3 --resolv-retry infinite --connect-retry-max 3 --server-poll-timeout 5 --explicit-exit-notify 3 --script-security 2 --up ${srcdir}/null_client_up.sh"
46
+CLIENT_CIPHER_OPTS=""
47
+CLIENT_CERT_OPTS="--ca ${CA} --cert ${CLIENT_CERT} --key ${CLIENT_KEY} --tls-auth ${TA} 1"
48
+
49
+TEST_RUN_LIST="1 2 3"
50
+CLIENT_CONF_BASE="${CLIENT_BASE_OPTS} ${CLIENT_CIPHER_OPTS} ${CLIENT_CERT_OPTS}"
51
+
52
+TEST_NAME_1="t_server_null_client.sh-openvpn_current_udp"
53
+SHOULD_PASS_1="yes"
54
+CLIENT_EXEC_1="${CLIENT_EXEC}"
55
+CLIENT_CONF_1="${CLIENT_CONF_BASE} --remote 127.0.0.1 1194 udp --proto udp"
56
+
57
+TEST_NAME_2="t_server_null_client.sh-openvpn_current_tcp"
58
+SHOULD_PASS_2="yes"
59
+CLIENT_EXEC_2="${CLIENT_EXEC}"
60
+CLIENT_CONF_2="${CLIENT_CONF_BASE} --remote 127.0.0.1 1195 tcp --proto tcp"
61
+
62
+TEST_NAME_3="t_server_null_client.sh-openvpn_current_udp_fail"
63
+SHOULD_PASS_3="no"
64
+CLIENT_EXEC_3="${CLIENT_EXEC}"
65
+CLIENT_CONF_3="${CLIENT_CONF_BASE} --remote 127.0.0.1 11194 udp --proto udp"
0 66
new file mode 100755
... ...
@@ -0,0 +1,78 @@
0
+#!/usr/bin/env sh
1
+
2
+launch_server() {
3
+    server_name=$1
4
+    server_exec=$2
5
+    server_conf=$3
6
+    log="${server_name}.log"
7
+    status="${server_name}.status"
8
+    pid="${server_name}.pid"
9
+
10
+    # Ensure that old status, log and pid files are gone
11
+    rm -f "${status}" "${log}" "${pid}"
12
+
13
+    "${server_exec}" \
14
+        $server_conf \
15
+        --status "${status}" 1 \
16
+        --log "${log}" \
17
+        --writepid "${pid}" \
18
+        --explicit-exit-notify 3
19
+
20
+}
21
+
22
+# Load base/default configuration
23
+. "${srcdir}/t_server_null_default.rc" || exit 1
24
+
25
+# Load local configuration, if any
26
+test -r ./t_server_null.rc && . ./t_server_null.rc
27
+
28
+# Launch test servers
29
+for SUF in $TEST_SERVER_LIST
30
+do
31
+    eval server_name=\"\$SERVER_NAME_$SUF\"
32
+    eval server_exec=\"\$SERVER_EXEC_$SUF\"
33
+    eval server_conf=\"\$SERVER_CONF_$SUF\"
34
+
35
+    (launch_server "${server_name}" "${server_exec}" "${server_conf}")
36
+done
37
+
38
+# Create a list of server pid files so that servers can be killed at the end of
39
+# the test run.
40
+#
41
+export server_pid_files=""
42
+for SUF in $TEST_SERVER_LIST
43
+do
44
+    eval server_name=\"\$SERVER_NAME_$SUF\"
45
+    server_pid_files="${server_pid_files} ./${server_name}.pid"
46
+done
47
+
48
+# Wait until clients are no more, based on the presence of their pid files.
49
+# Based on practical testing we have to wait at least four seconds to avoid
50
+# accidentally exiting too early.
51
+count=0
52
+maxcount=4
53
+while [ $count -le $maxcount ]; do
54
+    if ls t_server_null_client.sh*.pid > /dev/null 2>&1
55
+    then
56
+        count=0
57
+        sleep 1
58
+    else
59
+	count=$(( count + 1))
60
+        sleep 1
61
+    fi
62
+done
63
+
64
+echo "All clients have disconnected from all servers"
65
+
66
+for PID_FILE in $server_pid_files
67
+do
68
+    SERVER_PID=$(cat "${PID_FILE}")
69
+    $KILL_EXEC "${SERVER_PID}"
70
+
71
+    # Make sure that the server processes are truly dead before exiting
72
+    while :
73
+    do
74
+        ps -p "${SERVER_PID}" > /dev/null || break
75
+        sleep 0.2
76
+    done
77
+done
0 78
new file mode 100755
... ...
@@ -0,0 +1,33 @@
0
+#!/usr/bin/env sh
1
+#
2
+# Run this stress test as root to avoid sudo authorization from timing out.
3
+
4
+ITERATIONS="${1:-100}"
5
+
6
+. ./t_server_null_default.rc
7
+
8
+export pid_files=""
9
+for SUF in $TEST_SERVER_LIST
10
+do
11
+    eval server_name=\"\$SERVER_NAME_$SUF\"
12
+    pid_files="${pid_files} ./${server_name}.pid"
13
+done
14
+
15
+LOG_BASEDIR="make-check"
16
+mkdir -p "${LOG_BASEDIR}"
17
+
18
+count=0
19
+while [ $count -lt $ITERATIONS ]; do
20
+    count=$(( count + 1 ))
21
+    make check TESTS=t_server_null.sh SUBDIRS= > /dev/null 2>&1
22
+    retval=$?
23
+
24
+    echo "Iteration ${count}: return value ${retval}" >> "${LOG_BASEDIR}/make-check.log"
25
+    if [ $retval -ne 0 ]; then
26
+	DIR="${LOG_BASEDIR}/make-check-${count}"
27
+        mkdir -p "${DIR}"
28
+        cp t_server_null*.log "${DIR}/"
29
+        cp test-suite.log "${DIR}/"
30
+        ps aux|grep openvpn|grep -vE '(suppress|grep)' > "${DIR}/psaux"
31
+    fi
32
+done