[ovs-dev] [unixctl 2/2] unixctl: Timeout unit tests instead of hanging.

Ethan Jackson ethan at nicira.com
Wed Mar 7 01:53:08 UTC 2012


We've seen some unixctl tests hang indefinitely which makes them
difficult to debug.  ovs-appctl and appctl.py calls to timeout
instead.

Signed-off-by: Ethan Jackson <ethan at nicira.com>
---
 tests/appctl.py        |    6 +++++
 tests/test-unixctl.py  |    5 ++++
 tests/unixctl-py.at    |   66 +++++++++++++++++++++++++-----------------------
 utilities/ovs-appctl.c |    6 +++++
 4 files changed, 52 insertions(+), 31 deletions(-)

diff --git a/tests/appctl.py b/tests/appctl.py
index bc69481..4a2865e 100644
--- a/tests/appctl.py
+++ b/tests/appctl.py
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 import argparse
+import signal
 import sys
 
 import ovs.daemon
@@ -45,8 +46,13 @@ def main():
                         help="Command to run.")
     parser.add_argument("argv", metavar="ARG", nargs="*",
                         help="Arguments to the command.")
+    parser.add_argument("-T", "--timeout", metavar="SECS",
+                        help="wait at most SECS seconds for a response")
     args = parser.parse_args()
 
+    if args.timeout:
+        signal.alarm(int(args.timeout))
+
     ovs.vlog.Vlog.init()
     target = args.target
     client = connect_to_target(target)
diff --git a/tests/test-unixctl.py b/tests/test-unixctl.py
index cb9fed2..c262a95 100644
--- a/tests/test-unixctl.py
+++ b/tests/test-unixctl.py
@@ -39,6 +39,10 @@ def unixctl_echo_error(conn, argv, aux):
     conn.reply_error(str(argv))
 
 
+def unixctl_block(conn, unused_argv, unused_aux):
+    pass
+
+
 def main():
     parser = argparse.ArgumentParser(
         description="Open vSwitch unixctl test program for Python")
@@ -61,6 +65,7 @@ def main():
                                  "aux_echo")
     ovs.unixctl.command_register("echo_error", "[arg ...]", 1, 2,
                                  unixctl_echo_error, "aux_echo_error")
+    ovs.unixctl.command_register("block", "", 0, 0, unixctl_block, None)
     ovs.daemon.daemonize_complete()
 
     vlog.info("Entering run loop.")
diff --git a/tests/unixctl-py.at b/tests/unixctl-py.at
index 1d435ba..d169e71 100644
--- a/tests/unixctl-py.at
+++ b/tests/unixctl-py.at
@@ -1,13 +1,16 @@
 AT_BANNER([unixctl])
 
+m4_define([APPCTL], [[ovs-appctl --timeout 20]])
+m4_define([PYAPPCTL], [[$PYTHON $srcdir/appctl.py --timeout 20]])
+
 AT_SETUP([unixctl ovs-vswitchd exit - Python])
 AT_SKIP_IF([test $HAVE_PYTHON = no])
 OVS_VSWITCHD_START
 
-AT_CHECK([$PYTHON $srcdir/appctl.py -t ovs-vswitchd exit], [0], [])
+AT_CHECK([PYAPPCTL -t ovs-vswitchd exit], [0], [])
 OVS_WAIT_WHILE([test -s ovs-vswitchd.pid])
 
-AT_CHECK([$PYTHON $srcdir/appctl.py -t ovsdb-server exit], [0], [])
+AT_CHECK([PYAPPCTL -t ovsdb-server exit], [0], [])
 OVS_WAIT_WHILE([test -s ovsdb-server.pid])
 AT_CLEANUP
 
@@ -15,12 +18,12 @@ AT_SETUP([unixctl ovs-vswitchd help - Python])
 AT_SKIP_IF([test $HAVE_PYTHON = no])
 OVS_VSWITCHD_START
 
-AT_CHECK([ovs-appctl help], [0], [stdout])
+AT_CHECK([APPCTL help], [0], [stdout])
 AT_CHECK([head -1 stdout], [0], [dnl
 The available commands are:
 ])
 mv stdout expout
-AT_CHECK([$PYTHON $srcdir/appctl.py help], [0], [expout])
+AT_CHECK([PYAPPCTL help], [0], [expout])
 
 OVS_VSWITCHD_STOP
 AT_CLEANUP
@@ -30,40 +33,40 @@ AT_SETUP([unixctl ovs-vswitchd arguments - Python])
 AT_SKIP_IF([test $HAVE_PYTHON = no])
 OVS_VSWITCHD_START
 
-AT_CHECK([ovs-appctl bond/hash], [2], [], [stderr])
+AT_CHECK([APPCTL bond/hash], [2], [], [stderr])
 AT_CHECK([head -1 stderr], [0], [dnl
 "bond/hash" command requires at least 1 arguments
 ])
 sed 's/ovs-appctl/appctl.py/' stderr > experr
-AT_CHECK([$PYTHON $srcdir/appctl.py bond/hash], [2], [], [experr])
+AT_CHECK([PYAPPCTL bond/hash], [2], [], [experr])
 
-AT_CHECK([ovs-appctl bond/hash mac], [2], [], [stderr])
+AT_CHECK([APPCTL bond/hash mac], [2], [], [stderr])
 AT_CHECK([head -1 stderr], [0], [dnl
 invalid mac
 ])
 sed 's/ovs-appctl/appctl.py/' stderr > experr
-AT_CHECK([$PYTHON $srcdir/appctl.py bond/hash mac], [2], [], [experr])
+AT_CHECK([PYAPPCTL bond/hash mac], [2], [], [experr])
 
-AT_CHECK([ovs-appctl bond/hash mac vlan], [2], [], [stderr])
+AT_CHECK([APPCTL bond/hash mac vlan], [2], [], [stderr])
 AT_CHECK([head -1 stderr], [0], [dnl
 invalid vlan
 ])
 sed 's/ovs-appctl/appctl.py/' stderr > experr
-AT_CHECK([$PYTHON $srcdir/appctl.py bond/hash mac vlan], [2], [], [experr])
+AT_CHECK([PYAPPCTL bond/hash mac vlan], [2], [], [experr])
 
-AT_CHECK([ovs-appctl bond/hash mac vlan basis], [2], [], [stderr])
+AT_CHECK([APPCTL bond/hash mac vlan basis], [2], [], [stderr])
 AT_CHECK([head -1 stderr], [0], [dnl
 invalid vlan
 ])
 sed 's/ovs-appctl/appctl.py/' stderr > experr
-AT_CHECK([$PYTHON $srcdir/appctl.py bond/hash vlan basis], [2], [], [experr])
+AT_CHECK([PYAPPCTL bond/hash vlan basis], [2], [], [experr])
 
-AT_CHECK([ovs-appctl bond/hash mac vlan basis extra], [2], [], [stderr])
+AT_CHECK([APPCTL bond/hash mac vlan basis extra], [2], [], [stderr])
 AT_CHECK([head -1 stderr], [0], [dnl
 "bond/hash" command takes at most 3 arguments
 ])
 sed 's/ovs-appctl/appctl.py/' stderr > experr
-AT_CHECK([$PYTHON $srcdir/appctl.py bond/hash mac vlan basis extra], [2], [], [experr])
+AT_CHECK([PYAPPCTL bond/hash mac vlan basis extra], [2], [], [experr])
 
 OVS_VSWITCHD_STOP
 AT_CLEANUP
@@ -72,12 +75,12 @@ AT_SETUP([unixctl bad target - Python])
 OVS_RUNDIR=$PWD; export OVS_RUNDIR
 AT_SKIP_IF([test $HAVE_PYTHON = no])
 
-AT_CHECK([$PYTHON $srcdir/appctl.py -t bogus doit], [1], [], [stderr])
+AT_CHECK([PYAPPCTL -t bogus doit], [1], [], [stderr])
 AT_CHECK_UNQUOTED([tail -1 stderr], [0], [dnl
 appctl.py: cannot read pidfile "$PWD/bogus.pid" (No such file or directory)
 ])
 
-AT_CHECK([$PYTHON $srcdir/appctl.py -t /bogus/path.pid doit], [1], [], [stderr])
+AT_CHECK([PYAPPCTL -t /bogus/path.pid doit], [1], [], [stderr])
 AT_CHECK([tail -1 stderr], [0], [dnl
 appctl.py: cannot connect to "/bogus/path.pid" (No such file or directory)
 ])
@@ -93,9 +96,10 @@ trap 'kill `cat test-unixctl.py.pid`' 0
 AT_CAPTURE_FILE([$PWD/test-unixctl.py.log])
 AT_CHECK([$PYTHON $srcdir/test-unixctl.py --log-file --pidfile --detach])
 
-AT_CHECK([ovs-appctl -t test-unixctl.py help], [0], [stdout])
+AT_CHECK([APPCTL -t test-unixctl.py help], [0], [stdout])
 AT_CHECK([cat stdout], [0], [dnl
 The available commands are:
+  block
   echo                    [[arg ...]]
   echo_error              [[arg ...]]
   exit
@@ -103,52 +107,52 @@ The available commands are:
   version
 ])
 mv stdout expout
-AT_CHECK([$PYTHON $srcdir/appctl.py -t test-unixctl.py help], [0], [expout])
+AT_CHECK([PYAPPCTL -t test-unixctl.py help], [0], [expout])
 
 AT_CHECK([echo "test-unixctl.py (Open vSwitch) $VERSION $BUILDNR" > expout])
-AT_CHECK([ovs-appctl -t test-unixctl.py version], [0], [expout])
-AT_CHECK([$PYTHON $srcdir/appctl.py -t test-unixctl.py version], [0], [expout])
+AT_CHECK([APPCTL -t test-unixctl.py version], [0], [expout])
+AT_CHECK([PYAPPCTL -t test-unixctl.py version], [0], [expout])
 
-AT_CHECK([ovs-appctl -t test-unixctl.py echo robot ninja], [0], [stdout])
+AT_CHECK([APPCTL -t test-unixctl.py echo robot ninja], [0], [stdout])
 AT_CHECK([cat stdout], [0], [dnl
 [[u'robot', u'ninja']]
 ])
 mv stdout expout
-AT_CHECK([$PYTHON $srcdir/appctl.py -t test-unixctl.py echo robot ninja], [0], [expout])
+AT_CHECK([PYAPPCTL -t test-unixctl.py echo robot ninja], [0], [expout])
 
-AT_CHECK([ovs-appctl -t test-unixctl.py echo_error robot ninja], [2], [], [stderr])
+AT_CHECK([APPCTL -t test-unixctl.py echo_error robot ninja], [2], [], [stderr])
 AT_CHECK([cat stderr], [0], [dnl
 [[u'robot', u'ninja']]
 ovs-appctl: test-unixctl.py: server returned an error
 ])
 sed 's/ovs-appctl/appctl.py/' stderr > experr
-AT_CHECK([$PYTHON $srcdir/appctl.py -t test-unixctl.py echo_error robot ninja], [2], [], [experr])
+AT_CHECK([PYAPPCTL -t test-unixctl.py echo_error robot ninja], [2], [], [experr])
 
-AT_CHECK([ovs-appctl -t test-unixctl.py echo], [2], [], [stderr])
+AT_CHECK([APPCTL -t test-unixctl.py echo], [2], [], [stderr])
 AT_CHECK([cat stderr], [0], [dnl
 "echo" command requires at least 1 arguments
 ovs-appctl: test-unixctl.py: server returned an error
 ])
 sed 's/ovs-appctl/appctl.py/' stderr > experr
-AT_CHECK([$PYTHON $srcdir/appctl.py -t test-unixctl.py echo], [2], [], [experr])
+AT_CHECK([PYAPPCTL -t test-unixctl.py echo], [2], [], [experr])
 
-AT_CHECK([ovs-appctl -t test-unixctl.py echo robot ninja pirates], [2], [], [stderr])
+AT_CHECK([APPCTL -t test-unixctl.py echo robot ninja pirates], [2], [], [stderr])
 AT_CHECK([cat stderr], [0], [dnl
 "echo" command takes at most 2 arguments
 ovs-appctl: test-unixctl.py: server returned an error
 ])
 sed 's/ovs-appctl/appctl.py/' stderr > experr
-AT_CHECK([$PYTHON $srcdir/appctl.py -t test-unixctl.py echo robot ninja pirates], [2], [], [experr])
+AT_CHECK([PYAPPCTL -t test-unixctl.py echo robot ninja pirates], [2], [], [experr])
 
-AT_CHECK([ovs-appctl -t test-unixctl.py bogus], [2], [], [stderr])
+AT_CHECK([APPCTL -t test-unixctl.py bogus], [2], [], [stderr])
 AT_CHECK([cat stderr], [0], [dnl
 "bogus" is not a valid command
 ovs-appctl: test-unixctl.py: server returned an error
 ])
 sed 's/ovs-appctl/appctl.py/' stderr > experr
-AT_CHECK([$PYTHON $srcdir/appctl.py -t test-unixctl.py bogus], [2], [], [experr])
+AT_CHECK([PYAPPCTL -t test-unixctl.py bogus], [2], [], [experr])
 
-AT_CHECK([ovs-appctl -t test-unixctl.py exit])
+AT_CHECK([APPCTL -t test-unixctl.py exit])
 trap '' 0]
 AT_CLEANUP
 
diff --git a/utilities/ovs-appctl.c b/utilities/ovs-appctl.c
index 241b6c0..f761d5a 100644
--- a/utilities/ovs-appctl.c
+++ b/utilities/ovs-appctl.c
@@ -97,6 +97,7 @@ Common commands:\n\
       'off', 'emer', 'err', 'warn', 'info', or 'dbg' ('dbg', bydefault)\n\
   vlog/reopen        Make the program reopen its log file\n\
 Other options:\n\
+  --timeout=SECS     wait at most SECS seconds for a response\n\
   -h, --help         Print this helpful information\n\
   -V, --version      Display ovs-appctl version information\n",
            program_name, program_name);
@@ -111,6 +112,7 @@ parse_command_line(int argc, char *argv[])
         {"execute", no_argument, NULL, 'e'},
         {"help", no_argument, NULL, 'h'},
         {"version", no_argument, NULL, 'V'},
+        {"timeout", required_argument, NULL, 'T'},
         {NULL, 0, NULL, 0},
     };
     const char *target;
@@ -147,6 +149,10 @@ parse_command_line(int argc, char *argv[])
             usage();
             break;
 
+        case 'T':
+            time_alarm(atoi(optarg));
+            break;
+
         case 'V':
             ovs_print_version(0, 0);
             exit(EXIT_SUCCESS);
-- 
1.7.9.2




More information about the dev mailing list