From patchwork Mon Oct 29 16:25:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Pfaff X-Patchwork-Id: 990368 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ovn.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42kKj6282Mz9s3l for ; Tue, 30 Oct 2018 03:26:01 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 8318C31F6; Mon, 29 Oct 2018 16:25:58 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 692D631F2 for ; Mon, 29 Oct 2018 16:25:57 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 2F891735 for ; Mon, 29 Oct 2018 16:25:54 +0000 (UTC) X-Originating-IP: 208.91.3.26 Received: from sigabrt.benpfaff.org (unknown [208.91.3.26]) (Authenticated sender: blp@ovn.org) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id ACD642000D; Mon, 29 Oct 2018 16:25:51 +0000 (UTC) From: Ben Pfaff To: dev@openvswitch.org Date: Mon, 29 Oct 2018 09:25:45 -0700 Message-Id: <20181029162545.2082-1-blp@ovn.org> X-Mailer: git-send-email 2.16.1 X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Ben Pfaff Subject: [ovs-dev] [PATCH] tests: Simplify and improve the daemon tests. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org The daemon tests used files a lot when shell variables were easier to use and easier to understand. This commit changes that. The tests created empty databases that aren't really needed anymore. This commit changes them to use the ovsdb-server --no-db option instead. The tests had a lot of common code for checking the ancestry of processes. This commit factors out a new shell function check_ancestors. The tests tended to use random pidfile names. This switches to just using the defaults, which are fine. The tests didn't check the names of the child processes. This adds those checks using the new check_process_name shell function. This should avoid regression of the bug fixed by commit 266f79e32c60 ("daemon-unix: Use same name for original or restarted children.") Other minor improvements too. I only made small updates to the Windows-specific test, because it is hard for me to verify. Signed-off-by: Ben Pfaff Acked-by: Alin Gabriel Serdean > --- tests/daemon-py.at | 218 +++++++++++++++++++++++++---------------------------- tests/daemon.at | 214 +++++++++++++++++++++++++++++----------------------- 2 files changed, 222 insertions(+), 210 deletions(-) diff --git a/tests/daemon-py.at b/tests/daemon-py.at index 82852383b1f5..a08d65831069 100644 --- a/tests/daemon-py.at +++ b/tests/daemon-py.at @@ -6,20 +6,23 @@ m4_define([DAEMON_PYN], # Skip this test for Windows, echo $! gives shell pid instead of parent process AT_SKIP_IF([test "$IS_WIN32" = "yes"]) AT_KEYWORDS([python daemon]) - AT_CAPTURE_FILE([pid]) - AT_CAPTURE_FILE([expected]) + + on_exit 'kill $(cat *.pid)' + pidfile=test-daemon.py.pid + # Start the daemon and wait for the pidfile to get created # and that its contents are the correct pid. - AT_CHECK([$3 $srcdir/test-daemon.py --pidfile=pid& echo $! > expected], [0]) - OVS_WAIT_UNTIL([test -s pid], [kill `cat expected`]) - AT_CHECK( - [pid=`cat pid` && expected=`cat expected` && test "$pid" = "$expected"], - [0], [], [], [kill `cat expected`]) - AT_CHECK([kill -0 `cat pid`], [0], [], [], [kill `cat expected`]) + AT_CHECK([$3 $srcdir/test-daemon.py --pidfile & echo $!], [0], [stdout]) + pid=$(cat stdout) + + OVS_WAIT_UNTIL([test -s $pidfile], [kill $pid]) + AT_CHECK([test $pid = $(cat $pidfile)]) + AT_CHECK([kill -0 $pid]) + # Kill the daemon and make sure that the pidfile gets deleted. - kill `cat expected` - OVS_WAIT_WHILE([kill -0 `cat expected`]) - AT_CHECK([test ! -e pid]) + kill $pid + OVS_WAIT_WHILE([kill -0 $pid]) + AT_CHECK([test ! -e $pidfile]) AT_CLEANUP]) DAEMON_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2]) @@ -28,42 +31,38 @@ DAEMON_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3]) m4_define([DAEMON_MONITOR_PYN], [AT_SETUP([daemon --monitor - $1]) AT_SKIP_IF([test $2 = no]) + # Skip this test for Windows, echo $! gives shell pid instead of parent process AT_SKIP_IF([test "$IS_WIN32" = "yes"]) - AT_CAPTURE_FILE([pid]) - AT_CAPTURE_FILE([parent]) - AT_CAPTURE_FILE([parentpid]) - AT_CAPTURE_FILE([newpid]) + + on_exit 'kill $(cat *.pid)' + pidfile=test-daemon.py.pid + # Start the daemon and wait for the pidfile to get created. - AT_CHECK([$3 $srcdir/test-daemon.py --pidfile=pid --monitor& echo $! > parent], [0]) - on_exit 'kill `cat parent`' - OVS_WAIT_UNTIL([test -s pid]) + AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --monitor & echo $!], [0], [stdout]) + monitor=$(cat stdout) + OVS_WAIT_UNTIL([test -s $pidfile]) + child=$(cat $pidfile) + # Check that the pidfile names a running process, # and that the parent process of that process is our child process. - AT_CHECK([kill -0 `cat pid`]) - AT_CHECK([parent_pid `cat pid` > parentpid]) - AT_CHECK( - [parentpid=`cat parentpid` && - parent=`cat parent` && - test $parentpid = $parent]) + check_ancestors $child $monitor + # Kill the daemon process, making it look like a segfault, # and wait for a new child process to get spawned. - AT_CHECK([cp pid oldpid]) - AT_CHECK([kill -SEGV `cat pid`], [0], [], [ignore]) - OVS_WAIT_WHILE([kill -0 `cat oldpid`]) - OVS_WAIT_UNTIL([test -s pid && test `cat pid` != `cat oldpid`]) - AT_CHECK([cp pid newpid]) + AT_CHECK([kill -SEGV $child]) + OVS_WAIT_WHILE([kill -0 $child]) + OVS_WAIT_UNTIL([test -s $pidfile && test $(cat $pidfile) != $child]) + child2=$(cat $pidfile) + # Check that the pidfile names a running process, # and that the parent process of that process is our child process. - AT_CHECK([parent_pid `cat pid` > parentpid]) - AT_CHECK( - [parentpid=`cat parentpid` && - parent=`cat parent` && - test $parentpid = $parent]) + check_ancestors $child2 $monitor + # Kill the daemon process with SIGTERM, and wait for the daemon # and the monitor processes to go away and the pidfile to get deleted. - AT_CHECK([kill `cat pid`]) - OVS_WAIT_WHILE([kill -0 `cat parent` || kill -0 `cat newpid` || test -e pid]) + AT_CHECK([kill $child2]) + OVS_WAIT_WHILE([kill -0 $monitor || kill -0 $child2 || test -e $pidfile]) AT_CLEANUP]) DAEMON_MONITOR_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2]) @@ -74,40 +73,35 @@ m4_define([DAEMON_MONITOR_RESTART_PYN], AT_SKIP_IF([test $2 = no]) # Skip this test for Windows, echo $! gives shell pid instead of parent process AT_SKIP_IF([test "$IS_WIN32" = "yes"]) - AT_CAPTURE_FILE([pid]) - AT_CAPTURE_FILE([parent]) - AT_CAPTURE_FILE([parentpid]) - AT_CAPTURE_FILE([newpid]) + + on_exit 'kill $(cat *.pid)' + pidfile=test-daemon.py.pid + # Start the daemon and wait for the pidfile to get created. - AT_CHECK([$3 $srcdir/test-daemon.py --pidfile=pid --monitor& echo $! > parent], [0]) - on_exit 'kill `cat parent`' - OVS_WAIT_UNTIL([test -s pid]) + AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --monitor & echo $!], [0], [stdout]) + monitor=$(cat stdout) + OVS_WAIT_UNTIL([test -s $pidfile]) + child=$(cat $pidfile) + # Check that the pidfile names a running process, # and that the parent process of that process is our child process. - AT_CHECK([kill -0 `cat pid`]) - AT_CHECK([parent_pid `cat pid` > parentpid]) - AT_CHECK( - [parentpid=`cat parentpid` && - parent=`cat parent` && - test $parentpid = $parent]) + check_ancestors $child $monitor + # HUP the daemon process causing it to throw an exception, # and wait for a new child process to get spawned. - AT_CHECK([cp pid oldpid]) - AT_CHECK([kill -HUP `cat pid`]) - OVS_WAIT_WHILE([kill -0 `cat oldpid`]) - OVS_WAIT_UNTIL([test -s pid && test `cat pid` != `cat oldpid`]) - AT_CHECK([cp pid newpid]) + AT_CHECK([kill -HUP $child]) + OVS_WAIT_WHILE([kill -0 $child]) + OVS_WAIT_UNTIL([test -s $pidfile && test $child != $(cat $pidfile)]) + child2=$(cat $pidfile) + # Check that the pidfile names a running process, # and that the parent process of that process is our child process. - AT_CHECK([parent_pid `cat pid` > parentpid]) - AT_CHECK( - [parentpid=`cat parentpid` && - parent=`cat parent` && - test $parentpid = $parent]) + check_ancestors $child2 $monitor + # Kill the daemon process with SIGTERM, and wait for the daemon # and the monitor processes to go away and the pidfile to get deleted. - AT_CHECK([kill `cat pid`], [0], [], [ignore]) - OVS_WAIT_WHILE([kill -0 `cat parent` || kill -0 `cat newpid` || test -e pid]) + AT_CHECK([kill $child2]) + OVS_WAIT_WHILE([kill -0 $monitor || kill -0 $child2 || test -e $pidfile]) AT_CLEANUP]) DAEMON_MONITOR_RESTART_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2]) @@ -116,20 +110,25 @@ DAEMON_MONITOR_RESTART_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3]) m4_define([DAEMON_DETACH_PYN], [AT_SETUP([daemon --detach - $1]) AT_SKIP_IF([test $2 = no]) + # Skip this test for Windows, the pid file not removed if the daemon is killed AT_SKIP_IF([test "$IS_WIN32" = "yes"]) - AT_CAPTURE_FILE([pid]) + + on_exit 'kill $(cat *.pid)' + pidfile=test-daemon.py.pid + # Start the daemon and make sure that the pidfile exists immediately. # We don't wait for the pidfile to get created because the daemon is # supposed to do so before the parent exits. - AT_CHECK([$3 $srcdir/test-daemon.py --pidfile=pid --detach], [0]) - AT_CHECK([test -s pid]) - AT_CHECK([kill -0 `cat pid`]) + AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --detach], [0]) + AT_CHECK([test -s $pidfile]) + pid=$(cat $pidfile) + check_ancestors $pid 1 + # Kill the daemon and make sure that the pidfile gets deleted. - cp pid saved-pid - kill `cat pid` - OVS_WAIT_WHILE([kill -0 `cat saved-pid`]) - AT_CHECK([test ! -e pid]) + AT_CHECK([kill $pid]) + OVS_WAIT_WHILE([kill -0 $pid]) + AT_CHECK([test ! -e $pidfile]) AT_CLEANUP]) DAEMON_DETACH_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2]) @@ -138,49 +137,42 @@ DAEMON_DETACH_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3]) m4_define([DAEMON_DETACH_MONITOR_PYN], [AT_SETUP([daemon --detach --monitor - $1]) AT_SKIP_IF([test $2 = no]) + # Skip this test for Windows, uses Linux specific kill signal AT_SKIP_IF([test "$IS_WIN32" = "yes"]) - AT_CAPTURE_FILE([daemon]) - AT_CAPTURE_FILE([olddaemon]) - AT_CAPTURE_FILE([newdaemon]) - AT_CAPTURE_FILE([monitor]) - AT_CAPTURE_FILE([newmonitor]) - AT_CAPTURE_FILE([init]) + + on_exit 'kill $(cat *.pid)' + pidfile=test-daemon.py.pid + # Start the daemon and make sure that the pidfile exists immediately. # We don't wait for the pidfile to get created because the daemon is # supposed to do so before the parent exits. - AT_CHECK([$3 $srcdir/test-daemon.py --pidfile=daemon --detach --monitor], [0]) - on_exit 'kill `cat daemon olddaemon newdaemon monitor`' - AT_CHECK([test -s daemon]) + AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --detach --monitor], [0]) + AT_CHECK([test -s $pidfile]) + child=$(cat $pidfile) + AT_CHECK([parent_pid $child], [0], [stdout]) + monitor=$(cat stdout) + # Check that the pidfile names a running process, # and that the parent process of that process is a running process, # and that the parent process of that process is init. - AT_CHECK([kill -0 `cat daemon`]) - AT_CHECK([parent_pid `cat daemon` > monitor]) - AT_CHECK([kill -0 `cat monitor`]) - AT_CHECK([parent_pid `cat monitor` > init]) - AT_CHECK([test `cat init` != $$]) + check_ancestors $child $monitor 1 + # Kill the daemon process, making it look like a segfault, # and wait for a new daemon process to get spawned. - AT_CHECK([cp daemon olddaemon]) - AT_CHECK([kill -SEGV `cat daemon`], [0], [ignore], [ignore]) - OVS_WAIT_WHILE([kill -0 `cat olddaemon`]) - OVS_WAIT_UNTIL([test -s daemon && test `cat daemon` != `cat olddaemon`]) - AT_CHECK([cp daemon newdaemon]) + AT_CHECK([kill -SEGV $child]) + OVS_WAIT_WHILE([kill -0 $child]) + OVS_WAIT_UNTIL([test -s $pidfile && test $(cat $pidfile) != $child]) + child2=$(cat $pidfile) + # Check that the pidfile names a running process, # and that the parent process of that process is our child process. - AT_CHECK([kill -0 `cat daemon`]) - AT_CHECK([diff olddaemon newdaemon], [1], [ignore]) - AT_CHECK([parent_pid `cat daemon` > newmonitor]) - AT_CHECK([diff monitor newmonitor]) - AT_CHECK([kill -0 `cat newmonitor`]) - AT_CHECK([parent_pid `cat newmonitor` > init]) - AT_CHECK([test `cat init` != $$]) + check_ancestors $child2 $monitor 1 + # Kill the daemon process with SIGTERM, and wait for the daemon # and the monitor processes to go away and the pidfile to get deleted. - AT_CHECK([kill `cat daemon`], [0], [], [ignore]) - OVS_WAIT_WHILE( - [kill -0 `cat monitor` || kill -0 `cat newdaemon` || test -e daemon]) + AT_CHECK([kill $child2]) + OVS_WAIT_WHILE([kill -0 $child2 || kill -0 $monitor || test -e $pidfile]) AT_CLEANUP]) DAEMON_DETACH_MONITOR_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2]) @@ -189,11 +181,10 @@ DAEMON_DETACH_MONITOR_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3]) m4_define([DAEMON_DETACH_ERRORS_PYN], [AT_SETUP([daemon --detach startup errors - $1]) AT_SKIP_IF([test $2 = no]) - AT_CAPTURE_FILE([pid]) - AT_CHECK([$3 $srcdir/test-daemon.py --pidfile=pid --detach --bail], [1], [], [stderr]) + AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --detach --bail], [1], [], [stderr]) AT_CHECK([grep 'test-daemon.py: exiting after daemonize_start() as requested' stderr], - [0], [ignore], []) - AT_CHECK([test ! -s pid]) + [0], [ignore]) + AT_CHECK([test ! -s test-daemon.py.pid]) AT_CLEANUP]) DAEMON_DETACH_ERRORS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2]) @@ -203,10 +194,10 @@ m4_define([DAEMON_DETACH_MONITOR_ERRORS_PYN], [AT_SETUP([daemon --detach --monitor startup errors - $1]) AT_SKIP_IF([test $2 = no]) AT_CAPTURE_FILE([pid]) - AT_CHECK([$3 $srcdir/test-daemon.py --pidfile=pid --detach --monitor --bail], [1], [], [stderr]) + AT_CHECK([$3 $srcdir/test-daemon.py --pidfile --detach --monitor --bail], [1], [], [stderr]) AT_CHECK([grep 'test-daemon.py: exiting after daemonize_start() as requested' stderr], - [0], [ignore], []) - AT_CHECK([test ! -s pid]) + [0], [ignore]) + AT_CHECK([test ! -s test-daemon.py.pid]) AT_CLEANUP]) DAEMON_DETACH_MONITOR_ERRORS_PYN([Python2], [$HAVE_PYTHON2], [$PYTHON2]) @@ -215,13 +206,12 @@ DAEMON_DETACH_MONITOR_ERRORS_PYN([Python3], [$HAVE_PYTHON3], [$PYTHON3]) m4_define([DAEMON_DETACH_CLOSES_FDS_PYN], [AT_SETUP([daemon --detach closes standard fds - $1]) AT_SKIP_IF([test $2 = no]) + # Skip this test for Windows, uses Linux specific kill signal AT_SKIP_IF([test "$IS_WIN32" = "yes"]) - AT_CAPTURE_FILE([pid]) - AT_CAPTURE_FILE([status]) - AT_CAPTURE_FILE([stderr]) - AT_CHECK([(yes 2>stderr; echo $? > status) | $3 $srcdir/test-daemon.py --pidfile=pid --detach]) - AT_CHECK([kill `cat pid`]) + + AT_CHECK([(yes 2>stderr; echo $? > status) | $3 $srcdir/test-daemon.py --pidfile --detach]) + AT_CHECK([kill $(cat test-daemon.py.pid)]) AT_CHECK([test -s status]) if grep '[[bB]]roken pipe' stderr >/dev/null 2>&1; then # Something in the environment caused SIGPIPE to be ignored, but @@ -243,12 +233,8 @@ m4_define([DAEMON_DETACH_MONITOR_CLOSES_FDS_PYN], AT_SKIP_IF([test $2 = no]) # Skip this test for Windows, uses Linux specific kill signal AT_SKIP_IF([test "$IS_WIN32" = "yes"]) - AT_CAPTURE_FILE([pid]) - AT_CAPTURE_FILE([status]) - AT_CAPTURE_FILE([stderr]) - OVSDB_INIT([db]) - AT_CHECK([(yes 2>stderr; echo $? > status) | $3 $srcdir/test-daemon.py --pidfile=pid --detach], [0], [], []) - AT_CHECK([kill `cat pid`]) + AT_CHECK([(yes 2>stderr; echo $? > status) | $3 $srcdir/test-daemon.py --pidfile --detach], [0], [], []) + AT_CHECK([kill $(cat test-daemon.py.pid)]) AT_CHECK([test -s status]) if grep '[[bB]]roken pipe' stderr >/dev/null 2>&1; then # Something in the environment caused SIGPIPE to be ignored, but diff --git a/tests/daemon.at b/tests/daemon.at index b379fa83f9aa..3d9af9c5d823 100644 --- a/tests/daemon.at +++ b/tests/daemon.at @@ -1,5 +1,48 @@ AT_BANNER([daemon unit tests - C]) +OVS_START_SHELL_HELPERS +# check_process_name PID NAME +# +# On Linux, make sure that the name of process PID is NAME. +# (On other systems, don't bother.) +if test -e /proc/$$/comm; then + check_process_name() { + AT_CHECK_UNQUOTED([cat /proc/$1/comm], [0], [$2 +]) + } +else + check_process_name() { + : + } +fi + +# check_ancestors PID PARENT [GRANDPARENT...] +check_ancestors() { + echo "checking ancestry: $*" + local child=$1; shift + AT_CHECK([kill -0 $child]) + while test $# != 0; do + local parent=$1; shift + AT_CHECK([parent_pid $child], [0], [stdout]) + actual_parent=$(cat stdout) + if test $parent = 1; then + # Traditionally, if a parent's process exits, the process's new + # parent is pid 1 (init) but this is not always the case these + # days. Instead, if the parent process should be pid 1, be + # satisfied if the parent process is different from our own pid. + if test $actual_parent = $$; then + echo "parent of pid $child is this shell ($$) but should not be" + AT_FAIL_IF([:]) + fi + elif test $parent != $actual_parent; then + echo "parent of pid $child is $actual_parent but should be $parent" + AT_FAIL_IF([:]) + fi + child=$parent + done +} +OVS_END_SHELL_HELPERS + AT_SETUP([daemon]) AT_SKIP_IF([test "$IS_WIN32" = "yes"]) @@ -11,171 +54,154 @@ m4_define([OVS_SKIP_NON_ADMIN_WIN], AT_SKIP_IF([net session; test $? -ne 0]) ]) -OVSDB_INIT([db]) -AT_CAPTURE_FILE([pid]) -AT_CAPTURE_FILE([expected]) # Start the daemon and wait for the pidfile to get created # and that its contents are the correct pid. -AT_CHECK([ovsdb-server --pidfile --remote=punix:socket db 2>/dev/null & echo $! > expected], [0]) -on_exit 'kill `cat expected`' +on_exit 'kill $(cat *.pid)' +AT_CHECK([ovsdb-server --pidfile --no-db 2>/dev/null & echo $!], [0], [stdout]) +expected_pid=$(cat stdout) + OVS_WAIT_UNTIL([test -s ovsdb-server.pid]) -AT_CHECK([pid=`cat ovsdb-server.pid` && expected=`cat expected` && test "$pid" = "$expected"]) -AT_CHECK([kill -0 `cat ovsdb-server.pid`]) +pid=$(cat ovsdb-server.pid) + +AT_CHECK([test $pid = $expected_pid]) +AT_CHECK([kill -0 $pid]) + # Kill the daemon and make sure that the pidfile gets deleted. -kill `cat expected` -OVS_WAIT_WHILE([kill -0 `cat expected`]) +AT_CHECK([kill $pid]) +OVS_WAIT_WHILE([kill -0 $pid]) + AT_CHECK([test ! -e ovsdb-server.pid]) AT_CLEANUP AT_SETUP([daemon --monitor]) AT_SKIP_IF([test "$IS_WIN32" = "yes"]) -OVSDB_INIT([db]) -AT_CAPTURE_FILE([pid]) -AT_CAPTURE_FILE([parent]) -AT_CAPTURE_FILE([parentpid]) -AT_CAPTURE_FILE([newpid]) + # Start the daemon and wait for the pidfile to get created. -AT_CHECK([ovsdb-server --monitor --pidfile --remote=punix:socket db 2>/dev/null & echo $! > parent], [0]) -OVS_WAIT_UNTIL([test -s ovsdb-server.pid], [kill `cat parent`]) +on_exit 'kill $(cat *.pid)' +AT_CHECK([ovsdb-server --monitor --pidfile --no-db 2>/dev/null & echo $!], + [0], [stdout]) +parent=$(cat stdout) +OVS_WAIT_UNTIL([test -s ovsdb-server.pid]) + # Check that the pidfile names a running process, -# and that the parent process of that process is our child process. -AT_CHECK([kill -0 `cat ovsdb-server.pid`], [0], [], [], [kill `cat parent`]) -AT_CHECK([parent_pid `cat ovsdb-server.pid` > parentpid], - [0], [], [], [kill `cat parent`]) -AT_CHECK( - [parentpid=`cat parentpid` && - parent=`cat parent` && - test $parentpid = $parent], - [0], [], [], [kill `cat parent`]) +# and that the parent process of that process is our child process, +# and that (with a Linux kernel) the child's process name is correct. +child=$(cat ovsdb-server.pid) +check_ancestors $child $parent +check_process_name $child ovsdb-server + # Avoid a race between pidfile creation and notifying the parent, # which can easily trigger if ovsdb-server is slow (e.g. due to valgrind). -OVS_WAIT_UNTIL( - [ovs-appctl --timeout=10 -t ovsdb-server version], - [kill `cat ovsdb-server.pid`]) +OVS_WAIT_UNTIL([ovs-appctl --timeout=10 -t ovsdb-server version]) + # Kill the daemon process, making it look like a segfault, # and wait for a new child process to get spawned. -AT_CHECK([cp ovsdb-server.pid oldpid], [0], [], [], [kill `cat parent`]) -AT_CHECK([kill -SEGV `cat ovsdb-server.pid`], [0], [], [ignore], [kill `cat parent`]) -OVS_WAIT_WHILE([kill -0 `cat oldpid`], [kill `cat parent`]) -OVS_WAIT_UNTIL([test -s ovsdb-server.pid && test `cat ovsdb-server.pid` != `cat oldpid`], - [kill `cat parent`]) -AT_CHECK([cp ovsdb-server.pid newpid], [0], [], [], [kill `cat parent`]) +AT_CHECK([kill -SEGV $child], [0], [], [ignore]) +OVS_WAIT_WHILE([kill -0 $child]) +OVS_WAIT_UNTIL([test -s ovsdb-server.pid && test $(cat ovsdb-server.pid) != $child]) + # Check that the pidfile names a running process, # and that the parent process of that process is our child process. -AT_CHECK([parent_pid `cat ovsdb-server.pid` > parentpid], - [0], [], [], [kill `cat parent`]) -AT_CHECK( - [parentpid=`cat parentpid` && - parent=`cat parent` && - test $parentpid = $parent], - [0], [], [], [kill `cat parent`]) +child2=$(cat ovsdb-server.pid) +check_ancestors $child2 $parent +check_process_name $child2 ovsdb-server + # Kill the daemon process with SIGTERM, and wait for the daemon # and the monitor processes to go away and the pidfile to get deleted. -AT_CHECK([kill `cat ovsdb-server.pid`], [0], [], [ignore], [kill `cat parent`]) -OVS_WAIT_WHILE([kill -0 `cat parent` || kill -0 `cat newpid` || test -e ovsdb-server.pid], - [kill `cat parent`]) +AT_CHECK([kill $child2]) +OVS_WAIT_WHILE([kill -0 $parent || kill -0 $child2 || test -e ovsdb-server.pid]) AT_CLEANUP + AT_SETUP([daemon --detach]) -AT_CAPTURE_FILE([pid]) -OVSDB_INIT([db]) + # Start the daemon and make sure that the pidfile exists immediately. # We don't wait for the pidfile to get created because the daemon is # supposed to do so before the parent exits. -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db], [0]) +AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --no-db], [0]) AT_CHECK([test -s ovsdb-server.pid]) -AT_CHECK([kill -0 `cat ovsdb-server.pid`]) +child=$(cat ovsdb-server.pid) +AT_CHECK([kill -0 $child]) + # Kill the daemon and make sure that the pidfile gets deleted. -cp ovsdb-server.pid saved-pid if test "$IS_WIN32" = "yes"; then # When a 'kill pid' is done on windows (through 'taskkill //F'), # pidfiles are not deleted (because it is force kill), so use # 'ovs-appctl exit' instead OVS_APP_EXIT_AND_WAIT([ovsdb-server]) else - kill `cat ovsdb-server.pid` + kill $child fi -OVS_WAIT_WHILE([kill -0 `cat saved-pid`]) +OVS_WAIT_WHILE([kill -0 $child]) AT_CHECK([test ! -e ovsdb-server.pid]) + AT_CLEANUP + AT_SETUP([daemon --detach --monitor]) AT_SKIP_IF([test "$IS_WIN32" = "yes"]) -OVSDB_INIT([db]) -AT_CAPTURE_FILE([daemon]) -AT_CAPTURE_FILE([olddaemon]) -AT_CAPTURE_FILE([newdaemon]) -AT_CAPTURE_FILE([monitor]) -AT_CAPTURE_FILE([newmonitor]) -AT_CAPTURE_FILE([init]) + +on_exit 'kill $(cat *.pid)' + # Start the daemon and make sure that the pidfile exists immediately. # We don't wait for the pidfile to get created because the daemon is # supposed to do so before the parent exits. -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --monitor --remote=punix:socket db], [0]) -on_exit 'kill `cat ovsdb-server.pid olddaemon newdaemon monitor newmonitor`' +AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --monitor --no-db]) AT_CHECK([test -s ovsdb-server.pid]) -# Check that the pidfile names a running process, -# and that the parent process of that process is a running process, -# and that the parent process of that process is init. -AT_CHECK([kill -0 `cat ovsdb-server.pid`]) -AT_CHECK([parent_pid `cat ovsdb-server.pid` > monitor]) -AT_CHECK([kill -0 `cat monitor`]) -AT_CHECK([parent_pid `cat monitor` > init]) -AT_CHECK([test `cat init` != $$]) +child=$(cat ovsdb-server.pid) + +# Check process naming and ancestry. +monitor=$(parent_pid $child) +check_process_name $child ovsdb-server +check_ancestors $child $monitor 1 + # Kill the daemon process, making it look like a segfault, # and wait for a new daemon process to get spawned. -AT_CHECK([cp ovsdb-server.pid olddaemon]) -AT_CHECK([kill -SEGV `cat ovsdb-server.pid`], [0]) -OVS_WAIT_WHILE([kill -0 `cat olddaemon`]) -OVS_WAIT_UNTIL([test -s ovsdb-server.pid && test `cat ovsdb-server.pid` != `cat olddaemon`]) -AT_CHECK([cp ovsdb-server.pid newdaemon]) -# Check that the pidfile names a running process, -# and that the parent process of that process is our child process. -AT_CHECK([kill -0 `cat ovsdb-server.pid`]) -AT_CHECK([diff olddaemon newdaemon], [1], [ignore]) -AT_CHECK([parent_pid `cat ovsdb-server.pid` > newmonitor]) -AT_CHECK([diff monitor newmonitor]) -AT_CHECK([kill -0 `cat newmonitor`]) -AT_CHECK([parent_pid `cat newmonitor` > init]) -AT_CHECK([test `cat init` != $$]) +AT_CHECK([kill -SEGV $child], [0]) +OVS_WAIT_WHILE([kill -0 $child]) +OVS_WAIT_UNTIL([test -s ovsdb-server.pid && test `cat ovsdb-server.pid` != $child]) +child2=$(cat ovsdb-server.pid) + +# Check process naming and ancestry. +check_process_name $child2 ovsdb-server +check_ancestors $child2 $monitor 1 + # Kill the daemon process with SIGTERM, and wait for the daemon # and the monitor processes to go away and the pidfile to get deleted. -AT_CHECK([kill `cat ovsdb-server.pid`], [0], [], [ignore]) +AT_CHECK([kill $child2]) OVS_WAIT_WHILE( - [kill -0 `cat monitor` || kill -0 `cat newdaemon` || test -e ovsdb-server.pid]) + [kill -0 $monitor || kill -0 $child2 || test -e ovsdb-server.pid]) AT_CLEANUP + AT_SETUP([daemon --detach startup errors]) -AT_CAPTURE_FILE([pid]) -OVSDB_INIT([db]) -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --unixctl=nonexistent/unixctl db], [1], [], [stderr]) +AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --unixctl=nonexistent/unixctl --no-db], [1], [], [stderr]) AT_CHECK([grep 'could not initialize control socket' stderr], [0], [ignore]) -AT_CHECK([test ! -s pid]) +AT_CHECK([test ! -e ovsdb-server.pid]) AT_CLEANUP + AT_SETUP([daemon --detach --monitor startup errors]) AT_SKIP_IF([test "$IS_WIN32" = "yes"]) -AT_CAPTURE_FILE([pid]) -OVSDB_INIT([db]) -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --monitor --unixctl=nonexistent/unixctl db], [1], [], [stderr]) +AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --monitor --unixctl=nonexistent/unixctl --no-db], [1], [], [stderr]) AT_CHECK([grep 'could not initialize control socket' stderr], [0], [ignore]) -AT_CHECK([test ! -s pid]) +AT_CHECK([test ! -e ovsdb-server.pid]) AT_CLEANUP + AT_SETUP([daemon --service]) AT_KEYWORDS([windows-service]) AT_SKIP_IF([test "$IS_WIN32" != "yes"]) OVS_SKIP_NON_ADMIN_WIN AT_SKIP_IF([sc qc ovsdb-server]) -OVSDB_INIT([db]) AT_CAPTURE_FILE([pid]) # To create a Windows service, we need the absolute path for the executable. abs_path="$(cd $(dirname `which ovsdb-server`); pwd -W; cd $OLDPWD)" -AT_CHECK([sc create ovsdb-server binpath="$abs_path/ovsdb-server `pwd`/db --log-file=`pwd`/ovsdb-server.log --pidfile=`pwd`/ovsdb-server.pid --unixctl=`pwd`/ovsdb-server.ctl --remote=punix:`pwd`/socket --service"], +AT_CHECK([sc create ovsdb-server binpath="$abs_path/ovsdb-server --no-db --log-file=`pwd`/ovsdb-server.log --pidfile=`pwd`/ovsdb-server.pid --unixctl=`pwd`/ovsdb-server.ctl --remote=punix:`pwd`/socket --service"], [0], [[[SC]] CreateService SUCCESS ])