BIND 10 trac1959, updated. 9f8954c665a65233a6c697be3769f02d702a2728 [1959] Fixed doxygen typos in test_control.h.

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Sep 5 16:01:12 UTC 2012


The branch, trac1959 has been updated
       via  9f8954c665a65233a6c697be3769f02d702a2728 (commit)
       via  7c7d7c9120c5a8a8b7b9d324ee6733a968412750 (commit)
      from  5585299f3e340017f57307bbf9568bb98931279f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 9f8954c665a65233a6c697be3769f02d702a2728
Author: Marcin Siodelski <marcin at isc.org>
Date:   Wed Sep 5 18:00:13 2012 +0200

    [1959] Fixed doxygen typos in test_control.h.

commit 7c7d7c9120c5a8a8b7b9d324ee6733a968412750
Author: Marcin Siodelski <marcin at isc.org>
Date:   Wed Sep 5 17:53:45 2012 +0200

    [1959] Implemented changes for 4th part of code review.

-----------------------------------------------------------------------

Summary of changes:
 tests/tools/perfdhcp/command_options.cc            |    4 +
 tests/tools/perfdhcp/test_control.cc               |   27 +-
 tests/tools/perfdhcp/test_control.h                |   86 +++++--
 .../perfdhcp/tests/command_options_unittest.cc     |   54 ++--
 .../tools/perfdhcp/tests/test_control_unittest.cc  |  259 +++++++++++++++-----
 5 files changed, 318 insertions(+), 112 deletions(-)

-----------------------------------------------------------------------
diff --git a/tests/tools/perfdhcp/command_options.cc b/tests/tools/perfdhcp/command_options.cc
index dbb01e7..8d9f02e 100644
--- a/tests/tools/perfdhcp/command_options.cc
+++ b/tests/tools/perfdhcp/command_options.cc
@@ -495,6 +495,10 @@ CommandOptions::decodeDuid(const std::string& base) {
         }
         duid_template.push_back(static_cast<uint8_t>(ui));
     }
+    // @todo Get rid of this limitation when we manage add support
+    // for DUIDs other than LLT. Shorter DUIDs may be useful for
+    // server testing purposes.
+    check(duid_template.size() < 6, "DUID must be at least 6 octets long");
     // Assign the new duid only if successfully generated.
     std::swap(duid_template, duid_template_);
 }
diff --git a/tests/tools/perfdhcp/test_control.cc b/tests/tools/perfdhcp/test_control.cc
index 446de81..ba8bf25 100644
--- a/tests/tools/perfdhcp/test_control.cc
+++ b/tests/tools/perfdhcp/test_control.cc
@@ -298,9 +298,9 @@ OptionPtr
 TestControl::factoryOptionRequestOption6(Option::Universe,
                                          uint16_t,
                                          const OptionBuffer&) {
-    const uint8_t buf_array[] = {
-        0, D6O_NAME_SERVERS,
-        0, D6O_DOMAIN_SEARCH
+    const uint16_t buf_array[] = {
+        htons(D6O_NAME_SERVERS),
+        htons(D6O_DOMAIN_SEARCH)
     };
     OptionBuffer buf_with_options(buf_array, buf_array + sizeof(buf_array));
     return (OptionPtr(new Option(Option::V6, D6O_ORO, buf_with_options)));
@@ -331,7 +331,7 @@ std::vector<uint8_t>
 TestControl::generateMacAddress(uint8_t& randomized) const {
     CommandOptions& options = CommandOptions::instance();
     uint32_t clients_num = options.getClientsNum();
-    if ((clients_num == 0) || (clients_num == 1)) {
+    if (clients_num < 2) {
         return (options.getMacTemplate());
     }
     // Get the base MAC address. We are going to randomize part of it.
@@ -339,11 +339,7 @@ TestControl::generateMacAddress(uint8_t& randomized) const {
     if (mac_addr.size() != HW_ETHER_LEN) {
         isc_throw(BadValue, "invalid MAC address template specified");
     }
-    uint32_t r = random();
-    // The random number must be in the range 0..clients_num-1. This
-    // will guarantee that every client has exactly one random MAC
-    // address assigned.
-    r %= clients_num;
+    uint32_t r = macaddr_gen_->generate();
     randomized = 0;
     // Randomize MAC address octets.
     for (std::vector<uint8_t>::iterator it = mac_addr.end() - 1;
@@ -889,7 +885,10 @@ TestControl::reset() {
     last_sent_ = send_due_;
     last_report_ = send_due_;
     transid_gen_.reset();
-    transid_gen_ = TransidGeneratorPtr(new TransidGenerator());
+    // Actual generators will have to be set later on because we need to
+    // get command line parameters first.
+    setTransidGenerator(NumberGeneratorPtr());
+    setMacAddrGenerator(NumberGeneratorPtr());
     first_packet_serverid_.clear();
     interrupted_ = false;
 }
@@ -907,8 +906,16 @@ TestControl::run() {
     if (options.getIpVersion() == 0) {
         isc_throw(InvalidOperation,
                   "command options must be parsed before running a test");
+    } else if (options.getIpVersion() == 4) {
+        setTransidGenerator(NumberGeneratorPtr(new SequencialGenerator()));
+    } else {
+        setTransidGenerator(NumberGeneratorPtr(new SequencialGenerator(0x00FFFFFF)));
     }
 
+    uint32_t clients_num = options.getClientsNum() == 0 ?
+        1 : options.getClientsNum();
+    setMacAddrGenerator(NumberGeneratorPtr(new SequencialGenerator(clients_num)));
+
     // Diagnostics are command line options mainly.
     printDiagnostics();
     // Option factories have to be registered.
diff --git a/tests/tools/perfdhcp/test_control.h b/tests/tools/perfdhcp/test_control.h
index cf83113..8e492af 100644
--- a/tests/tools/perfdhcp/test_control.h
+++ b/tests/tools/perfdhcp/test_control.h
@@ -39,11 +39,11 @@ namespace perfdhcp {
 /// test end to end.
 ///
 /// Option factory functions are registered using
-/// \ref LibDHCP::OptionFactoryRegister. Registered factory functions
+/// \ref dhcp::LibDHCP::OptionFactoryRegister. Registered factory functions
 /// provide a way to create options of the same type in the same way.
 ///  When new option instance is needed the corresponding factory
 /// function is called to create it. This is done by calling
-/// \ref Option::factory with DHCP message type specified as one of
+/// \ref dhcp::Option::factory with DHCP message type specified as one of
 ///  parameters. Some of the parameters passed to factory function
 /// may be ignored (e.g. option buffer).
 class TestControl : public boost::noncopyable {
@@ -127,26 +127,52 @@ public:
         void initSocketData();
     };
 
-    /// \brief Default transaction id generator class.
+    /// \brief Number generator class.
     ///
-    /// This is default transaction id generator class. The member
-    /// function is used to generate unique transaction id value.
-    /// Other generator classes should derive from this one to
-    /// override the standard generation algorithm (e.g. unit tests
-    /// override this class wih algorithm that produces more predictable
-    /// transaction id values).
-    class TransidGenerator {
+    /// This is default numbers generator class. The member function is
+    /// used to generate uint32_t values. Other generator classes should
+    /// derive from this one to implement generation algorithms
+    /// (e.g. sequencial or based on random function).
+    class NumberGenerator {
     public:
-        /// \brief generate transaction id.
+        /// \brief Generate number.
         ///
-        /// \return generated transazction id value.
+        /// \return Generate number.
+        virtual uint32_t generate() = 0;
+    };
+
+    /// The default generator pointer.
+    typedef boost::shared_ptr<NumberGenerator> NumberGeneratorPtr;
+
+    /// \brief Sequencial numbers generatorc class.
+    class SequencialGenerator : public NumberGenerator {
+    public:
+        /// \brief Constructor.
+        ///
+        /// \param range maximum number generated. If 0 is given then
+        /// range defaults to maximym uint32_t value.
+        SequencialGenerator(uint32_t range = 0xFFFFFFFF) :
+            NumberGenerator(),
+            num_(0),
+            range_(range) {
+            if (range_ == 0) {
+                range_ = 0xFFFFFFFF;
+            }
+        }
+
+        /// \brief Generate number sequencialy.
+        ///
+        /// \return generated number.
         virtual uint32_t generate() {
-            return static_cast<uint32_t>(random() % 0x00FFFFFF);
+            uint32_t num = num_;
+            num_ = (num_ + 1) % range_;
+            return (num);
         }
+    private:
+        uint32_t num_;   ///< Current number.
+        uint32_t range_; ///< Maximum number generated.
     };
 
-    typedef boost::shared_ptr<TransidGenerator> TransidGeneratorPtr;
-
     /// \brief Length of the Ethernet HW address (MAC) in bytes.
     ///
     /// \todo Make this variable length as there are cases when HW
@@ -172,11 +198,22 @@ public:
     /// \brief Set new transaction id generator.
     ///
     /// \param generator generator object to be used.
-    void setTransidGenerator(TransidGeneratorPtr& generator) {
+    void setTransidGenerator(const NumberGeneratorPtr& generator) {
         transid_gen_.reset();
         transid_gen_ = generator;
     }
 
+    /// \brief Set new MAC address generator.
+    ///
+    /// Set numbers generator that will be used to generate various
+    /// MAC addresses to simulate number of clients.
+    ///
+    /// \param generator object to be used.
+    void setMacAddrGenerator(const NumberGeneratorPtr& generator) {
+        macaddr_gen_.reset();
+        macaddr_gen_ = generator;
+    }
+
     // We would really like following methods and members to be private but
     // they have to be accessible for unit-testing. Another, possibly better,
     // solution is to make this class friend of test class but this is not
@@ -337,7 +374,7 @@ protected:
     ///
     /// \return generated transaction id.
     uint32_t generateTransid() {
-        return(transid_gen_->generate());
+        return (transid_gen_->generate());
     }
 
     /// \brief Returns number of exchanges to be started.
@@ -345,7 +382,7 @@ protected:
     /// Method returns number of new exchanges to be started as soon
     /// as possible to satisfy expected rate. Calculation used here
     /// is based on current time, due time calculated with
-    /// \ref updateSendTime function and expected rate.
+    /// \ref updateSendDue function and expected rate.
     ///
     /// \return number of exchanges to be started immediately.
     uint64_t getNextExchangesNum() const;
@@ -457,15 +494,15 @@ protected:
     /// valid. Ensure that it is valid prior to calling it.
     ///
     /// \param socket socket to be used.
-    /// \throw::BadValue if unknown message type received.
-    /// \throw::Unexpected if unexpected error occured.
+    /// \throw isc::BadValue if unknown message type received.
+    /// \throw isc::Unexpected if unexpected error occured.
     void receivePackets(const TestControlSocket& socket);
 
     /// \brief Register option factory functions for DHCPv4
     ///
     /// Method registers option factory functions for DHCPv4.
     /// These functions are called to create instances of DHCPv4
-    /// options. Call \ref Option::factory to invoke factory
+    /// options. Call \ref dhcp::Option::factory to invoke factory
     /// function for particular option. Don't use this function directly.
     /// Use \ref registerOptionFactories instead.
     void registerOptionFactories4() const;
@@ -474,7 +511,7 @@ protected:
     ///
     /// Method registers option factory functions for DHCPv6.
     /// These functions are called to create instances of DHCPv6
-    /// options. Call \ref Option::factory to invoke factory
+    /// options. Call \ref dhcp::Option::factory to invoke factory
     /// function for particular option. Don't use this function directly.
     /// Use \ref registerOptionFactories instead.
     void registerOptionFactories6() const;
@@ -498,7 +535,7 @@ protected:
     /// with the following options:
     /// - MESSAGE_TYPE set to DHCPDISCOVER
     /// - PARAMETER_REQUEST_LIST with the same list of requested options
-    /// as described in \ref factoryRequestList.
+    /// as described in \ref factoryRequestList4.
     /// The transaction id and MAC address are randomly generated for
     /// the message. Range of unique MAC addresses generated depends
     /// on the number of clients specified from the command line.
@@ -738,7 +775,8 @@ private:
     StatsMgr4Ptr stats_mgr4_;  ///< Statistics Manager 4.
     StatsMgr6Ptr stats_mgr6_;  ///< Statistics Manager 6.
 
-    TransidGeneratorPtr transid_gen_; ///< Transaction id generator.
+    NumberGeneratorPtr transid_gen_; ///< Transaction id generator.
+    NumberGeneratorPtr macaddr_gen_; ///< Numbers generator for MAC address.
 
     /// Buffer holiding server id received in first packet
     dhcp::OptionBuffer first_packet_serverid_;
diff --git a/tests/tools/perfdhcp/tests/command_options_unittest.cc b/tests/tools/perfdhcp/tests/command_options_unittest.cc
index 70cb77d..0481d28 100644
--- a/tests/tools/perfdhcp/tests/command_options_unittest.cc
+++ b/tests/tools/perfdhcp/tests/command_options_unittest.cc
@@ -264,39 +264,65 @@ TEST_F(CommandOptionsTest, ClientsNum) {
 
 TEST_F(CommandOptionsTest, Base) {
     CommandOptions& opt = CommandOptions::instance();
-    process("perfdhcp -6 -b MAC=10::20::30::40::50::60 "
-            "-l ethx -b duiD=1AB7F5670901FF all");
     uint8_t mac[6] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60 };
     uint8_t duid[14] = {  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
                           0x01, 0x01, 0x01, 0x10, 0x11, 0x1F, 0x14 };
-
-    // Test Mac
+    // Test DUID and MAC together.
+    EXPECT_NO_THROW(process("perfdhcp -b DUID=0101010101010101010110111F14"
+                            " -b MAC=10::20::30::40::50::60"
+                            " -l 127.0.0.1 all"));
     std::vector<uint8_t> v1 = opt.getMacTemplate();
-    ASSERT_EQ(6, v1.size());
+    std::vector<uint8_t> v2 = opt.getDuidTemplate();
+    v2 = opt.getDuidTemplate();
     EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
-    // "3x" is invalid value in MAC address
-    EXPECT_THROW(process("perfdhcp -b mac=10::2::3x::4::5::6 -l ethx all"),
-                 isc::InvalidParameter);
-
-    // Test DUID
+    EXPECT_TRUE(std::equal(v2.begin(), v2.end(), duid));
+    // Test valid DUID.
     EXPECT_NO_THROW(
         process("perfdhcp -b duid=0101010101010101010110111F14 -l 127.0.0.1 all")
     );
-    std::vector<uint8_t> v2 = opt.getDuidTemplate();
+
     ASSERT_EQ(sizeof(duid) / sizeof(uint8_t), v2.size());
     EXPECT_TRUE(std::equal(v2.begin(), v2.end(), duid));
+    // Test mix of upper/lower case letters.
+    EXPECT_NO_THROW(process("perfdhcp -b DuiD=0101010101010101010110111F14"
+                            " -b Mac=10::20::30::40::50::60"
+                            " -l 127.0.0.1 all"));
+    v1 = opt.getMacTemplate();
+    v2 = opt.getDuidTemplate();
+    EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
+    EXPECT_TRUE(std::equal(v2.begin(), v2.end(), duid));
+    // Use "ether" instead of "mac".
+    EXPECT_NO_THROW(process("perfdhcp -b ether=10::20::30::40::50::60"
+                            " -l 127.0.0.1 all"));
+    v1 = opt.getMacTemplate();
+    EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
+    // Use "ETHER" in upper case.
+    EXPECT_NO_THROW(process("perfdhcp -b ETHER=10::20::30::40::50::60"
+                            " -l 127.0.0.1 all"));
+    v1 = opt.getMacTemplate();
+    EXPECT_TRUE(std::equal(v1.begin(), v1.end(), mac));
     // "t" is invalid character in DUID
     EXPECT_THROW(process("perfdhcp -6 -l ethx -b "
-                         "duiD=010101010101010101t110111F14 all"),
+                         "duid=010101010101010101t110111F14 all"),
+                 isc::InvalidParameter);
+    // "3x" is invalid value in MAC address
+    EXPECT_THROW(process("perfdhcp -b mac=10::2::3x::4::5::6 -l ethx all"),
                  isc::InvalidParameter);
-
-    // Some more negative test cases
     // Base is not specified
     EXPECT_THROW(process("perfdhcp -b -l ethx all"),
                  isc::InvalidParameter);
     // Typo: should be mac= instead of mc=
     EXPECT_THROW(process("perfdhcp -l ethx -b mc=00:01:02:03::04:05 all"),
                  isc::InvalidParameter);
+    // Too short DUID (< 6).
+    EXPECT_THROW(process("perfdhcp -l ethx -b duid=00010203 all"),
+                 isc::InvalidParameter);
+    // Odd number of digits.
+    EXPECT_THROW(process("perfdhcp -l ethx -b duid=000102030405060 all"),
+                 isc::InvalidParameter);
+    // Too short MAC (!= 6).
+    EXPECT_THROW(process("perfdhcp -l ethx -b mac=00:01:02:04 all"),
+                 isc::InvalidParameter);
 }
 
 TEST_F(CommandOptionsTest, DropTime) {
diff --git a/tests/tools/perfdhcp/tests/test_control_unittest.cc b/tests/tools/perfdhcp/tests/test_control_unittest.cc
index f75c310..f94f6f7 100644
--- a/tests/tools/perfdhcp/tests/test_control_unittest.cc
+++ b/tests/tools/perfdhcp/tests/test_control_unittest.cc
@@ -15,6 +15,7 @@
 #include <cstddef>
 #include <stdint.h>
 #include <string>
+#include <fstream>
 #include <gtest/gtest.h>
 
 #include <boost/date_time/posix_time/posix_time.hpp>
@@ -45,11 +46,11 @@ public:
     /// the default transaction id generator that generates transaction
     /// ids using random function. This generator will generate values
     /// like: 1,2,3 etc.
-    class IncrementalGenerator : public TestControl::TransidGenerator {
+    class IncrementalGenerator : public TestControl::NumberGenerator {
     public:
         /// \brief Default constructor.
         IncrementalGenerator() :
-            TransidGenerator(),
+            NumberGenerator(),
             transid_(0) {
         }
 
@@ -88,7 +89,11 @@ public:
     using TestControl::setDefaults4;
     using TestControl::setDefaults6;
 
-    NakedTestControl() : TestControl() { };
+    NakedTestControl() : TestControl() {
+        uint32_t clients_num = CommandOptions::instance().getClientsNum() == 0 ?
+            1 : CommandOptions::instance().getClientsNum();
+        setMacAddrGenerator(NumberGeneratorPtr(new TestControl::SequencialGenerator(clients_num)));
+    };
 
 };
 
@@ -109,9 +114,27 @@ public:
     /// \brief Default Constructor
     TestControlTest() { }
 
-    static uint32_t generateTransidIncremental() {
-        static uint32_t transid(1);
-        return (++transid);
+    /// \brief Create packet template file from binary data.
+    ///
+    /// Function creates file containing data from the provided buffer
+    /// in hexadecimal format.
+    /// \param filename template file to be created.
+    /// \param buffer with binary datato be stored in file.
+    /// \return true if file creation successful.
+    bool createTemplateFile(const std::string& filename,
+                            const std::vector<uint8_t>& buf) const {
+        std::ofstream temp_file;
+        temp_file.open(filename.c_str(), ios::out | ios::trunc);
+        if (!temp_file.is_open()) {
+            return (false);
+        }
+        for (int i = 0; i < buf.size(); ++i) {
+            int first_digit = buf[i] / 16;
+            int second_digit = buf[i] % 16;
+            temp_file << std::hex << first_digit << second_digit << std::dec;
+        }
+        temp_file.close();
+        return (true);
     }
 
     /// \brief Get local loopback interface name.
@@ -130,14 +153,8 @@ public:
         for (IfaceMgr::IfaceCollection::const_iterator iface = ifaces.begin();
              iface != ifaces.end();
              ++iface) {
-            for (IfaceMgr::AddressCollection::const_iterator addr_it =
-                     iface->getAddresses().begin();
-                 addr_it != iface->getAddresses().end();
-                 ++addr_it) {
-                if (asiolink::IOAddress("127.0.0.1").getAddress() ==
-                    addr_it->getAddress()) {
-                    return (iface->getName());
-                }
+            if (iface->flag_loopback_) {
+                return (iface->getName());
             }
         }
         return ("");
@@ -147,7 +164,7 @@ public:
     ///
     /// This method iterates through options provided in the buffer
     /// and matches them with the options specified with first parameter.
-    /// Options in both vectors may be layed in different order.
+    /// Options in both vectors may be laid in different order.
     ///
     /// \param requested_options reference buffer with options.
     /// \param buf test buffer with options that will be matched.
@@ -168,6 +185,38 @@ public:
         return (matched_num);
     }
 
+    /// \brief Match requested DHCPv6 options in the buffer with given list.
+    ///
+    /// This method iterates through options provided in the buffer and
+    /// matches them with the options specified with first parameter.
+    /// Options in both vectors ma be laid in different order.
+    ///
+    /// \param requested_options reference buffer with options.
+    /// \param buf test buffer with options that will be matched.
+    /// \return number of options from the buffer matched with options in
+    /// the reference buffer or -1 if error occured.
+    int matchRequestedOptions6(const dhcp::OptionBuffer& requested_options,
+                               const dhcp::OptionBuffer& buf) const {
+        // Sanity check.
+        if ((requested_options.size() % 2 != 0) ||
+            (buf.size() % 2 != 0)) {
+            return -1;
+        }
+        size_t matched_num = 0;
+        for (size_t i = 0; i < buf.size(); i += 2) {
+            for (int j = 0; j < requested_options.size(); j += 2) {
+                uint16_t opt_i = buf[i + 1] << 8 + buf[i];
+                uint16_t opt_j = buf[j + 1] << 8 + buf[j];
+                if (opt_i == opt_j) {
+                    // Requested option has been found.
+                    ++matched_num;
+                    break;
+                }
+            }
+        }
+        return (matched_num);
+    }
+
     /// \brief Calculate the maximum vectors' mismatch position.
     ///
     /// This helper function calculates the maximum mismatch position
@@ -180,22 +229,20 @@ public:
     /// on two last positions so the returned value will be 2 and so on.
     ///
     /// \param clients_num number of simulated clinets
-    /// \param randomization range - for either MAC or DUID it is 6
     /// \return maximum mismatch position
-    int unequalOctetPosition(const int clients_num,
-                             const size_t random_size) const {
-        int unequal_pos = 0;
-        int n = clients_num - 1;
-        if (n > 0) {
-            for (int i = 0; i < random_size; ++i) {
-                if (n < 256) {
-                    unequal_pos = i + 1;
-                    break;
-                }
-                n %= 256;
-            }
+    int unequalOctetPosition(int clients_num) const {
+        if (!clients_num) {
+            return (0);
         }
-        return (unequal_pos);
+        clients_num--;
+
+        int cnt = 0;
+        while (clients_num) {
+            clients_num >>= 8;
+            ++cnt;
+        }
+
+        return (cnt);
     }
 
     /// brief Test generation of mulitple DUIDs
@@ -212,32 +259,32 @@ public:
     /// and do not change if single client is simulated.
     void testDuid() const {
         int clients_num = CommandOptions::instance().getClientsNum();
+        // Initialize Test Control class.
+        NakedTestControl tc;
         // The old duid will be holding the previously generated DUID.
         // It will be used to compare against the new one. If we have
         // multiple clients we want to make sure that duids differ.
-        Duid old_duid(CommandOptions::instance().getDuidTemplate());
+        uint8_t randomized = 0;
+        Duid old_duid(tc.generateDuid(randomized));
         Duid new_duid(0);
         // total_dist shows the total difference between generated duid.
         // It has to be greater than zero if multiple clients are simulated.
         size_t total_dist = 0;
+        // Number of unique DUIDs.
+        size_t unique_duids = 0;
         // Holds the position if the octet on which two DUIDS can be different.
         // If number of clients is 256 or less it is last DUID octet (except for
         // single client when subsequent DUIDs have to be equal). If number of
         // clients is between 257 and 65536 the last two octets can differ etc.
-        const size_t mac_addr_size = 6;
-        int unequal_pos = unequalOctetPosition(clients_num, mac_addr_size);
-
-        // Initialize Test Control class.
-        NakedTestControl tc;
+        int unequal_pos = unequalOctetPosition(clients_num);
+        // Keep generated DUIDs in this container.
+        std::list<std::vector<uint8_t> > duids;
         // Perform number of iterations to generate number of DUIDs.
-        // If single clinet is involved, try multiple times (10) and
-        // see if the same DUID is always generated.
-        for (int i = 0; i < clients_num * 10; ++i) {
+        for (int i = 0; i < 10 * clients_num; ++i) {
             if (new_duid.empty()) {
                 new_duid = old_duid;
             } else {
                 std::swap(old_duid, new_duid);
-                uint8_t randomized = 0;
                 new_duid = tc.generateDuid(randomized);
             }
             // The DUID-LLT is expected to start with DUID_LLT value
@@ -259,8 +306,8 @@ public:
             uint32_t duid_time = 0;
             // Pick 4 bytes of the time from generated DUID and put them
             // in reverse order (in DUID they are stored in network order).
-            for (int i = 4; i < 8; ++i) {
-                duid_time |= new_duid[i] << (i - 4);
+            for (int j = 4; j < 8; ++j) {
+                duid_time |= new_duid[j] << (j - 4);
             }
             // Calculate the duration since epoch time.
             ptime now = microsec_clock::universal_time();
@@ -288,11 +335,35 @@ public:
             // Mismatch may have occured on the DUID octet position
             // up to calculated earlier unequal_pos.
             ASSERT_LE(mismatch_dist, unequal_pos);
+            // unique will inform if tested DUID is unique.
+            bool unique = true;
+            for (std::list<std::vector<uint8_t> >::const_iterator it =
+                     duids.begin();
+                 it != duids.end(); ++it) {
+                // DUIDs should be of the same size if we want to compare them.
+                ASSERT_EQ(new_duid.size(), it->size());
+                // Check if DUID is unique.
+                if (std::equal(new_duid.begin(), new_duid.end(), it->begin())) {
+                    unique = false;
+                }
+            }
+            // Expecting that DUIDs will be unique only when
+            // first clients-num iterations is performed.
+            // After that, DUIDs become non unique.
+            if (unique) {
+                ++unique_duids;
+            }
+            // For number of iterations equal to clients_num,2*clients_num
+            // 3*clients_num ... we have to have number of unique duids
+            // equal to clients_num.
+            if ((i != 0) && (i % clients_num == 0)) {
+                ASSERT_EQ(clients_num, unique_duids);
+            }
+            // Remember generated DUID.
+            duids.push_back(new_duid);
         }
         // If we have more than one client at least one mismatch occured.
-        if (clients_num > 1) {
-            EXPECT_GT(total_dist, 0);
-        } else {
+        if (clients_num < 2) {
             EXPECT_EQ(0, total_dist);
         }
     }
@@ -327,10 +398,10 @@ public:
 
         // Incremental transaction id generator will generate
         // predictable values of transaction id for each iteration.
-        // This is important because we need to simulate reponses
+        // This is important because we need to simulate responses
         // from the server and use the same transaction ids as in
         // packets sent by client.
-        TestControl::TransidGeneratorPtr
+        TestControl::NumberGeneratorPtr
             generator(new NakedTestControl::IncrementalGenerator());
         tc.setTransidGenerator(generator);
         // Socket is needed to send packets through the interface.
@@ -393,7 +464,7 @@ public:
         // This is important because we need to simulate reponses
         // from the server and use the same transaction ids as in
         // packets sent by client.
-        TestControl::TransidGeneratorPtr
+        TestControl::NumberGeneratorPtr
             generator(new NakedTestControl::IncrementalGenerator());
         tc.setTransidGenerator(generator);
         // Socket is needed to send packets through the interface.
@@ -445,10 +516,14 @@ public:
         // octet (except for single client when subsequent MAC addresses
         // have to be equal). If number of clients is between 257 and 65536
         // the last two octets can differ etc.
-        int unequal_pos = unequalOctetPosition(clients_num, old_mac.size());;
-
+        int unequal_pos = unequalOctetPosition(clients_num);
+        // Number of unique MACs.
+        size_t unique_macs = 0;
+        // Initialize Test Controller.
         NakedTestControl tc;
         size_t total_dist = 0;
+        // Keep generated MACs in this container.
+        std::list<std::vector<uint8_t> > macs;
         // Do many iterations to generate and test MAC address values.
         for (int i = 0; i < clients_num * 10; ++i) {
             // Generate new MAC address.
@@ -470,11 +545,35 @@ public:
             // Mismatch may have occured on the MAC address'es octet position
             // up to calculated earlier unequal_pos.
             ASSERT_LE(mismatch_dist, unequal_pos);
+            // unique will inform if tested DUID is unique.
+            bool unique = true;
+            for (std::list<std::vector<uint8_t> >::const_iterator it =
+                     macs.begin();
+                 it != macs.end(); ++it) {
+                // MACs should be of the same size if we want to compare them.
+                ASSERT_EQ(new_mac.size(), it->size());
+                // Check if MAC is unique.
+                if (std::equal(new_mac.begin(), new_mac.end(), it->begin())) {
+                    unique = false;
+                }
+            }
+            // Expecting that MACs will be unique only when
+            // first clients-num iterations is performed.
+            // After that, MACs become non unique.
+            if (unique) {
+                ++unique_macs;
+            }
+            // For number of iterations equal to clients_num,2*clients_num
+            // 3*clients_num ... we have to have number of unique MACs
+            // equal to clients_num.
+            if ((i != 0) && (i % clients_num == 0)) {
+                ASSERT_EQ(clients_num, unique_macs);
+            }
+            // Remember generated MAC.
+            macs.push_back(new_mac);
+
         }
-        // If we have more than one client at least one mismatch occured.
-        if (clients_num > 1) {
-            EXPECT_GT(total_dist, 0);
-        } else {
+        if (clients_num < 2)  {
             EXPECT_EQ(total_dist, 0);
         }
     }
@@ -489,6 +588,10 @@ public:
     }
 
 private:
+    /// \brief Create DHCPv4 OFFER packet.
+    ///
+    /// \param transid transaction id.
+    /// \return instance of the packet.
     boost::shared_ptr<Pkt4>
     createOfferPkt4(uint32_t transid) const {
         boost::shared_ptr<Pkt4> offer(new Pkt4(DHCPOFFER, transid));
@@ -504,6 +607,10 @@ private:
         return (offer);
     }
 
+    /// \brief Create DHCPv6 ADVERTISE packet.
+    ///
+    /// \param transid transaction id.
+    /// \return instance of the packet.
     boost::shared_ptr<Pkt6>
     createAdvertisePkt6(uint32_t transid) const {
         OptionPtr opt_ia_na = Option::factory(Option::V6, D6O_IA_NA);
@@ -664,10 +771,12 @@ TEST_F(TestControlTest, Options6) {
     // Validate the D6O_ORO (Option Request Option).
     OptionPtr opt_oro(Option::factory(Option::V6, D6O_ORO));
     // Prepare the reference buffer with requested options.
-    const uint8_t requested_options[] = {
-        0, D6O_NAME_SERVERS,
-        0, D6O_DOMAIN_SEARCH
+    const uint16_t requested_options[] = {
+        htons(D6O_NAME_SERVERS),
+        htons(D6O_DOMAIN_SEARCH)
     };
+    int requested_options_num =
+        sizeof(requested_options) / sizeof(requested_options[0]);
     OptionBuffer
         requested_options_ref(requested_options,
                               requested_options + sizeof(requested_options));
@@ -677,9 +786,9 @@ TEST_F(TestControlTest, Options6) {
     // the same for comparison.
     EXPECT_EQ(requested_options_ref.size(), requested_options_buf.size());
     // Check if all options in the buffer are matched with reference buffer.
-    size_t matched_num = matchRequestedOptions(requested_options_ref,
-                                               requested_options_buf);
-    EXPECT_EQ(sizeof(requested_options), matched_num);
+    size_t matched_num = matchRequestedOptions6(requested_options_ref,
+                                                requested_options_buf);
+    EXPECT_EQ(requested_options_num, matched_num);
 
     // Validate the D6O_IA_NA option.
     OptionPtr opt_ia_na(Option::factory(Option::V6, D6O_IA_NA));
@@ -698,7 +807,7 @@ TEST_F(TestControlTest, Options6) {
     EXPECT_TRUE(std::equal(opt_ia_na_ref.begin(), opt_ia_na_ref.end(),
                            opt_ia_na_buf.begin()));
 
-    // TODO: Add more tests for IA address options.
+    // @todo Add more tests for IA address options.
 }
 
 TEST_F(TestControlTest, Packet4) {
@@ -826,7 +935,8 @@ TEST_F(TestControlTest, Packet6Exchange) {
     // Set number of received packets equal to number of iterations.
     // This simulates no packet drops.
     bool use_templates = false;
-    testPkt6Exchange(iterations_num, iterations_num, use_templates, iterations_performed);
+    testPkt6Exchange(iterations_num, iterations_num, use_templates,
+                     iterations_performed);
     // Actual number of iterations should be 10.
     EXPECT_EQ(10, iterations_performed);
 
@@ -841,20 +951,40 @@ TEST_F(TestControlTest, Packet6Exchange) {
     // then test should be interrupted and actual number of iterations will
     // be 6.
     const int received_num = 3;
-    testPkt6Exchange(iterations_num, received_num, use_templates, iterations_performed);
+    testPkt6Exchange(iterations_num, received_num, use_templates,
+                     iterations_performed);
     EXPECT_EQ(6, iterations_performed);
 }
 
 TEST_F(TestControlTest, PacketTemplates) {
+    std::vector<uint8_t> template1(256);
+    std::string file1("../templates/test1.hex");
+    std::vector<uint8_t> template2(233);
+    std::string file2("../templates/test2.hex");
+    for (int i = 0; i < template1.size(); ++i) {
+        template1[i] = static_cast<uint8_t>(random() % 256);
+    }
+    for (int i = 0; i < template2.size(); ++i) {
+        template2[i] = static_cast<uint8_t>(random() % 256);
+    }
+    ASSERT_TRUE(createTemplateFile(file1, template1));
+    ASSERT_TRUE(createTemplateFile(file2, template2));
     CommandOptions& options = CommandOptions::instance();
     NakedTestControl tc;
 
     ASSERT_NO_THROW(
         processCmdLine("perfdhcp -l 127.0.0.1"
-                       " -T ../templates/discover-example.hex"
-                       " -T ../templates/request4-example.hex all")
+                       " -T " + file1 + " -T " + file2 + " all")
     );
     ASSERT_NO_THROW(tc.initPacketTemplates());
+    TestControl::TemplateBuffer buf1;
+    TestControl::TemplateBuffer buf2;
+    ASSERT_NO_THROW(buf1 = tc.getTemplateBuffer(0));
+    ASSERT_NO_THROW(buf2 = tc.getTemplateBuffer(1));
+    ASSERT_EQ(template1.size(), buf1.size());
+    ASSERT_EQ(template2.size(), buf2.size());
+    EXPECT_TRUE(std::equal(template1.begin(), template1.end(), buf1.begin()));
+    EXPECT_TRUE(std::equal(template2.begin(), template2.end(), buf2.begin()));
 }
 
 TEST_F(TestControlTest, RateControl) {
@@ -879,4 +1009,5 @@ TEST_F(TestControlTest, RateControl) {
     xchgs_num = tc2.getNextExchangesNum();
     EXPECT_GT(xchgs_num, 0);
     EXPECT_LT(xchgs_num, options.getAggressivity());
+    // @todo add more thorough checks for rate values.
 }



More information about the bind10-changes mailing list