diff options
Diffstat (limited to 'src/bin/perfdhcp/tests/stats_mgr_unittest.cc')
-rw-r--r-- | src/bin/perfdhcp/tests/stats_mgr_unittest.cc | 598 |
1 files changed, 598 insertions, 0 deletions
diff --git a/src/bin/perfdhcp/tests/stats_mgr_unittest.cc b/src/bin/perfdhcp/tests/stats_mgr_unittest.cc new file mode 100644 index 0000000..54253d5 --- /dev/null +++ b/src/bin/perfdhcp/tests/stats_mgr_unittest.cc @@ -0,0 +1,598 @@ +// Copyright (C) 2012-2021 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include "command_options_helper.h" + +#include <perfdhcp/stats_mgr.h> + +#include <exceptions/exceptions.h> +#include <dhcp/dhcp4.h> +#include <dhcp/dhcp6.h> +#include <dhcp/pkt4.h> +#include <dhcp/pkt6.h> + +#include <gtest/gtest.h> + +#include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> + +using namespace std; +using namespace isc; +using namespace isc::dhcp; +using namespace isc::perfdhcp; + +namespace { + +const uint32_t common_transid = 123; + +/// @brief Number of packets to be used for testing packets collecting. +const size_t TEST_COLLECTED_PKT_NUM = 10; + +/// @brief DHCPv4 packet with modifiable internal values. +/// +/// Currently the only additional modifiable value is a packet +/// timestamp. +class Pkt4Modifiable : public Pkt4 { +public: + + /// @brief Constructor. + /// + /// @param msg_type DHCPv4 message type. + /// @param transid Transaction id. + Pkt4Modifiable(const uint8_t msg_type, const uint32_t transid) + : Pkt4(msg_type, transid) { + } + + /// @brief Modifies packet timestamp. + /// + /// @param delta Number of seconds to be added to the current + /// packet time. If this number is negative, the new timestamp + /// will point to earlier time than the original timestamp. + void modifyTimestamp(const long delta) { + timestamp_ += boost::posix_time::seconds(delta); + } +}; + +/// @brief Pointer to the Pkt4Modifiable. +typedef boost::shared_ptr<Pkt4Modifiable> Pkt4ModifiablePtr; + +class StatsMgrTest : public ::testing::Test { +public: + StatsMgrTest() { + } + + /// \brief Create DHCPv4 packet. + /// + /// Method creates DHCPv4 packet and updates its timestamp. + /// + /// \param msg_type DHCPv4 message type. + /// \param transid transaction id for the packet. + /// \return DHCPv4 packet. + Pkt4Modifiable* createPacket4(const uint8_t msg_type, + const uint32_t transid) { + Pkt4Modifiable* pkt = new Pkt4Modifiable(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 + // ourselves. + pkt->updateTimestamp(); + return (pkt); + } + + /// \brief Create DHCPv6 packet. + /// + /// Method creates DHCPv6 packet and updates its timestamp. + /// + /// \param msg_type DHCPv6 message type. + /// \param transid transaction id. + /// \return DHCPv6 packet. + 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 + // ourselves. + pkt->updateTimestamp(); + return pkt; + } + + /// \brief Pass multiple DHCPv6 packets to Statistics Manager. + /// + /// Method simulates sending or receiving multiple DHCPv6 packets. + /// + /// \note The xchg_type parameter is passed as non-const value to avoid + /// false cppcheck errors which expect enum value being passed by reference. + /// This error is not reported when non-const enum is passed by value. + /// + /// \param stats_mgr Statistics Manager instance to be used. + /// \param xchg_type packet exchange types. + /// \param packet_type DHCPv6 packet type. + /// \param num_packets packets to be passed to Statistics Manager. + /// \param receive simulated packets are received (if true) + /// or sent (if false) + void passMultiplePackets6(const boost::shared_ptr<StatsMgr> stats_mgr, + 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<Pkt6> + 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) + ); + } + } + } + + /// \brief Simulate DHCPv4 DISCOVER-OFFER with delay. + /// + /// Method simulates DHCPv4 DISCOVER-OFFER exchange. The OFFER packet + /// creation is delayed by the specified number of seconds. This imposes + /// different packet timestamps and affects delay counters in Statistics + /// Manager. + /// + /// \param stats_mgr Statistics Manager instance. + /// \param delay delay in seconds between DISCOVER and OFFER packets. + void passDOPacketsWithDelay(const boost::shared_ptr<StatsMgr> stats_mgr, + unsigned int delay, + uint32_t transid) { + boost::shared_ptr<Pkt4> sent_packet(createPacket4(DHCPDISCOVER, + transid)); + ASSERT_NO_THROW( + stats_mgr->passSentPacket(ExchangeType::DO, sent_packet) + ); + + // Simulate time difference by changing time of sent packet + auto ts = sent_packet->getTimestamp() - boost::posix_time::seconds(delay); + sent_packet->setTimestamp(ts); + + boost::shared_ptr<Pkt4> rcvd_packet(createPacket4(DHCPOFFER, + transid)); + ASSERT_NO_THROW( + stats_mgr->passRcvdPacket(ExchangeType::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()); + } + + /// @brief This test verifies that timed out packets are collected. + /// + /// @param transid_index Index in the table of transaction ids which + /// points to the transaction id to be selected for the DHCPOFFER. + void testSendReceiveCollected(const size_t transid_index) { + CommandOptions opt; + boost::scoped_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + // The second parameter indicates that transactions older than + // 2 seconds should be removed and respective packets collected. + stats_mgr->addExchangeStats(ExchangeType::DO, 2); + + // Transaction ids of packets to be sent. All transaction ids + // belong to the same bucket (match the transid & 1023 hashing + // function). + uint32_t transid[TEST_COLLECTED_PKT_NUM] = + { 1, 1025, 2049, 3073, 4097, 5121, 6145, 7169, 8193, 9217 }; + + // Simulate sending a number of packets. + for (unsigned int i = 0; i < TEST_COLLECTED_PKT_NUM; ++i) { + Pkt4ModifiablePtr sent_packet(createPacket4(DHCPDISCOVER, + transid[i])); + // For packets with low indexes we set the timestamps to + // 10s in the past. When DHCPOFFER is processed, the + // packets with timestamps older than 2s should be collected. + if (i < TEST_COLLECTED_PKT_NUM / 2) { + sent_packet->modifyTimestamp(-10); + } + ASSERT_NO_THROW( + stats_mgr->passSentPacket(ExchangeType::DO, sent_packet) + ) << "failure for transaction id " << transid[i]; + } + + // Create a server response for one of the packets sent. + Pkt4ModifiablePtr rcvd_packet(createPacket4(DHCPOFFER, + transid[transid_index])); + ASSERT_NO_THROW( + stats_mgr->passRcvdPacket(ExchangeType::DO, rcvd_packet); + ); + + // There is exactly one case (transaction id) for which perfdhcp + // will find a packet using ordered lookup. In this case, no + // packets will be collected. Otherwise, for any unordered lookup + // all packets from a bucket should be collected. + if (stats_mgr->getUnorderedLookups(ExchangeType::DO) > 0) { + // All packets in the bucket having transaction id + // index below TEST_COLLECTED_PKT_NUM / 2 should be removed. + EXPECT_EQ(TEST_COLLECTED_PKT_NUM / 2, + stats_mgr->getCollectedNum(ExchangeType::DO)); + } + + // Make sure that we can still use the StatsMgr. It is possible + // that the pointer to 'next sent' packet was invalidated + // during packet removal. + for (unsigned int i = 0; i < TEST_COLLECTED_PKT_NUM; ++i) { + // Increase transaction ids by 1 so as they don't duplicate + // with transaction ids of already sent packets. + Pkt4ModifiablePtr sent_packet(createPacket4(DHCPDISCOVER, + transid[i] + 1)); + Pkt4ModifiablePtr rcvd_packet(createPacket4(DHCPOFFER, + transid[i] + 1)); + ASSERT_NO_THROW( + stats_mgr->passSentPacket(ExchangeType::DO, sent_packet) + ) << "failure for transaction id " << transid[i]; + + ASSERT_NO_THROW( + stats_mgr->passRcvdPacket(ExchangeType::DO, rcvd_packet); + ) << "failure for transaction id " << transid[i]; + } + + // We should have processed TEST_COLLECTED_PKT_NUM but it is possible + // that one of them we couldn't match (orphan packet), because + // the matched packet had to be collected because of the transaction + // timeout. Therefore, we have to count both received packets and + // orphans. + EXPECT_EQ(TEST_COLLECTED_PKT_NUM + 1, + stats_mgr->getRcvdPacketsNum(ExchangeType::DO) + + stats_mgr->getOrphans(ExchangeType::DO)); + } +}; + +TEST_F(StatsMgrTest, Constructor) { + CommandOptions opt; + boost::scoped_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + stats_mgr->addExchangeStats(ExchangeType::DO); + EXPECT_DOUBLE_EQ( + std::numeric_limits<double>::max(), + stats_mgr->getMinDelay(ExchangeType::DO) + ); + EXPECT_DOUBLE_EQ(0, stats_mgr->getMaxDelay(ExchangeType::DO)); + EXPECT_EQ(0, stats_mgr->getOrphans(ExchangeType::DO)); + EXPECT_EQ(0, stats_mgr->getOrderedLookups(ExchangeType::DO)); + EXPECT_EQ(0, stats_mgr->getUnorderedLookups(ExchangeType::DO)); + EXPECT_EQ(0, stats_mgr->getSentPacketsNum(ExchangeType::DO)); + EXPECT_EQ(0, stats_mgr->getRcvdPacketsNum(ExchangeType::DO)); + EXPECT_EQ(0, stats_mgr->getCollectedNum(ExchangeType::DO)); + + EXPECT_THROW(stats_mgr->getAvgDelay(ExchangeType::DO), InvalidOperation); + EXPECT_THROW(stats_mgr->getStdDevDelay(ExchangeType::DO), + InvalidOperation); + EXPECT_THROW(stats_mgr->getAvgUnorderedLookupSetSize(ExchangeType::DO), + InvalidOperation); +} + +TEST_F(StatsMgrTest, Exchange) { + CommandOptions opt; + boost::scoped_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + boost::shared_ptr<Pkt4> sent_packet(createPacket4(DHCPDISCOVER, + common_transid)); + boost::shared_ptr<Pkt4> rcvd_packet(createPacket4(DHCPOFFER, + common_transid)); + // This is expected to throw because XCHG_DO was not yet + // added to Stats Manager for tracking. + ASSERT_FALSE(stats_mgr->hasExchangeStats(ExchangeType::DO)); + ASSERT_FALSE(stats_mgr->hasExchangeStats(ExchangeType::RA)); + EXPECT_THROW( + stats_mgr->passSentPacket(ExchangeType::DO, sent_packet), + BadValue + ); + EXPECT_THROW( + stats_mgr->passRcvdPacket(ExchangeType::DO, rcvd_packet), + BadValue + ); + + + // Adding DISCOVER-OFFER exchanges to be tracked by Stats Manager. + stats_mgr->addExchangeStats(ExchangeType::DO); + ASSERT_TRUE(stats_mgr->hasExchangeStats(ExchangeType::DO)); + ASSERT_FALSE(stats_mgr->hasExchangeStats(ExchangeType::RA)); + // 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(ExchangeType::RA, sent_packet), + BadValue + ); + EXPECT_THROW( + stats_mgr->passRcvdPacket(ExchangeType::RA, rcvd_packet), + BadValue + ); + + // The following two attempts are expected to run fine because + // right exchange type is specified. + EXPECT_NO_THROW( + stats_mgr->passSentPacket(ExchangeType::DO, sent_packet) + ); + EXPECT_NO_THROW( + stats_mgr->passRcvdPacket(ExchangeType::DO, rcvd_packet) + ); +} + +TEST_F(StatsMgrTest, MultipleExchanges) { + CommandOptions opt; + boost::shared_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + stats_mgr->addExchangeStats(ExchangeType::SA); + stats_mgr->addExchangeStats(ExchangeType::RR); + + // Simulate sending number of solicit packets. + const int solicit_packets_num = 10; + passMultiplePackets6(stats_mgr, ExchangeType::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, ExchangeType::RR, DHCPV6_REQUEST, + request_packets_num); + + // Check if all packets are successfully passed to packet lists. + EXPECT_EQ(solicit_packets_num, + stats_mgr->getSentPacketsNum(ExchangeType::SA)); + EXPECT_EQ(request_packets_num, + stats_mgr->getSentPacketsNum(ExchangeType::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, ExchangeType::SA, DHCPV6_ADVERTISE, + solicit_packets_num, receive_packets); + + passMultiplePackets6(stats_mgr, ExchangeType::RR, DHCPV6_REPLY, + request_packets_num, receive_packets); + + // Verify that all received packets are counted. + EXPECT_EQ(solicit_packets_num, + stats_mgr->getRcvdPacketsNum(ExchangeType::SA)); + EXPECT_EQ(request_packets_num, + stats_mgr->getRcvdPacketsNum(ExchangeType::RR)); +} + +TEST_F(StatsMgrTest, SendReceiveSimple) { + CommandOptions opt; + boost::scoped_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + boost::shared_ptr<Pkt4> sent_packet(createPacket4(DHCPDISCOVER, + common_transid)); + boost::shared_ptr<Pkt4> rcvd_packet(createPacket4(DHCPOFFER, + common_transid)); + stats_mgr->addExchangeStats(ExchangeType::DO); + // The following attempt is expected to pass because the right + // exchange type is used. + ASSERT_NO_THROW( + stats_mgr->passSentPacket(ExchangeType::DO, sent_packet) + ); + // 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(ExchangeType::DO, rcvd_packet) + ); + ASSERT_NO_THROW( + stats_mgr->passRcvdPacket(ExchangeType::DO, rcvd_packet) + ); + EXPECT_EQ(1, stats_mgr->getOrphans(ExchangeType::DO)); +} + +TEST_F(StatsMgrTest, SendReceiveUnordered) { + CommandOptions opt; + const int packets_num = 10; + boost::scoped_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + stats_mgr->addExchangeStats(ExchangeType::DO); + + // 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<Pkt4> sent_packet(createPacket4(DHCPDISCOVER, + transid[i])); + ASSERT_NO_THROW( + stats_mgr->passSentPacket(ExchangeType::DO, sent_packet) + ); + } + + // 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<Pkt4> + rcvd_packet(createPacket4(DHCPDISCOVER, + transid[packets_num - 1 - i])); + ASSERT_NO_THROW( + stats_mgr->passRcvdPacket(ExchangeType::DO, rcvd_packet); + ); + } + // All packets are expected to match (we did not drop any) + EXPECT_EQ(0, stats_mgr->getOrphans(ExchangeType::DO)); + // 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(ExchangeType::DO)); + EXPECT_EQ(9, stats_mgr->getUnorderedLookups(ExchangeType::DO)); +} + +TEST_F(StatsMgrTest, SendReceiveCollected) { + // Check that the packet collection mechanism works fine + // for any packet returned by the server. + for (unsigned int i = 0; i < TEST_COLLECTED_PKT_NUM; ++i) { + testSendReceiveCollected(i); + } +} + +TEST_F(StatsMgrTest, Orphans) { + CommandOptions opt; + const int packets_num = 6; + boost::scoped_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + stats_mgr->addExchangeStats(ExchangeType::DO); + + // We skip every second packet to simulate drops. + for (int i = 0; i < packets_num; i += 2) { + boost::shared_ptr<Pkt4> sent_packet(createPacket4(DHCPDISCOVER, i)); + ASSERT_NO_THROW( + stats_mgr->passSentPacket(ExchangeType::DO, sent_packet) + ); + } + // We pass all received packets. + for (int i = 0; i < packets_num; ++i) { + boost::shared_ptr<Pkt4> rcvd_packet(createPacket4(DHCPOFFER, i)); + ASSERT_NO_THROW( + stats_mgr->passRcvdPacket(ExchangeType::DO, rcvd_packet); + ); + } + // The half of received packets are expected not to have matching + // sent packet. + EXPECT_EQ(packets_num / 2, stats_mgr->getOrphans(ExchangeType::DO)); +} + +TEST_F(StatsMgrTest, Delays) { + CommandOptions opt; + boost::shared_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + stats_mgr->addExchangeStats(ExchangeType::DO, 5); + + // Send DISCOVER, wait 2s and receive OFFER. This will affect + // counters in Stats Manager. + passDOPacketsWithDelay(stats_mgr, 2, common_transid); + + // 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(ExchangeType::DO), + std::numeric_limits<double>::max()); + EXPECT_GT(stats_mgr->getMinDelay(ExchangeType::DO), 1); + + // Max delay is supposed to the same value as minimum + // or maximum delay. + EXPECT_GT(stats_mgr->getMaxDelay(ExchangeType::DO), 1); + + // Delay sums are now the same as minimum or maximum delay. + EXPECT_GT(stats_mgr->getAvgDelay(ExchangeType::DO), 1); + + // Simulate another DISCOVER-OFFER exchange with delay between + // sent and received packets. Delay is now shorter than earlier + // so standard deviation of delay will now increase. + const unsigned int delay2 = 1; + passDOPacketsWithDelay(stats_mgr, delay2, common_transid + 1); + // Standard deviation is expected to be non-zero. + EXPECT_GT(stats_mgr->getStdDevDelay(ExchangeType::DO), 0); +} + +TEST_F(StatsMgrTest, CustomCounters) { + CommandOptions opt; + boost::scoped_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + + // Specify counter keys and names. + const std::string too_short_key("tooshort"); + const std::string too_short_name("Too short packets"); + const std::string too_late_key("toolate"); + const std::string too_late_name("Packets sent too late"); + + // Add two custom counters. + stats_mgr->addCustomCounter(too_short_key, too_short_name); + stats_mgr->addCustomCounter(too_late_key, too_late_name); + + // Increment one of the counters 10 times. + const uint64_t tooshort_num = 10; + for (uint64_t i = 0; i < tooshort_num; ++i) { + stats_mgr->incrementCounter(too_short_key); + } + + // Increment another counter by 5 times. + const uint64_t toolate_num = 5; + for (uint64_t i = 0; i < toolate_num; ++i) { + stats_mgr->incrementCounter(too_late_key); + } + + // Check counter's current value and name. + CustomCounterPtr tooshort_counter = + stats_mgr->getCounter(too_short_key); + EXPECT_EQ(too_short_name, tooshort_counter->getName()); + EXPECT_EQ(tooshort_num, tooshort_counter->getValue()); + + // Check counter's current value and name. + CustomCounterPtr toolate_counter = + stats_mgr->getCounter(too_late_key); + EXPECT_EQ(too_late_name, toolate_counter->getName()); + EXPECT_EQ(toolate_num, toolate_counter->getValue()); + +} + +TEST_F(StatsMgrTest, PrintStats) { + std::cout << "This unit test is checking statistics printing " + << "capabilities. It is expected that some counters " + << "will be printed during this test. It may also " + << "cause spurious errors." << std::endl; + CommandOptions opt; + boost::shared_ptr<StatsMgr> stats_mgr(new StatsMgr(opt)); + stats_mgr->addExchangeStats(ExchangeType::SA); + + // Simulate sending and receiving one packet. Otherwise printing + // functions will complain about lack of packets. + const int packets_num = 1; + passMultiplePackets6(stats_mgr, ExchangeType::SA, DHCPV6_SOLICIT, + packets_num); + passMultiplePackets6(stats_mgr, ExchangeType::SA, DHCPV6_ADVERTISE, + packets_num, true); + + // This function will print statistics even if packets are not + // archived because it relies on counters. There is at least one + // exchange needed to count the average delay and std deviation. + EXPECT_NO_THROW(stats_mgr->printStats()); + + // Printing timestamps is expected to fail because by default we + // disable packets archiving mode. Without packets we can't get + // timestamps. + EXPECT_THROW(stats_mgr->printTimestamps(), isc::InvalidOperation); + + // Now, we create another statistics manager instance and enable timestamp + // printing, thus also enabling packets archiving mode. + CommandOptionsHelper::process(opt, "perfdhcp -x t 127.0.0.1"); + stats_mgr.reset(new StatsMgr(opt)); + stats_mgr->addExchangeStats(ExchangeType::SA); + + // Timestamps should now get printed because packets have been preserved. + EXPECT_NO_THROW(stats_mgr->printTimestamps()); + + // Create another statistics manager instance and enable lease printing for + // v4, thus also enabling packets archiving mode. + CommandOptionsHelper::process(opt, "perfdhcp -4 -x l 127.0.0.1"); + stats_mgr.reset(new StatsMgr(opt)); + stats_mgr->addExchangeStats(ExchangeType::RNA); + stats_mgr->addExchangeStats(ExchangeType::RLA); + ASSERT_TRUE(stats_mgr->hasExchangeStats(ExchangeType::DO)); + ASSERT_TRUE(stats_mgr->hasExchangeStats(ExchangeType::RA)); + ASSERT_TRUE(stats_mgr->hasExchangeStats(ExchangeType::RNA)); + ASSERT_TRUE(stats_mgr->hasExchangeStats(ExchangeType::RLA)); + + // Leases should now get printed because packets have been preserved. + EXPECT_NO_THROW(stats_mgr->printLeases()); + + // For v6 this time. + CommandOptionsHelper::process(opt, "perfdhcp -6 -x l 127.0.0.1"); + stats_mgr.reset(new StatsMgr(opt)); + stats_mgr->addExchangeStats(ExchangeType::RN); + stats_mgr->addExchangeStats(ExchangeType::RL); + ASSERT_TRUE(stats_mgr->hasExchangeStats(ExchangeType::SA)); + ASSERT_TRUE(stats_mgr->hasExchangeStats(ExchangeType::RR)); + ASSERT_TRUE(stats_mgr->hasExchangeStats(ExchangeType::RN)); + ASSERT_TRUE(stats_mgr->hasExchangeStats(ExchangeType::RL)); + + // Leases should now get printed because packets have been preserved. + EXPECT_NO_THROW(stats_mgr->printLeases()); +} + +} // namespace |