From: Marcin Siodelski Date: Thu, 19 Jul 2012 14:48:19 +0000 (+0200) Subject: [1958] Provided access to all basic counters and created corresponding unit tests. X-Git-Tag: trac2351_base~113^2~20^2~1^2~17 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5d2116c14a18c5aa2f41fa75e0f893ad8a645bf3;p=thirdparty%2Fkea.git [1958] Provided access to all basic counters and created corresponding unit tests. --- diff --git a/tests/tools/perfdhcp/stats_mgr.h b/tests/tools/perfdhcp/stats_mgr.h index b224fa7d8b..0fed0ae0a2 100644 --- a/tests/tools/perfdhcp/stats_mgr.h +++ b/tests/tools/perfdhcp/stats_mgr.h @@ -85,7 +85,9 @@ public: boost::multi_index::sequenced<>, boost::multi_index::hashed_non_unique< boost::multi_index::global_fun< - boost::shared_ptr, uint32_t, &ExchangeStats::transid_hash + boost::shared_ptr, + uint32_t, + &ExchangeStats::transid_hash > > > @@ -111,7 +113,9 @@ public: square_sum_delay_(0.), ordered_lookups_(0), unordered_lookup_size_sum_(0), - unordered_lookups_(0) { + unordered_lookups_(0), + sent_packets_num_(0), + rcvd_packets_num_(0) { sent_packets_cache_ = sent_packets_.begin(); } @@ -121,6 +125,7 @@ public: /// /// \param packet packet object to be added. void appendSent(const boost::shared_ptr packet) { + ++sent_packets_num_; sent_packets_.template get<0>().push_back(packet); } @@ -130,9 +135,55 @@ public: /// /// \param packet packet object to be added. void appendRcvd(const boost::shared_ptr packet) { + ++rcvd_packets_num_; rcvd_packets_.template get<0>().push_back(packet); } + /// \brief Update delay counters. + /// + /// Method updates delay counters based on timestamps of + /// sent and received packets. + /// + /// \param sent_packet sent packet + /// \param rcvd_packet received packet + /// \throw isc::Unexpected if failed to calculate timestamps + void updateDelays(const boost::shared_ptr sent_packet, + const boost::shared_ptr rcvd_packet) { + boost::posix_time::ptime sent_time = sent_packet->getTimestamp(); + boost::posix_time::ptime rcvd_time = rcvd_packet->getTimestamp(); + + if (sent_time.is_not_a_date_time() || + rcvd_time.is_not_a_date_time()) { + isc_throw(Unexpected, + "Timestamp must be set for sent and " + "received packet to measure RTT"); + } + boost::posix_time::time_period period(sent_time, rcvd_time); + // We don't bother calculating deltas in nanoseconds. It is much + // more convenient to use seconds instead because we are going to + // sum them up. + double delta = + static_cast(period.length().total_nanoseconds()) / 1e9; + + if (delta < 0) { + isc_throw(Unexpected, "Sent packet's timestamp must not be " + "greater than received packet's timestamp"); + } + + // Record the minimum delay between sent and received packets. + if (delta < min_delay_) { + min_delay_ = delta; + } + // Record the maximum delay between sent and received packets. + if (delta > max_delay_) { + max_delay_ = delta; + } + // Update delay sum and square sum. That will be used to calculate + // mean delays. + sum_delay_ += delta; + square_sum_delay_ += delta * delta; + } + /// \brief Find packet on the list of sent packets. /// /// Method finds packet with specified transaction id on the list @@ -149,21 +200,54 @@ public: /// not found boost::shared_ptr findSent(const uint32_t transid) { if (sent_packets_.size() == 0) { + // List of sent packets is empty so there is no sense + // to continue looking fo the packet. It also means + // that the received packet we got has no corresponding + // sent packet so orphans counter has to be updated. ++orphans_; return boost::shared_ptr(); } else if (sent_packets_cache_ == sent_packets_.end()) { + // Even if there are still many unmatched packets on the + // list we might hit the end of it because of unordered + // lookups. The next logical step is to reset cache. sent_packets_cache_ = sent_packets_.begin(); } + // With this variable we will be signalling success or failure + // to find the packet. bool packet_found = false; + // Most likely responses are sent from the server in the same + // order as client's requests to the server. We are caching + // next sent packet and first try to match with it the next + // incoming packet. We are successful if there is no + // packet drop or out of order packets sent. This is actually + // the fastest way to look for packets. if ((*sent_packets_cache_)->getTransid() == transid) { ++ordered_lookups_; packet_found = true; } else { + // If we are here, it means that we were unable to match the + // next incoming packet with next sent packet so we need to + // take a little more expensive approach to look packets using + // alternative index (transaction id & 1023). PktListTransidIndex& idx = sent_packets_.template get<1>(); + // Packets are grouped using trasaction id masking with value + // of 1023. For instance, packets with transaction id equal to + // 1, 1024 ... will belong to the same group (a.k.a. bucket). + // When using alternative index we don't find the packet but + // bucket of packets and need to iterate through the bucket + // to find the one that has desired transaction id. std::pair p = idx.equal_range(transid & 1023); + // We want to keep statistics of unordered lookups to make + // sure that there is a right balance before number of + // unordered lookups and ordered lookups. If number of unordered + // lookups is high it may mean that many packets are lost or + // sent out of order. ++unordered_lookups_; + // We also want to keep the mean value of the bucket. The lower + // bucket size the better. If bucket sizes appear to big we + // might want to increase number of buckets. unordered_lookup_size_sum_ += std::distance(p.first, p.second); for (PktListTransidIterator it = p.first; it != p.second; ++it) { @@ -177,53 +261,20 @@ public: } if (!packet_found) { + // If we are here, it means that both ordered lookup and + // unordered lookup failed. Searched packet is not on the list. ++orphans_; return boost::shared_ptr(); } boost::shared_ptr sent_packet(*sent_packets_cache_); - ++sent_packets_cache_; + // If packet was found, we assume it will be never searched + // again. We want to delete this packet from the list to + // improve performance of future searches. + sent_packets_cache_ = eraseSent(sent_packets_cache_); return sent_packet; } - /// \brief Update delay counters. - /// - /// Method updates delay counters based on timestamps of - /// sent and received packets. - /// - /// \param sent_packet sent packet - /// \param rcvd_packet received packet - /// \throw isc::Unexpected if failed to calculate timestamps - void updateDelays(const boost::shared_ptr sent_packet, - const boost::shared_ptr rcvd_packet) { - boost::posix_time::ptime sent_time = sent_packet->getTimestamp(); - boost::posix_time::ptime rcvd_time = rcvd_packet->getTimestamp(); - - if (sent_time.is_not_a_date_time() || - rcvd_time.is_not_a_date_time()) { - isc_throw(Unexpected, - "Timestamp must be set for sent and " - "received packet to measure RTT"); - } - boost::posix_time::time_period period(sent_time, rcvd_time); - double delta = - static_cast(period.length().total_nanoseconds()) / 1e9; - - if (delta < 0) { - isc_throw(Unexpected, "Sent packet's timestamp must not be " - "greater than received packet's timestamp"); - } - - if (delta < min_delay_) { - min_delay_ = delta; - } - if (delta > max_delay_) { - max_delay_ = delta; - } - sum_delay_ += delta; - square_sum_delay_ += delta * delta; - } - /// \brief Return minumum delay between sent and received packet. /// /// Method returns minimum delay between sent and received packet. @@ -271,6 +322,9 @@ public: /// /// \return average unordered lookup set size. double getAvgUnorderedLookupSetSize() const { + if (unordered_lookups_ == 0) { + return 0.; + } return static_cast(unordered_lookup_size_sum_) / static_cast(unordered_lookups_); } @@ -285,7 +339,6 @@ public: /// \return number of unordered lookups. uint64_t getUnorderedLookups() const { return unordered_lookups_; } - /// \brief Return number of ordered sent packets lookups /// /// Method returns number of ordered sent packet lookups. @@ -296,6 +349,25 @@ public: /// /// \return number of ordered lookups. uint64_t getOrderedLookups() const { return ordered_lookups_; } + + /// \brief Return total number of sent packets + /// + /// Method returns total number of sent packets. + /// + /// \return number of sent packets. + uint64_t getSentPacketsNum() const { + return sent_packets_num_; + } + + /// \brief Return total number of received packets + /// + /// Method returns total number of received packets. + /// + /// \return number of received packets. + uint64_t getRcvdPacketsNum() const { + return rcvd_packets_num_; + } + private: /// \brief Private default constructor. @@ -304,6 +376,18 @@ public: /// class to specify exchange type explicitely. ExchangeStats(); + + /// \brief Erase packet from the list of sent packets. + /// + /// Method erases packet from the list of sent packets. + /// + /// \param it iterator pointing to packet to be erased. + /// \return iterator pointing to packet following erased + /// packet or sent_packets_.end() if packet not found. + PktListIterator eraseSent(const PktListIterator it) { + return sent_packets_.template get<0>().erase(it); + } + ExchangeType xchg_type_; ///< Packet exchange type. PktList sent_packets_; ///< List of sent packets. @@ -337,6 +421,8 @@ public: uint64_t ordered_lookups_; ///< Number of ordered sent packets ///< lookups. + uint64_t sent_packets_num_; ///< Total number of sent packets. + uint64_t rcvd_packets_num_; ///< Total number of received packets. }; /// Pointer to ExchangeStats. @@ -400,6 +486,59 @@ public: } } + /// \brief Return minumum delay between sent and received packet. + /// + /// Method returns minimum delay between sent and received packet + /// for specified exchange type. + /// + /// \param xchg_type exchange type. + /// \throw isc::BadValue if invalid exchange type specified. + /// \return minimum delay between packets. + double getMinDelay(const ExchangeType xchg_type) const { + ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type); + return xchg_stats->getMinDelay(); + } + + /// \brief Return maxmimum delay between sent and received packet. + /// + /// Method returns maximum delay between sent and received packet + /// for specified exchange type. + /// + /// \param xchg_type exchange type. + /// \throw isc::BadValue if invalid exchange type specified. + /// \return maximum delay between packets. + double getMaxDelay(const ExchangeType xchg_type) const { + ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type); + return xchg_stats->getMaxDelay(); + } + + /// \brief Return sum of delays between sent and received packets. + /// + /// Method returns sum of delays between sent and received packets + /// for specified exchange type. + /// + /// \param xchg_type exchange type. + /// \throw isc::BadValue if invalid exchange type specified. + /// \return sum of delays between sent and received packets. + double getSumDelay(const ExchangeType xchg_type) const { + ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type); + return xchg_stats->getSumDelay(); + } + + /// \brief Return square sum of delays between sent and received + /// packets. + /// + /// Method returns square sum of delays between sent and received + /// packets for specified exchange type. + /// + /// \param xchg_type exchange type. + /// \throw isc::BadValue if invalid exchange type specified. + /// \return square sum of delays between sent and received packets. + double getSquareSumDelay(const ExchangeType xchg_type) const { + ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type); + return xchg_stats->getSquareSumDelay(); + } + /// \brief Return number of orphant packets. /// /// Method returns number of orphant packets for specified @@ -420,6 +559,7 @@ public: /// unordered packet lookup using transaction id. /// /// \param xchg_type exchange type. + /// \throw isc::BadValue if invalid exchange type specified. /// \return average unordered lookup set size. double getAvgUnorderedLookupSetSize(const ExchangeType xchg_type) const { ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type); @@ -433,6 +573,8 @@ public: /// out of order by server - transaction id of received /// packet does not match transaction id of next sent packet. /// + /// \param xchg_type exchange type. + /// \throw isc::BadValue if invalid exchange type specified. /// \return number of unordered lookups. uint64_t getUnorderedLookups(const ExchangeType xchg_type) const { ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type); @@ -447,14 +589,40 @@ public: /// If packets are skipped or received out of order, lookup /// function will use unordered lookup (with hash table). /// + /// \param xchg_type exchange type. + /// \throw isc::BadValue if invalid exchange type specified. /// \return number of ordered lookups. uint64_t getOrderedLookups(const ExchangeType xchg_type) const { ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type); return xchg_stats->getOrderedLookups(); } -private: + /// \brief Return total number of sent packets + /// + /// Method returns total number of sent packets for specified + /// exchange type. + /// + /// \param xchg_type exchange type. + /// \throw isc::BadValue if invalid exchange type specified. + /// \return number of sent packets. + uint64_t getSentPacketsNum(const ExchangeType xchg_type) const { + ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type); + return xchg_stats->getSentPacketsNum(); + } + /// \brief Return total number of received packets + /// + /// Method returns total number of received packets for specified + /// exchange type. + /// + /// \param xchg_type exchange type. + /// \throw isc::BadValue if invalid exchange type specified. + /// \return number of received packets. + uint64_t getRcvdPacketsNum(const ExchangeType xchg_type) const { + ExchangeStatsPtr xchg_stats = getExchangeStats(xchg_type); + return xchg_stats->getRcvdPacketsNum(); + } +private: /// \brief Return exchange stats object for given exchange type /// /// Method returns exchange stats object for given exchange type. diff --git a/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc b/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc index 2d6ab14d54..38cd1c28ac 100644 --- a/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc +++ b/tests/tools/perfdhcp/tests/stats_mgr_unittest.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -43,21 +44,79 @@ public: Pkt4* createPacket4(const uint8_t msg_type, const uint32_t transid) { Pkt4* pkt = new Pkt4(msg_type, transid); + // Packet timestamp is normally updated by interface + // manager on packets reception or send. Unit tests + // do not use interface manager so we need to do it + // ourselfs. pkt->updateTimestamp(); return pkt; } + + Pkt6* createPacket6(const uint8_t msg_type, + const uint32_t transid) { + Pkt6* pkt = new Pkt6(msg_type, transid); + // Packet timestamp is normally updated by interface + // manager on packets reception or send. Unit tests + // do not use interface manager so we need to do it + // ourselfs. + pkt->updateTimestamp(); + return pkt; + } + + void passMultiplePackets6(const boost::shared_ptr stats_mgr, + const StatsMgr6::ExchangeType xchg_type, + const uint8_t packet_type, + const int num_packets, + const bool receive = false) { + for (int i = 0; i < num_packets; ++i) { + boost::shared_ptr + packet(createPacket6(packet_type, i)); + + if (receive) { + ASSERT_NO_THROW( + stats_mgr->passRcvdPacket(xchg_type, packet); + ); + } else { + ASSERT_NO_THROW( + stats_mgr->passSentPacket(xchg_type, packet) + ); + } + } + } + }; TEST_F(StatsMgrTest, Constructor) { boost::scoped_ptr stats_mgr(new StatsMgr4()); + stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO); + EXPECT_EQ( + std::numeric_limits::max(), + stats_mgr->getMinDelay(StatsMgr4::XCHG_DO) + ); + EXPECT_EQ(0, stats_mgr->getMaxDelay(StatsMgr4::XCHG_DO)); + EXPECT_EQ(0, stats_mgr->getSumDelay(StatsMgr4::XCHG_DO)); + EXPECT_EQ(0, stats_mgr->getOrphans(StatsMgr4::XCHG_DO)); + EXPECT_EQ(0, stats_mgr->getSquareSumDelay(StatsMgr4::XCHG_DO)); + EXPECT_EQ(0, stats_mgr->getOrderedLookups(StatsMgr4::XCHG_DO)); + EXPECT_EQ(0, stats_mgr->getUnorderedLookups(StatsMgr4::XCHG_DO)); + EXPECT_EQ(0, stats_mgr->getSentPacketsNum(StatsMgr4::XCHG_DO)); + EXPECT_EQ(0, stats_mgr->getRcvdPacketsNum(StatsMgr4::XCHG_DO)); + + double avg_size = 0.; + ASSERT_NO_THROW( + avg_size = stats_mgr->getAvgUnorderedLookupSetSize(StatsMgr4::XCHG_DO); + ); + EXPECT_EQ(0., avg_size); } -TEST_F(StatsMgrTest, Exchanges) { +TEST_F(StatsMgrTest, Exchange) { boost::scoped_ptr stats_mgr(new StatsMgr4()); boost::shared_ptr sent_packet(createPacket4(DHCPDISCOVER, common_transid)); boost::shared_ptr rcvd_packet(createPacket4(DHCPOFFER, common_transid)); + // This is expected to throw because XCHG_DO was not yet + // added to Stats Manager for tracking. EXPECT_THROW( stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet), BadValue @@ -67,7 +126,10 @@ TEST_F(StatsMgrTest, Exchanges) { BadValue ); + // Adding DISCOVER-OFFER exchanges to be tracked by Stats Manager. stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO); + // The following two attempts are expected to throw because + // invalid exchange types are passed (XCHG_RA instead of XCHG_DO) EXPECT_THROW( stats_mgr->passSentPacket(StatsMgr4::XCHG_RA, sent_packet), BadValue @@ -77,6 +139,8 @@ TEST_F(StatsMgrTest, Exchanges) { BadValue ); + // The following two attempts are expected to run fine because + // right exchange type is specified. EXPECT_NO_THROW( stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet) ); @@ -85,6 +149,46 @@ TEST_F(StatsMgrTest, Exchanges) { ); } +TEST_F(StatsMgrTest, MultipleExchanges) { + boost::shared_ptr stats_mgr(new StatsMgr6()); + stats_mgr->addExchangeStats(StatsMgr6::XCHG_SA); + stats_mgr->addExchangeStats(StatsMgr6::XCHG_RR); + + // Simulate sending number of solicit packets. + const int solicit_packets_num = 10; + passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_SA, DHCPV6_SOLICIT, + solicit_packets_num); + + // Simulate sending number of request packets. It is important that + // number of request packets is different then number of solicit + // packets. We can now check if right number packets went to + // the right exchange type group. + const int request_packets_num = 5; + passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_RR, DHCPV6_REQUEST, + request_packets_num); + + // Check if all packets are successfuly passed to packet lists. + EXPECT_EQ(solicit_packets_num, + stats_mgr->getSentPacketsNum(StatsMgr6::XCHG_SA)); + EXPECT_EQ(request_packets_num, + stats_mgr->getSentPacketsNum(StatsMgr6::XCHG_RR)); + + // Simulate reception of multiple packets for both SOLICIT-ADVERTISE + // and REQUEST-REPLY exchanges. Assume no packet drops. + const bool receive_packets = true; + passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_SA, DHCPV6_ADVERTISE, + solicit_packets_num, receive_packets); + + passMultiplePackets6(stats_mgr, StatsMgr6::XCHG_RR, DHCPV6_REPLY, + request_packets_num, receive_packets); + + // Verify that all received packets are counted. + EXPECT_EQ(solicit_packets_num, + stats_mgr->getRcvdPacketsNum(StatsMgr6::XCHG_SA)); + EXPECT_EQ(request_packets_num, + stats_mgr->getRcvdPacketsNum(StatsMgr6::XCHG_RR)); +} + TEST_F(StatsMgrTest, SendReceiveSimple) { boost::scoped_ptr stats_mgr(new StatsMgr4()); boost::shared_ptr sent_packet(createPacket4(DHCPDISCOVER, @@ -92,15 +196,22 @@ TEST_F(StatsMgrTest, SendReceiveSimple) { boost::shared_ptr rcvd_packet(createPacket4(DHCPOFFER, common_transid)); stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO); + // The following attempt is expected to pass becase the right + // exchange type is used. ASSERT_NO_THROW( stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet) ); - EXPECT_NO_THROW( + // It is ok, to pass to received packets here. First one will + // be matched with sent packet. The latter one will not be + // matched with sent packet but orphans counter will simply + // increase. + ASSERT_NO_THROW( stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet) ); - EXPECT_NO_THROW( + ASSERT_NO_THROW( stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet) ); + EXPECT_EQ(1, stats_mgr->getOrphans(StatsMgr4::XCHG_DO)); } TEST_F(StatsMgrTest, SendReceiveUnordered) { @@ -108,7 +219,9 @@ TEST_F(StatsMgrTest, SendReceiveUnordered) { boost::scoped_ptr stats_mgr(new StatsMgr4()); stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO); - uint32_t transid[packets_num] = { 1, 1024, 2, 1025, 3, 1026, 4, 1027, 5, 1028 }; + // Transaction ids of 10 packets to be sent and received. + uint32_t transid[packets_num] = + { 1, 1024, 2, 1025, 3, 1026, 4, 1027, 5, 1028 }; for (int i = 0; i < packets_num; ++i) { boost::shared_ptr sent_packet(createPacket4(DHCPDISCOVER, transid[i])); @@ -117,16 +230,24 @@ TEST_F(StatsMgrTest, SendReceiveUnordered) { ); } + // We are simulating that received packets are coming in reverse order: + // 1028, 5, 1027 .... for (int i = 0; i < packets_num; ++i) { - boost::shared_ptr rcvd_packet(createPacket4(DHCPDISCOVER, - transid[packets_num - 1 - i])); + boost::shared_ptr + rcvd_packet(createPacket4(DHCPDISCOVER, + transid[packets_num - 1 - i])); ASSERT_NO_THROW( stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet); ); } + // All packets are expected to match (we did not drop any) EXPECT_EQ(0, stats_mgr->getOrphans(StatsMgr4::XCHG_DO)); - EXPECT_EQ(10, stats_mgr->getUnorderedLookups(StatsMgr4::XCHG_DO)); - std::cout << stats_mgr->getAvgUnorderedLookupSetSize(StatsMgr4::XCHG_DO) << std::endl; + // Most of the time we have to do unordered lookups except for the last + // one. Packets are removed from the sent list every time we have a match + // so eventually we come up with the single packet that caching iterator + // is pointing to. This is counted as ordered lookup. + EXPECT_EQ(1, stats_mgr->getOrderedLookups(StatsMgr4::XCHG_DO)); + EXPECT_EQ(9, stats_mgr->getUnorderedLookups(StatsMgr4::XCHG_DO)); } TEST_F(StatsMgrTest, Orphans) { @@ -134,19 +255,73 @@ TEST_F(StatsMgrTest, Orphans) { boost::scoped_ptr stats_mgr(new StatsMgr4()); stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO); + // We skip every second packet to simulate drops. for (int i = 0; i < packets_num; i += 2) { boost::shared_ptr sent_packet(createPacket4(DHCPDISCOVER, i)); ASSERT_NO_THROW( stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet) ); } + // We pass all received packets. for (int i = 0; i < packets_num; ++i) { boost::shared_ptr rcvd_packet(createPacket4(DHCPOFFER, i)); ASSERT_NO_THROW( stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet); ); } + // The half of received packets are expected not to have matching + // sent packet. EXPECT_EQ(packets_num / 2, stats_mgr->getOrphans(StatsMgr4::XCHG_DO)); } +TEST_F(StatsMgrTest, Delays) { + boost::scoped_ptr stats_mgr(new StatsMgr4()); + stats_mgr->addExchangeStats(StatsMgr4::XCHG_DO); + + boost::shared_ptr sent_packet(createPacket4(DHCPDISCOVER, + common_transid)); + ASSERT_NO_THROW( + stats_mgr->passSentPacket(StatsMgr4::XCHG_DO, sent_packet) + ); + + // There is way to differentiate timstamps of two packets other than + // sleep for before we create another packet. Packet is using current + // time to update its timestamp. + // Sleeping for two seconds will guarantee that delay between packets + // will be greater than 1 second. Note that posix time value is + // transformed to double value and it makes it hard to determine + // actual value to expect. + std::cout << "Sleeping for 2 seconds to test packet delays" << std::endl; + sleep(2); + + boost::shared_ptr rcvd_packet(createPacket4(DHCPOFFER, + common_transid)); + ASSERT_NO_THROW( + stats_mgr->passRcvdPacket(StatsMgr4::XCHG_DO, rcvd_packet); + ); + + // Calculate period between packets. + boost::posix_time::ptime sent_time = sent_packet->getTimestamp(); + boost::posix_time::ptime rcvd_time = rcvd_packet->getTimestamp(); + + ASSERT_FALSE(sent_time.is_not_a_date_time()); + ASSERT_FALSE(rcvd_time.is_not_a_date_time()); + + boost::posix_time::time_period period(sent_time, rcvd_time); + + // Initially min delay is equal to MAX_DOUBLE. After first packets + // are passed, it is expected to set to actual value. + EXPECT_LT(stats_mgr->getMinDelay(StatsMgr4::XCHG_DO), + std::numeric_limits::max()); + EXPECT_GT(stats_mgr->getMinDelay(StatsMgr4::XCHG_DO), 1); + + // Max delay is supposed to the same value as mininimum + // or maximum delay. + EXPECT_GT(stats_mgr->getMaxDelay(StatsMgr4::XCHG_DO), 1); + + // Delay sums are now the same as minimum or maximum delay. + EXPECT_GT(stats_mgr->getSumDelay(StatsMgr4::XCHG_DO), 1); + EXPECT_GT(stats_mgr->getSquareSumDelay(StatsMgr4::XCHG_DO), 1); +} + }