diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index 7c1cbab958..4f4fc08038 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc @@ -2244,8 +2244,14 @@ TEST_F(Dhcpv4SrvTest, sanityCheck) { RFCViolation); } -// Checks if received relay agent info option is echoed back to the client -TEST_F(Dhcpv4SrvTest, relayAgentInfoEcho) { +} // end of anonymous namespace + +namespace isc { +namespace dhcp { +namespace test { + +void +Dhcpv4SrvTest::relayAgentInfoEcho() { IfaceMgrTestConfig test_config(true); NakedDhcpv4Srv srv(0); @@ -2288,9 +2294,8 @@ TEST_F(Dhcpv4SrvTest, relayAgentInfoEcho) { EXPECT_TRUE(rai_response->equals(rai_query)); } -// Checks if received bad relay agent info option is not echoed back -// to the client -TEST_F(Dhcpv4SrvTest, badRelayAgentInfoEcho) { +void +Dhcpv4SrvTest::badRelayAgentInfoEcho() { IfaceMgrTestConfig test_config(true); NakedDhcpv4Srv srv(0); @@ -2333,8 +2338,8 @@ TEST_F(Dhcpv4SrvTest, badRelayAgentInfoEcho) { ASSERT_FALSE(rai_response); } -// Checks if client port can be overridden in packets being sent. -TEST_F(Dhcpv4SrvTest, portsClientPort) { +void +Dhcpv4SrvTest::portsClientPort() { IfaceMgrTestConfig test_config(true); NakedDhcpv4Srv srv(0); @@ -2374,8 +2379,8 @@ TEST_F(Dhcpv4SrvTest, portsClientPort) { EXPECT_EQ(srv.client_port_, offer->getRemotePort()); } -// Checks if server port can be overridden in packets being sent. -TEST_F(Dhcpv4SrvTest, portsServerPort) { +void +Dhcpv4SrvTest::portsServerPort() { IfaceMgrTestConfig test_config(true); // Do not use DHCP4_SERVER_PORT here as 0 means don't open sockets. @@ -2415,6 +2420,52 @@ TEST_F(Dhcpv4SrvTest, portsServerPort) { EXPECT_EQ(srv.server_port_, offer->getLocalPort()); } +} // end of isc::dhcp::test namespace +} // end of isc::dhcp namespace +} // end of isc namespace + +namespace { + +TEST_F(Dhcpv4SrvTest, relayAgentInfoEcho) { + Dhcpv4SrvMTTestGuard guard(*this, false); + relayAgentInfoEcho(); +} + +TEST_F(Dhcpv4SrvTest, relayAgentInfoEchoMultiThreading) { + Dhcpv4SrvMTTestGuard guard(*this, true); + relayAgentInfoEcho(); +} + +TEST_F(Dhcpv4SrvTest, badRelayAgentInfoEcho) { + Dhcpv4SrvMTTestGuard guard(*this, false); + badRelayAgentInfoEcho(); +} + +TEST_F(Dhcpv4SrvTest, badRelayAgentInfoEchoMultiThreading) { + Dhcpv4SrvMTTestGuard guard(*this, true); + badRelayAgentInfoEcho(); +} + +TEST_F(Dhcpv4SrvTest, portsClientPort) { + Dhcpv4SrvMTTestGuard guard(*this, false); + portsClientPort(); +} + +TEST_F(Dhcpv4SrvTest, portsClientPortMultiThreading) { + Dhcpv4SrvMTTestGuard guard(*this, true); + portsClientPort(); +} + +TEST_F(Dhcpv4SrvTest, portsServerPort) { + Dhcpv4SrvMTTestGuard guard(*this, false); + portsServerPort(); +} + +TEST_F(Dhcpv4SrvTest, portsServerPortMultiTHreading) { + Dhcpv4SrvMTTestGuard guard(*this, true); + portsServerPort(); +} + /// @todo Implement tests for subnetSelect See tests in dhcp6_srv_unittest.cc: /// selectSubnetAddr, selectSubnetIface, selectSubnetRelayLinkaddr, /// selectSubnetRelayInterfaceId. Note that the concept of interface-id is not diff --git a/src/bin/dhcp4/tests/dhcp4_test_utils.cc b/src/bin/dhcp4/tests/dhcp4_test_utils.cc index 59a0ecdc26..6f57b9fed5 100644 --- a/src/bin/dhcp4/tests/dhcp4_test_utils.cc +++ b/src/bin/dhcp4/tests/dhcp4_test_utils.cc @@ -456,8 +456,6 @@ Dhcpv4SrvTest::TearDown() { << " class after the test. Exception has been caught: " << ex.what(); } - - setMultiThreading(false); } void diff --git a/src/bin/dhcp4/tests/dhcp4_test_utils.h b/src/bin/dhcp4/tests/dhcp4_test_utils.h index 15a6caa588..6b794ecd19 100644 --- a/src/bin/dhcp4/tests/dhcp4_test_utils.h +++ b/src/bin/dhcp4/tests/dhcp4_test_utils.h @@ -170,6 +170,11 @@ public: } } + /// @brief fake receive packet from server + /// + /// The client uses this packet as a reply from the server. + /// + /// @return The received packet. Pkt4Ptr receiveOneMsg() { if (isc::util::MultiThreadingMgr::instance().getMode()) { std::lock_guard lk(mutex_); @@ -179,6 +184,12 @@ public: } } + /// @brief fake receive packet from server + /// + /// The client uses this packet as a reply from the server. + /// This function should be called in a thread safe context. + /// + /// @return The received packet. Pkt4Ptr receiveOneMsgInternal() { // Return empty pointer if server hasn't responded. if (fake_sent_.empty()) { @@ -216,7 +227,7 @@ public: processRelease(release, context); } - /// @brief Runs processing DHCPDECLINE + /// @brief Runs processing DHCPDECLINE. /// /// @param decline message received from client void processDecline(Pkt4Ptr& decline) { @@ -227,7 +238,7 @@ public: /// @brief Dummy server identifier option used by various tests. OptionPtr server_id_; - /// @brief packets we pretend to receive + /// @brief packets we pretend to receive. /// /// Instead of setting up sockets on interfaces that change between OSes, it /// is much easier to fake packet reception. This is a list of packets that @@ -235,7 +246,7 @@ public: /// using fakeReceive() and NakedDhcpv4Srv::receivePacket() methods. std::list fake_received_; - /// @brief packets we pretend to send + /// @brief packets we pretend to send. std::list fake_sent_; using Dhcpv4Srv::adjustIfaceData; @@ -556,9 +567,19 @@ public: ExpectedResult expected_result); /// @brief Checks if received relay agent info option is echoed back to the - /// client + /// client. void relayAgentInfoEcho(); + /// @brief Checks if received bad relay agent info option is not echoed back + /// to the client. + void badRelayAgentInfoEcho(); + + /// @brief Checks if client port can be overridden in packets being sent. + void portsClientPort(); + + /// @brief Checks if server port can be overridden in packets being sent. + void portsServerPort(); + /// @brief This function cleans up after the test. virtual void TearDown(); @@ -567,25 +588,25 @@ public: multi_threading_ = enabled; } - /// @brief A subnet used in most tests + /// @brief A subnet used in most tests. Subnet4Ptr subnet_; - /// @brief A pool used in most tests + /// @brief A pool used in most tests. Pool4Ptr pool_; - /// @brief A client-id used in most tests + /// @brief A client-id used in most tests. ClientIdPtr client_id_; /// @brief Return code int rcode_; - /// @brief Comment + /// @brief Comment received from configuration. isc::data::ConstElementPtr comment_; /// @brief Server object under test. NakedDhcpv4Srv srv_; - /// @brief The multi-threading flag + /// @brief The multi-threading flag. bool multi_threading_; }; diff --git a/src/bin/dhcp6/tests/dhcp6_client.cc b/src/bin/dhcp6/tests/dhcp6_client.cc index 45c0831feb..fb612a9c4d 100644 --- a/src/bin/dhcp6/tests/dhcp6_client.cc +++ b/src/bin/dhcp6/tests/dhcp6_client.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ using namespace isc::asiolink; using namespace isc::dhcp; using namespace isc::dhcp::test; +using namespace isc::util; namespace { @@ -618,7 +620,6 @@ Dhcp6Client::doRelease() { } } - void Dhcp6Client::generateIAFromLeases(const Pkt6Ptr& query, const bool include_address) { @@ -778,8 +779,7 @@ Dhcp6Client::hasLeaseForAddressRange(const asiolink::IOAddress& first, } bool -Dhcp6Client:: -hasLeaseWithZeroLifetimeForAddress(const asiolink::IOAddress& address) const { +Dhcp6Client::hasLeaseWithZeroLifetimeForAddress(const asiolink::IOAddress& address) const { std::vector leases = getLeasesByAddress(address); BOOST_FOREACH(const Lease6& lease, leases) { if ((lease.preferred_lft_ == 0) && (lease.valid_lft_ == 0)) { @@ -919,13 +919,7 @@ Dhcp6Client::modifyDUID() { Pkt6Ptr Dhcp6Client::receiveOneMsg() { - // Return empty pointer if server hasn't responded. - if (srv_->fake_sent_.empty()) { - return (Pkt6Ptr()); - } - Pkt6Ptr msg = srv_->fake_sent_.front(); - srv_->fake_sent_.pop_front(); - return (msg); + return (srv_->receiveOneMsg()); } void @@ -991,6 +985,9 @@ Dhcp6Client::sendMsg(const Pkt6Ptr& msg) { } catch (...) { // Suppress errors, as the DHCPv6 server does. } + + // Make sure the server processed all packets in MT. + isc::util::MultiThreadingMgr::instance().getThreadPool().wait(); } void diff --git a/src/bin/dhcp6/tests/dhcp6_test_utils.cc b/src/bin/dhcp6/tests/dhcp6_test_utils.cc index e9591cecdb..31ff44a789 100644 --- a/src/bin/dhcp6/tests/dhcp6_test_utils.cc +++ b/src/bin/dhcp6/tests/dhcp6_test_utils.cc @@ -6,13 +6,14 @@ #include #include +#include #include #include #include #include #include +#include #include -#include #include #include #include @@ -22,6 +23,7 @@ using namespace isc::data; using namespace isc::dhcp; using namespace isc::asiolink; using namespace isc::stats; +using namespace isc::util; namespace isc { namespace dhcp { @@ -53,16 +55,14 @@ BaseServerTest::~BaseServerTest() { } Dhcpv6SrvTest::Dhcpv6SrvTest() - : NakedDhcpv6SrvTest(), srv_(0) { - subnet_ = isc::dhcp::Subnet6Ptr - (new isc::dhcp::Subnet6(isc::asiolink::IOAddress("2001:db8:1::"), - 48, 1000, 2000, 3000, 4000)); + : NakedDhcpv6SrvTest(), srv_(0), multi_threading_(false) { + subnet_ = isc::dhcp::Subnet6Ptr(new isc::dhcp::Subnet6(isc::asiolink::IOAddress("2001:db8:1::"), + 48, 1000, 2000, 3000, 4000)); subnet_->setIface("eth0"); - pool_ = isc::dhcp::Pool6Ptr - (new isc::dhcp::Pool6(isc::dhcp::Lease::TYPE_NA, - isc::asiolink::IOAddress("2001:db8:1:1::"), - 64)); + pool_ = isc::dhcp::Pool6Ptr(new isc::dhcp::Pool6(isc::dhcp::Lease::TYPE_NA, + isc::asiolink::IOAddress("2001:db8:1:1::"), + 64)); subnet_->addPool(pool_); isc::dhcp::CfgMgr::instance().clear(); @@ -71,10 +71,9 @@ Dhcpv6SrvTest::Dhcpv6SrvTest() isc::dhcp::CfgMgr::instance().commit(); // configure PD pool - pd_pool_ = isc::dhcp::Pool6Ptr - (new isc::dhcp::Pool6(isc::dhcp::Lease::TYPE_PD, - isc::asiolink::IOAddress("2001:db8:1:2::"), - 64, 80)); + pd_pool_ = isc::dhcp::Pool6Ptr(new isc::dhcp::Pool6(isc::dhcp::Lease::TYPE_PD, + isc::asiolink::IOAddress("2001:db8:1:2::"), + 64, 80)); subnet_->addPool(pd_pool_); } @@ -809,6 +808,7 @@ Dhcpv6SrvTest::configure(const std::string& config) { void Dhcpv6SrvTest::configure(const std::string& config, NakedDhcpv6Srv& srv) { + MultiThreadingCriticalSection cs; ConstElementPtr json; try { json = parseJSON(config); @@ -822,6 +822,9 @@ Dhcpv6SrvTest::configure(const std::string& config, NakedDhcpv6Srv& srv) { // Disable the re-detect flag disableIfacesReDetect(json); + // Set up multi-threading + configureMultiThreading(multi_threading_, json); + // Configure the server and make sure the config is accepted EXPECT_NO_THROW(status = configureDhcp6Server(srv, json)); ASSERT_TRUE(status); @@ -830,11 +833,18 @@ Dhcpv6SrvTest::configure(const std::string& config, NakedDhcpv6Srv& srv) { ASSERT_EQ(0, rcode) << "configuration failed, test is broken: " << comment->str(); + try { + CfgMultiThreading::apply(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading()); + } catch (const std::exception& ex) { + ADD_FAILURE() << "Error applying multi threading settings: " + << ex.what(); + } + CfgMgr::instance().commit(); } NakedDhcpv6SrvTest::NakedDhcpv6SrvTest() -: rcode_(-1) { + : rcode_(-1) { // it's ok if that fails. There should not be such a file anyway static_cast(remove(DUID_FILE)); diff --git a/src/bin/dhcp6/tests/dhcp6_test_utils.h b/src/bin/dhcp6/tests/dhcp6_test_utils.h index a41431ff41..3172ef8f2e 100644 --- a/src/bin/dhcp6/tests/dhcp6_test_utils.h +++ b/src/bin/dhcp6/tests/dhcp6_test_utils.h @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -157,6 +158,9 @@ public: return (pkt); } + // Make sure the server processed all packets in MT. + isc::util::MultiThreadingMgr::instance().getThreadPool().wait(); + // If not, just trigger shutdown and // return immediately shutdown(); @@ -169,7 +173,42 @@ public: /// it in fake_send_ list where test can later inspect /// server's response. virtual void sendPacket(const isc::dhcp::Pkt6Ptr& pkt) { - fake_sent_.push_back(pkt); + if (isc::util::MultiThreadingMgr::instance().getMode()) { + std::lock_guard lk(mutex_); + fake_sent_.push_back(pkt); + } else { + fake_sent_.push_back(pkt); + } + } + + /// @brief fake receive packet from server + /// + /// The client uses this packet as a reply from the server. + /// + /// @return The received packet. + Pkt6Ptr receiveOneMsg() { + if (isc::util::MultiThreadingMgr::instance().getMode()) { + std::lock_guard lk(mutex_); + return (receiveOneMsgInternal()); + } else { + return (receiveOneMsgInternal()); + } + } + + /// @brief fake receive packet from server + /// + /// The client uses this packet as a reply from the server. + /// This function should be called in a thread safe context. + /// + /// @return The received packet. + Pkt6Ptr receiveOneMsgInternal() { + // Return empty pointer if server hasn't responded. + if (fake_sent_.empty()) { + return (Pkt6Ptr()); + } + Pkt6Ptr msg = fake_sent_.front(); + fake_sent_.pop_front(); + return (msg); } /// @brief adds a packet to fake receive queue @@ -276,7 +315,7 @@ public: using Dhcpv6Srv::server_port_; using Dhcpv6Srv::client_port_; - /// @brief packets we pretend to receive + /// @brief packets we pretend to receive. /// /// Instead of setting up sockets on interfaces that change between /// OSes, it is much easier to fake packet reception. This is a list @@ -285,7 +324,11 @@ public: /// NakedDhcpv6Srv::receivePacket() methods. std::list fake_received_; + /// @brief packets we pretend to send. std::list fake_sent_; + + /// @brief Mutex to protect the packet buffers. + std::mutex mutex_; }; /// @brief Test fixture for any tests requiring blank/empty configuration @@ -497,6 +540,17 @@ public: NO_IA // Client will not send IA_NA at all }; + class Dhcpv6SrvMTTestGuard { + public: + Dhcpv6SrvMTTestGuard(Dhcpv6SrvTest& test, bool mt_enabled) : test_(test) { + test_.setMultiThreading(mt_enabled); + } + ~Dhcpv6SrvMTTestGuard() { + test_.setMultiThreading(false); + } + Dhcpv6SrvTest& test_; + }; + /// @brief Constructor that initializes a simple default configuration /// /// Sets up a single subnet6 with one pool for addresses and second @@ -587,9 +641,10 @@ public: // Checks if the lease sent to client is present in the database // and is valid when checked against the configured subnet - isc::dhcp::Lease6Ptr checkLease - (const isc::dhcp::DuidPtr& duid, const isc::dhcp::OptionPtr& ia_na, - boost::shared_ptr addr); + isc::dhcp::Lease6Ptr + checkLease(const isc::dhcp::DuidPtr& duid, + const isc::dhcp::OptionPtr& ia_na, + boost::shared_ptr addr); /// @brief Check if the specified lease is present in the data base. /// @@ -606,9 +661,10 @@ public: /// @param ia_pd IA_PD option that contains the IAPRefix option /// @param prefix pointer to the IAPREFIX option /// @return corresponding IPv6 lease (if found) - isc::dhcp::Lease6Ptr checkPdLease - (const isc::dhcp::DuidPtr& duid, const isc::dhcp::OptionPtr& ia_pd, - boost::shared_ptr prefix); + isc::dhcp::Lease6Ptr + checkPdLease(const isc::dhcp::DuidPtr& duid, + const isc::dhcp::OptionPtr& ia_pd, + boost::shared_ptr prefix); /// @brief Creates a message with specified IA /// @@ -761,18 +817,25 @@ public: /// @param stat_name this statistic is expected to be set to 1 void testReceiveStats(uint8_t pkt_type, const std::string& stat_name); + /// @brief Set multi-threading mode. + void setMultiThreading(bool enabled) { + multi_threading_ = enabled; + } - /// A subnet used in most tests + /// A subnet used in most tests. isc::dhcp::Subnet6Ptr subnet_; - /// A normal, non-temporary pool used in most tests + /// A normal, non-temporary pool used in most tests. isc::dhcp::Pool6Ptr pool_; - /// A prefix pool used in most tests + /// A prefix pool used in most tests. isc::dhcp::Pool6Ptr pd_pool_; /// @brief Server object under test. NakedDhcpv6Srv srv_; + + /// @brief The multi-threading flag. + bool multi_threading_; }; /// @brief Patch the server config to add interface-config/re-detect=false @@ -787,13 +850,35 @@ disableIfacesReDetect(isc::data::ConstElementPtr json) { } } +/// @brief Patch the server config to add multi-threading/enable-multi-threading +/// @param json the server config +inline void +configureMultiThreading(bool enabled, isc::data::ConstElementPtr json) { + isc::data::ConstElementPtr multi_threading = json->get("multi-threading"); + if (!multi_threading) { + isc::data::ElementPtr mutable_cfg = + boost::const_pointer_cast(json); + multi_threading = isc::data::Element::createMap(); + mutable_cfg->set("multi-threading", multi_threading); + } + + isc::data::ElementPtr mutable_cfg = + boost::const_pointer_cast(multi_threading); + if (enabled) { + mutable_cfg->set("enable-multi-threading", isc::data::Element::create(true)); + mutable_cfg->set("thread-pool-size", isc::data::Element::create(4)); + mutable_cfg->set("packet-queue-size", isc::data::Element::create(4)); + } else { + mutable_cfg->set("enable-multi-threading", isc::data::Element::create(false)); + } +} + /// @brief Runs parser in JSON mode, useful for parser testing /// /// @param in string to be parsed /// @return ElementPtr structure representing parsed JSON inline isc::data::ElementPtr -parseJSON(const std::string& in) -{ +parseJSON(const std::string& in) { isc::dhcp::Parser6Context ctx; return (ctx.parseString(in, isc::dhcp::Parser6Context::PARSER_JSON)); } @@ -807,8 +892,7 @@ parseJSON(const std::string& in) /// @param verbose display the exception message when it fails /// @return ElementPtr structure representing parsed JSON inline isc::data::ElementPtr -parseDHCP6(const std::string& in, bool verbose = false) -{ +parseDHCP6(const std::string& in, bool verbose = false) { try { isc::dhcp::Parser6Context ctx; isc::data::ElementPtr json; @@ -832,8 +916,7 @@ parseDHCP6(const std::string& in, bool verbose = false) /// @param verbose display the exception message when it fails /// @return ElementPtr structure representing parsed JSON inline isc::data::ElementPtr -parseOPTION_DEFS(const std::string& in, bool verbose = false) -{ +parseOPTION_DEFS(const std::string& in, bool verbose = false) { try { isc::dhcp::Parser6Context ctx; return (ctx.parseString(in, isc::dhcp::Parser6Context::PARSER_OPTION_DEFS)); @@ -846,8 +929,8 @@ parseOPTION_DEFS(const std::string& in, bool verbose = false) } } -}; // end of isc::dhcp::test namespace -}; // end of isc::dhcp namespace -}; // end of isc namespace +} // end of isc::dhcp::test namespace +} // end of isc::dhcp namespace +} // end of isc namespace #endif // DHCP6_TEST_UTILS_H diff --git a/src/bin/dhcp6/tests/sarr_unittest.cc b/src/bin/dhcp6/tests/sarr_unittest.cc index 88caa68992..cd485eed93 100644 --- a/src/bin/dhcp6/tests/sarr_unittest.cc +++ b/src/bin/dhcp6/tests/sarr_unittest.cc @@ -242,17 +242,69 @@ public: isc::stats::StatsMgr::instance().removeAll(); } + /// @brief Check that server processes correctly a prefix hint sent by the + /// client. This test checks that the server doesn't allocate colliding + /// prefixes as a result of receiving hints from two clients which set the + /// non-significant bytes of the prefix in their hints. The server should + /// zero the non-significant bytes of the hint and allocate the prefix of + /// the correct (configured) length. + void directClientPrefixHint(); + + /// @brief This test verifies that the same options can be specified on the + /// global level, subnet level and pool level. The options associated with + /// pools are used when the lease is handed out from these pools. + void optionsInheritance(); + + /// @brief This test verifies that it is possible to specify an excluded + /// prefix (RFC 6603) and send it back to the client requesting prefix + /// delegation. + void directClientExcludedPrefix(); + + /// @brief Check that when the client includes the Rapid Commit option in + /// its Solicit, the server responds with Reply and commits the lease. + void rapidCommitEnable(); + + /// @brief Check that the server responds with Advertise if the client + /// hasn't included the Rapid Commit option in the Solicit. + void rapidCommitNoOption(); + + /// @brief Check that when the Rapid Commit support is disabled for the + /// subnet the server replies with an Advertise and ignores the Rapid Commit + /// option sent by the client. + void rapidCommitDisable(); + + /// @brief This test verifies that regular Solicit/Adv/Request/Reply + /// exchange will result in appropriately set statistics. + void sarrStats(); + + /// @brief This test verifies that pkt6-receive-drop is increased properly + /// when the client's packet is rejected due to mismatched server-id value. + void pkt6ReceiveDropStat1(); + + /// @brief This test verifies that pkt6-receive-drop is increased properly + /// when the client's packet is rejected due to being unicast communication. + void pkt6ReceiveDropStat2(); + + /// @brief This test verifies that pkt6-receive-drop is increased properly + /// when the client's packet is rejected due to having too many client-id + /// options (exactly one is expected). + void pkt6ReceiveDropStat3(); + + /// @brief This test verifies that in pool reservations are ignored when the + /// reservations-out-of-pool flag is set to true. + void reservationModeOutOfPool(); + + /// @brief This test verifies that the in-pool reservation can be assigned + /// to a client not owning this reservation when the + /// reservations-out-of-pool flag is set to true. + void reservationIgnoredInOutOfPoolMode(); + /// @brief Interface Manager's fake configuration control. IfaceMgrTestConfig iface_mgr_test_config_; }; -/// Check that server processes correctly a prefix hint sent by the client. -/// This test checks that the server doesn't allocate colliding prefixes -/// as a result of receiving hints from two clients which set the -/// non-significant bytes of the prefix in their hints. The server should zero -/// the non-significant bytes of the hint and allocate the prefix of the -/// correct (configured) length. -TEST_F(SARRTest, directClientPrefixHint) { +void +SARRTest::directClientPrefixHint() { Dhcp6Client client; // Configure client to request IA_PD. client.requestPrefix(); @@ -306,10 +358,18 @@ TEST_F(SARRTest, directClientPrefixHint) { ASSERT_TRUE(lease_server); } -// This test verifies that the same options can be specified on the global -// level, subnet level and pool level. The options associated with pools -// are used when the lease is handed out from these pools. -TEST_F(SARRTest, optionsInheritance) { +TEST_F(SARRTest, directClientPrefixHint) { + Dhcpv6SrvMTTestGuard guard(*this, false); + directClientPrefixHint(); +} + +TEST_F(SARRTest, directClientPrefixHintMultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + directClientPrefixHint(); +} + +void +SARRTest::optionsInheritance() { Dhcp6Client client; // Request a single address and single prefix. ASSERT_NO_THROW(client.requestPrefix(0xabac, 64, IOAddress("2001:db8:4::"))); @@ -367,9 +427,18 @@ TEST_F(SARRTest, optionsInheritance) { ASSERT_TRUE(client.hasOptionWithAddress(D6O_SNTP_SERVERS, "3000:2::2")); } -/// This test verifies that it is possible to specify an excluded prefix -/// (RFC 6603) and send it back to the client requesting prefix delegation. -TEST_F(SARRTest, directClientExcludedPrefix) { +TEST_F(SARRTest, optionsInheritance) { + Dhcpv6SrvMTTestGuard guard(*this, false); + optionsInheritance(); +} + +TEST_F(SARRTest, optionsInheritanceMultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + optionsInheritance(); +} + +void +SARRTest::directClientExcludedPrefix() { Dhcp6Client client; // Configure client to request IA_PD. client.requestPrefix(); @@ -408,9 +477,18 @@ TEST_F(SARRTest, directClientExcludedPrefix) { EXPECT_EQ(120, static_cast(pd_exclude->getExcludedPrefixLength())); } -// Check that when the client includes the Rapid Commit option in its -// Solicit, the server responds with Reply and commits the lease. -TEST_F(SARRTest, rapidCommitEnable) { +TEST_F(SARRTest, directClientExcludedPrefix) { + Dhcpv6SrvMTTestGuard guard(*this, false); + directClientExcludedPrefix(); +} + +TEST_F(SARRTest, directClientExcludedPrefixMultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + directClientExcludedPrefix(); +} + +void +SARRTest::rapidCommitEnable() { Dhcp6Client client; // Configure client to request IA_NA client.requestAddress(); @@ -446,9 +524,18 @@ TEST_F(SARRTest, rapidCommitEnable) { EXPECT_EQ(1, CfgMgr::instance().getD2ClientMgr().getQueueSize()); } -// Check that the server responds with Advertise if the client hasn't -// included the Rapid Commit option in the Solicit. -TEST_F(SARRTest, rapidCommitNoOption) { +TEST_F(SARRTest, rapidCommitEnable) { + Dhcpv6SrvMTTestGuard guard(*this, false); + rapidCommitEnable(); +} + +TEST_F(SARRTest, rapidCommitEnableMultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + rapidCommitEnable(); +} + +void +SARRTest::rapidCommitNoOption() { Dhcp6Client client; // Configure client to request IA_NA client.requestAddress(); @@ -476,10 +563,18 @@ TEST_F(SARRTest, rapidCommitNoOption) { EXPECT_EQ(0, CfgMgr::instance().getD2ClientMgr().getQueueSize()); } -// Check that when the Rapid Commit support is disabled for the subnet -// the server replies with an Advertise and ignores the Rapid Commit -// option sent by the client. -TEST_F(SARRTest, rapidCommitDisable) { +TEST_F(SARRTest, rapidCommitNoOption) { + Dhcpv6SrvMTTestGuard guard(*this, false); + rapidCommitNoOption(); +} + +TEST_F(SARRTest, rapidCommitNoOptionMultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + rapidCommitNoOption(); +} + +void +SARRTest::rapidCommitDisable() { Dhcp6Client client; // The subnet assigned to eth1 has Rapid Commit disabled. client.setInterface("eth1"); @@ -511,9 +606,18 @@ TEST_F(SARRTest, rapidCommitDisable) { EXPECT_EQ(0, CfgMgr::instance().getD2ClientMgr().getQueueSize()); } -// This test verifies that regular Solicit/Adv/Request/Reply exchange will -// result in appropriately set statistics. -TEST_F(SARRTest, sarrStats) { +TEST_F(SARRTest, rapidCommitDisable) { + Dhcpv6SrvMTTestGuard guard(*this, false); + rapidCommitDisable(); +} + +TEST_F(SARRTest, rapidCommitDisableMultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + rapidCommitDisable(); +} + +void +SARRTest::sarrStats() { // Let's use one of the existing configurations and tell the client to // ask for an address. @@ -577,9 +681,18 @@ TEST_F(SARRTest, sarrStats) { EXPECT_EQ(2, pkt6_sent->getInteger().first); } -// This test verifies that pkt6-receive-drop is increased properly when the -// client's packet is rejected due to mismatched server-id value. -TEST_F(SARRTest, pkt6ReceiveDropStat1) { +TEST_F(SARRTest, sarrStats) { + Dhcpv6SrvMTTestGuard guard(*this, false); + sarrStats(); +} + +TEST_F(SARRTest, sarrStatsMultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + sarrStats(); +} + +void +SARRTest::pkt6ReceiveDropStat1() { // Dummy server-id (0xff repeated 10 times) std::vector data(10, 0xff); @@ -606,9 +719,18 @@ TEST_F(SARRTest, pkt6ReceiveDropStat1) { EXPECT_EQ(1, pkt6_recv_drop->getInteger().first); } -// This test verifies that pkt6-receive-drop is increased properly when the -// client's packet is rejected due to being unicast communication. -TEST_F(SARRTest, pkt6ReceiveDropStat2) { +TEST_F(SARRTest, pkt6ReceiveDropStat1) { + Dhcpv6SrvMTTestGuard guard(*this, false); + pkt6ReceiveDropStat1(); +} + +TEST_F(SARRTest, pkt6ReceiveDropStat1MultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + pkt6ReceiveDropStat1(); +} + +void +SARRTest::pkt6ReceiveDropStat2() { // Let's use one of the existing configurations and tell the client to // ask for an address. @@ -630,10 +752,18 @@ TEST_F(SARRTest, pkt6ReceiveDropStat2) { EXPECT_EQ(1, pkt6_recv_drop->getInteger().first); } -// This test verifies that pkt6-receive-drop is increased properly when the -// client's packet is rejected due to having too many client-id options -// (exactly one is expected). -TEST_F(SARRTest, pkt6ReceiveDropStat3) { +TEST_F(SARRTest, pkt6ReceiveDropStat2) { + Dhcpv6SrvMTTestGuard guard(*this, false); + pkt6ReceiveDropStat2(); +} + +TEST_F(SARRTest, pkt6ReceiveDropStat2MultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + pkt6ReceiveDropStat2(); +} + +void +SARRTest::pkt6ReceiveDropStat3() { // Let's use one of the existing configurations and tell the client to // ask for an address. @@ -658,9 +788,18 @@ TEST_F(SARRTest, pkt6ReceiveDropStat3) { EXPECT_EQ(1, pkt6_recv_drop->getInteger().first); } -// This test verifies that in pool reservations are ignored when the -// reservations-out-of-pool flag is set to true. -TEST_F(SARRTest, reservationModeOutOfPool) { +TEST_F(SARRTest, pkt6ReceiveDropStat3) { + Dhcpv6SrvMTTestGuard guard(*this, false); + pkt6ReceiveDropStat3(); +} + +TEST_F(SARRTest, pkt6ReceiveDropStat3MultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + pkt6ReceiveDropStat3(); +} + +void +SARRTest::reservationModeOutOfPool() { // Create the first client for which we have a reservation out of the // dynamic pool. Dhcp6Client client; @@ -694,10 +833,18 @@ TEST_F(SARRTest, reservationModeOutOfPool) { ASSERT_EQ("2001:db8:1::3", lease.addr_.toText()); } -// This test verifies that the in-pool reservation can be assigned to a client -// not owning this reservation when the reservations-out-of-pool flag is set to -// true. -TEST_F(SARRTest, reservationIgnoredInOutOfPoolMode) { +TEST_F(SARRTest, reservationModeOutOfPool) { + Dhcpv6SrvMTTestGuard guard(*this, false); + reservationModeOutOfPool(); +} + +TEST_F(SARRTest, reservationModeOutOfPoolMultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + reservationModeOutOfPool(); +} + +void +SARRTest::reservationIgnoredInOutOfPoolMode() { // Create the first client for which we have a reservation out of the // dynamic pool. Dhcp6Client client; @@ -716,4 +863,14 @@ TEST_F(SARRTest, reservationIgnoredInOutOfPoolMode) { ASSERT_EQ("2001:db8:1::5", lease.addr_.toText()); } +TEST_F(SARRTest, reservationIgnoredInOutOfPoolMode) { + Dhcpv6SrvMTTestGuard guard(*this, false); + reservationIgnoredInOutOfPoolMode(); +} + +TEST_F(SARRTest, reservationIgnoredInOutOfPoolModeMultiThreading) { + Dhcpv6SrvMTTestGuard guard(*this, true); + reservationIgnoredInOutOfPoolMode(); +} + } // end of anonymous namespace