tests: Add vlog tests for C implementation to match Python tests.
authorBen Pfaff <blp@ovn.org>
Tue, 8 Dec 2015 08:59:56 +0000 (00:59 -0800)
committerBen Pfaff <blp@ovn.org>
Wed, 3 Feb 2016 19:21:43 +0000 (11:21 -0800)
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Russell Bryant <russell@ovn.org>
tests/automake.mk
tests/test-unixctl.c [new file with mode: 0644]
tests/vlog.at

index 4109052..ef0a2f6 100644 (file)
@@ -170,6 +170,7 @@ valgrind_wrappers = \
        tests/valgrind/test-stp \
        tests/valgrind/test-type-props \
        tests/valgrind/test-unix-socket \
+       tests/valgrind/test-unixctl \
        tests/valgrind/test-uuid \
        tests/valgrind/test-vconn
 
@@ -313,6 +314,7 @@ tests_ovstest_SOURCES = \
        tests/test-sflow.c \
        tests/test-sha1.c \
        tests/test-stp.c \
+       tests/test-unixctl.c \
        tests/test-util.c \
        tests/test-uuid.c \
        tests/test-bitmap.c \
diff --git a/tests/test-unixctl.c b/tests/test-unixctl.c
new file mode 100644 (file)
index 0000000..bf35b19
--- /dev/null
@@ -0,0 +1,186 @@
+/* Copyright (c) 2015 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include <getopt.h>
+
+#include "command-line.h"
+#include "daemon.h"
+#include "fatal-signal.h"
+#include "openvswitch/vlog.h"
+#include "ovstest.h"
+#include "poll-loop.h"
+#include "unixctl.h"
+#include "util.h"
+
+VLOG_DEFINE_THIS_MODULE(test_unixctl);
+
+static void parse_options(int *argc, char **argvp[], char **unixctl_pathp);
+OVS_NO_RETURN static void usage(void);
+
+static void
+test_unixctl_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                  const char *argv[] OVS_UNUSED, void *exiting_)
+{
+    bool *exiting = exiting_;
+    *exiting = true;
+    unixctl_command_reply(conn, NULL);
+}
+
+static void
+test_unixctl_echo(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                  const char *argv[], void *aux OVS_UNUSED)
+{
+    unixctl_command_reply(conn, argv[1]);
+}
+
+static void
+test_unixctl_echo_error(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                        const char *argv[], void *aux OVS_UNUSED)
+{
+    unixctl_command_reply_error(conn, argv[1]);
+}
+
+static void
+test_unixctl_log(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                  const char *argv[], void *aux OVS_UNUSED)
+{
+    VLOG_INFO("%s", argv[1]);
+    unixctl_command_reply(conn, NULL);
+}
+
+static void
+test_unixctl_block(struct unixctl_conn *conn OVS_UNUSED, int argc OVS_UNUSED,
+                   const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
+{
+    VLOG_INFO("%s", argv[1]);
+    unixctl_command_reply(conn, NULL);
+}
+
+static int
+test_unixctl_main(int argc, char *argv[])
+{
+    char *unixctl_path = NULL;
+    struct unixctl_server *unixctl;
+    bool exiting = false;
+
+    ovs_cmdl_proctitle_init(argc, argv);
+    set_program_name(argv[0]);
+    service_start(&argc, &argv);
+    fatal_ignore_sigpipe();
+    parse_options(&argc, &argv, &unixctl_path);
+
+    daemonize_start(false);
+    int retval = unixctl_server_create(unixctl_path, &unixctl);
+    if (retval) {
+        exit(EXIT_FAILURE);
+    }
+    unixctl_command_register("exit", "", 0, 0, test_unixctl_exit, &exiting);
+    unixctl_command_register("echo", "ARG", 1, 1, test_unixctl_echo, NULL);
+    unixctl_command_register("echo_error", "ARG", 1, 1,
+                             test_unixctl_echo_error, NULL);
+    unixctl_command_register("log", "ARG", 1, 1, test_unixctl_log, NULL);
+    unixctl_command_register("block", "", 0, 0, test_unixctl_block, NULL);
+    daemonize_complete();
+
+    VLOG_INFO("Entering run loop.");
+    while (!exiting) {
+        unixctl_server_run(unixctl);
+        unixctl_server_wait(unixctl);
+        if (exiting) {
+            poll_immediate_wake();
+        }
+        poll_block();
+    }
+    unixctl_server_destroy(unixctl);
+
+    service_stop();
+    return 0;
+}
+
+static void
+parse_options(int *argcp, char **argvp[], char **unixctl_pathp)
+{
+    enum {
+        OPT_REMOTE = UCHAR_MAX + 1,
+        OPT_UNIXCTL,
+        VLOG_OPTION_ENUMS,
+        DAEMON_OPTION_ENUMS
+    };
+    static const struct option long_options[] = {
+        {"unixctl",     required_argument, NULL, OPT_UNIXCTL},
+        {"help",        no_argument, NULL, 'h'},
+        {"version",     no_argument, NULL, 'V'},
+        DAEMON_LONG_OPTIONS,
+        VLOG_LONG_OPTIONS,
+        {NULL, 0, NULL, 0},
+    };
+    char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
+    int argc = *argcp;
+    char **argv = *argvp;
+
+    for (;;) {
+        int c;
+
+        c = getopt_long(argc, argv, short_options, long_options, NULL);
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+        case OPT_UNIXCTL:
+            *unixctl_pathp = optarg;
+            break;
+
+        case 'h':
+            usage();
+
+        case 'V':
+            ovs_print_version(0, 0);
+            exit(EXIT_SUCCESS);
+
+        VLOG_OPTION_HANDLERS
+        DAEMON_OPTION_HANDLERS
+
+        case '?':
+            exit(EXIT_FAILURE);
+
+        default:
+            abort();
+        }
+    }
+    free(short_options);
+
+    *argcp -= optind;
+    *argvp += optind;
+}
+
+static void
+usage(void)
+{
+    printf("%s: Open vSwitch unixctl test program\n"
+           "usage: %s [OPTIONS]\n",
+           program_name, program_name);
+    daemon_usage();
+    vlog_usage();
+    printf("\nOther options:\n"
+           "  --unixctl=SOCKET        override default control socket name\n"
+           "  -h, --help              display this help message\n"
+           "  -V, --version           display version information\n");
+    exit(EXIT_SUCCESS);
+}
+
+OVSTEST_REGISTER("test-unixctl", test_unixctl_main);
index 7c1b445..4842c15 100644 (file)
@@ -101,6 +101,47 @@ AssertionError
 
 AT_CLEANUP
 
+m4_divert_push([PREPARE_TESTS])
+vlog_filt () {
+    sed 's/.*\(opened log file\).*/\1/
+s/.*|//' "$@"
+}
+m4_divert_pop([PREPARE_TESTS])
+
+AT_SETUP([vlog - vlog/reopen - C])
+# This test won't work as-is on Windows because Windows doesn't allow
+# files that are open to be renamed.
+AT_SKIP_IF([test "$IS_WIN32" = "yes"])
+on_exit 'kill `cat test-unixctl.pid`'
+
+AT_CAPTURE_FILE([log])
+AT_CAPTURE_FILE([log.old])
+AT_CHECK([ovstest test-unixctl --log-file=`pwd`/log --pidfile --detach],
+  [0], [], [stderr])
+AT_CHECK([vlog_filt stderr], [0],
+  [opened log file
+])
+
+AT_CHECK([APPCTL -t test-unixctl log message])
+mv log log.old
+AT_CHECK([APPCTL -t test-unixctl log message2])
+AT_CHECK([APPCTL -t test-unixctl vlog/reopen])
+AT_CHECK([APPCTL -t test-unixctl log message3])
+AT_CHECK([APPCTL -t test-unixctl exit])
+
+AT_CHECK([vlog_filt log.old], [0], [dnl
+opened log file
+Entering run loop.
+message
+message2
+closing log file
+])
+AT_CHECK([vlog_filt log], [0], [dnl
+opened log file
+message3
+])
+AT_CLEANUP
+
 AT_SETUP([vlog - vlog/reopen - Python])
 AT_SKIP_IF([test $HAVE_PYTHON = no])
 on_exit 'kill `cat test-unixctl.py.pid`'
@@ -126,6 +167,17 @@ AT_CHECK([sed 's/.*|//' log], [0], [dnl
 ])
 AT_CLEANUP
 
+AT_SETUP([vlog - vlog/reopen without log file - C])
+on_exit 'kill `cat test-unixctl.pid`'
+
+AT_CHECK([ovstest test-unixctl --pidfile --detach])
+
+AT_CHECK([APPCTL -t test-unixctl vlog/reopen], [2], [],
+  [Logging to file not configured
+ovs-appctl: test-unixctl: server returned an error
+])
+AT_CLEANUP
+
 AT_SETUP([vlog - vlog/reopen without log file - Python])
 AT_SKIP_IF([test $HAVE_PYTHON = no])
 on_exit 'kill `cat test-unixctl.py.pid`'
@@ -137,6 +189,41 @@ AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen], [0],
 ])
 AT_CLEANUP
 
+dnl This checks that if vlog/reopen can't reopen the log file,
+dnl nothing particularly bad (e.g. a crash) happens.
+AT_SETUP([vlog - vlog/reopen can't reopen log file - C])
+# Verify that /dev/full is a character device that fails writes.
+AT_SKIP_IF([test ! -c /dev/full])
+AT_SKIP_IF([echo > /dev/full])
+
+on_exit 'kill `cat test-unixctl.pid`'
+
+AT_CHECK([ovstest test-unixctl --log-file=`pwd`/log --pidfile --detach],
+  [0], [], [stderr])
+AT_CHECK([vlog_filt stderr], [0], [opened log file
+])
+
+AT_CHECK([APPCTL -t test-unixctl log message])
+mv log log.old
+ln -s /dev/full log
+AT_CHECK([APPCTL -t test-unixctl vlog/reopen])
+AT_CHECK([APPCTL -t test-unixctl log message2])
+rm log
+AT_CHECK([APPCTL -t test-unixctl vlog/reopen])
+AT_CHECK([APPCTL -t test-unixctl log message3])
+AT_CHECK([APPCTL -t test-unixctl exit])
+AT_CHECK([vlog_filt log.old], [0], [dnl
+opened log file
+Entering run loop.
+message
+closing log file
+])
+AT_CHECK([vlog_filt log], [0], [dnl
+opened log file
+message3
+])
+AT_CLEANUP
+
 dnl This checks that if vlog/reopen can't reopen the log file,
 dnl nothing particularly bad (e.g. Python throws an exception and
 dnl aborts the program) happens.
@@ -168,6 +255,50 @@ AT_CHECK([sed 's/.*|//' log], [0], [dnl
 ])
 AT_CLEANUP
 
+AT_SETUP([vlog - vlog/set and vlog/list - C])
+on_exit 'kill `cat test-unixctl.pid`'
+
+AT_CAPTURE_FILE([log])
+AT_CHECK([ovstest test-unixctl --log-file=`pwd`/log --pidfile --detach],
+  [0], [], [stderr])
+AT_CHECK([vlog_filt stderr], [0], [opened log file
+])
+
+AT_CHECK([APPCTL -t test-unixctl vlog/list | sed -n '1,2p
+/\(test_unixctl\|daemon\) /p'], [0], [dnl
+                 console    syslog    file
+                 -------    ------    ------
+daemon             OFF       INFO       INFO
+test_unixctl       OFF       INFO       INFO
+])
+
+AT_CHECK([APPCTL -t test-unixctl vlog/set daemon:syslog:err])
+AT_CHECK([APPCTL -t test-unixctl vlog/set file:dbg])
+AT_CHECK([APPCTL -t test-unixctl vlog/set nonexistent], [2], [],
+  [no destination, level, or module "nonexistent"
+ovs-appctl: test-unixctl: server returned an error
+])
+AT_CHECK([APPCTL -t test-unixctl vlog/list | sed -n '1,2p
+/\(test_unixctl\|daemon\) /p'], [0], [dnl
+                 console    syslog    file
+                 -------    ------    ------
+daemon             OFF        ERR        DBG
+test_unixctl       OFF       INFO        DBG
+])
+
+AT_CHECK([APPCTL -t test-unixctl vlog/set pattern], [2], [],
+  [missing destination
+ovs-appctl: test-unixctl: server returned an error
+])
+AT_CHECK([APPCTL -t test-unixctl vlog/set pattern:nonexistent], [2], [],
+  [unknown destination "nonexistent"
+ovs-appctl: test-unixctl: server returned an error
+])
+AT_CHECK([APPCTL -t test-unixctl vlog/set pattern:file:'I<3OVS|%m'])
+AT_CHECK([APPCTL -t test-unixctl log patterntest])
+AT_CHECK([grep -q 'I<3OVS' log])
+AT_CLEANUP
+
 AT_SETUP([vlog - vlog/set and vlog/list - Python])
 AT_SKIP_IF([test $HAVE_PYTHON = no])
 on_exit 'kill `cat test-unixctl.py.pid`'