BIND 10 trac3181, updated. 3c33b14cb434d745187877e56dd3858648343281 [3181] Moved perfdhcp rate control logic to a new class.

BIND 10 source code commits bind10-changes at lists.isc.org
Fri Dec 6 13:08:13 UTC 2013


The branch, trac3181 has been updated
       via  3c33b14cb434d745187877e56dd3858648343281 (commit)
      from  68ec7bd3331f98e87e5a0f59cc0894d4e6792a84 (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 3c33b14cb434d745187877e56dd3858648343281
Author: Marcin Siodelski <marcin at isc.org>
Date:   Fri Dec 6 14:08:05 2013 +0100

    [3181] Moved perfdhcp rate control logic to a new class.

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

Summary of changes:
 tests/tools/perfdhcp/Makefile.am                   |    1 +
 tests/tools/perfdhcp/test_control.cc               |  162 +++++------------
 tests/tools/perfdhcp/test_control.h                |   62 ++-----
 tests/tools/perfdhcp/tests/Makefile.am             |    2 +
 .../tools/perfdhcp/tests/rate_control_unittest.cc  |  187 ++++++++++++++++++++
 .../tools/perfdhcp/tests/test_control_unittest.cc  |   60 ++-----
 6 files changed, 268 insertions(+), 206 deletions(-)
 create mode 100644 tests/tools/perfdhcp/tests/rate_control_unittest.cc

-----------------------------------------------------------------------
diff --git a/tests/tools/perfdhcp/Makefile.am b/tests/tools/perfdhcp/Makefile.am
index 31e5a31..014a4e2 100644
--- a/tests/tools/perfdhcp/Makefile.am
+++ b/tests/tools/perfdhcp/Makefile.am
@@ -25,6 +25,7 @@ perfdhcp_SOURCES += perf_pkt6.cc perf_pkt6.h
 perfdhcp_SOURCES += perf_pkt4.cc perf_pkt4.h
 perfdhcp_SOURCES += packet_storage.h
 perfdhcp_SOURCES += pkt_transform.cc pkt_transform.h
+perfdhcp_SOURCES += rate_control.cc rate_control.h
 perfdhcp_SOURCES += stats_mgr.h
 perfdhcp_SOURCES += test_control.cc test_control.h
 libb10_perfdhcp___la_CXXFLAGS = $(AM_CXXFLAGS)
diff --git a/tests/tools/perfdhcp/test_control.cc b/tests/tools/perfdhcp/test_control.cc
index 75adcd5..6e9e1b9 100644
--- a/tests/tools/perfdhcp/test_control.cc
+++ b/tests/tools/perfdhcp/test_control.cc
@@ -98,6 +98,21 @@ TestControl::TestControl() {
 }
 
 void
+TestControl::checkLateMessages(RateControl& rate_control) {
+    // If diagnostics is disabled, there is no need to log late sent messages.
+    // If it is enabled and the rate control object indicates that the last
+    // sent message was late, bump up the counter in Stats Manager.
+    if (rate_control.isLateSent() && testDiags('i')) {
+        CommandOptions& options = CommandOptions::instance();
+        if (options.getIpVersion() == 4) {
+            stats_mgr4_->incrementCounter("latesend");
+        } else if (options.getIpVersion() == 6) {
+            stats_mgr6_->incrementCounter("latesend");
+        }
+    }
+}
+
+void
 TestControl::cleanCachedPackets() {
     CommandOptions& options = CommandOptions::instance();
     // When Renews are not sent, Reply packets are not cached so there
@@ -504,23 +519,25 @@ TestControl::getCurrentTimeout() const {
     ptime now(microsec_clock::universal_time());
     // Check that we haven't passed the moment to send the next set of
     // packets.
-    if (now >= send_due_ ||
-        (options.getRenewRate() != 0 && now >= renew_due_) ||
-        (options.getReleaseRate() != 0 && now >= release_due_)) {
+    if (now >= basic_rate_control_.getDue() ||
+        (options.getRenewRate() != 0 && now >= renew_rate_control_.getDue()) ||
+        (options.getReleaseRate() != 0 &&
+         now >= release_rate_control_.getDue())) {
         return (0);
     }
 
     // Let's assume that the due time for Solicit is the soonest.
-    ptime due = send_due_;
+    ptime due = basic_rate_control_.getDue();
     // If we are sending Renews and due time for Renew occurs sooner,
     // set the due time to Renew due time.
-    if ((options.getRenewRate()) != 0 && (renew_due_ < due)) {
-        due = renew_due_;
+    if ((options.getRenewRate()) != 0 && (renew_rate_control_.getDue() < due)) {
+        due = renew_rate_control_.getDue();
     }
     // If we are sending Releases and the due time for Release occurs
     // sooner than the current due time, let's use the due for Releases.
-    if ((options.getReleaseRate() != 0) && (release_due_ < due)) {
-        due = release_due_;
+    if ((options.getReleaseRate() != 0) &&
+        (release_rate_control_.getDue() < due)) {
+        due = release_rate_control_.getDue();
     }
     // Return the timeout in microseconds.
     return (time_period(now, due).length().total_microseconds());
@@ -554,49 +571,6 @@ TestControl::getElapsedTime(const T& pkt1, const T& pkt2) {
     return(elapsed_period.length().total_milliseconds());
 }
 
-
-uint64_t
-TestControl::getNextExchangesNum(const boost::posix_time::ptime& send_due,
-                                 const int rate) {
-    CommandOptions& options = CommandOptions::instance();
-    // Get current time.
-    ptime now(microsec_clock::universal_time());
-    if (now >= send_due) {
-        // Reset number of exchanges.
-        uint64_t due_exchanges = 0;
-        // If rate is specified from the command line we have to
-        // synchornize with it.
-        if (rate != 0) {
-            time_period period(send_due, now);
-            time_duration duration = period.length();
-            // due_factor indicates the number of seconds that
-            // sending next chunk of packets will take.
-            double due_factor = duration.fractional_seconds() /
-                time_duration::ticks_per_second();
-            due_factor += duration.total_seconds();
-            // Multiplying due_factor by expected rate gives the number
-            // of exchanges to be initiated.
-            due_exchanges = static_cast<uint64_t>(due_factor * rate);
-            // We want to make sure that at least one packet goes out.
-            if (due_exchanges == 0) {
-                due_exchanges = 1;
-            }
-            // We should not exceed aggressivity as it could have been
-            // restricted from command line.
-            if (due_exchanges > options.getAggressivity()) {
-                due_exchanges = options.getAggressivity();
-            }
-        } else {
-            // Rate is not specified so we rely on aggressivity
-            // which is the number of packets to be sent in
-            // one chunk.
-            due_exchanges = options.getAggressivity();
-        }
-        return (due_exchanges);
-    }
-    return (0);
-}
-
 int
 TestControl::getRandomOffset(const int arg_idx) const {
     int rand_offset = CommandOptions::instance().getIpVersion() == 4 ?
@@ -1280,14 +1254,16 @@ TestControl::registerOptionFactories() const {
 
 void
 TestControl::reset() {
-    send_due_ = microsec_clock::universal_time();
-    last_sent_ = send_due_;
-    last_report_ = send_due_;
-    renew_due_ = send_due_;
-    release_due_ = send_due_;
-    last_renew_ = send_due_;
-    last_release_ = send_due_;
+    CommandOptions& options = CommandOptions::instance();
+    basic_rate_control_.setAggressivity(options.getAggressivity());
+    basic_rate_control_.setRate(options.getRate());
+    renew_rate_control_.setAggressivity(options.getAggressivity());
+    renew_rate_control_.setRate(options.getRenewRate());
+    release_rate_control_.setAggressivity(options.getAggressivity());
+    release_rate_control_.setRate(options.getReleaseRate());
+
     transid_gen_.reset();
+    last_report_ = microsec_clock::universal_time();
     // Actual generators will have to be set later on because we need to
     // get command line parameters first.
     setTransidGenerator(NumberGeneratorPtr());
@@ -1353,11 +1329,10 @@ TestControl::run() {
     // Initialize Statistics Manager. Release previous if any.
     initializeStatsMgr();
     for (;;) {
-        // Calculate send due based on when last exchange was initiated.
-        updateSendDue(last_sent_, options.getRate(), send_due_);
         // Calculate number of packets to be sent to stay
         // catch up with rate.
-        uint64_t packets_due = getNextExchangesNum(send_due_, options.getRate());
+        uint64_t packets_due = basic_rate_control_.getOutboundMessageCount();
+        checkLateMessages(basic_rate_control_);
         if ((packets_due == 0) && testDiags('i')) {
             if (options.getIpVersion() == 4) {
                 stats_mgr4_->incrementCounter("shortwait");
@@ -1383,9 +1358,9 @@ TestControl::run() {
         // If -f<renew-rate> option was specified we have to check how many
         // Renew packets should be sent to catch up with a desired rate.
         if ((options.getIpVersion() == 6) && (options.getRenewRate() != 0)) {
-            updateSendDue(last_renew_, options.getRenewRate(), renew_due_);
             uint64_t renew_packets_due =
-                getNextExchangesNum(renew_due_, options.getRenewRate());
+                renew_rate_control_.getOutboundMessageCount();
+            checkLateMessages(renew_rate_control_);
             // Send Renew messages.
             sendMultipleMessages6(socket, DHCPV6_RENEW, renew_packets_due);
         }
@@ -1393,10 +1368,9 @@ TestControl::run() {
         // If -F<release-rate> option was specified we have to check how many
         // Release messages should be sent to catch up with a desired rate.
         if ((options.getIpVersion() == 6) && (options.getReleaseRate() != 0)) {
-            updateSendDue(last_release_, options.getReleaseRate(),
-                          release_due_);
             uint64_t release_packets_due =
-                getNextExchangesNum(release_due_, options.getReleaseRate());
+                release_rate_control_.getOutboundMessageCount();
+            checkLateMessages(release_rate_control_);
             // Send Release messages.
             sendMultipleMessages6(socket, DHCPV6_RELEASE, release_packets_due);
         }
@@ -1494,7 +1468,7 @@ TestControl::saveFirstPacket(const Pkt6Ptr& pkt) {
 void
 TestControl::sendDiscover4(const TestControlSocket& socket,
                            const bool preload /*= false*/) {
-    last_sent_ = microsec_clock::universal_time();
+    basic_rate_control_.updateSendTime();
     // Generate the MAC address to be passed in the packet.
     uint8_t randomized = 0;
     std::vector<uint8_t> mac_address = generateMacAddress(randomized);
@@ -1539,9 +1513,7 @@ void
 TestControl::sendDiscover4(const TestControlSocket& socket,
                            const std::vector<uint8_t>& template_buf,
                            const bool preload /* = false */) {
-    // last_sent_ has to be updated for each function that initiates
-    // new transaction. The packet exchange synchronization relies on this.
-    last_sent_ = microsec_clock::universal_time();
+    basic_rate_control_.updateSendTime();
     // Get the first argument if mulitple the same arguments specified
     // in the command line. First one refers to DISCOVER packets.
     const uint8_t arg_idx = 0;
@@ -1599,9 +1571,9 @@ TestControl::sendMessageFromReply(const uint16_t msg_type,
     }
     // We track the timestamp of last Release and Renew in different variables.
     if (msg_type == DHCPV6_RENEW) {
-        last_renew_ = microsec_clock::universal_time();
+        renew_rate_control_.updateSendTime();
     } else {
-        last_release_ = microsec_clock::universal_time();
+        release_rate_control_.updateSendTime();
     }
     Pkt6Ptr reply = reply_storage_.getRandom();
     if (!reply) {
@@ -1960,7 +1932,7 @@ TestControl::sendRequest6(const TestControlSocket& socket,
 void
 TestControl::sendSolicit6(const TestControlSocket& socket,
                           const bool preload /*= false*/) {
-    last_sent_ = microsec_clock::universal_time();
+    basic_rate_control_.updateSendTime();
     // Generate DUID to be passed to the packet
     uint8_t randomized = 0;
     std::vector<uint8_t> duid = generateDuid(randomized);
@@ -2009,7 +1981,7 @@ void
 TestControl::sendSolicit6(const TestControlSocket& socket,
                           const std::vector<uint8_t>& template_buf,
                           const bool preload /*= false*/) {
-    last_sent_ = microsec_clock::universal_time();
+    basic_rate_control_.updateSendTime();
     const int arg_idx = 0;
     // Get transaction id offset.
     size_t transid_offset = getTransactionIdOffset(arg_idx);
@@ -2108,47 +2080,5 @@ TestControl::testDiags(const char diag) const {
     return (false);
 }
 
-void
-TestControl::updateSendDue(const boost::posix_time::ptime& last_sent,
-                           const int rate,
-                           boost::posix_time::ptime& send_due) {
-    // If default constructor was called, this should not happen but
-    // if somebody has changed default constructor it is better to
-    // keep this check.
-    if (last_sent.is_not_a_date_time()) {
-        isc_throw(Unexpected, "time of last sent packet not initialized");
-    }
-    // Get the expected exchange rate.
-    CommandOptions& options = CommandOptions::instance();
-    // If rate was not specified we will wait just one clock tick to
-    // send next packet. This simulates best effort conditions.
-    long duration = 1;
-    if (rate != 0) {
-        // We use number of ticks instead of nanoseconds because
-        // nanosecond resolution may not be available on some
-        // machines. Number of ticks guarantees the highest possible
-        // timer resolution.
-        duration = time_duration::ticks_per_second() / rate;
-    }
-    // Calculate due time to initiate next chunk of exchanges.
-    send_due = last_sent + time_duration(0, 0, 0, duration);
-    // Check if it is already due.
-    ptime now(microsec_clock::universal_time());
-    // \todo verify if this condition is not too tight. In other words
-    // verify if this will not produce too many late sends.
-    // We might want to look at this once we are done implementing
-    // microsecond timeouts in IfaceMgr.
-    if (now > send_due) {
-        if (testDiags('i')) {
-            if (options.getIpVersion() == 4) {
-                stats_mgr4_->incrementCounter("latesend");
-            } else if (options.getIpVersion() == 6) {
-                stats_mgr6_->incrementCounter("latesend");
-            }
-        }
-    }
-}
-
-
 } // namespace perfdhcp
 } // namespace isc
diff --git a/tests/tools/perfdhcp/test_control.h b/tests/tools/perfdhcp/test_control.h
index c949ee7..3b3cdb7 100644
--- a/tests/tools/perfdhcp/test_control.h
+++ b/tests/tools/perfdhcp/test_control.h
@@ -15,8 +15,9 @@
 #ifndef TEST_CONTROL_H
 #define TEST_CONTROL_H
 
-#include "packet_storage.h"
-#include "stats_mgr.h"
+#include <tests/tools/perfdhcp/packet_storage.h>
+#include <tests/tools/perfdhcp/rate_control.h>
+#include <tests/tools/perfdhcp/stats_mgr.h>
 
 #include <dhcp/iface_mgr.h>
 #include <dhcp/dhcp6.h>
@@ -491,21 +492,6 @@ protected:
     /// \return A current timeout in microseconds.
     uint32_t getCurrentTimeout() const;
 
-    /// \brief Returns number of exchanges to be started.
-    ///
-    /// 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 updateSendDue function and expected rate.
-    ///
-    /// \param send_due Due time to initiate next chunk set exchanges.
-    /// \param rate A rate at which exchanges are initiated.
-    ///
-    /// \return number of exchanges to be started immediately.
-    static uint64_t
-    getNextExchangesNum(const boost::posix_time::ptime& send_due,
-                        const int rate);
-
     /// \brief Return template buffer.
     ///
     /// Method returns template buffer at specified index.
@@ -916,21 +902,18 @@ protected:
     /// \return true if diagnostics flag has been set.
     bool testDiags(const char diag) const;
 
-    /// \brief Update due time to initiate next chunk of exchanges.
+protected:
+
+    /// \brief Increments counter of late sent messages if required.
     ///
-    /// Method updates due time to initiate next chunk of exchanges.
-    /// Function takes current time, last sent packet's time and
-    /// expected rate in its calculations.
+    /// This function checks if the message or set of messages of a given type,
+    /// were sent later than their due time. If they were sent late, it is
+    /// an indication that the perfdhcp doesn't catch up with the desired rate
+    /// for sending messages.
     ///
-    /// \param last_sent A time when the last exchange was initiated.
-    /// \param rate A rate at which exchangesa re initiated
-    /// \param [out] send_due A reference to the time object to be updated
-    /// with the next due time.
-    void updateSendDue(const boost::posix_time::ptime& last_sent,
-                       const int rate,
-                       boost::posix_time::ptime& send_due);
-
-protected:
+    /// \param rate_control An object tracking due times for a particular
+    /// type of messages.
+    void checkLateMessages(RateControl& rate_control);
 
     /// \brief Copies IA_NA or IA_PD option from one packet to another.
     ///
@@ -1073,20 +1056,13 @@ protected:
     std::string vector2Hex(const std::vector<uint8_t>& vec,
                            const std::string& separator = "") const;
 
-protected:
+    /// \brief A rate control class for Discover and Solicit messages.
+    RateControl basic_rate_control_;
+    /// \brief A rate control class for Renew messages.
+    RateControl renew_rate_control_;
+    /// \brief A rate control class for Release messages.
+    RateControl release_rate_control_;
 
-    boost::posix_time::ptime send_due_;    ///< Due time to initiate next chunk
-                                           ///< of exchanges.
-    boost::posix_time::ptime last_sent_;   ///< Indicates when the last exchange
-                                           ///< was initiated.
-    boost::posix_time::ptime renew_due_;   ///< Due time to send next set of
-                                           ///< Renew requests.
-    boost::posix_time::ptime release_due_; ///< Due time to send next set of
-                                           ///< Release requests.
-    boost::posix_time::ptime last_renew_;  ///< Indicates when the last Renew
-                                           ///< was attempted.
-    boost::posix_time::ptime last_release_;///< Indicates when the last Release
-                                           ///< was attempted.
     boost::posix_time::ptime last_report_; ///< Last intermediate report time.
 
     StatsMgr4Ptr stats_mgr4_;  ///< Statistics Manager 4.
diff --git a/tests/tools/perfdhcp/tests/Makefile.am b/tests/tools/perfdhcp/tests/Makefile.am
index e48757a..64f446b 100644
--- a/tests/tools/perfdhcp/tests/Makefile.am
+++ b/tests/tools/perfdhcp/tests/Makefile.am
@@ -26,6 +26,7 @@ run_unittests_SOURCES += perf_pkt6_unittest.cc
 run_unittests_SOURCES += perf_pkt4_unittest.cc
 run_unittests_SOURCES += localized_option_unittest.cc
 run_unittests_SOURCES += packet_storage_unittest.cc
+run_unittests_SOURCES += rate_control_unittest.cc
 run_unittests_SOURCES += stats_mgr_unittest.cc
 run_unittests_SOURCES += test_control_unittest.cc
 run_unittests_SOURCES += command_options_helper.h
@@ -33,6 +34,7 @@ run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/command_options.cc
 run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/pkt_transform.cc
 run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/perf_pkt6.cc
 run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/perf_pkt4.cc
+run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/rate_control.cc
 run_unittests_SOURCES += $(top_builddir)/tests/tools/perfdhcp/test_control.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
diff --git a/tests/tools/perfdhcp/tests/rate_control_unittest.cc b/tests/tools/perfdhcp/tests/rate_control_unittest.cc
new file mode 100644
index 0000000..ae1897a
--- /dev/null
+++ b/tests/tools/perfdhcp/tests/rate_control_unittest.cc
@@ -0,0 +1,187 @@
+// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <exceptions/exceptions.h>
+#include <tests/tools/perfdhcp/rate_control.h>
+#include <gtest/gtest.h>
+
+
+using namespace isc;
+using namespace isc::perfdhcp;
+
+/// \brief A class which exposes protected methods and members of the
+/// RateControl class (under test).
+class NakedRateControl : public RateControl {
+public:
+
+    /// \brief Default constructor.
+    NakedRateControl()
+        : RateControl() {
+    }
+
+    /// \brief Constructor which sets up the rate and aggressivity.
+    ///
+    /// \param rate A rate at which messages are sent.
+    /// \param aggressivity A value of aggressivity. This value controls the
+    /// maximal number of messages sent in one chunk.
+    NakedRateControl(const int rate, const int aggressivity)
+        : RateControl(rate, aggressivity) {
+    }
+
+    using RateControl::currentTime;
+    using RateControl::updateSendTime;
+    using RateControl::updateSendDue;
+    using RateControl::send_due_;
+    using RateControl::last_sent_;
+    using RateControl::late_sent_;
+
+};
+
+// Test default constructor.
+TEST(RateControl, constructorDefault) {
+    NakedRateControl rc;
+    EXPECT_EQ(1, rc.getAggressivity());
+    EXPECT_EQ(0, rc.getRate());
+    EXPECT_FALSE(rc.getDue().is_not_a_date_time());
+    EXPECT_FALSE(rc.last_sent_.is_not_a_date_time());
+    EXPECT_FALSE(rc.isLateSent());
+}
+
+// Test the constructor which sets the rate and aggressivity.
+TEST(RateControl, constructor) {
+    // Call the constructor and verify that it sets the appropriate
+    // values.
+    NakedRateControl rc1(3, 2);
+    EXPECT_EQ(2, rc1.getAggressivity());
+    EXPECT_EQ(3, rc1.getRate());
+    EXPECT_FALSE(rc1.getDue().is_not_a_date_time());
+    EXPECT_FALSE(rc1.last_sent_.is_not_a_date_time());
+    EXPECT_FALSE(rc1.isLateSent());
+
+    // Call the constructor again and make sure that different values
+    // will be set correctly.
+    NakedRateControl rc2(5, 6);
+    EXPECT_EQ(6, rc2.getAggressivity());
+    EXPECT_EQ(5, rc2.getRate());
+    EXPECT_FALSE(rc2.getDue().is_not_a_date_time());
+    EXPECT_FALSE(rc2.last_sent_.is_not_a_date_time());
+    EXPECT_FALSE(rc2.isLateSent());
+
+    // The 0 value of aggressivity < 1 is not acceptable.
+    EXPECT_THROW(RateControl(3, 0), isc::BadValue);
+}
+
+// Check the aggressivity accessor.
+TEST(RateControl, getAggressivity) {
+    RateControl rc;
+    ASSERT_EQ(1, rc.getAggressivity());
+    rc.setAggressivity(5);
+    ASSERT_EQ(5, rc.getAggressivity());
+    rc.setAggressivity(10);
+    EXPECT_EQ(10, rc.getAggressivity());
+}
+
+// Check the due time accessor.
+TEST(RateControl, getDue) {
+    NakedRateControl rc;
+    ASSERT_FALSE(rc.getDue().is_not_a_date_time());
+    rc.send_due_ = NakedRateControl::currentTime();
+    EXPECT_TRUE(NakedRateControl::currentTime() >= rc.getDue());
+    rc.send_due_ = NakedRateControl::currentTime() + boost::posix_time::seconds(10);
+    EXPECT_TRUE(NakedRateControl::currentTime() < rc.getDue());
+}
+
+// Check the rate accessor.
+TEST(RateControl, getRate) {
+    RateControl rc;
+    ASSERT_EQ(0, rc.getRate());
+    rc.setRate(5);
+    ASSERT_EQ(5, rc.getRate());
+    rc.setRate(10);
+    EXPECT_EQ(10, rc.getRate());
+}
+
+// Check if late send flag accessor.
+TEST(RateControl, isLateSent) {
+    NakedRateControl rc;
+    ASSERT_FALSE(rc.isLateSent());
+    rc.late_sent_ = true;
+    EXPECT_TRUE(rc.isLateSent());
+}
+
+// Check that the function returns the number of messages to be sent "now"
+// correctly.
+// @todo Possibly extend this test to cover more complex scenarios. Note that
+// it is quite hard to fully test this function as its behaviour strongly
+// depends on time.
+TEST(RateControl, getOutboundMessageCount) {
+    NakedRateControl rc1;
+    // Set the timestamp of the last sent message well to the past.
+    // The resulting due time will be in the past too.
+    rc1.last_sent_ =
+        NakedRateControl::currentTime() - boost::posix_time::seconds(5);
+    // The number of messages to be sent must be greater than 0.
+    uint64_t count;
+    ASSERT_NO_THROW(count = rc1.getOutboundMessageCount());
+    EXPECT_GT(count, 0);
+    // Now, don't specify the rate. In this case the aggressivity dictates
+    // how many messages to send.
+    NakedRateControl rc2(0, 3);
+    rc2.last_sent_ =
+        NakedRateControl::currentTime() - boost::posix_time::seconds(5);
+    ASSERT_NO_THROW(count = rc2.getOutboundMessageCount());
+    EXPECT_EQ(3, count);
+    // Specify the rate and set the timestamp of the last sent message well
+    // to the future. If the resulting due time is well in the future too,
+    // the number of messages to be sent must be 0.
+    NakedRateControl rc3(10, 3);
+    rc3.last_sent_ = NakedRateControl::currentTime() + boost::posix_time::seconds(5);
+    ASSERT_NO_THROW(count = rc3.getOutboundMessageCount());
+    EXPECT_EQ(0, count);
+
+}
+
+// Test the function which calculates the due time to send next set of
+// messages.
+TEST(RateControl, updateSendDue) {
+    NakedRateControl rc;
+    // Set the send due timestamp to the value which is well in the future.
+    // If we don't hit the due time, the function should not modify the
+    // due time.
+    rc.send_due_ =
+        NakedRateControl::currentTime() + boost::posix_time::seconds(10);
+    boost::posix_time::ptime last_send_due = rc.send_due_;
+    ASSERT_NO_THROW(rc.updateSendDue());
+    EXPECT_TRUE(rc.send_due_ == last_send_due);
+    // Set the due time to the value which is already behind.
+    rc.send_due_ =
+        NakedRateControl::currentTime() - boost::posix_time::seconds(10);
+    last_send_due = rc.send_due_;
+    ASSERT_NO_THROW(rc.updateSendDue());
+    // The value should be modified to the new value.
+    EXPECT_TRUE(rc.send_due_ != last_send_due);
+
+}
+
+// Test that the message send time is updated to the current time.
+TEST(RateControl, updateSendTime) {
+    NakedRateControl rc;
+    // Set the timestamp to the future.
+    rc.last_sent_ =
+        NakedRateControl::currentTime() + boost::posix_time::seconds(5);
+    rc.updateSendTime();
+    // Updated timestamp should be set to now or to the past.
+    EXPECT_TRUE(rc.last_sent_ <= NakedRateControl::currentTime());
+
+}
diff --git a/tests/tools/perfdhcp/tests/test_control_unittest.cc b/tests/tools/perfdhcp/tests/test_control_unittest.cc
index 384ae4a..b84d58d 100644
--- a/tests/tools/perfdhcp/tests/test_control_unittest.cc
+++ b/tests/tools/perfdhcp/tests/test_control_unittest.cc
@@ -92,12 +92,9 @@ public:
     void setRelativeDueTimes(const int send_secs, const int renew_secs = 0,
                              const int release_secs = 0) {
         ptime now = microsec_clock::universal_time();
-        send_due_ = send_secs > 0 ?
-            now + seconds(abs(send_secs)) : now - seconds(abs(send_secs));
-        renew_due_ = renew_secs > 0 ?
-            now + seconds(abs(renew_secs)) : now - seconds(abs(renew_secs));
-        release_due_ = release_secs > 0 ?
-            now + seconds(abs(release_secs)) : now - seconds(abs(release_secs));
+        basic_rate_control_.setRelativeDue(send_secs);
+        renew_rate_control_.setRelativeDue(renew_secs);
+        release_rate_control_.setRelativeDue(release_secs);
 
     }
 
@@ -112,7 +109,6 @@ public:
     using TestControl::generateDuid;
     using TestControl::generateMacAddress;
     using TestControl::getCurrentTimeout;
-    using TestControl::getNextExchangesNum;
     using TestControl::getTemplateBuffer;
     using TestControl::initPacketTemplates;
     using TestControl::initializeStatsMgr;
@@ -128,13 +124,10 @@ public:
     using TestControl::sendSolicit6;
     using TestControl::setDefaults4;
     using TestControl::setDefaults6;
-    using TestControl::send_due_;
-    using TestControl::last_sent_;
+    using TestControl::basic_rate_control_;
+    using TestControl::renew_rate_control_;
+    using TestControl::release_rate_control_;
     using TestControl::last_report_;
-    using TestControl::renew_due_;
-    using TestControl::release_due_;
-    using TestControl::last_renew_;
-    using TestControl::last_release_;
     using TestControl::transid_gen_;
     using TestControl::macaddr_gen_;
     using TestControl::first_packet_serverid_;
@@ -913,16 +906,16 @@ public:
 
 // This test verifies that the class members are reset to expected values.
 TEST_F(TestControlTest, reset) {
+    ASSERT_NO_THROW(processCmdLine("perfdhcp -6 -l ethx -r 50 -f 30 -F 10 -a 3 all"));
     NakedTestControl tc;
     tc.reset();
-    EXPECT_FALSE(tc.send_due_.is_not_a_date_time());
-    EXPECT_FALSE(tc.last_sent_.is_not_a_date_time());
+    EXPECT_EQ(3, tc.basic_rate_control_.getAggressivity());
+    EXPECT_EQ(3, tc.renew_rate_control_.getAggressivity());
+    EXPECT_EQ(3, tc.release_rate_control_.getAggressivity());
+    EXPECT_EQ(50, tc.basic_rate_control_.getRate());
+    EXPECT_EQ(30, tc.renew_rate_control_.getRate());
+    EXPECT_EQ(10, tc.release_rate_control_.getRate());
     EXPECT_FALSE(tc.last_report_.is_not_a_date_time());
-    EXPECT_FALSE(tc.renew_due_.is_not_a_date_time());
-    EXPECT_FALSE(tc.release_due_.is_not_a_date_time());
-    EXPECT_FALSE(tc.last_renew_.is_not_a_date_time());
-    EXPECT_FALSE(tc.last_release_.is_not_a_date_time());
-    EXPECT_FALSE(tc.send_due_.is_not_a_date_time());
     EXPECT_FALSE(tc.transid_gen_);
     EXPECT_FALSE(tc.macaddr_gen_);
     EXPECT_TRUE(tc.first_packet_serverid_.empty());
@@ -1446,33 +1439,6 @@ TEST_F(TestControlTest, PacketTemplates) {
     EXPECT_THROW(tc.initPacketTemplates(), isc::BadValue);
 }
 
-TEST_F(TestControlTest, RateControl) {
-    // We don't specify the exchange rate here so the aggressivity
-    // value will determine how many packets are to be send each
-    // time we query the getNextExchangesNum.
-    ASSERT_NO_THROW(processCmdLine("perfdhcp -l 127.0.0.1 all"));
-    CommandOptions& options = CommandOptions::instance();
-
-    NakedTestControl tc1;
-    uint64_t xchgs_num = tc1.getNextExchangesNum(microsec_clock::universal_time(),
-                                                 options.getRate());
-    EXPECT_EQ(options.getAggressivity(), xchgs_num);
-
-    // The exchange rate is now 1 per second. We don't know how many
-    // exchanges have to initiated exactly but for sure it has to be
-    // non-zero value. Also, since aggressivity is very high we expect
-    // that it will not be restricted by aggressivity.
-    ASSERT_NO_THROW(
-        processCmdLine("perfdhcp -l 127.0.0.1 -a 1000000 -r 1 all")
-    );
-    NakedTestControl tc2;
-    xchgs_num = tc2.getNextExchangesNum(microsec_clock::universal_time(),
-                                        options.getRate());
-    EXPECT_GT(xchgs_num, 0);
-    EXPECT_LT(xchgs_num, options.getAggressivity());
-    // @todo add more thorough checks for rate values.
-}
-
 TEST_F(TestControlTest, processRenew) {
     testSendRenewRelease(DHCPV6_RENEW);
 }



More information about the bind10-changes mailing list