unit-test: Improve ovstest user interface
authorAndy Zhou <azhou@nicira.com>
Mon, 31 Mar 2014 20:38:04 +0000 (13:38 -0700)
committerAndy Zhou <azhou@nicira.com>
Thu, 3 Apr 2014 18:16:16 +0000 (11:16 -0700)
Improve help output. Running without argument now exit with an error
message and an error code. Simplify OVSTEST_REGISTER() since not all
test programs uses sub_commands.

Signed-off-by: Andy Zhou <azhou@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
tests/ovstest.c
tests/ovstest.h
tests/test-heap.c

index b8f5bfa..dbb4555 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdlib.h>
 #include "command-line.h"
 #include "ovstest.h"
+#include "dynamic-string.h"
 #include "util.h"
 
 static struct command *commands = NULL;
@@ -43,45 +44,60 @@ add_command(struct command *cmd)
     n_commands++;
 }
 
+#define OVSTEST_USAGE \
+"TEST [TESTARGS] where 'TEST' is a string, 'TESTARGS' are optional \n"\
+"arguments of the TEST"
+
+static void
+flush_help_string(struct ds *ds)
+{
+    if (ds->length > 2 ) {
+        ds->length -= 2;
+        printf ("%s\n", ds_cstr(ds));
+        ds_clear(ds);
+    }
+}
+
 static void
-list(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
     const struct command *p;
+    struct ds test_names = DS_EMPTY_INITIALIZER;
+    const int linesize = 70;
+
+    printf("%s: the big test executable\n"
+           "usage: %s TEST [TESTARGS]\n"
+           "where TEST is one of the following. \n\n",
+           program_name, program_name);
 
     for(p = commands; p->name != NULL; p++) {
-        printf("%s, %d, %d\n", p->name,p->min_args, p->max_args);
+        if (*p->name != '-') { /* Skip internal commands */
+            ds_put_format(&test_names, "%s, ", p->name);
+            if ((test_names.length) >= linesize) {
+                flush_help_string(&test_names);
+            }
+        }
     }
+    flush_help_string(&test_names);
+    ds_destroy(&test_names);
 }
 
 static void
 add_top_level_commands(void)
 {
-    struct command help_cmd = {"--help", 0, 0, list};
+    struct command help_cmd = {"--help", 0, 0, help};
 
     add_command(&help_cmd);
 }
 
 void
-ovstest_register(const char *test_name, ovstest_func f,
-                  const struct command *sub_commands)
+ovstest_register(const char *test_name, ovstest_func f)
 {
     struct command test_cmd;
-    int max_args = 0;
-
-    if (sub_commands) {
-        const struct command *p;
-
-        for(p = sub_commands; p->name != NULL; p++) {
-            if (p->max_args > max_args) {
-                max_args = p->max_args;
-            }
-        }
-    }
-    max_args++;  /* adding in the sub program */
 
     test_cmd.name = test_name;
-    test_cmd.min_args = 1;
-    test_cmd.max_args = max_args;
+    test_cmd.min_args = 0;
+    test_cmd.max_args = INT_MAX;
     test_cmd.handler = f;
 
     add_command(&test_cmd);
@@ -100,6 +116,11 @@ main(int argc, char *argv[])
 {
     set_program_name(argv[0]);
 
+    if (argc < 2) {
+        ovs_fatal(0, "expect test program to be specified; "
+                  "use --help for usage");
+    }
+
     add_top_level_commands();
     if (argc > 1) {
         run_command(argc - 1, argv + 1, commands);
index 6d10a5d..b4aad1b 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef OVSTEST_H
 #define OVSTEST_H
 
+#include "compiler.h"
+
 /* Overview
  * ========
  *
  * the number of test programs, linking will be done only once to produce
  * ovstest.
  *
- * With ovs-test, each test programs now becomes a sub program of ovstest.
+ * With ovstest, each test programs now becomes a sub program of ovstest.
  * For example, 'mytest' program, can now be invoked as 'ovs mytest'.
  *
  * 'ovstest --help' will list all test programs can be invoked.
  *
- * The Usage comment section below documents how a new test program can
- * be added to ovs-test.
+ * The 'Usage' section below documents how to add a new sub program
+ * to ovstest using OVSTEST_REIGSTER macros.
  */
 
 typedef void (*ovstest_func)(int argc, char *argv[]);
-
-void
-ovstest_register(const char *test_name, ovstest_func f,
-                  const struct command * sub_commands);
+void ovstest_register(const char *test_name, ovstest_func f);
 
 /* Usage
  * =====
  *
- * For each test sub program, its 'main' program should be named as
+ * For each sub test program, its 'main' program should be named as
  * '<test_name>_main()'.
  *
- * OVSTEST_REGISTER register the sub program with ovs-test top level
- * command line parser. <test_name> is expected as argv[1] when invoking
- * ovs-test.
+ * The 'main' programs should be registered with ovstest as a sub program.
+ *    OVSTEST_REGISTER(name, function)
+ *
+ * 'name' will be name of the test program. It is expected as argv[1] when
+ * invoking with ovstest.
  *
- * In case the test program has sub commands, its command array can be
- * passed in  as <sub_command>. Otherwise, NULL can be used instead.
+ * 'function' is the 'main' program mentioned above.
  *
  * Example:
  * ----------
@@ -69,16 +69,11 @@ ovstest_register(const char *test_name, ovstest_func f,
  *   ....
  * }
  *
- * // The last parameter is NULL in case my-test.c does
- * // not have sub commands. Otherwise, its command
- * // array can replace the NULL here.
- *
- * OVSTEST_REGISTER("my-test", my_test_main, NULL);
+ * OVSTEST_REGISTER("my-test", my_test_main);
  */
-
-#define OVSTEST_REGISTER(name, function, sub_commands) \
+#define OVSTEST_REGISTER(name, function) \
     OVS_CONSTRUCTOR(register_##function) { \
-        ovstest_register(name, function, sub_commands); \
+        ovstest_register(name, function); \
     }
 
 #endif
index 3e0940c..3a0afa5 100644 (file)
@@ -485,4 +485,4 @@ test_heap_main(int argc, char *argv[])
     run_command(argc - 1, argv + 1, commands);
 }
 
-OVSTEST_REGISTER("test-heap", test_heap_main, commands);
+OVSTEST_REGISTER("test-heap", test_heap_main);