Commit 06d6be69 authored by John DuBois's avatar John DuBois

[1324]

Avoid use of externals.
Completed option processing modules, and gtests for options.
Work around GNU getopt() bug.
Bring all modules into conformity with BIND10 coding guidelines.
parent cb1c34cd
......@@ -19,7 +19,7 @@
#include "perfdhcp.h"
#include "cloptions.h"
static void printHelp(const char *progName, const char *usage);
static void printHelp(const char* progName, const char* usage);
/*
* Return value:
......@@ -28,43 +28,43 @@ 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[], confdata_t* confdata,
const char** server) {
char usage[] =
"Usage:\n\
"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;
char *maxDropOpt;
const char *localName;
const char* localName = NULL;
const char* msg;
char* maxDropOpt;
double dropTime;
double testPeriod;
const char *msg;
/* Names of configuration variables, for defaults file processor */
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_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, 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 }
};
/* Process command line options and config file */
msg = procOpts(&argc, &argv, optConf, confdata, NULL, progName, NULL);
if (msg != NULL) {
fprintf(stderr, "%s\n", msg);
fprintf(stderr, "%s: %s\n", progName, msg);
return 2;
}
......@@ -78,37 +78,37 @@ perfdhcp [-hv] [-4|-6] [-r<rate>] [-n<num-request>] [-p<test-period>]\n\
}
if (v4 && v6) {
fprintf(stderr, "Must not give -4 and -6 together.\n");
fprintf(stderr, "%s: Must not give -4 and -6 together.\n", progName);
return 2;
}
switch (argc) {
case 0:
if (v6 && localName != NULL)
*server = "all";
else {
if (v6)
fprintf(stderr, "Use -l to specify an interface name.\n\%s\n",
usage);
else
fprintf(stderr, "Must specify a DHCP server.\n\%s\n", usage);
return 2;
}
break;
if (v6 && localName != NULL) {
*server = "all";
} else {
if (v6)
fprintf(stderr, "%s: Use -l to specify an interface name.\n\%s\n",
progName, usage);
else {
fprintf(stderr, "%s: Must specify a DHCP server.\n\%s\n", progName, usage);
}
return 2;
}
break;
case 1:
*server = argv[0];
break;
*server = argv[0];
break;
default:
fprintf(stderr, "Too many arguments.\n\%s\n", usage);
return 2;
fprintf(stderr, "%s: Too many arguments.\n\%s\n", progName, usage);
return 2;
}
return 1;
}
static void
printHelp(const char *progName, const char *usage)
{
printHelp(const char* progName, const char* usage) {
printf(
"%s: Execute a performance test against a DHCP server.\n\
"%s: Execute a performance test against a DHCP server.\n\
%s\n\
The [server] argument is the name/address of the DHCP server to contact. \n\
For DHCPv4 operation, exchanges are initiated by transmitting a DHCP\n\
......@@ -180,5 +180,5 @@ The exit status is:\n\
2 if an error is found in the command line arguments.\n\
3 if there are no general failures in operation, but one or more exchanges\n\
are not successfully completed.\n",
progName, usage);
progName, usage);
}
#include <stdint.h>
#include "procconf.h"
int procArgs(int argc, const char *argv[], confdata_t *confdata,
const char **server);
int procArgs(int argc, const char* argv[], confdata_t* confdata,
const char** server);
......@@ -21,26 +21,25 @@
unsigned dk_diag_mask;
int
dk_setup(const char *diag_str, const struct dkdesc *diags)
{
dk_setup(const char* diag_str, const struct dkdesc* diags) {
dk_diag_mask = 0;
int i;
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;
}
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;
}
void
dkprintf(unsigned diag_req, const char format[], ...)
{
dkprintf(unsigned diag_req, const char format[], ...) {
va_list ap;
va_start(ap,format);
......@@ -49,14 +48,13 @@ dkprintf(unsigned diag_req, const char format[], ...)
}
void
vdkprintf(unsigned diag_req, const char format[], va_list ap)
{
if (diag_req & dk_diag_mask)
vfprintf(stderr, format, ap);
vdkprintf(unsigned diag_req, const char format[], va_list ap) {
if (diag_req & dk_diag_mask) {
vfprintf(stderr, format, ap);
}
}
int
dk_set(unsigned diag_req)
{
dk_set(unsigned diag_req) {
return diag_req & dk_diag_mask;
}
#ifdef __cplusplus
extern "C" {
#endif
#endif
#include <stdarg.h>
......@@ -13,7 +13,7 @@ struct dkdesc {
void dkprintf(unsigned diag_req, const char format[], ...);
void vdkprintf(unsigned diag_req, const char format[], va_list ap);
int dk_setup(const char *diag_str, const struct dkdesc *diags);
int dk_setup(const char* diag_str, const struct dkdesc* diags);
int dk_set(unsigned diag_req);
#ifdef __cplusplus
......
......@@ -27,7 +27,14 @@ static void printOption(int v6, unsigned optnum, size_t len, const unsigned char
static void print_dhcpv4_packet(const struct dhcp_packet *pkt, size_t len);
static void print_dhcpv6_packet(const struct dhcpv6_packet *pkt, size_t len);
typedef enum { T_UNK, T_STRING, T_PERIOD, T_IPADDR, T_MTYPE, T_STATUS } opt_type;
typedef enum {
T_UNK,
T_STRING,
T_PERIOD,
T_IPADDR,
T_MTYPE,
T_STATUS
} opt_type;
struct dhcp_option_desc {
char *name;
......
This diff is collapsed.
#ifdef __cplusplus
extern "C" {
#endif
#endif
#define FLEXIBLE_ARRAY_MEMBER 500
#define ADDR_NAME_BUFSIZE (NI_MAXHOST + 30)
......@@ -23,8 +23,8 @@ struct v6_option {
typedef char aaddr_buf[ADDR_NAME_BUFSIZE];
char *addrtoa(int addr_fam, const struct in_addr *addr, aaddr_buf buf);
void print_dhcp_packet(int v6, const void *pkt, size_t len);
char* addrtoa(int addr_fam, const struct in_addr* addr, aaddr_buf buf);
void print_dhcp_packet(int v6, const void* pkt, size_t len);
const char progName[] = "dhcpperf";
......
This diff is collapsed.
#ifndef PROCCONF_H
#define PROCCONF_H
#include <limits.h> /* for UINT_MAX */
#include <limits.h> /* for UINT_MAX */
typedef enum {
CF_CHAR,
......@@ -14,14 +14,16 @@ typedef enum {
CF_NON_NEG_FLOAT,
CF_POS_FLOAT,
CF_SWITCH,
CF_NOCONF, /* option to specify that config file should not be read */
CF_PDEBUG, /* option to turn on debugging, with positive integer value */
CF_SDEBUG, /* option to turn on debugging, without a value */
CF_ENDLIST /* End of option list */
CF_NOCONF, /* option to specify that config file should not be read */
CF_PDEBUG, /* option to turn on debugging, with positive integer value */
CF_SDEBUG, /* option to turn on debugging, without a value */
CF_ENDLIST /* End of option list */
} cf_type;
typedef enum {
CF_NONE, CF_ARGS, CF_FILE
CF_NONE,
CF_ARGS,
CF_FILE
} cf_source;
/*
......@@ -33,51 +35,51 @@ typedef enum {
/*
* Structure for passing varname/value pairs.
* This gives the variable names to search for, and allows variable names to
* This gives the variable names to search for, and allows variable names to
* mapped to characters so that the characters may be used as indexes into the
* results array.
*/
typedef struct {
unsigned outind; /* Single-character option, or option output index */
char *varname; /* Long name, for config file and long option */
cf_type type; /* Option type */
const void *addr; /* Address of variable associated with this option */
int value; /* Value to assign to switch options */
unsigned outind; /* Single-character option, or option output index */
char* varname; /* Long name, for config file and long option */
cf_type type; /* Option type */
const void* addr; /* Address of variable associated with this option */
int value; /* Value to assign to switch options */
} confvar_t;
/*
* Structure for returning assigned values.
*/
typedef struct confval_struct {
const char *strval; /* String form of value */
cf_source source; /* Where value was taken from */
unsigned index; /* Relative position of this instance */
const char* strval; /* String form of value */
cf_source source; /* Where value was taken from */
unsigned index; /* Relative position of this instance */
union {
int intval;
unsigned int nnint;
double floatval;
const char *string;
int switchval;
char charval;
int intval;
unsigned int nnint;
double floatval;
const char* string;
int switchval;
char charval;
} value;
struct confval_struct *next;
struct confval_struct* next;
} confval;
/* Information about the values assigned to a particular option */
typedef struct {
int num; /* number of instances of this option */
confvar_t *confvar; /* which option descriptor this corresponds to */
confval **values; /* Start of pointers to values for this option */
int num; /* number of instances of this option */
confvar_t* confvar; /* which option descriptor this corresponds to */
confval** values; /* Start of pointers to values for this option */
} cf_option;
typedef struct {
cf_option *optVals; /* All option values */
cf_option **map; /* Option values indexed by option-char/option-index */
cf_option* optVals; /* All option values */
cf_option** map; /* Option values indexed by option-char/option-index */
} confdata_t;
const char *
procOpts(int *argc, const char **argv[], const confvar_t optConf[],
confdata_t *confdata, const char confFile[], const char name[],
const char usage[]);
const char*
procOpts(int* argc, const char** argv[], const confvar_t optConf[],
confdata_t* confdata, const char confFile[], const char name[],
const char usage[]);
#endif
......@@ -18,126 +18,91 @@
#include "../cloptions.h"
int checkOption(const char* optflag, const char* optval,
confdata_t* confdata, int retExpected) {
const char* argv[] = { "perfdhcp", NULL, NULL, NULL };
int argc = 1;
const char* server;
int ret;
argv[argc++] = optflag;
if (optval != NULL) {
argv[argc++] = optval;
}
argv[argc++] = "foo"; /* server */
ret = procArgs(argc, argv, confdata, &server);
EXPECT_EQ(ret, retExpected);
return ret == retExpected;
}
///// \brief Check Non-Limit Options
/////
///// Checks that the options that are NOT related to the message are set to
///// their default values.
//void checkDefaultOtherValues() {
// EXPECT_STREQ("127.0.0.1", getAddress());
// EXPECT_EQ(53, getPort());
// EXPECT_EQ(500, getTimeout());
// EXPECT_STREQ("www.example.com", getQname());
//}
//
///// \brief Checks the minimum and maximum value specified for an option
/////
///// Checks the values for one of the options whose values are stored in the
///// class's options_ array.
/////
///// \param index Index of the option in the limits_ array
///// \param minval Expected minimum value
///// \param maxval Expected maximum value
//void checkValuePair(int, uint32_t, uint32_t) {
////void checkValuePair(int index, uint32_t minval = 0, uint32_t maxval = 0) {
// // Argument names commented out as they are not used, so this avoid a
// // compiler warning (which by default in BIND 10 is promoted to an
// // error).
// // maximum and minimum are not yet defined so following lines commented
// // out.
// // EXPECT_EQ(minimum(index), minval);
// // EXPECT_EQ(maximum(index), maxval);
//}
//
///// \brief Checks that all options are at default values
/////
///// Checks that all options have both their maximum and minimum set to the
///// default values.
/////
///// \param except Index not to check. (This allows options not being tested
///// to be checked to see that they are at the default value.) As all
///// index values are positive, a negative value means check
///// everything.
//void checkDefaultLimitsValues(int except = -1) {
// // Dummy use of except to avoid an error
// EXPECT_EQ(-1, except);
// // OptionInfo not yet defined!
// /*
// for (int i = 0; i < OptionInfo::SIZE; ++i) {
// if (i != except) {
// checkValuePair(i, OptionInfo::defval(i), OptionInfo::defval(i));
// }
// }
// */
//}
//
///// \brief Check valid command option
/////
///// Checks that the command line specification of one of the options taking
///// a value correctly processes the option.
/////
///// \param index Option index
///// \param optflag Option flag (in the form '--option')
///// \param optval Value to be passed to the option.
///// \param minval Expected minimum value
///// \param maxval Expected maximum value
//void checkCommandValid(int index, const char* optflag, const char* optval,
// uint32_t minval, uint32_t maxval) {
//
// // Set up the command line and parse it.
// const char* argv[] = {"badpacket", NULL, NULL};
// argv[1] = optflag;
// argv[2] = optval;
// int argc = 3;
// parse(argc, const_cast<char**>(argv));
//
// // Check the results. Everything should be at the defaults except for
// // the specified option, where the minimum and maximum should be as
// // specified.
// checkDefaultOtherValues();
// checkDefaultLimitsValues(index);
// checkValuePair(index, minval, maxval);
//}
//
/// \brief Check invalid command option
///
/// Passed a command with an invalid value, checks that the parsing indicates
/// error.
///
/// \param optflag Option flag (in the form '-c')
/// \param optval Value to be passed to the option.
void checkOptionInvalid(const char* optflag, const char* optval) {
const char* argv[] = { "perfdhcp", NULL, NULL, "foo" };
int argc = sizeof(argv) / sizeof(const char* );
confdata_t confdata;
const char *server;
argv[1] = optflag;
argv[2] = optval;
EXPECT_EQ(procArgs(argc, argv, &confdata, &server), 2);
checkOption(optflag, optval, &confdata, 2);
}
int checkOptionValid(const char* optflag, const char* optval,
confdata_t* confdata) {
return checkOption(optflag, optval, confdata, 1);
}
void checkOptionValid(const char* optflag, const char* optval,
confdata_t *confdata) {
const char* argv[] = { "perfdhcp", NULL, NULL, "foo" };
int argc = sizeof(argv) / sizeof(const char* );
const char *server;
void checkPosFloatOpt(const char* optflag) {
confdata_t confdata;
argv[1] = optflag;
argv[2] = optval;
EXPECT_EQ(procArgs(argc, argv, confdata, &server), 1);
if (checkOptionValid(optflag, "100.0", &confdata))
EXPECT_EQ(100.0,
confdata.map[(unsigned)optflag[1]]->values[0]->value.floatval);
checkOptionInvalid(optflag, "0");
checkOptionInvalid(optflag, "-1");
checkOptionInvalid(optflag, "0.0");
checkOptionInvalid(optflag, "-1.0");
checkOptionInvalid(optflag, "x");
}
void checkPosIntOpt(const char *optflag) {
void checkPosIntOpt(const char* optflag) {
confdata_t confdata;
checkOptionValid(optflag, "100", &confdata);
EXPECT_EQ(100, confdata.map[(unsigned)optflag[1]]->values[0]->value.nnint);
if (checkOptionValid(optflag, "100", &confdata))
EXPECT_EQ(100,
confdata.map[(unsigned)optflag[1]]->values[0]->value.nnint);
checkOptionInvalid(optflag, "0");
checkOptionInvalid(optflag, "-1");
checkOptionInvalid(optflag, "1.0");
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 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 checkNEStrOpt(const char* optflag) {
confdata_t confdata;
if (checkOptionValid(optflag, "bar", &confdata))
EXPECT_EQ("bar",
confdata.map[(unsigned)optflag[1]]->values[0]->value.string);
checkOptionInvalid(optflag, "");
}
void checkFlagHandled(const char* optflag) {
confdata_t confdata;
checkOption(optflag, NULL, &confdata, 0);
}
TEST(CommandOptionsTest, numreq) {
checkPosIntOpt("-n");
}
......@@ -146,166 +111,52 @@ TEST(CommandOptionsTest, rate) {
checkPosIntOpt("-r");
}
///// \brief Check one-bit field
/////
///// Explicitly for those fields in the flags word that are one bit wide,
///// perform a series of tests to check that they accept valid values and
///// reject invalid ones.
/////
///// \param index Option index
///// \param optflag Option flag (in the form '--option')
//void checkOneBitField(int index, const char* optflag) {
// checkCommandValid(index, optflag, "0", 0, 0);
// checkCommandValid(index, optflag, "1", 1, 1);
// checkCommandValid(index, optflag, "0-1", 0, 1);
// checkCommandValid(index, optflag, "1-0", 0, 1);
// checkCommandInvalid(optflag, "0-3");
// checkCommandInvalid(optflag, "4");
// checkCommandInvalid(optflag, "xyz");
//}
//
///// \brief Check four-bit field
/////
///// Explicitly for those fields in the flags word that are four bits wide,
///// perform a series of tests to check that they accept valid values and
///// reject invalid ones.
/////
///// \param index Option index
///// \param optflag Option flag (in the form '--option')
//void checkFourBitField(int index, const char* optflag) {
// checkCommandValid(index, optflag, "0", 0, 0);
// checkCommandValid(index, optflag, "15", 15, 15);
// checkCommandValid(index, optflag, "0-15", 0, 15);
// checkCommandValid(index, optflag, "15-0", 0, 15);
// checkCommandInvalid(optflag, "0-17");
// checkCommandInvalid(optflag, "24");
// checkCommandInvalid(optflag, "xyz");
//}
//
///// \brief Check sixteen-bit field
/////
///// Explicitly test the parsing of the fields that can take a 16-bit
///// value ranging from 0 to 65535.
/////
///// \param index Option index
///// \param optflag Option flag (in the form '--option')
//void checkSixteenBitField(int index, const char* optflag) {
// checkCommandValid(index, optflag, "0", 0, 0);
// checkCommandValid(index, optflag, "65535", 65535, 65535);
// checkCommandValid(index, optflag, "0-65535", 0, 65535);
// checkCommandValid(index, optflag, "65535-0", 0, 65535);
// checkCommandInvalid(optflag, "0-65536");
// checkCommandInvalid(optflag, "65537");
// checkCommandInvalid(optflag, "xyz");
//}
//
//// Check that each of the non-message options will be recognised
//
//TEST(CommandOptionsTest, address) {
//
// const char* argv[] = {"badpacket", "--address", "192.0.2.1"};
// int argc = sizeof(arg