Browse Source

[trac703] Integrated new command processing into the program

Stephen Morris 14 years ago
parent
commit
f155c3edec

+ 1 - 0
tests/tools/badpacket/Makefile.am

@@ -16,6 +16,7 @@ noinst_PROGRAMS  = badpacket
 badpacket_SOURCES  = badpacket.cc
 badpacket_SOURCES += command_options.cc command_options.h
 badpacket_SOURCES += header_flags.h
+badpacket_SOURCES += option_info.cc option_info.h
 badpacket_SOURCES += scan.cc scan.h
 badpacket_SOURCES += version.h
 

+ 44 - 51
tests/tools/badpacket/command_options.cc

@@ -24,6 +24,7 @@
 #include "log/strutil.h"
 
 #include "command_options.h"
+#include "option_info.h"
 #include "version.h"
 
 using namespace std;
@@ -108,43 +109,16 @@ CommandOptions::parse(int argc, char* const argv[]) {
                 break;
 
             case 'Q':   // --qr (query/response)
-                processOptionValue("qr", optarg, values_.qr, 0, 1);
-                break;
-
             case 'O':   // --op (operation code)
-                processOptionValue("op", optarg, values_.op, 0, 15);
-                break;
-
             case 'A':   // --aa (authoritative answer)
-                processOptionValue("aa", optarg, values_.aa, 0, 1);
-                break;
-
             case 'T':   // --tc (truncated)
-                processOptionValue("tc", optarg, values_.tc, 0, 1);
-                break;
-
             case 'D':   // --rd (recursion desired)
-                processOptionValue("rd", optarg, values_.rd, 0, 1);
-                break;
-
             case 'R':   // --ra (recursion available)
-                processOptionValue("ra", optarg, values_.ra, 0, 1);
-                break;
-
             case 'Z':   // --z (zero: reserved bit)
-                processOptionValue("z", optarg, values_.z, 0, 1);
-                break;
-
             case 'U':   // --ad (authenticated data)
-                processOptionValue("ad", optarg, values_.ad, 0, 1);
-                break;
-
             case 'C':   // --cd (checking disabled)
-                processOptionValue("cd", optarg, values_.cd, 0, 1);
-                break;
-
             case 'E':   // --rc (result code)
-                processOptionValue("rc", optarg, values_.rc, 0, 15);
+                processOptionValue(c, optarg);
                 break;
 
             default:
@@ -212,13 +186,18 @@ CommandOptions::version() {
 
 // Process single flag
 void
-CommandOptions::processOptionValue(const char* what, const char* arg,
-                                   uint32_t* where, uint32_t minval, uint32_t maxval)
-{
+CommandOptions::processOptionValue(int c, const char* value) {
+
+    // Get values for this option
+    int index = OptionInfo::getIndex(c);
+    const char* name = OptionInfo::name(index);
+    uint32_t minval = OptionInfo::minval(index);
+    uint32_t maxval = OptionInfo::maxval(index);
+
     // Split the string up into one or two tokens
-    vector<string> values = isc::strutil::tokens(string(arg), "-");
-    if ((values.size() < 1) || (values.size() > 2)) {
-        isc_throw(isc::BadValue, "value given for " << what << " is '" << arg <<
+    vector<string> tokens = isc::strutil::tokens(string(value), "-");
+    if ((tokens.size() < 1) || (tokens.size() > 2)) {
+        isc_throw(isc::BadValue, "value given for " << name << " is '" << value <<
                   "': it must be in the form 'int' or 'int1-int2'");
     }
 
@@ -226,36 +205,50 @@ CommandOptions::processOptionValue(const char* what, const char* arg,
     int i = 0;
     try {
         do {
-            where[i] = boost::lexical_cast<uint32_t>(values[i]);
+            limits_[index][i] = boost::lexical_cast<uint32_t>(tokens[i]);
             ++i;
-        } while (i < values.size());
+        } while (i < tokens.size());
     } catch (boost::bad_lexical_cast) {
-        isc_throw(isc::BadValue, "value given for " << what << " is '" << arg <<
+        isc_throw(isc::BadValue, "value given for " << name << " is '" << value <<
                   "': it must be in the form 'int' or 'int1-int2'");
     }
 
     // Set the limits in the correct order.
-    if (values.size() == 1) {
-        where[1] = where[0];
-    } else if (where[0] > where[1]) {
-        swap(where[0], where[1]);
+    if (tokens.size() == 1) {
+        limits_[index][1] = limits_[index][0];
+    } else if (limits_[index][0] > limits_[index][1]) {
+        swap(limits_[index][0], limits_[index][1]);
     }
 
-    // Coerce values into the desired range
-    if ((values.size() == 1) && ((where[0] < minval) || (where[0] > maxval))) {
-        isc_throw(isc::BadValue, "the values of " << where[0] <<
-                  " given for " << what << " is outside the range of " <<
+    // Check that tokens lie inside the allowed ranges
+    if ((tokens.size() == 1) &&
+        ((limits_[index][0] < OptionInfo::minval(index)) || (limits_[index][0] > maxval))) {
+        isc_throw(isc::BadValue, "the tokens of " << limits_[index][0] <<
+                  " given for " << name << " is outside the range of " <<
                   minval << " to " << maxval);
-    } else if (where[0] < minval) {
-        isc_throw(isc::BadValue, "the lower limit of " << where[0] <<
-                  " given for " << what << " is below the minimum permitted"
+    } else if (limits_[index][0] < minval) {
+        isc_throw(isc::BadValue, "the lower limit of " << limits_[index][0] <<
+                  " given for " << name << " is below the minimum permitted"
                   " value of " << minval);
-    } else if (where[1] > maxval) {
-        isc_throw(isc::BadValue, "the upper limit of " << where[1] <<
-                  " given for " << what << " is above the maximum permitted"
+    } else if (limits_[index][1] > maxval) {
+        isc_throw(isc::BadValue, "the upper limit of " << limits_[index][1] <<
+                  " given for " << name << " is above the maximum permitted"
                   " value of " << maxval);
     }
 }
 
+// Minimum and maximum value of the flag
+uint32_t
+CommandOptions::minimum(int index) const {
+    OptionInfo::checkIndex(index);
+    return (limits_[index][0]);
+}
+
+uint32_t
+CommandOptions::maximum(int index) const {
+    OptionInfo::checkIndex(index);
+    return (limits_[index][1]);
+}
+
 } // namespace badpacket
 } // namespace isc

+ 28 - 61
tests/tools/badpacket/command_options.h

@@ -19,6 +19,8 @@
 #include <stdint.h>
 #include <utility>
 
+#include "option_info.h"
+
 namespace isc {
 namespace badpacket {
 
@@ -34,8 +36,8 @@ namespace badpacket {
 /// - \c --option value1-value2
 ///
 /// Either way, two values are extracted the low value and the high value (in
-/// the former case, bost are the same).  The values are stored in a
-/// "FlagValues" structure, which can be returned on request.
+/// the former case, both are the same).  The values are stored in an array
+/// and can be returned on request.
 ///
 /// For simplicity, the class also takes care of the --help and --version flags,
 /// each of which will cause a message to be printed to stdout and the program
@@ -44,47 +46,6 @@ namespace badpacket {
 class CommandOptions {
 public:
 
-    /// \brief Flags Word Values
-    ///
-    /// Structure holding the values for the flag settings.  Each variable in
-    /// the structure corresponds to one of the fields in the flags word.  The
-    /// variables are two-ewlement arrays: element 0 of the array holds the low
-    /// value in the range given, and element 1 the high value.  If only a
-    /// single value is given, both elements hold the same value.
-    struct FlagValues {
-        uint32_t qr[2];         // QR bit
-        uint32_t op[2];         // OPCODE field
-        uint32_t aa[2];         // AA bit
-        uint32_t tc[2];         // TC bit
-        uint32_t rd[2];         // RD bit
-        uint32_t ra[2];         // RA bit
-        uint32_t z[2];          // Z bit (reserved bit)
-        uint32_t ad[2];         // AD bit
-        uint32_t cd[2];         // CD bit
-        uint32_t rc[2];         // RCODE field
-
-        /// \brief Default Constructor
-        ///
-        /// Sets everything to zero.
-        FlagValues() {
-            reset();
-        }
-
-        /// \brief Reset All Values to Zero
-        void reset() {
-            qr[0] = qr[1] = 0;
-            op[0] = op[1] = 0;
-            aa[0] = aa[1] = 0;
-            tc[0] = tc[1] = 0;
-            rd[0] = rd[1] = 0;
-            ra[0] = ra[1] = 0;
-            z[0] = z[1] = 0;
-            ad[0] = ad[1] = 0;
-            cd[0] = cd[1] = 0;
-            rc[0] = rc[1] = 0;
-        }
-    };
-
     /// \brief CommandOptions Constructor
     ///
     /// Set values to defaults.
@@ -92,15 +53,21 @@ public:
         reset();
     }
 
-    /// \brief Return Flags Word Values
+    /// \brief Return minimum value for option
     ///
-    /// Returns a copy of the flags word structure for use by the caller.  This
-    /// structure holds the flags field settings specified on the command line.
+    /// \param index Index of the command-line option.
     ///
-    /// \return Copy of the values specified on the command line.
-    FlagValues getFlagValues() const {
-        return values_;
-    }
+    /// \return uint32_t holding the minimum value given (or the default if
+    ///         the option was not specified on the command line).
+    uint32_t minimum(int index) const;
+
+    /// \brief Return maximum value for option
+    ///
+    /// \param index Index of the command-line option.
+    ///
+    /// \return uint32_t holding the maximum value given (or the default if
+    ///         the option was not specified on the command line).
+    uint32_t maximum(int index) const;
 
     /// \brief Return Target Address
     std::string getAddress() const {
@@ -124,11 +91,14 @@ public:
 
     /// \brief Reset To Defaults
     void reset() {
-        values_.reset();
         address_ = "127.0.0.1";
         port_ = 53;
         timeout_ = 500;
         qname_ = "www.example.com";
+
+        for (int i = 0; i < OptionInfo::SIZE; ++i) {
+            limits_[i][0] = limits_[i][1] = 0;
+            }
     }
 
     /// \brief Parse Command Line
@@ -142,10 +112,10 @@ public:
     /// \param argv Argument value array passed to main().
     void parse(int argc, char* const argv[]);
 
-    /// \brief Print Usage Information
+    /// \brief Print Usage Information And Exit Program
     void usage();
 
-    /// \brief Print Version Information
+    /// \brief Print Version Information And Exit Program
     void version();
 
     // The following are protected to aid testing
@@ -157,18 +127,15 @@ protected:
     /// placing it in the appropriate location.  On error a BadValue exception
     /// is thrown.
     ///
-    /// \param what (Long) name of the command switch being parsed
-    /// \param arg Switch argument read from the command line
-    /// \param where Two-element uint32_t array into which the data is put
-    /// \param minval Minimum allowed value
-    /// \param maxval Maximum allowed value
-    void processOptionValue(const char* what, const char* arg, uint32_t* where,
-                            uint32_t minval,  uint32_t maxval);
+    /// \param c Short form option character from the command line
+    /// \param value Value of the option read from the command line
+    void processOptionValue(int c, const char* value);
 
     // Member variables
 
 private:
-    FlagValues      values_;        ///< Values read from command line
+    uint32_t        limits_[OptionInfo::SIZE][2];
+                                    ///< Value of options (minimum and maximum)
     std::string     address_;       ///< Address to where query is sent
     uint16_t        port_;          ///< Target port
     int             timeout_;       ///< Timeout for query

+ 23 - 169
tests/tools/badpacket/header_flags.h

@@ -15,6 +15,9 @@
 #ifndef __HEADER_FLAGS_H
 #define __HEADER_FLAGS_H
 
+#include <exceptions/exceptions.h>
+#include "option_info.h"
+
 namespace isc {
 namespace badpacket {
 
@@ -26,31 +29,6 @@ namespace badpacket {
 class HeaderFlags {
 public:
 
-    // The following declaration describes the various fields in the DNS
-    // packet header.
-    enum FieldParameter {
-        QR_MASK = 0x8000,   // Maskd efining the field
-        QR_OFF  = 15,       // Offset of field in the flags word (i.e. shift
-        OP_MASK = 0x7800,   //    ... this number of bits to the left)
-        OP_OFF  = 11,
-        AA_MASK = 0x0400,
-        AA_OFF  = 10,
-        TC_MASK = 0x0200,
-        TC_OFF  = 9,
-        RD_MASK = 0x0100,
-        RD_OFF  = 8,
-        RA_MASK = 0x0080,
-        RA_OFF  = 7,
-        Z_MASK  = 0x0040,
-        Z_OFF   = 6,
-        AD_MASK = 0x0020,
-        AD_OFF  = 5,
-        CD_MASK = 0x0010,
-        CD_OFF  = 4,
-        RC_MASK = 0x000F,
-        RC_OFF  = 0
-    };
-
     /// \brief Constructor
     HeaderFlags() {
         reset();
@@ -76,169 +54,45 @@ public:
         flags_ = value;
     }
 
-    /// \brief Get QR Bit
-    uint16_t getQR() const {
-        return (getField(QR_MASK, QR_OFF));
-    }
-
-    /// \brief Set QR Bit
-    ///
-    /// \param value New value of the field, which must be 0 or 1: values
-    ///        outside that range are coerced to the nearest boundary.
-    void setQR(uint16_t value) {
-        setField(value, QR_MASK, QR_OFF);
-    }
-
-    /// \brief Get OP Value
-    uint16_t getOP() const {
-        return (getField(OP_MASK, OP_OFF));
-    }
-
-    /// \brief Set OP Value
-    ///
-    /// \param value New value of the field, which must in the range 0 to 15:
-    ///        values outside that range are coerced to the nearest boundary.
-    void setOP(uint16_t value) {
-        setField(value, OP_MASK, OP_OFF);
-    }
-
-    /// \brief Get AA Bit
-    uint16_t getAA() const {
-        return (getField(AA_MASK, AA_OFF));
-    }
-
-    /// \brief Set AA Bit
-    ///
-    /// \param value New value of the field, which must be 0 or 1: values
-    ///        outside that range are coerced to the nearest boundary.
-    void setAA(uint16_t value) {
-        setField(value, AA_MASK, AA_OFF);
-    }
-
-    /// \brief Get TC Bit
-    uint16_t getTC() const {
-        return (getField(TC_MASK, TC_OFF));
-    }
-
-    /// \brief Set TC Bit
-    ///
-    /// \param value New value of the field, which must be 0 or 1: values
-    ///        outside that range are coerced to the nearest boundary.
-    void setTC(uint16_t value) {
-        setField(value, TC_MASK, TC_OFF);
-    }
-
-    /// \brief Get RD Bit
-    uint16_t getRD() const {
-        return (getField(RD_MASK, RD_OFF));
-    }
-
-    /// \brief Set RD Bit
-    ///
-    /// \param value New value of the field, which must be 0 or 1: values
-    ///        outside that range are coerced to the nearest boundary.
-    void setRD(uint16_t value) {
-        setField(value, RD_MASK, RD_OFF);
-    }
-
-    /// \brief Get RA Bit
-    uint16_t getRA() const {
-        return (getField(RA_MASK, RA_OFF));
-    }
-
-    /// \brief Set RA Bit
-    ///
-    /// \param value New value of the field, which must be 0 or 1: values
-    ///        outside that range are coerced to the nearest boundary.
-    void setRA(uint16_t value) {
-        setField(value, RA_MASK, RA_OFF);
-    }
-
-    /// \brief Get Z Bit
-    uint16_t getZ() const {
-        return (getField(Z_MASK, Z_OFF));
-    }
-
-    /// \brief Set Z Bit
-    ///
-    /// \param value New value of the field, which must be 0 or 1: values
-    ///        outside that range are coerced to the nearest boundary.
-    void setZ(uint16_t value) {
-        setField(value, Z_MASK, Z_OFF);
-    }
-
-    /// \brief Get AD Bit
-    uint16_t getAD() const {
-        return (getField(AD_MASK, AD_OFF));
-    }
-
-    /// \brief Set AD Bit
-    ///
-    /// \param value New value of the field, which must be 0 or 1: values
-    ///        outside that range are coerced to the nearest boundary.
-    void setAD(uint16_t value) {
-        setField(value, AD_MASK, AD_OFF);
-    }
-
-    /// \brief Get CD Bit
-    uint16_t getCD() const {
-        return (getField(CD_MASK, CD_OFF));
-    }
-
-    /// \brief Set CD Bit
-    ///
-    /// \param value New value of the field, which must be 0 or 1: values
-    ///        outside that range are coerced to the nearest boundary.
-    void setCD(uint16_t value) {
-        setField(value, CD_MASK, CD_OFF);
-    }
-
-    /// \brief Get RC Value
-    uint16_t getRC() const {
-        return (getField(RC_MASK, RC_OFF));
-    }
-
-    /// \brief Set RC Value
-    ///
-    /// \param value New value of the field, which must be in the range 0 to 15:
-    ///        values outside that range are coerced to the nearest boundary.
-    void setRC(uint16_t value) {
-        setField(value, RC_MASK, RC_OFF);
-    }
-
-private:
-
     /// \brief Get Field
     ///
     /// Return the value of a bit field in the flags word.
     ///
-    /// \param mask Bit mask identifying the field.
-    /// \param offset Offset of the field in the flags word.
+    /// \param int Index of the bit field in the OptionInfo data structure
     ///
     /// \return Value of the field.
-    uint16_t getField(FieldParameter mask, FieldParameter offset) const {
-        return ((flags_ & mask) >> offset);
+    uint16_t get(int index) const {
+        OptionInfo::checkIndex(index);
+        return ((flags_ & OptionInfo::mask(index)) >> OptionInfo::offset(index));
     }
 
     /// \brief Set Field
     ///
     /// Sets the value of a bit field.
     ///
+    /// \param int Index of the bit field in the OptionInfo data structure
     /// \param value Value to set.  If the value is more than the field can
     ///        hold, it is set to the maximum.
-    /// \param mask Bit mask identifying the field.
-    /// \param offset Offset of the field in the flags word.
-    void setField(uint16_t value, FieldParameter mask, FieldParameter offset) {
+    void set(int index, uint16_t value) {
+        // Declare an OptionInfo object for brevity
+        OptionInfo o;
+
+        // Ensure in range
+        o.checkIndex(index);
 
-        // Ensure the value is within limits.
-        uint16_t maxval = mask >> offset;
-        uint16_t val = (value > maxval) ? maxval : value;
+        // Ensure the value is within limits and throw an exception if not. (This
+        // should not really be needed, as the command line parsing should have
+        // checked the limits.  But be safe.)
+        if ((value < o.minval(index)) || (value > o.maxval(index))) {
+            isc_throw(isc::BadValue, "value of index " << index << " is out of range");
+        }
 
         // Clear the field then set it with the value.
-        flags_ &= ~mask;
-        flags_ |= (val << offset);
+        flags_ &= ~o.mask(index);
+        flags_ |= (value << o.offset(index));
     }
 
+private:
     uint16_t        flags_;     ///< Variable holding field values
 };
 

+ 33 - 19
tests/tools/badpacket/option_info.cc

@@ -14,22 +14,25 @@
 
 #include "option_info.h"
 
-// Define the various options for the command switches
-
-
 namespace {
 
-    isc::badpacket::OptionInfo::Parameter option_information[] = {
-    {"qr", 0x8000, 15, 0,  1},
-    {"op", 0x7800, 11, 0, 15},
-    {"aa", 0x0400, 10, 0,  1},
-    {"tc", 0x0200,  9, 0,  1},
-    {"rd", 0x0100,  8, 0,  1},
-    {"ra", 0x0080,  7, 0,  1},
-    {"z",  0x0040,  6, 0,  1},
-    {"ad", 0x0020,  5, 0,  1},
-    {"cd", 0x0010,  4, 0,  1},
-    {"rc", 0x000F,  0, 0, 15}
+// Define the various options for the command switches.  This includes both the
+// long form and short form of the switch.  Unfortunately this means that the
+// information is duplicated here and where the long options are specified for
+// getopt_long, but this inconvenience is outweighed by the simplified command
+// processing.
+
+isc::badpacket::OptionInfo::Parameter option_information[] = {
+    {'Q', "qr", 0x8000, 15, 0,  1},
+    {'O', "op", 0x7800, 11, 0, 15},
+    {'A', "aa", 0x0400, 10, 0,  1},
+    {'T', "tc", 0x0200,  9, 0,  1},
+    {'D', "rd", 0x0100,  8, 0,  1},
+    {'R', "ra", 0x0080,  7, 0,  1},
+    {'Z', "z",  0x0040,  6, 0,  1},
+    {'U', "ad", 0x0020,  5, 0,  1},
+    {'C', "cd", 0x0010,  4, 0,  1},
+    {'E', "rc", 0x000F,  0, 0, 15}
 };
 
 }   // Anonymous namespace
@@ -37,34 +40,45 @@ namespace {
 namespace isc {
 namespace badpacket {
 
+// Locate the index of the information in the array from the short switch.
+int
+OptionInfo::getIndex(int c) {
+    for (int i = 0; i < SIZE; ++i) {
+        if (c == option_information[i].short_form) {
+            return (i);
+        }
+    }
+    isc_throw(isc::BadValue, "unknown option: " << c);
+}
+
 // Methods to return values from the array
 
 const char*
-OptionInfo::name(OptionInfo::Index i) {
+OptionInfo::name(int i) {
     checkIndex(i);
     return (option_information[i].long_form);
 }
 
 uint16_t
-OptionInfo::mask(OptionInfo::Index i) {
+OptionInfo::mask(int i) {
     checkIndex(i);
     return (option_information[i].mask);
 }
 
 int
-OptionInfo::offset(OptionInfo::Index i) {
+OptionInfo::offset(int i) {
     checkIndex(i);
     return (option_information[i].offset);
 }
 
 uint32_t
-OptionInfo::minval(OptionInfo::Index i) {
+OptionInfo::minval(int i) {
     checkIndex(i);
     return (option_information[i].minval);
 }
 
 uint32_t
-OptionInfo::maxval(OptionInfo::Index i) {
+OptionInfo::maxval(int i) {
     checkIndex(i);
     return (option_information[i].maxval);
 }

+ 57 - 12
tests/tools/badpacket/option_info.h

@@ -24,16 +24,23 @@ namespace badpacket {
 /// \brief Option Information
 ///
 /// Holds details about the options that can be specified on the command line
-/// that require values.  Some of these options correspond to fields in the
-/// DNS message header, and information about these fields is supplied.
+/// that require values and which control data put in the DNS message sent to
+/// the remote system.
+///
+/// Currently all of these options correspond to fields in the flags word of the
+/// DNS message header, so the information includes details about the position
+/// of the fields and an appropriate bit mask.
+///
+/// Note that the class does not hold values specified on the command line - it
+/// only holds information about command-line options.
 
 class OptionInfo {
 public:
 
     /// \brief Array Indexes
     ///
-    /// The data for the flags options are held in an array.  This enum
-    /// specifies the position of the data for each flags field.
+    /// The data for the flags options are held in an array.  Although an enum,
+    /// only the numeric values are used - they are indexes into arrays.
     enum Index {
         QR = 0,
         OP = 1,
@@ -53,6 +60,7 @@ public:
     /// Defines a structure that holds information associated with each of the
     /// flags field command options.
     struct Parameter {
+        const char      short_form;     // Short form of the command switch
         const char*     long_form;      // Long form of the command switch
         uint16_t        mask;           // Bit mask of the field in the flags word
         int             offset;         // Offset of field in flags word
@@ -60,26 +68,63 @@ public:
         uint32_t        maxval;         // Maximum valid value for this field
     };
 
+    /// \brief Return index for command option
+    ///
+    /// Given the short form of a switch, return the index into the options
+    /// array.
+    ///
+    /// \param c The character that is the short form of the command line option.
+    ///        An 'int' is used as the value passed will be the return vaue from
+    ///        'getopt()' (or equivalent) which is an int.
+    ///
+    /// \return A valid index value (else an exception is thrown).
+    static int getIndex(int c);
+
     /// \brief Return long form of command switch for this field
-    static const char* name(Index i);
+    ///
+    /// \param index A valid index (one of the values in the 'Index' enum).
+    ///
+    /// \return The long option name (e.q. "qr" for the Query/Response field).
+    static const char* name(int index);
 
     /// \brief Return mask associated with switch field
-    static uint16_t mask(Index i);
+    ///
+    /// \param index A valid index (one of the values in the 'Index' enum).
+    ///
+    /// \return The mask for this particular option in the DNS message flags field.
+    static uint16_t mask(int index);
 
     /// \brief Return offset associated with switch field
-    static int offset(Index i);
+    ///
+    /// \param index A valid index (one of the values in the 'Index' enum).
+    ///
+    /// \return The offset of the field corresponding to this option in the DNS
+    ///         message flags field.
+    static int offset(int index);
 
     /// \brief Return minimum allowed value of field
-    static uint32_t minval(Index i);
+    ///
+    /// \param index A valid index (one of the values in the 'Index' enum).
+    ///
+    /// \return Minimum allowed value for this option.  This is usually 0.
+    static uint32_t minval(int index);
 
     /// \brief Return maximum allowed value of field
-    static uint32_t maxval(Index i);
+    ///
+    /// \param index A valid index (one of the values in the 'Index' enum).
+    ///
+    /// \return Maximum allowed value for this option.  If the option is a bit
+    ///         in the flags field of the DNS message hearder, this will be 1.
+    static uint32_t maxval(int index);
 
-private:
     /// \brief Check Array Index
     ///
-    /// Checks the passed field index and throws an exception if out of range.
-    static void checkIndex(Index i) {
+    /// Checks the passed field index and throws an exception if it does not
+    /// correspond to one of the valid indexes in the 'Index' enum.
+    ///
+    /// \param index An index value.
+    ///
+    static void checkIndex(int i) {
         if ((i < 0) || (i >= SIZE)) {
             isc_throw(isc::OutOfRange, "option index must be in the range "
                       "0 to " << SIZE);

+ 61 - 34
tests/tools/badpacket/scan.cc

@@ -60,34 +60,61 @@ Scan::scan(const CommandOptions& options) {
     MessageRenderer renderer(*msgbuf);
     message.toWire(renderer);
 
-    // Now loop through the flags setting data.  This is quite deep nesting,
+    iterateFlagsFields(msgbuf, options);
+}
+
+// Iterate through the various settings in the flags fields
+void
+Scan::iterateFlagsFields(OutputBufferPtr& msgbuf, const CommandOptions& options) {
+
+    // Loop through the flags setting data.  This is quite deep nesting,
     // but we will continue to indent so as to make things clear (for those
     // readers lucky enough to have a wide screen).
-    CommandOptions::FlagValues values = options.getFlagValues();
     HeaderFlags flags;
-    for (uint16_t qr = values.qr[0]; qr <= values.qr[1]; ++qr) {
-        flags.setQR(qr);
-        for (uint16_t op = values.op[0]; op <= values.op[1]; ++op) {
-            flags.setOP(op);
-            for (uint16_t aa = values.aa[0]; aa <= values.aa[1]; ++aa) {
-                flags.setAA(aa);
-                for (uint16_t tc = values.tc[0]; tc <= values.tc[1]; ++tc) {
-                    flags.setTC(tc);
-                    for (uint16_t rd = values.rd[0]; rd <= values.rd[1]; ++rd) {
-                        flags.setRD(rd);
-                        for (uint16_t ra = values.ra[0]; ra <= values.ra[1]; ++ra) {
-                            flags.setRA(ra);
-                            for (uint16_t z = values.z[0]; z <= values.z[1]; ++z) {
-                                flags.setZ(z);
-                                for (uint16_t ad = values.ad[0]; ad <= values.ad[1]; ++ad) {
-                                    flags.setAD(ad);
-                                    for (uint16_t cd = values.cd[0]; cd <= values.cd[1]; ++cd) {
-                                        flags.setCD(cd);
-                                        for (uint16_t rc = values.rc[0]; rc <= values.rc[1]; ++rc) {
-                                            flags.setRC(rc);
-
-                                            // Set the flags in the message and do the I/O.
+    for (uint32_t qr =  options.minimum(OptionInfo::QR);
+                  qr <= options.maximum(OptionInfo::QR); ++qr) {
+        flags.set(OptionInfo::QR, qr);
+
+        for (uint32_t op =  options.minimum(OptionInfo::OP);
+                      op <= options.maximum(OptionInfo::OP); ++op) {
+            flags.set(OptionInfo::OP, op);
+
+            for (uint32_t aa =  options.minimum(OptionInfo::AA);
+                          aa <= options.maximum(OptionInfo::AA); ++aa) {
+                flags.set(OptionInfo::AA, aa);
+
+                for (uint32_t tc =  options.minimum(OptionInfo::TC);
+                              tc <= options.maximum(OptionInfo::TC); ++tc) {
+                    flags.set(OptionInfo::TC, tc);
+
+                    for (uint32_t rd =  options.minimum(OptionInfo::RD);
+                                  rd <= options.maximum(OptionInfo::RD); ++rd) {
+                        flags.set(OptionInfo::RD, rd);
+
+                        for (uint32_t ra =  options.minimum(OptionInfo::RA);
+                                      ra <= options.maximum(OptionInfo::RA); ++ra) {
+                            flags.set(OptionInfo::RA, ra);
+
+                            for (uint32_t z =  options.minimum(OptionInfo::Z);
+                                          z <= options.maximum(OptionInfo::Z); ++z) {
+                                flags.set(OptionInfo::Z, z);
+
+                                for (uint32_t ad =  options.minimum(OptionInfo::AD);
+                                              ad <= options.maximum(OptionInfo::AD); ++ad) {
+                                    flags.set(OptionInfo::AD, ad);
+
+                                    for (uint32_t cd =  options.minimum(OptionInfo::CD);
+                                                  cd <= options.maximum(OptionInfo::CD); ++cd) {
+                                        flags.set(OptionInfo::CD, cd);
+
+                                        for (uint32_t rc =  options.minimum(OptionInfo::RC);
+                                                      rc <= options.maximum(OptionInfo::RC); ++rc) {
+                                            flags.set(OptionInfo::RC, rc);
+
+                                            // Set the flags in the message.
                                             msgbuf->writeUint16At(flags.getValue(), 2);
+
+                                            // Do the I/O.
                                             scanOne(msgbuf, options);
                                         }
                                     }
@@ -156,16 +183,16 @@ Scan::getFields(isc::dns::OutputBufferPtr& msgbuf) {
 
     std::ostringstream os;
     os << std::hex << std::uppercase <<
-        "QR:" << flags.getQR() << " " <<
-        "OP:" << flags.getOP() << " " <<
-        "AA:" << flags.getAA() << " " <<
-        "TC:" << flags.getTC() << " " <<
-        "RD:" << flags.getRD() << " " <<
-        "RA:" << flags.getRA() << " " <<
-         "Z:" << flags.getZ()  << " " <<
-        "AD:" << flags.getAD() << " " <<
-        "CD:" << flags.getCD() << " " <<
-        "RC:" << flags.getRC();
+        "QR:" << flags.get(OptionInfo::QR) << " " <<
+        "OP:" << flags.get(OptionInfo::OP) << " " <<
+        "AA:" << flags.get(OptionInfo::AA) << " " <<
+        "TC:" << flags.get(OptionInfo::TC) << " " <<
+        "RD:" << flags.get(OptionInfo::RD) << " " <<
+        "RA:" << flags.get(OptionInfo::RA) << " " <<
+         "Z:" << flags.get(OptionInfo::Z)  << " " <<
+        "AD:" << flags.get(OptionInfo::AD) << " " <<
+        "CD:" << flags.get(OptionInfo::CD) << " " <<
+        "RC:" << flags.get(OptionInfo::RC);
     return (os.str());
 }
 

+ 13 - 0
tests/tools/badpacket/scan.h

@@ -59,6 +59,19 @@ public:
     virtual void operator()(asiolink::IOFetch::Result result);
 
 private:
+    /// \brief Set Flags Fields Options
+    ///
+    /// Iterates through all combinations of the DNS message flags fields specified
+    /// on the command line and calls scanOne for each combination.
+    ///
+    /// \param msgbuf Message that will be sent to the remote nameserver.  The
+    ///        QID given will be ignored - the value used will be determined by
+    ///        the sending code
+    /// \param options Command-line options (the important ones being address,
+    ///        port and timeout).
+    void iterateFlagsFields(isc::dns::OutputBufferPtr& msgbuf,
+                 const CommandOptions& options);
+
     /// \brief Scan One Value
     ///
     /// Performs one exchange of packets with the remote nameserver, sending

+ 234 - 280
tests/tools/badpacket/tests/command_options_unittest.cc

@@ -25,96 +25,57 @@ using namespace isc;
 using namespace isc::badpacket;
 
 
-// Test fixture class
+/// \brief Test Fixture Class
 
 class CommandOptionsTest : public virtual ::testing::Test,
                            public virtual CommandOptions
 {
 public:
-    CommandOptionsTest() {}
-};
-
-// Check that the getRange() method works
-
-TEST_F(CommandOptionsTest, processOptionValue) {
-
-    uint32_t    result[2];
-
-    // Check valid data
-    processOptionValue("dummy", "1", result, 0, 1);
-    EXPECT_EQ(1, result[0]);
-    EXPECT_EQ(1, result[1]);
-
-    processOptionValue("dummy", "0-2", result, 0, 5);
-    EXPECT_EQ(0, result[0]);
-    EXPECT_EQ(2, result[1]);
-
-    processOptionValue("dummy", "4-8", result, 0, 10);
-    EXPECT_EQ(4, result[0]);
-    EXPECT_EQ(8, result[1]);
-
-    processOptionValue("dummy", "172-103", result, 0, 200);
-    EXPECT_EQ(103, result[0]);
-    EXPECT_EQ(172, result[1]);
-
-    // Check out of range values cause a BadValue exception
-    EXPECT_THROW(processOptionValue("dummy", "1", result, 3, 4),
-                 isc::BadValue);    // Single value below range
-    EXPECT_THROW(processOptionValue("dummy", "7", result, 3, 6),
-                 isc::BadValue);    // Single value above range
-    EXPECT_THROW(processOptionValue("dummy", "2-6", result, 5, 10),
-                 isc::BadValue);    // Range overlaps valid range on low side
-    EXPECT_THROW(processOptionValue("dummy", "4-7", result, 5, 9),
-                 isc::BadValue);   // Range overlaps valid range on high side
-    EXPECT_THROW(processOptionValue("dummy", "9-1", result, 4, 8),
-                 isc::BadValue);   // Range overlaps valid range
 
-    // ... and that any invalid string does the same
-    EXPECT_THROW(processOptionValue("dummy", "", result, 0, 1),
-                 isc::BadValue);
-    EXPECT_THROW(processOptionValue("dummy", " ", result, 0, 1),
-                 isc::BadValue);
-    EXPECT_THROW(processOptionValue("dummy", "abc", result, 0, 1),
-                 isc::BadValue);
-    EXPECT_THROW(processOptionValue("dummy", "xyz-def", result, 0, 1),
-                 isc::BadValue);
-    EXPECT_THROW(processOptionValue("dummy", "0.7", result, 0, 1),
-                 isc::BadValue);
-    EXPECT_THROW(processOptionValue("dummy", "0.7-2.3", result, 0, 1),
-                 isc::BadValue);
-}
-
-
-// Checks the minimum and maximum values specified for a flag
-void
-checkValuePair(const uint32_t value[2], uint32_t minval = 0,
-               uint32_t maxval = 0)
-{
-    EXPECT_EQ(minval, value[0]);
-    EXPECT_EQ(maxval, value[1]);
-}
-
-// Checks that all flag values in the command values are zero
-void
-checkDefaultFlagValues(const CommandOptions::FlagValues& values) {
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
-}
+    /// \brief Default Constructor
+    CommandOptionsTest() {}
 
-// Checks non-flag options are set to defaults.
-void
-checkDefaultOtherValues(CommandOptions& options) {
-    EXPECT_EQ("127.0.0.1", options.getAddress());
-    EXPECT_EQ(53, options.getPort());
-    EXPECT_EQ(500, options.getTimeout());
-    EXPECT_EQ("www.example.com", options.getQname());
-}
+    /// \brief Checks the minimum and maximum () specified for an option
+    ///
+    /// Checks the () for one of the options whose values are stored in the
+    /// class's limits) array.
+    ///
+    /// \param index Index of the option in the limits_ array
+    /// \param minval Expected minimum value
+    /// \param maxval Expected maximum value
+    void checkValuePair(int index, uint32_t minval = 0, uint32_t maxval = 0)
+    {
+        EXPECT_EQ(minimum(index), minval);
+        EXPECT_EQ(maximum(index), maxval);
+    }
+
+    /// \brief Checks that all options giving flags () are zero.
+    ///
+    /// Checks that all options whose () are stored in the class's limits_
+    /// array have both their maximum and minimum () set to zero.
+    void checkDefaultLimitsValues() {
+        checkValuePair(OptionInfo::QR);
+        checkValuePair(OptionInfo::OP);
+        checkValuePair(OptionInfo::AA);
+        checkValuePair(OptionInfo::TC);
+        checkValuePair(OptionInfo::Z);
+        checkValuePair(OptionInfo::AD);
+        checkValuePair(OptionInfo::CD);
+        checkValuePair(OptionInfo::RC);
+    }
+
+    /// \brief Check Non-Limit Options
+    ///
+    /// Checks that the options whose () are NOT stored in the limits_
+    /// array are set to their default ().
+    void
+    checkDefaultOtherValues() {
+        EXPECT_EQ("127.0.0.1", getAddress());
+        EXPECT_EQ(53, getPort());
+        EXPECT_EQ(500, getTimeout());
+        EXPECT_EQ("www.example.com", getQname());
+    }
+};
 
 // Check that each of the options will be recognised
 
@@ -131,7 +92,7 @@ TEST_F(CommandOptionsTest, address) {
     EXPECT_EQ(53, getPort());
     EXPECT_EQ(500, getTimeout());
     EXPECT_EQ("www.example.com", getQname());
-    checkDefaultFlagValues(getFlagValues());
+    checkDefaultLimitsValues();
 }
 
 TEST_F(CommandOptionsTest, port) {
@@ -143,7 +104,7 @@ TEST_F(CommandOptionsTest, port) {
     EXPECT_EQ(153, getPort());
     EXPECT_EQ(500, getTimeout());
     EXPECT_EQ("www.example.com", getQname());
-    checkDefaultFlagValues(getFlagValues());
+    checkDefaultLimitsValues();
 }
 
 TEST_F(CommandOptionsTest, timeout) {
@@ -155,7 +116,7 @@ TEST_F(CommandOptionsTest, timeout) {
     EXPECT_EQ(53, getPort());
     EXPECT_EQ(250, getTimeout());
     EXPECT_EQ("www.example.com", getQname());
-    checkDefaultFlagValues(getFlagValues());
+    checkDefaultLimitsValues();
 }
 
 TEST_F(CommandOptionsTest, parameter) {
@@ -167,348 +128,325 @@ TEST_F(CommandOptionsTest, parameter) {
     EXPECT_EQ(53, getPort());
     EXPECT_EQ(500, getTimeout());
     EXPECT_EQ("ftp.example.net", getQname());
-    checkDefaultFlagValues(getFlagValues());
+    checkDefaultLimitsValues();
 }
 
 // The various tests of the different flags
 TEST_F(CommandOptionsTest, qr) {
 
-    // Specifying a value of zero, we expect all flag values to be zero
+    // Specifying a value of zero, we expect all flag () to be zero
     const char* argv1[] = {"badpacket",  "--qr", "0"};
     int argc1 = sizeof(argv1) / sizeof(const char*);
 
     parse(argc1, const_cast<char**>(argv1));
-    checkDefaultOtherValues(*this);
-    FlagValues values = getFlagValues();
-    checkDefaultFlagValues(values);
+    checkDefaultOtherValues();
+    checkDefaultLimitsValues();
 
     // Check that a value of 1 is accepted
     const char* argv2[] = {"badpacket",  "--qr", "1"};
     int argc2 = sizeof(argv2) / sizeof(const char*);
 
     parse(argc2, const_cast<char**>(argv2));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr, 1, 1);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR, 1, 1);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 
     // Check that a range is accepted (in this case, specified backwards)
     const char* argv3[] = {"badpacket",  "--qr", "1-0"};
     int argc3 = sizeof(argv3) / sizeof(const char*);
 
     parse(argc3, const_cast<char**>(argv3));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr, 0, 1);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR, 0, 1);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 }
 
 // The following are cut-and-pasted from the "qr" test.  (It is awkward to put
-// the test into a general function because of differing string values and
+// the test into a general function because of differing string () and
 // variables.)
 
 TEST_F(CommandOptionsTest, op) {
 
-    // Specifying a value of zero, we expect all flag values to be zero
+    // Specifying a value of zero, we expect all flag () to be zero
     const char* argv1[] = {"badpacket",  "--op", "0"};
     int argc1 = sizeof(argv1) / sizeof(const char*);
 
     parse(argc1, const_cast<char**>(argv1));
-    checkDefaultOtherValues(*this);
-    FlagValues values = getFlagValues();
-    checkDefaultFlagValues(values);
+    checkDefaultOtherValues();
+    checkDefaultLimitsValues();
 
     // Check that a value of 1 is accepted
     const char* argv2[] = {"badpacket",  "--op", "8"};
     int argc2 = sizeof(argv2) / sizeof(const char*);
 
     parse(argc2, const_cast<char**>(argv2));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op, 8, 8);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP, 8, 8);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 
     // Check that a range is accepted (in this case, specified backwards)
     const char* argv3[] = {"badpacket",  "--op", "14-2"};
     int argc3 = sizeof(argv3) / sizeof(const char*);
 
     parse(argc3, const_cast<char**>(argv3));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op, 2, 14);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP, 2, 14);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 }
 
 TEST_F(CommandOptionsTest, aa) {
 
-    // Specifying a value of zero, we expect all flag values to be zero
+    // Specifying a value of zero, we expect all flag () to be zero
     const char* argv1[] = {"badpacket",  "--aa", "0"};
     int argc1 = sizeof(argv1) / sizeof(const char*);
 
     parse(argc1, const_cast<char**>(argv1));
-    checkDefaultOtherValues(*this);
-    FlagValues values = getFlagValues();
-    checkDefaultFlagValues(values);
+    checkDefaultOtherValues();
+    checkDefaultLimitsValues();
 
     // Check that a value of 1 is accepted
     const char* argv2[] = {"badpacket",  "--aa", "1"};
     int argc2 = sizeof(argv2) / sizeof(const char*);
 
     parse(argc2, const_cast<char**>(argv2));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa, 1, 1);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA, 1, 1);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 
     // Check that a range is accepted.
     const char* argv3[] = {"badpacket",  "--aa", "1-0"};
     int argc3 = sizeof(argv3) / sizeof(const char*);
 
     parse(argc3, const_cast<char**>(argv3));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa, 0, 1);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA, 0, 1);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 }
 
 TEST_F(CommandOptionsTest, tc) {
 
-    // Specifying a value of zero, we expect all flag values to be zero
+    // Specifying a value of zero, we expect all flag () to be zero
     const char* argv1[] = {"badpacket",  "--tc", "0"};
     int argc1 = sizeof(argv1) / sizeof(const char*);
 
     parse(argc1, const_cast<char**>(argv1));
-    checkDefaultOtherValues(*this);
-    FlagValues values = getFlagValues();
-    checkDefaultFlagValues(values);
+    checkDefaultOtherValues();
+    checkDefaultLimitsValues();
 
     // Check that a value of 1 is accepted
     const char* argv2[] = {"badpacket",  "--tc", "1"};
     int argc2 = sizeof(argv2) / sizeof(const char*);
 
     parse(argc2, const_cast<char**>(argv2));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc, 1, 1);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC, 1, 1);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 
     // Check that a range is accepted.
     const char* argv3[] = {"badpacket",  "--tc", "1-0"};
     int argc3 = sizeof(argv3) / sizeof(const char*);
 
     parse(argc3, const_cast<char**>(argv3));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc, 0, 1);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC, 0, 1);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 }
 
 TEST_F(CommandOptionsTest, z) {
 
-    // Specifying a value of zero, we expect all flag values to be zero
+    // Specifying a value of zero, we expect all flag () to be zero
     const char* argv1[] = {"badpacket",  "--z", "0"};
     int argc1 = sizeof(argv1) / sizeof(const char*);
 
     parse(argc1, const_cast<char**>(argv1));
-    checkDefaultOtherValues(*this);
-    FlagValues values = getFlagValues();
-    checkDefaultFlagValues(values);
+    checkDefaultOtherValues();
+    checkDefaultLimitsValues();
 
     // Check that a value of 1 is accepted
     const char* argv2[] = {"badpacket",  "--z", "1"};
     int argc2 = sizeof(argv2) / sizeof(const char*);
 
     parse(argc2, const_cast<char**>(argv2));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z, 1, 1);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z, 1, 1);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 
     // Check that a range is accepted.
     const char* argv3[] = {"badpacket",  "--z", "1-0"};
     int argc3 = sizeof(argv3) / sizeof(const char*);
 
     parse(argc3, const_cast<char**>(argv3));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z, 0, 1);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z, 0, 1);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 }
 
 TEST_F(CommandOptionsTest, ad) {
 
-    // Specifying a value of zero, we expect all flag values to be zero
+    // Specifying a value of zero, we expect all flag () to be zero
     const char* argv1[] = {"badpacket",  "--ad", "0"};
     int argc1 = sizeof(argv1) / sizeof(const char*);
 
     parse(argc1, const_cast<char**>(argv1));
-    checkDefaultOtherValues(*this);
-    FlagValues values = getFlagValues();
-    checkDefaultFlagValues(values);
+    checkDefaultOtherValues();
+    checkDefaultLimitsValues();
 
     // Check that a value of 1 is accepted
     const char* argv2[] = {"badpacket",  "--ad", "1"};
     int argc2 = sizeof(argv2) / sizeof(const char*);
 
     parse(argc2, const_cast<char**>(argv2));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad, 1, 1);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD, 1, 1);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 
     // Check that a range is accepted.
     const char* argv3[] = {"badpacket",  "--ad", "0-1"};
     int argc3 = sizeof(argv3) / sizeof(const char*);
 
     parse(argc3, const_cast<char**>(argv3));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad, 0, 1);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD, 0, 1);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC);
 }
 
 TEST_F(CommandOptionsTest, cd) {
 
-    // Specifying a value of zero, we expect all flag values to be zero
+    // Specifying a value of zero, we expect all flag () to be zero
     const char* argv1[] = {"badpacket",  "--cd", "0"};
     int argc1 = sizeof(argv1) / sizeof(const char*);
 
     parse(argc1, const_cast<char**>(argv1));
-    checkDefaultOtherValues(*this);
-    FlagValues values = getFlagValues();
-    checkDefaultFlagValues(values);
+    checkDefaultOtherValues();
+    checkDefaultLimitsValues();
 
     // Check that a value of 1 is accepted
     const char* argv2[] = {"badpacket",  "--cd", "1"};
     int argc2 = sizeof(argv2) / sizeof(const char*);
 
     parse(argc2, const_cast<char**>(argv2));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd, 1, 1);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD, 1, 1);
+    checkValuePair(OptionInfo::RC);
 
     // Check that a range is accepted.
     const char* argv3[] = {"badpacket",  "--cd", "1-0"};
     int argc3 = sizeof(argv3) / sizeof(const char*);
 
     parse(argc3, const_cast<char**>(argv3));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd, 0, 1);
-    checkValuePair(values.rc);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD, 0, 1);
+    checkValuePair(OptionInfo::RC);
 }
 
 TEST_F(CommandOptionsTest, rc) {
 
-    // Specifying a value of zero, we expect all flag values to be zero
+    // Specifying a value of zero, we expect all flag () to be zero
     const char* argv1[] = {"badpacket",  "--rc", "0"};
     int argc1 = sizeof(argv1) / sizeof(const char*);
 
     parse(argc1, const_cast<char**>(argv1));
-    checkDefaultOtherValues(*this);
-    FlagValues values = getFlagValues();
-    checkDefaultFlagValues(values);
+    checkDefaultOtherValues();
+    checkDefaultLimitsValues();
 
     // Check that a valid value is accepted.
     const char* argv2[] = {"badpacket",  "--rc", "15"};
     int argc2 = sizeof(argv2) / sizeof(const char*);
 
     parse(argc2, const_cast<char**>(argv2));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc, 15, 15);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC, 15, 15);
 
     // Check that a range is accepted (in this case, specified backwards and
     // outside the range - so it should be truncated).
@@ -516,14 +454,30 @@ TEST_F(CommandOptionsTest, rc) {
     int argc3 = sizeof(argv3) / sizeof(const char*);
 
     parse(argc3, const_cast<char**>(argv3));
-    checkDefaultOtherValues(*this);
-    values = getFlagValues();
-    checkValuePair(values.qr);
-    checkValuePair(values.op);
-    checkValuePair(values.aa);
-    checkValuePair(values.tc);
-    checkValuePair(values.z);
-    checkValuePair(values.ad);
-    checkValuePair(values.cd);
-    checkValuePair(values.rc, 4, 8);
+    checkDefaultOtherValues();
+    checkValuePair(OptionInfo::QR);
+    checkValuePair(OptionInfo::OP);
+    checkValuePair(OptionInfo::AA);
+    checkValuePair(OptionInfo::TC);
+    checkValuePair(OptionInfo::Z);
+    checkValuePair(OptionInfo::AD);
+    checkValuePair(OptionInfo::CD);
+    checkValuePair(OptionInfo::RC, 4, 8);
+}
+
+// Check that invalid () are caught.
+TEST_F(CommandOptionsTest, processOptionValue) {
+
+    // Check out of range () cause a BadValue exception
+    EXPECT_THROW(processOptionValue('Q', "2"), isc::BadValue);      // Single value above range
+    EXPECT_THROW(processOptionValue('O', "0-17"), isc::BadValue);   // Range overlapping valid range
+
+    // ... and that any invalid string does the same
+    EXPECT_THROW(processOptionValue('O', ""), isc::BadValue);
+    EXPECT_THROW(processOptionValue('O', " "), isc::BadValue);
+    EXPECT_THROW(processOptionValue('O', "1-2-3"), isc::BadValue);
+    EXPECT_THROW(processOptionValue('O', "abc"), isc::BadValue);
+    EXPECT_THROW(processOptionValue('O', "abc-xyz"), isc::BadValue);
+    EXPECT_THROW(processOptionValue('O', "0.7"), isc::BadValue);
+    EXPECT_THROW(processOptionValue('O', "0.7-2.3"), isc::BadValue);
 }

+ 150 - 149
tests/tools/badpacket/tests/header_flags_unittest.cc

@@ -16,6 +16,7 @@
 #include <stdint.h>
 #include <gtest/gtest.h>
 
+#include "../option_info.h"
 #include "../header_flags.h"
 
 using namespace isc::badpacket;
@@ -31,16 +32,16 @@ public:
 // Convenience function to check that all values are zero
 void
 checkZero(const HeaderFlags& flags) {
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
 
     EXPECT_EQ(0, flags.getValue());
 }
@@ -53,20 +54,20 @@ TEST_F(HeaderFlagsTest, QRfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setQR(1);
-    EXPECT_EQ(1, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    flags.set(OptionInfo::QR, 1);
+    EXPECT_EQ(1, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setQR(0);
+    flags.set(OptionInfo::QR, 0);
     checkZero(flags);
 }
 
@@ -74,20 +75,20 @@ TEST_F(HeaderFlagsTest, OPfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setOP(15);
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(15, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    flags.set(OptionInfo::OP, 15);
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(15, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setOP(0);
+    flags.set(OptionInfo::OP, 0);
     checkZero(flags);
 }
 
@@ -95,20 +96,20 @@ TEST_F(HeaderFlagsTest, AAfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setAA(1);
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(1, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    flags.set(OptionInfo::AA, 1);
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(1, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setAA(0);
+    flags.set(OptionInfo::AA, 0);
     checkZero(flags);
 }
 
@@ -116,20 +117,20 @@ TEST_F(HeaderFlagsTest, TCfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setTC(1);
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(1, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    flags.set(OptionInfo::TC, 1);
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(1, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setTC(0);
+    flags.set(OptionInfo::TC, 0);
     checkZero(flags);
 }
 
@@ -137,20 +138,20 @@ TEST_F(HeaderFlagsTest, RDfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setRD(1);
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(1, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    flags.set(OptionInfo::RD, 1);
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(1, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setRD(0);
+    flags.set(OptionInfo::RD, 0);
     checkZero(flags);
 }
 
@@ -158,20 +159,20 @@ TEST_F(HeaderFlagsTest, RAfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setRA(1);
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(1, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    flags.set(OptionInfo::RA, 1);
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(1, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setRA(0);
+    flags.set(OptionInfo::RA, 0);
     checkZero(flags);
 }
 
@@ -179,20 +180,20 @@ TEST_F(HeaderFlagsTest, Zfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setZ(1);
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(1, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    flags.set(OptionInfo::Z, 1);
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(1, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setZ(0);
+    flags.set(OptionInfo::Z, 0);
     checkZero(flags);
 }
 
@@ -200,20 +201,20 @@ TEST_F(HeaderFlagsTest, ADfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setAD(1);
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(1, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    flags.set(OptionInfo::AD, 1);
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(1, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setAD(0);
+    flags.set(OptionInfo::AD, 0);
     checkZero(flags);
 }
 
@@ -221,20 +222,20 @@ TEST_F(HeaderFlagsTest, CDfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setCD(1);
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(1, flags.getCD());
-    EXPECT_EQ(0, flags.getRC());
+    flags.set(OptionInfo::CD, 1);
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(1, flags.get(OptionInfo::CD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setCD(0);
+    flags.set(OptionInfo::CD, 0);
     checkZero(flags);
 }
 
@@ -242,20 +243,20 @@ TEST_F(HeaderFlagsTest, RCfield) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setRC(7);
-    EXPECT_EQ(0, flags.getQR());
-    EXPECT_EQ(0, flags.getOP());
-    EXPECT_EQ(0, flags.getAA());
-    EXPECT_EQ(0, flags.getTC());
-    EXPECT_EQ(0, flags.getRD());
-    EXPECT_EQ(0, flags.getRA());
-    EXPECT_EQ(0, flags.getZ());
-    EXPECT_EQ(0, flags.getAD());
-    EXPECT_EQ(0, flags.getCD());
-    EXPECT_EQ(7, flags.getRC());
+    flags.set(OptionInfo::RC, 15);
+    EXPECT_EQ(0, flags.get(OptionInfo::QR));
+    EXPECT_EQ(0, flags.get(OptionInfo::OP));
+    EXPECT_EQ(0, flags.get(OptionInfo::AA));
+    EXPECT_EQ(0, flags.get(OptionInfo::TC));
+    EXPECT_EQ(0, flags.get(OptionInfo::RD));
+    EXPECT_EQ(0, flags.get(OptionInfo::RA));
+    EXPECT_EQ(0, flags.get(OptionInfo::Z));
+    EXPECT_EQ(0, flags.get(OptionInfo::AD));
+    EXPECT_EQ(0, flags.get(OptionInfo::CD));
+    EXPECT_EQ(15, flags.get(OptionInfo::RC));
     EXPECT_NE(0, flags.getValue());
 
-    flags.setRC(0);
+    flags.set(OptionInfo::RC, 0);
     checkZero(flags);
 }
 
@@ -265,42 +266,42 @@ TEST_F(HeaderFlagsTest, bitValues) {
     HeaderFlags flags;
     checkZero(flags);
 
-    flags.setQR(1);
+    flags.set(OptionInfo::QR, 1);
     EXPECT_EQ(0x8000, flags.getValue());
 
-    flags.setQR(0);
-    flags.setOP(15);
+    flags.set(OptionInfo::QR, 0);
+    flags.set(OptionInfo::OP, 15);
     EXPECT_EQ(0x7800, flags.getValue());
 
-    flags.setOP(0);
-    flags.setAA(1);
+    flags.set(OptionInfo::OP, 0);
+    flags.set(OptionInfo::AA, 1);
     EXPECT_EQ(0x0400, flags.getValue());
 
-    flags.setAA(0);
-    flags.setTC(1);
+    flags.set(OptionInfo::AA, 0);
+    flags.set(OptionInfo::TC, 1);
     EXPECT_EQ(0x0200, flags.getValue());
 
-    flags.setTC(0);
-    flags.setRD(1);
+    flags.set(OptionInfo::TC, 0);
+    flags.set(OptionInfo::RD, 1);
     EXPECT_EQ(0x0100, flags.getValue());
 
-    flags.setRD(0);
-    flags.setRA(1);
+    flags.set(OptionInfo::RD, 0);
+    flags.set(OptionInfo::RA, 1);
     EXPECT_EQ(0x0080, flags.getValue());
 
-    flags.setRA(0);
-    flags.setZ(1);
+    flags.set(OptionInfo::RA, 0);
+    flags.set(OptionInfo::Z, 1);
     EXPECT_EQ(0x0040, flags.getValue());
 
-    flags.setZ(0);
-    flags.setAD(1);
+    flags.set(OptionInfo::Z, 0);
+    flags.set(OptionInfo::AD, 1);
     EXPECT_EQ(0x0020, flags.getValue());
 
-    flags.setAD(0);
-    flags.setCD(1);
+    flags.set(OptionInfo::AD, 0);
+    flags.set(OptionInfo::CD, 1);
     EXPECT_EQ(0x0010, flags.getValue());
 
-    flags.setCD(0);
-    flags.setRC(15);
+    flags.set(OptionInfo::CD, 0);
+    flags.set(OptionInfo::RC, 15);
     EXPECT_EQ(0x000F, flags.getValue());
 }

+ 10 - 1
tests/tools/badpacket/tests/option_info_unittest.cc

@@ -32,62 +32,71 @@ public:
 // Check the values are as expected
 
 TEST_F(OptionInfoTest, values) {
-
     EXPECT_STREQ("qr", OptionInfo::name(OptionInfo::QR));
+    EXPECT_STREQ("qr", OptionInfo::name(OptionInfo::getIndex('Q')));
     EXPECT_EQ(0x8000,  OptionInfo::mask(OptionInfo::QR));
     EXPECT_EQ(15,      OptionInfo::offset(OptionInfo::QR));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::QR));
     EXPECT_EQ(1,       OptionInfo::maxval(OptionInfo::QR));
 
     EXPECT_STREQ("op", OptionInfo::name(OptionInfo::OP));
+    EXPECT_STREQ("op", OptionInfo::name(OptionInfo::getIndex('O')));
     EXPECT_EQ(0x7800,  OptionInfo::mask(OptionInfo::OP));
     EXPECT_EQ(11,      OptionInfo::offset(OptionInfo::OP));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::OP));
     EXPECT_EQ(15,      OptionInfo::maxval(OptionInfo::OP));
 
     EXPECT_STREQ("aa", OptionInfo::name(OptionInfo::AA));
+    EXPECT_STREQ("aa", OptionInfo::name(OptionInfo::getIndex('A')));
     EXPECT_EQ(0x0400,  OptionInfo::mask(OptionInfo::AA));
     EXPECT_EQ(10,      OptionInfo::offset(OptionInfo::AA));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::AA));
     EXPECT_EQ(1,       OptionInfo::maxval(OptionInfo::AA));
 
     EXPECT_STREQ("tc", OptionInfo::name(OptionInfo::TC));
+    EXPECT_STREQ("tc", OptionInfo::name(OptionInfo::getIndex('T')));
     EXPECT_EQ(0x0200,  OptionInfo::mask(OptionInfo::TC));
     EXPECT_EQ(9,       OptionInfo::offset(OptionInfo::TC));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::TC));
     EXPECT_EQ(1,       OptionInfo::maxval(OptionInfo::TC));
 
     EXPECT_STREQ("rd", OptionInfo::name(OptionInfo::RD));
+    EXPECT_STREQ("rd", OptionInfo::name(OptionInfo::getIndex('D')));
     EXPECT_EQ(0x0100,  OptionInfo::mask(OptionInfo::RD));
     EXPECT_EQ(8,       OptionInfo::offset(OptionInfo::RD));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::RD));
     EXPECT_EQ(1,       OptionInfo::maxval(OptionInfo::RD));
 
     EXPECT_STREQ("ra", OptionInfo::name(OptionInfo::RA));
+    EXPECT_STREQ("ra", OptionInfo::name(OptionInfo::getIndex('R')));
     EXPECT_EQ(0x0080,  OptionInfo::mask(OptionInfo::RA));
     EXPECT_EQ(7,       OptionInfo::offset(OptionInfo::RA));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::RA));
     EXPECT_EQ(1,       OptionInfo::maxval(OptionInfo::RA));
 
     EXPECT_STREQ("z",  OptionInfo::name(OptionInfo::Z));
+    EXPECT_STREQ("z",  OptionInfo::name(OptionInfo::getIndex('Z')));
     EXPECT_EQ(0x0040,  OptionInfo::mask(OptionInfo::Z));
     EXPECT_EQ(6,       OptionInfo::offset(OptionInfo::Z));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::Z));
     EXPECT_EQ(1,       OptionInfo::maxval(OptionInfo::Z));
 
     EXPECT_STREQ("ad", OptionInfo::name(OptionInfo::AD));
+    EXPECT_STREQ("ad", OptionInfo::name(OptionInfo::getIndex('U')));
     EXPECT_EQ(0x0020,  OptionInfo::mask(OptionInfo::AD));
     EXPECT_EQ(5,       OptionInfo::offset(OptionInfo::AD));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::AD));
     EXPECT_EQ(1,       OptionInfo::maxval(OptionInfo::AD));
 
     EXPECT_STREQ("cd", OptionInfo::name(OptionInfo::CD));
+    EXPECT_STREQ("cd", OptionInfo::name(OptionInfo::getIndex('C')));
     EXPECT_EQ(0x0010,  OptionInfo::mask(OptionInfo::CD));
     EXPECT_EQ(4,       OptionInfo::offset(OptionInfo::CD));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::CD));
     EXPECT_EQ(1,       OptionInfo::maxval(OptionInfo::CD));
 
     EXPECT_STREQ("rc", OptionInfo::name(OptionInfo::RC));
+    EXPECT_STREQ("rc", OptionInfo::name(OptionInfo::getIndex('E')));
     EXPECT_EQ(0x000F,  OptionInfo::mask(OptionInfo::RC));
     EXPECT_EQ(0,       OptionInfo::offset(OptionInfo::RC));
     EXPECT_EQ(0,       OptionInfo::minval(OptionInfo::RC));