Parcourir la source

[1324]
Rewrote command line processing interface to conform to requirements.
Rewrote gtests for new interface.
Completed changes for BIND9 coding guidelines.

John DuBois il y a 13 ans
Parent
commit
3a330862f1

+ 120 - 32
tests/tools/perfdhcp/cloptions.cc

@@ -18,8 +18,20 @@
 #include "procconf.h"
 #include "perfdhcp.h"
 #include "cloptions.h"
+#include "dkdebug.h"
 
 static void printHelp(const char* progName, const char* usage);
+static void initialize(void);
+
+static int v6 = 0;                      // DHCPv6 operation (-6)
+static int initialOnly = 0;             // Do only initial exchange (-i)
+static unsigned rate = 0;               // Request rate (-r)
+static unsigned numRequest = 0;         // Number of requests (-n)
+static double dropTime = 0.0;           // Response timeout (-d)
+static double testPeriod = 0.0;         // Test period (-p)
+static const char* server;              // Server to contact
+static const char* maxDropOpt = NULL;   // Max dropped responses (-D)
+static const char* localName = NULL;    // Local host/interface (-l)
 
 /*
  * Return value:
@@ -28,54 +40,69 @@ static void printHelp(const char* progName, const char* usage);
  * 1 if argument processing was successful and the program should continue.
  */
 int
-procArgs(int argc, const char* argv[], confdata_t* confdata,
-         const char** server) {
+procArgs(int argc, const char* argv[]) {
     char usage[] =
         "Usage:\n\
 perfdhcp [-hv] [-4|-6] [-r<rate>] [-n<num-request>] [-p<test-period>]\n\
          [-d<drop-time>] [-D<max-drop>] [-l<local-addr|interface>] [-i]\n\
          [-x<diagnostic-selector>] [server]\n";
-    int v4 = 0;
-    int v6 = 0;
-    const char* localName = NULL;
-    const char* msg;
-
-    char* maxDropOpt;
-    double dropTime;
-    double testPeriod;
+    int v4 = 0;                 /* DHCPv4 operation explicitly requested */
+    const char* msg;            /* Failure message from procOpts() */
+    int help = 0;               /* Help requested */
+    int version = 0;            /* Version requested */
+    const char* diagStr = NULL; /* Diagnostics requested (-x) */
 
-    /* Names of configuration variables, for defaults file processor */
+    /* option descriptions */
     confvar_t optConf[] = {
-        { 'h', NULL,        CF_SWITCH,    NULL,        0 },
-        { 'v', NULL,        CF_SWITCH,    NULL,        0 },
-        { '4', NULL,        CF_SWITCH,    &v4,         1 },
-        { '6', NULL,        CF_SWITCH,    &v6,         1 },
-        { 'i', NULL,        CF_SWITCH,    NULL,        1 },
-        { 'l', NULL,        CF_NE_STRING, &localName,  0 },
-        { 'r', NULL,        CF_POS_INT,   NULL,        0 },
-        { 'x', NULL,        CF_STRING,    NULL,        0 },
-        { 'd', NULL,        CF_POS_FLOAT, &dropTime,   0 },
-        { 'D', NULL,        CF_NE_STRING, &maxDropOpt, 0 },
-        { 'n', NULL,        CF_POS_INT,   NULL,        0 },
-        { 'p', NULL,        CF_POS_FLOAT, &testPeriod, 0 },
-        { '\0', NULL,       CF_ENDLIST,   NULL,        0 }
+        { 'h', NULL,        CF_SWITCH,    &help,        1 },
+        { 'v', NULL,        CF_SWITCH,    &version,     1 },
+        { '4', NULL,        CF_SWITCH,    &v4,          1 },
+        { '6', NULL,        CF_SWITCH,    &v6,          1 },
+        { 'i', NULL,        CF_SWITCH,    &initialOnly, 1 },
+        { 'l', NULL,        CF_NE_STRING, &localName,   0 },
+        { 'r', NULL,        CF_POS_INT,   &rate,        0 },
+        { 'n', NULL,        CF_POS_INT,   &numRequest,  0 },
+        { 'd', NULL,        CF_POS_FLOAT, &dropTime,    0 },
+        { 'p', NULL,        CF_POS_FLOAT, &testPeriod,  0 },
+        { 'D', NULL,        CF_NE_STRING, &maxDropOpt,  0 },
+        { 'x', NULL,        CF_STRING,    &diagStr,     0 },
+        { '\0', NULL,       CF_ENDLIST,   NULL,         0 }
+    };
+
+    /* diagnostic map */
+    const struct dkdesc diagLetters[] = {
+        { 's', DK_SOCK },
+        { 'm', DK_MSG },
+        { 'p', DK_PACKET },
+        { 'a', DK_ALL },
+        { '\0', 0 }
     };
 
-    /* Process command line options and config file */
-    msg = procOpts(&argc, &argv, optConf, confdata, progName, NULL);
+    initialize();
+    /* Process command line options */
+    msg = procOpts(&argc, &argv, optConf, NULL, progName, NULL);
     if (msg != NULL) {
         fprintf(stderr, "%s: %s\n", progName, msg);
         return(2);
     }
 
-    if (confdata->map['h']->num > 0) {
+    if (help) {
         printHelp(progName, usage);
         return(0);
     }
-    if (confdata->map['v']->num > 0) {
+    if (version) {
         printf("dhcpperf v1.0 2011-10-30\n");
         return(0);
     }
+    if (diagStr != NULL) {
+        char c;
+        if ((c = dk_setup(diagStr, diagLetters)) != '\0') {
+            fprintf(stderr,
+                    "%s: Invalid selector character given with -x: '%c'\n",
+                    progName, c);
+            return(2);
+        }
+    }
 
     if (v4 && v6) {
         fprintf(stderr, "%s: Must not give -4 and -6 together.\n", progName);
@@ -84,7 +111,7 @@ perfdhcp [-hv] [-4|-6] [-r<rate>] [-n<num-request>] [-p<test-period>]\n\
     switch (argc) {
     case 0:
         if (v6 && localName != NULL) {
-            *server = "all";
+            server = "all";
         } else {
             if (v6) {
                 fprintf(stderr,
@@ -99,7 +126,7 @@ perfdhcp [-hv] [-4|-6] [-r<rate>] [-n<num-request>] [-p<test-period>]\n\
         }
         break;
     case 1:
-        *server = argv[0];
+        server = argv[0];
         break;
     default:
         fprintf(stderr, "%s: Too many arguments.\n\%s\n", progName, usage);
@@ -108,6 +135,22 @@ perfdhcp [-hv] [-4|-6] [-r<rate>] [-n<num-request>] [-p<test-period>]\n\
     return(1);
 }
 
+/*
+ * Initialize values set by procArgs().
+ * Initialized though they are static to allow for repeated calls for testing.
+ */
+static void
+initialize(void) {
+    v6 = 0;
+    initialOnly = 0;
+    rate = 0;
+    numRequest = 0;
+    dropTime = 0.0;
+    testPeriod = 0.0;
+    maxDropOpt = NULL;
+    localName = NULL;
+}
+
 static void
 printHelp(const char* progName, const char* usage) {
     printf(
@@ -152,8 +195,8 @@ Options:\n\
     generated.\n\
 -v: Report the version number of this program.\n\
 -x<diagnostic-selector>: Include extended diagnostics in the output.\n\
-    <diagnostic-selector> is a string of single-keywords specifying the\n\
-    operations for which verbose output is desired.  The selector keyletters\n\
+    <diagnostic-selector> is a string of characters, each specifying an\n\
+    operation for which verbose output is desired.  The selector characters\n\
     are:\n\
     [TO BE ADDED]\n\
 \n\
@@ -185,3 +228,48 @@ The exit status is:\n\
   are not successfully completed.\n",
         progName, usage);
 }
+
+int
+getv6(void) {
+    return v6;
+}
+
+int
+getinitialOnly(void) {
+    return initialOnly;
+}
+
+unsigned
+getrate(void) {
+    return rate;
+}
+
+unsigned
+getnumRequest(void) {
+    return numRequest;
+}
+
+double
+getdropTime(void) {
+    return dropTime;
+}
+
+double
+gettestPeriod(void) {
+    return testPeriod;
+}
+
+const char *
+getserver(void) {
+    return server;
+}
+
+const char *
+getlocalName(void) {
+    return localName;
+}
+
+const char *
+getmaxDrop(void) {
+    return maxDropOpt;
+}

+ 14 - 7
tests/tools/perfdhcp/cloptions.h

@@ -26,17 +26,24 @@
  * Input varibles:
  * argc, argv: Command line data.
  *
- * Output variables:
- * confdata; Processed command line data.
- * server: The server to contact.  This will always be set, either to the given
- *     value or to "all" (see usage).
- *
  * Return value:
  * 0 if the command has been satisfied and the program should exit 0.
  * 2 for usage error, in which case an error message will have been printed.
  * 1 if argument processing was successful and the program should continue.
  */
-int procArgs(int argc, const char* argv[], confdata_t* confdata,
-             const char** server);
+int procArgs(int argc, const char* argv[]);
+
+/*
+ * These functions return values set by command line options
+ */
+int getv6(void);                // DHCPv6 operation (-6)
+int getinitialOnly(void);       // Do only initial exchange (-i)
+unsigned getrate(void);         // Request rate (-r)
+unsigned getnumRequest(void);   // Number of requests (-n)
+double getdropTime(void);       // Response timeout (-d)
+double gettestPeriod(void);     // Test period (-p)
+const char* getserver(void);    // Server to contact
+const char* getlocalName(void); // Local host/interface (-l)
+const char* getmaxDrop(void);   // Max dropped responses (-D)
 
 #endif

+ 8 - 7
tests/tools/perfdhcp/dkdebug.cc

@@ -20,22 +20,23 @@
 
 unsigned dk_diag_mask;
 
-int
+char
 dk_setup(const char* diag_str, const struct dkdesc* diags) {
     dk_diag_mask = 0;
     int i;
 
-    for (; *diag_str != '\0'; diag_str++)
+    for (; *diag_str != '\0'; diag_str++) {
         for (i = 0; diags[i].keyletter != '\0'; i++) {
             if (diags[i].keyletter == *diag_str) {
                 dk_diag_mask |= diags[i].mask;
                 break;
             }
-            if (diags[i].keyletter == '\0') {
-                return(0);
-            }
         }
-    return(1);
+        if (diags[i].keyletter == '\0') {
+            return(*diag_str);
+        }
+    }
+    return('\0');
 }
 
 void
@@ -56,5 +57,5 @@ vdkprintf(unsigned diag_req, const char format[], va_list ap) {
 
 int
 dk_set(unsigned diag_req) {
-    return(diag_req & dk_diag_mask);
+    return((diag_req & dk_diag_mask) != 0);
 }

+ 48 - 1
tests/tools/perfdhcp/dkdebug.h

@@ -14,6 +14,13 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+/*
+ * This module implements a mask-style diagnostic printing/selection system.
+ * Each diagnostic is enabled by including an associated keyletter in a
+ * selector string given at initialization time (typically as a command-line
+ * option).
+ */
+
 #ifndef DKDEBUG_H
 #define DKDEBUG_H
 
@@ -23,16 +30,56 @@ extern "C" {
 
 #include <stdarg.h>
 
+/* Use as the mask in a dkdesc structure to enable all diagnostics */
 #define DK_ALL (~0)
 
+/*
+ * Elements of this type are used to map the available diagnostic keyletters to
+ * mask bits.
+ */
 struct dkdesc {
     char keyletter;
     unsigned mask;
 };
 
+/*
+ * Initialize diagnostic mask.
+ *
+ * Input variables:
+ *
+ * diag_str is a string giving the keyletters for diagnostics to enable.
+ *
+ * diags describes the available diagnostics, mapping each keyletter to any
+ * number of mask bits.  It should be terminated with an element with keyletter
+ * set to the null character.
+ *
+ * Return value:
+ * If an invalid character is given in diag_str, that character; otherwise a
+ * null character.
+ */
+char dk_setup(const char* diag_str, const struct dkdesc* diags);
+
+/*
+ * The remaining functions test the mask bitset diag_req against the currently
+ * enabled diagnostics, as set by dk_setup().  If any bits set in diag_req are
+ * among the enabled diagnostics, the diagnostic operation is enabled.
+ */
+
+/*
+ * If diagnostic operation is enabled, use the remaining arguments to print
+ * like fprintf(stderr, )
+ */
 void dkprintf(unsigned diag_req, const char format[], ...);
+
+/*
+ * If diagnostic operation is enabled, use the remaining arguments to print
+ * like vfprintf(stderr, )
+ */
 void vdkprintf(unsigned diag_req, const char format[], va_list ap);
-int dk_setup(const char* diag_str, const struct dkdesc* diags);
+
+/*
+ * If diagnostic operation is enabled, return 1; else return false.
+ */
 int dk_set(unsigned diag_req);
 
 #ifdef __cplusplus

+ 4 - 0
tests/tools/perfdhcp/perfdhcp.h

@@ -21,6 +21,10 @@
 extern "C" {
 #endif
 
+#define DK_SOCK 1
+#define DK_MSG 2
+#define DK_PACKET 4
+
 const char progName[] = "dhcpperf";
 
 #ifdef __cplusplus

+ 60 - 24
tests/tools/perfdhcp/procconf.cc

@@ -106,7 +106,8 @@ opterror(const char* expected, const char* value, const confvar_t* varDesc,
  * varDesc is the description structure for this option.
  *
  * Output variables:
- * The option value is stored in the option list pointed to by first.
+ * The option data is stored in a malloced confval structure, which is appended
+ * to the option list pointed to by first.  The 'next' element is set to NULL.
  * last is used to track the last record in each option list, so option values
  * can be appended easily.
  *
@@ -136,7 +137,7 @@ addOptVal(const char* value, const confvar_t* varDesc,
         }
         data.value.charval = *value;
         if (addr != NULL) {
-            *(char*) addr = *value;
+            *(char*)addr = *value;
         }
         break;
     case CF_STRING:
@@ -147,7 +148,7 @@ addOptVal(const char* value, const confvar_t* varDesc,
         }
         data.value.string = value;
         if (addr != NULL) {
-            *(const char**) addr = value;
+            *(const char**)addr = value;
         }
         break;
     case CF_INT:
@@ -189,7 +190,7 @@ addOptVal(const char* value, const confvar_t* varDesc,
             ;
         }
         if (addr != NULL) {
-            *(int*) addr = data.value.intval;
+            *(int*)addr = data.value.intval;
         }
         break;
     case CF_FLOAT:
@@ -228,14 +229,14 @@ addOptVal(const char* value, const confvar_t* varDesc,
             ;
         }
         if (addr != NULL) {
-            *(double*) addr = data.value.floatval;
+            *(double*)addr = data.value.floatval;
         }
         break;
     case CF_SWITCH:
         data.value.switchval = varDesc->value;
         value = "1";    /* for debugging */
         if (addr != NULL) {
-            *(int*) addr = varDesc->value;
+            *(int*)addr = varDesc->value;
         }
         break;
     case CF_ENDLIST:
@@ -282,7 +283,7 @@ procCmdLineArgs(int* argc, const char** argv[], const confvar_t optConf[],
     char optstr[514];       /* List of option chars, for getopt */
     unsigned optCharToConf[256];        /* Map option char/num to confvar */
     int optchar;            /* value returned by getopt() */
-    unsigned confNum;       /* to iterate over confvars */
+    int confNum;       /* to iterate over confvars */
     int count = 0;          /* number of options processed */
 
     p = optstr;
@@ -290,7 +291,7 @@ procCmdLineArgs(int* argc, const char** argv[], const confvar_t optConf[],
     for (confNum = 0; optConf[confNum].type != CF_ENDLIST; confNum++) {
         unsigned outind = optConf[confNum].outind;
         if (outind < 256 && isprint(outind)) {
-            *(p++) = (char) outind;
+            *(p++) = (char)outind;
             switch (optConf[confNum].type) {
             case CF_SWITCH:
                 break;
@@ -304,7 +305,8 @@ procCmdLineArgs(int* argc, const char** argv[], const confvar_t optConf[],
 
     *p = '\0';
     optind = 1;
-    while ((optchar = getopt(*argc, const_cast<char**>(*argv), optstr)) != -1) {
+    while ((optchar = getopt(*argc, const_cast<char**>(*argv), optstr)) != -1)
+    {
         int ind;
         int ret;
 
@@ -341,15 +343,23 @@ procCmdLineArgs(int* argc, const char** argv[], const confvar_t optConf[],
  *    and the program exits.
  *
  * Output variables:
- * The processed option values are stored in confdata.
+ * Option values are stored at the value given by any confvar that has a
+ * non-null address. 
+ * If confdatda is not null, the processed option values are stored in
+ * confdata.
  * A pointer to the start of the values for each option is stored in
  * confdata->optVals[].values at the same offset as the option appears in
  * confdata[].
- * For any option for option characters/indexes have been used,
+ * For any option for option characters/indexes that have been used,
  * confdata->map[index] is set to the same data.
  * After processing, argc will have been adjusted to be the number of
  * non-option arguments and argv will have been adjusted to start with the
  * first non-option argument.
+ * The malloced data structures returned in confdata are:
+ *   optVals
+ *   optVals[0].values
+ *   If any option characters/indexes are used, map.  If not used, this will be
+ *     a null pointer.
  *
  * Return value:
  * On success, NULL.
@@ -366,8 +376,8 @@ procOpts(int* argc, const char** argv[], const confvar_t optConf[],
     unsigned maxOptIndex = 0;   /* The highest option index number seen */
     /* number of option instances + assignments given */
     int numOptsFound;
-    unsigned optNum;    /* to iterate through the possible options */
-    unsigned i; /* index into the global list of option value structures */
+    int optNum;    /* to iterate through the possible options */
+    int i;         /* index into the global list of option value structures */
     confval** valuePointers;    /* global list of value structures */
 
     pc_name = name;
@@ -379,6 +389,10 @@ procOpts(int* argc, const char** argv[], const confvar_t optConf[],
             maxOptIndex = outind & ~CF_NOTFLAG;
         }
     }
+    if (numConf == 0) {
+        error(INTERNAL_ERROR, "Empty confvar list");
+        return(errmsg);
+    }
     if ((first = (confval**)pc_malloc(sizeof(confval*) * numConf)) == NULL ||
             (last =
                  (confval**)pc_malloc(sizeof(confval*) * numConf)) == NULL) {
@@ -387,28 +401,36 @@ procOpts(int* argc, const char** argv[], const confvar_t optConf[],
     memset(first, '\0', sizeof(confval*) * numConf);
     memset(last, '\0', sizeof(confval*) * numConf);
 
-    if ((numOptsFound =
-                procCmdLineArgs(argc, argv, optConf, first, last)) < 0) {
+    numOptsFound = procCmdLineArgs(argc, argv, optConf, first, last);
+    free(last);
+    last = NULL;
+
+    if (numOptsFound < 0)
+    {
+        free(first);
         return(errmsg);
     }
-
-    free(last);
+    if (confdata == NULL) {
+        free(first);
+        return NULL;
+    }
 
     /*
      * All options have been read & initial processing done.
      * An array of pointers is now generated for the options.
      */
     if ((valuePointers =
-                (confval**)pc_malloc(sizeof(confval*) * numOptsFound)) == NULL ||
+            (confval**)pc_malloc(sizeof(confval*) * numOptsFound)) == NULL ||
             (confdata->optVals =
-                 (cf_option*)pc_malloc(sizeof(cf_option) * numConf)) == NULL) {
+            (cf_option*)pc_malloc(sizeof(cf_option) * numConf)) == NULL) {
         return(errmsg);
     }
-    /* If option index numbers are used, allocate a map for them */
-    if (maxOptIndex != 0) {
-        if ((confdata->map =
-                    (cf_option**)pc_malloc(sizeof(cf_option) * (maxOptIndex+1)))
-                == NULL) {
+    /* If option characters / indexes are used, allocate a map for them */
+    if (maxOptIndex == 0) {
+	confdata->map = NULL;
+    } else {
+        if ((confdata->map = (cf_option**)pc_malloc(sizeof(cf_option) *
+             (maxOptIndex+1))) == NULL) {
             return(errmsg);
         }
         memset(confdata->map, '\0', sizeof(confval*) * (maxOptIndex+1));
@@ -437,3 +459,17 @@ procOpts(int* argc, const char** argv[], const confvar_t optConf[],
     free(first);
     return(NULL);
 }
+
+/*
+ * Free the malloced data stored in confdata elements by ProcOpts()
+ */
+void
+confdataFree(confdata_t *confdata) {
+    if (confdata->map != NULL) {
+        free(confdata->map);
+        confdata->map = NULL;
+    }
+    free(confdata->optVals[0].values);
+    free(confdata->optVals);
+    confdata->optVals = NULL;
+}

+ 5 - 0
tests/tools/perfdhcp/procconf.h

@@ -120,4 +120,9 @@ procOpts(int* argc, const char** argv[], const confvar_t optConf[],
          confdata_t* confdata, const char name[],
          const char usage[]);
 
+/*
+ * Free the malloced data stored in confdata elements by ProcOpts()
+ */
+void confdataFree(confdata_t *confdata);
+
 #endif

+ 2 - 0
tests/tools/perfdhcp/tests/Makefile.am

@@ -3,6 +3,7 @@ SUBDIRS = .
 AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CXXFLAGS = $(B10_CXXFLAGS)
+AM_CXXFLAGS += -g
 
 if USE_STATIC_LINK
 AM_LDFLAGS = -static
@@ -17,6 +18,7 @@ run_unittests_SOURCES  = run_unittests.cc
 run_unittests_SOURCES += cloptions_unittest.cc
 run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/cloptions.cc
 run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/procconf.cc
+run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/dkdebug.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)

+ 63 - 81
tests/tools/perfdhcp/tests/cloptions_unittest.cc

@@ -18,13 +18,14 @@
 #include <stdarg.h>
 
 #include "../cloptions.h"
+#include "../perfdhcp.h"
+#include "../dkdebug.h"
 
 // Up to 4 arguments may be specified
 // The final argument must be NULL.  This is not counted in the 4 arguments.
-int checkOption(confdata_t* confdata, int retExpected, ...) {
+int checkOption(int retExpected, ...) {
     const char* argv[6] = { "perfdhcp" };
     int argc = 1;
-    const char* server;
     int ret;
     const char* p;
     va_list ap;
@@ -37,30 +38,23 @@ int checkOption(confdata_t* confdata, int retExpected, ...) {
     }
     va_end(ap);
     argv[argc++] = "foo";   /* server */
-    ret = procArgs(argc, argv, confdata, &server);
+    ret = procArgs(argc, argv);
     EXPECT_EQ(ret, retExpected);
     return(ret == retExpected);
 }
 
 void checkOptionInvalid(const char* optflag, const char* optval) {
-    confdata_t confdata;
-
-    checkOption(&confdata, 2, optflag, optval, NULL);
+    checkOption(2, optflag, optval, NULL);
 }
 
-int checkOptionValid(const char* optflag, const char* optval,
-                     confdata_t* confdata) {
+int checkOptionValid(const char* optflag, const char* optval) {
 
-    return(checkOption(confdata, 1, optflag, optval, NULL));
+    return(checkOption(1, optflag, optval, NULL));
 }
 
-void checkPosFloatOpt(const char* optflag) {
-    confdata_t confdata;
-
-    if (checkOptionValid(optflag, "100.0", &confdata)) {
-        EXPECT_EQ(100.0,
-                  confdata.map[(unsigned)optflag[1]]->values[0]->
-                  value.floatval);
+void checkPosFloatOpt(const char* optflag, double (*retfunc)(void)) {
+    if (checkOptionValid(optflag, "100.0")) {
+        EXPECT_EQ(100.0, (*retfunc)());
     }
     checkOptionInvalid(optflag, "0");
     checkOptionInvalid(optflag, "-1");
@@ -69,12 +63,9 @@ void checkPosFloatOpt(const char* optflag) {
     checkOptionInvalid(optflag, "x");
 }
 
-void checkPosIntOpt(const char* optflag) {
-    confdata_t confdata;
-
-    if (checkOptionValid(optflag, "100", &confdata)) {
-        EXPECT_EQ(100,
-                  confdata.map[(unsigned)optflag[1]]->values[0]->value.nnint);
+void checkPosIntOpt(const char* optflag, unsigned (*retfunc)(void)) {
+    if (checkOptionValid(optflag, "100")) {
+        EXPECT_EQ(100, (*retfunc)());
     }
     checkOptionInvalid(optflag, "0");
     checkOptionInvalid(optflag, "-1");
@@ -82,87 +73,84 @@ void checkPosIntOpt(const char* optflag) {
     checkOptionInvalid(optflag, "x");
 }
 
-void checkFlag(const char* optflag) {
-    confdata_t confdata;
-
-    if (checkOptionValid(optflag, NULL, &confdata)) {
-        EXPECT_EQ(1,
-                  confdata.map[(unsigned)optflag[1]]->values[0]->
-                  value.switchval);
+void checkFlag(const char* optflag, int (*retfunc)(void)) {
+    if (checkOptionValid(optflag, NULL)) {
+        EXPECT_EQ(1, (*retfunc)());
     }
 }
 
-void checkStrOpt(const char* optflag) {
-    confdata_t confdata;
-
-    if (checkOptionValid(optflag, "bar", &confdata)) {
-        EXPECT_EQ("bar",
-                  confdata.map[(unsigned)optflag[1]]->values[0]->value.string);
+void checkStrOpt(const char* optflag, const char *(*retfunc)(void)) {
+    if (checkOptionValid(optflag, "bar")) {
+        EXPECT_EQ("bar", (*retfunc)());
     }
 }
 
-void checkNEStrOpt(const char* optflag) {
-    confdata_t confdata;
-
-    if (checkOptionValid(optflag, "bar", &confdata)) {
-        EXPECT_EQ("bar",
-                  confdata.map[(unsigned)optflag[1]]->values[0]->value.string);
+void checkNEStrOpt(const char* optflag, const char *(*retfunc)(void)) {
+    if (checkOptionValid(optflag, "bar")) {
+        EXPECT_EQ("bar", (*retfunc)());
     }
     checkOptionInvalid(optflag, "");
 }
 
 void checkFlagHandled(const char* optflag) {
-    confdata_t confdata;
-
-    checkOption(&confdata, 0, optflag, NULL);
+    checkOption(0, optflag, NULL);
 }
 
+// Command line option tests
+
 TEST(CommandOptionsTest, numreq) {
-    checkPosIntOpt("-n");
+    checkPosIntOpt("-n", getnumRequest);
 }
 
 TEST(CommandOptionsTest, rate) {
-    checkPosIntOpt("-r");
+    checkPosIntOpt("-r", getrate);
 }
 
 TEST(CommandOptionsTest, droptime) {
-    checkPosFloatOpt("-d");
+    checkPosFloatOpt("-d", getdropTime);
 }
 
 TEST(CommandOptionsTest, period) {
-    checkPosFloatOpt("-p");
+    checkPosFloatOpt("-p", gettestPeriod);
 }
 
-TEST(CommandOptionsTest, v4) {
-    checkFlag("-4");
+TEST(CommandOptionsTest, help) {
+    checkFlagHandled("-h");
 }
 
-TEST(CommandOptionsTest, v6) {
-    checkFlag("-6");
+TEST(CommandOptionsTest, version) {
+    checkFlagHandled("-v");
 }
 
-TEST(CommandOptionsTest, initial) {
-    checkFlag("-i");
+TEST(CommandOptionsTest, v4) {
+    if (checkOptionValid("-4", NULL)) {
+        EXPECT_EQ(0, getv6());
+    }
 }
 
-TEST(CommandOptionsTest, help) {
-    checkFlagHandled("-h");
+TEST(CommandOptionsTest, v6) {
+    checkFlag("-6", getv6);
 }
 
-TEST(CommandOptionsTest, version) {
-    checkFlagHandled("-v");
+TEST(CommandOptionsTest, initial) {
+    checkFlag("-i", getinitialOnly);
 }
 
 TEST(CommandOptionsTest, localname) {
-    checkNEStrOpt("-l");
+    checkNEStrOpt("-l", getlocalName);
 }
 
 TEST(CommandOptionsTest, diagnostics) {
-    checkStrOpt("-x");
+    if (checkOptionValid("-x", "sm")) {
+        EXPECT_EQ(1, dk_set(DK_SOCK));
+        EXPECT_EQ(1, dk_set(DK_MSG));
+        EXPECT_EQ(0, dk_set(DK_PACKET));
+    }
+    checkOptionInvalid("-x", "z");
 }
 
 TEST(CommandOptionsTest, maxdrop) {
-    checkNEStrOpt("-D");
+    checkNEStrOpt("-D", getmaxDrop);
 }
 
 /*
@@ -180,33 +168,27 @@ TEST(CommandOptionsTest, v4v6) {
 }
 
 TEST(CommandOptionsTest, ilr6) {
-    confdata_t confdata;
-
-    if (checkOption(&confdata, 1, "-6i", "-leth0", "-r", "50", NULL)) {
-        EXPECT_EQ("eth0",
-                  confdata.map[(unsigned)'l']->values[0]->value.string);
-        EXPECT_EQ(50, confdata.map[(unsigned)'r']->values[0]->value.nnint);
-        EXPECT_EQ(1, confdata.map[(unsigned)'6']->values[0]-> value.switchval);
-        EXPECT_EQ(1, confdata.map[(unsigned)'i']->values[0]-> value.switchval);
+    if (checkOption(1, "-6i", "-leth0", "-r", "50", NULL)) {
+        EXPECT_EQ("eth0", getlocalName());
+        EXPECT_EQ(50, getrate());
+        EXPECT_EQ(1, getv6());
+        EXPECT_EQ(1, getinitialOnly());
     }
 }
 
 TEST(CommandOptionsTest, ind) {
-    confdata_t confdata;
-
-    if (checkOption(&confdata, 1, "-i", "-n10", "-d", "5", NULL)) {
-        EXPECT_EQ(1, confdata.map[(unsigned)'i']->values[0]-> value.switchval);
-        EXPECT_EQ(10, confdata.map[(unsigned)'n']->values[0]->value.nnint);
-        EXPECT_EQ(5, confdata.map[(unsigned)'d']->values[0]-> value.floatval);
+    if (checkOption(1, "-i", "-n10", "-d", "5", NULL)) {
+        EXPECT_EQ(1, getinitialOnly());
+        EXPECT_EQ(10, getnumRequest());
+        EXPECT_EQ(5, getdropTime());
     }
 }
 
 TEST(CommandOptionsTest, px) {
-    confdata_t confdata;
-
-    if (checkOption(&confdata, 1, "-p", "5.5", "-x", "fo", NULL)) {
-        EXPECT_EQ("fo",
-                  confdata.map[(unsigned)'x']->values[0]->value.string);
-        EXPECT_EQ(5.5, confdata.map[(unsigned)'p']->values[0]->value.floatval);
+    if (checkOption(1, "-p", "5.5", "-x", "a", NULL)) {
+        EXPECT_EQ(5.5, gettestPeriod());
+        EXPECT_EQ(1, dk_set(DK_SOCK));
+        EXPECT_EQ(1, dk_set(DK_MSG));
+        EXPECT_EQ(1, dk_set(DK_PACKET));
     }
 }