serval-dna/tests/server
Andrew Bettison 7f0fef2209 Fix an intermittent server test failure
The quit-on-monitor-client-disconnect test was non-deterministic
depending on load (eg, other concurrently running tests).  Under load,
it was likely that the server did not process the "monitor quit" command
before checking for disconnect, so the server did not terminate.

The fix was to make the monitor interface read and process all queued
input from the client before checking for HUP or ERR condition on the
socket.  With this fix, the "sleep 1" kludges before and after the echo
"monitor quit" to the console command are no longer needed.

In the process the monitor interface code was modernised: eg, now it
calls read_nonblock() instead of read(2).
2016-09-06 12:33:29 +09:30

358 lines
10 KiB
Bash
Executable File

#!/bin/bash
# Tests for Serval DNA server operations.
#
# Copyright 2012 Serval Project, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
source "${0%/*}/../testframework.sh"
source "${0%/*}/../testdefs.sh"
setup() {
setup_servald
assert_no_servald_processes
}
teardown() {
get_servald_server_pidfile && stop_servald_server
kill_all_servald_processes
assert_no_servald_processes
report_all_servald_servers
}
configure_servald_server() {
executeOk_servald config \
set log.console.level debug \
set log.console.show_time true \
set log.console.show_pid true
}
doc_StartCreateInstanceDir="Starting server creates instance directory"
setup_StartCreateInstanceDir() {
# Ensure there is initially no instance directory.
configure_servald_server() {
:
}
setup
assert [ ! -d "$SERVALINSTANCE_PATH" ]
}
test_StartCreateInstanceDir() {
executeOk $servald start
assert [ -d "$SERVALINSTANCE_PATH" ]
executeOk $servald stop
tfw_cat --stdout --stderr
}
doc_StartLogfile="Starting server gives no errors"
setup_StartLogfile() {
setup
executeOk_servald config set log.file.directory_path "$PWD/log"
}
test_StartLogfile() {
start_servald_server
assert_servald_server_no_errors
}
doc_StartNoInterfaces="Starting server with no configured interfaces gives warning"
setup_StartNoInterfaces() {
setup
}
test_StartNoInterfaces() {
start_servald_server
sleep 0.1
assertGrep --message="log contains 'no interfaces' warning" "$instance_servald_log" '^WARN:.*interfaces'
tfw_cat "$instance_servald_log"
}
doc_StartNoErrors="Starting server on dummy file interface gives no errors"
setup_StartNoErrors() {
setup
add_servald_interface --file
}
test_StartNoErrors() {
start_servald_server
wait_until grep "Interface .* is up" $instance_servald_log
assert_servald_server_no_errors
tfw_cat "$instance_servald_log"
}
doc_StartLocalNoErrors="Starting server on local interface gives no errors"
setup_StartLocalNoErrors() {
setup
add_servald_interface
}
test_StartLocalNoErrors() {
start_servald_server
wait_until grep "Interface .* is up" $instance_servald_log
assert_servald_server_no_errors
tfw_cat "$instance_servald_log"
}
doc_StartRealNoErrors="Starting server with real interface config gives no errors"
setup_StartRealNoErrors() {
setup
executeOk_servald config \
set interfaces.0.match BAD0 \
set interfaces.1.match BAD1 \
set interfaces.2.match BAD2
}
test_StartRealNoErrors() {
start_servald_server
assert_servald_server_no_errors
tfw_cat "$instance_servald_log"
}
doc_StartStart="Start server while already running"
setup_StartStart() {
setup
start_servald_server
}
test_StartStart() {
execute --exit-status=10 $servald start
extract_stdout_keyvalue start_instance_path 'instancepath' '.*'
extract_stdout_keyvalue start_pid 'pid' '[0-9]\+'
assert [ "$start_instance_path" = "$SERVALINSTANCE_PATH" ]
assert [ "$servald_pid" = "$start_pid" ]
}
doc_StartTwice="Attempt to start the server twice at the same time"
setup_StartTwice() {
setup
export SERVALD_SERVER_START_DELAY=2000
set_instance +A
executeOk_servald config set debug.io on
}
start_other(){
start_servald_server
echo $servald_pid > other_pid
}
test_StartTwice() {
fork %server start_other
start_servald_server
fork_wait %server
# both servald start commands should return success with the same PID
assertGrep other_pid "^$servald_pid$"
stop_servald_server
assert_no_servald_processes
}
doc_MonitorQuit="Server stops due to monitor client disconnection"
setup_MonitorQuit() {
configure_servald_server() {
executeOk_servald config \
set log.console.level debug \
set log.console.show_time true \
set log.console.show_pid true \
set debug.monitor on
}
setup
start_servald_server
}
test_MonitorQuit() {
executeOk_servald console < <(echo "monitor quit")
tfw_cat --stdout --stderr
wait_until ! kill -0 $servald_pid 2>/dev/null
}
doc_NoZombie="Server process does not become a zombie"
setup_NoZombie() {
setup
export SERVALD_START_POST_SLEEP=10000
servald_start &
start_pid=$!
wait_until get_servald_server_pidfile servald_pid
assert kill -0 $start_pid
}
test_NoZombie() {
tfw_log "Before kill -KILL $servald_pid"
ps -l $start_pid $servald_pid
assert kill -KILL $servald_pid
tfw_log "After kill -KILL $servald_pid"
ps -l $start_pid $servald_pid
wait_until --timeout=2 ! kill -0 $servald_pid 2>/dev/null
tfw_log "After waiting"
ps -l $start_pid $servald_pid
assert --message="zombie servald process does not exist" ! kill -0 $servald_pid 2>/dev/null
}
teardown_NoZombie() {
kill -TERM $start_pid
kill_all_servald_processes
assert_no_servald_processes
}
doc_ServerWatchdog="Server process invokes watchdog periodically"
setup_ServerWatchdog() {
cat >watchdog <<EOF
#!/bin/sh
date >> $PWD/trace
EOF
chmod 0550 watchdog
>trace
setup
executeOk_servald config \
set log.console.level debug \
set log.console.show_time true \
set log.console.show_pid true \
set debug.watchdog on \
set server.watchdog.executable "$PWD/watchdog" \
set server.watchdog.interval_ms 100
start_servald_server
}
test_ServerWatchdog() {
wait_until --sleep=0.1 --timeout=15 line_count_at_least trace 10
stop_servald_server
assert_servald_server_no_errors
}
line_count_at_least() {
local file="$1"
local lines="$2"
[ $(wc -l <"$file") -ge "$lines" ]
}
doc_ReloadConfigAuto="Server automatically reloads configuration"
setup_ReloadConfigAuto() {
cat >watchdog1 <<EOF
#!/bin/sh
date >> $PWD/trace1
EOF
cat >watchdog2 <<EOF
#!/bin/sh
date >> $PWD/trace2
EOF
chmod 0550 watchdog1 watchdog2
>trace1
>trace2
setup
executeOk_servald config \
set log.console.level debug \
set log.console.show_time true \
set log.console.show_pid true \
set debug.watchdog on \
set server.watchdog.executable "$PWD/watchdog1" \
set server.watchdog.interval_ms 100
start_servald_server
}
test_ReloadConfigAuto() {
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace1 3
assert [ $(wc -l <trace2) -eq 0 ]
executeOk_servald config \
set server.watchdog.executable "$PWD/watchdog2"
tfw_cat --stderr
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace2 3
stop_servald_server
assert_servald_server_no_errors
}
doc_ReloadConfigSync="Server configuration sync"
setup_ReloadConfigSync() {
cat >watchdog1 <<EOF
#!/bin/sh
date >> $PWD/trace1
EOF
cat >watchdog2 <<EOF
#!/bin/sh
date >> $PWD/trace2
EOF
chmod 0550 watchdog1 watchdog2
>trace1
>trace2
setup
executeOk_servald config \
set log.console.level debug \
set log.console.show_time true \
set log.console.show_pid true \
set debug.config on \
set debug.watchdog on \
set debug.mdprequests on \
set server.config_reload_interval_ms 600000 \
set server.watchdog.executable "$PWD/watchdog1" \
set server.watchdog.interval_ms 100
start_servald_server
}
test_ReloadConfigSync() {
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace1 10
assert [ $(wc -l <trace2) -eq 0 ]
executeOk_servald config set server.watchdog.executable "$PWD/watchdog2"
tfw_cat --stderr
>trace1
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace1 3
assert [ $(wc -l <trace2) -eq 0 ]
executeOk_servald config sync
tfw_cat --stderr
>trace1
wait_until --sleep=0.5 --timeout=15 line_count_at_least trace2 3
assert [ $(wc -l <trace1) -eq 0 ]
stop_servald_server
assert_servald_server_no_errors
}
doc_ReloadConfigSetSync="Server configuration always syncs after set"
setup_ReloadConfigSetSync() {
setup_curl 7
setup
set_instance +A
create_single_identity
executeOk_servald config \
set log.console.level debug \
set log.console.show_time true \
set log.console.show_pid true \
set debug.config on \
set debug.mdprequests on \
set server.config_reload_interval_ms 600000 \
set server.motd "Abcdef"
start_servald_server
get_servald_http_server_port PORTA +A
conf_size=$(wc -l <"$SERVALINSTANCE_PATH/serval.conf")
assert [ "$conf_size" -gt 0 ]
}
test_ReloadConfigSetSync() {
# Set the MOTD without changing the config file size and sync it, and the
# HTTP server returns it in the root page immediately.
executeOk_servald config set server.motd "Yoicks" sync
tfw_cat --stderr
assert [ $conf_size -eq $(wc -l <"$SERVALINSTANCE_PATH/serval.conf") ]
executeOk curl \
--silent --fail --show-error \
--output root.html \
--dump-header http.headers \
"http://$addr_localhost:$PORTA/"
assertGrep root.html Yoicks
# Set the MOTD without changing the config file size but do not sync it, and
# the HTTP server still returns the prior value of the MOTD.
executeOk_servald config set server.motd "Flarng"
tfw_cat --stderr
assert [ $conf_size -eq $(wc -l <"$SERVALINSTANCE_PATH/serval.conf") ]
executeOk curl \
--silent --fail --show-error \
--output root.html \
--dump-header http.headers \
"http://$addr_localhost:$PORTA/"
assertGrep root.html Yoicks
# Sync the config to the daemon, and now the HTTP server returns the new
# MOTD.
executeOk_servald config sync
executeOk curl \
--silent --fail --show-error \
--output root.html \
--dump-header http.headers \
"http://$addr_localhost:$PORTA/"
assertGrep root.html Flarng
stop_servald_server
assert_servald_server_no_errors
}
runTests "$@"