]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3038] UTs for hook point lease4_offer
authorPiotrek Zadroga <piotrek@isc.org>
Mon, 11 Sep 2023 17:25:16 +0000 (19:25 +0200)
committerPiotrek Zadroga <piotrek@isc.org>
Mon, 18 Sep 2023 17:19:45 +0000 (19:19 +0200)
src/bin/dhcp4/tests/hooks_unittest.cc

index 905ce87a6afdc1e3b6d7e1f2636fe3abb82d9560..c0556ed1c60bb40f33545d6ca6311a9d1e0fe273 100644 (file)
@@ -57,6 +57,7 @@ TEST_F(Dhcpv4SrvTest, Hooks) {
     int hook_index_select_subnet = -1;
     int hook_index_leases4_committed = -1;
     int hook_index_host4_identifier = -1;
+    int hook_index_lease4_offer = -1;
 
     // check if appropriate indexes are set
     EXPECT_NO_THROW(hook_index_dhcp4_srv_configured = ServerHooks::getServerHooks()
@@ -81,6 +82,8 @@ TEST_F(Dhcpv4SrvTest, Hooks) {
                     .getIndex("leases4_committed"));
     EXPECT_NO_THROW(hook_index_host4_identifier = ServerHooks::getServerHooks()
                     .getIndex("host4_identifier"));
+    EXPECT_NO_THROW(hook_index_lease4_offer = ServerHooks::getServerHooks()
+                    .getIndex("lease4_offer"));
 
     EXPECT_TRUE(hook_index_dhcp4_srv_configured > 0);
     EXPECT_TRUE(hook_index_buffer4_receive > 0);
@@ -93,6 +96,7 @@ TEST_F(Dhcpv4SrvTest, Hooks) {
     EXPECT_TRUE(hook_index_select_subnet > 0);
     EXPECT_TRUE(hook_index_leases4_committed > 0);
     EXPECT_TRUE(hook_index_host4_identifier > 0);
+    EXPECT_TRUE(hook_index_lease4_offer > 0);
 }
 
 // A dummy MAC address, padded with 0s
@@ -159,6 +163,7 @@ public:
         HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_release");
         HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_decline");
         HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("host4_identifier");
+        HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease4_offer");
 
         HooksManager::setTestMode(false);
         bool status = HooksManager::unloadLibraries();
@@ -766,6 +771,41 @@ public:
         return (lease4_decline_callout(callout_handle));
     }
 
+    /// @brief Test callback that stores callout name and passed parameters.
+    ///
+    /// @param callout_handle handle passed by the hooks framework
+    /// @return always 0
+    static int
+    lease4_offer_callout(CalloutHandle& callout_handle) {
+        callback_name_ = string("lease4_offer");
+
+        callout_handle.getArgument("query4", callback_qry_pkt4_);
+
+        Lease4CollectionPtr leases4;
+        callout_handle.getArgument("leases4", leases4);
+        if (leases4->size() > 0) {
+            callback_lease4_ = leases4->at(0);
+        }
+
+        Lease4CollectionPtr deleted_leases4;
+        callout_handle.getArgument("deleted_leases4", deleted_leases4);
+        if (deleted_leases4->size() > 0) {
+            callback_deleted_lease4_ = deleted_leases4->at(0);
+        }
+
+        callout_handle.getArgument("offer_lifetime", callback_offer_lft_);
+        callout_handle.getArgument("old_lease", callback_old_lease_);
+
+        callback_argument_names_ = callout_handle.getArgumentNames();
+        sort(callback_argument_names_.begin(), callback_argument_names_.end());
+
+        if (callback_qry_pkt4_) {
+            callback_qry_options_copy_ = callback_qry_pkt4_->isCopyRetrievedOptions();
+        }
+
+        return (0);
+    }
+
     /// @brief Test callback that stores callout name and passed parameters.
     ///
     /// @param callout_handle handle passed by the hooks framework
@@ -976,6 +1016,12 @@ public:
     /// Flag indicating if copying retrieved options was enabled for
     /// a response during callout execution.
     static bool callback_resp_options_copy_;
+
+    /// Offer lifetime returned in the lease4_offer callout
+    static uint32_t callback_offer_lft_;
+
+    /// Old lease returned in the lease4_offer callout
+    static Lease4Ptr callback_old_lease_;
 };
 
 // The following fields are used in testing pkt4_receive_callout.
@@ -993,6 +1039,8 @@ Lease4Ptr HooksDhcpv4SrvTest::callback_deleted_lease4_;
 vector<string> HooksDhcpv4SrvTest::callback_argument_names_;
 bool HooksDhcpv4SrvTest::callback_qry_options_copy_;
 bool HooksDhcpv4SrvTest::callback_resp_options_copy_;
+uint32_t HooksDhcpv4SrvTest::callback_offer_lft_;
+Lease4Ptr HooksDhcpv4SrvTest::callback_old_lease_;
 
 /// @brief Fixture class used to do basic library load/unload tests
 class LoadUnloadDhcpv4SrvTest : public ::testing::Test {
@@ -3439,4 +3487,142 @@ TEST_F(HooksDhcpv4SrvTest, leases4ParkedPacketLimit) {
     EXPECT_EQ(1, getStatistic("pkt4-receive-drop"));
 }
 
+// This test verifies that the lease4_offer hook point is triggered
+// for the DHCPDISCOVER and is NOT triggered for the DHCPREQUEST.
+TEST_F(HooksDhcpv4SrvTest, lease4OfferDiscoverRequest) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    // Install lease4_offer_callout
+    ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+        "lease4_offer", lease4_offer_callout));
+
+    Dhcp4Client client(Dhcp4Client::SELECTING);
+    client.setIfaceName("eth1");
+    client.setIfaceIndex(ETH1_INDEX);
+    ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
+
+    // Make sure that we received a response
+    ASSERT_TRUE(client.getContext().response_);
+
+    // Check that the callback called is indeed the one we installed
+    EXPECT_EQ("lease4_offer", callback_name_);
+
+    // Check if all expected parameters were really received
+    vector<string> expected_argument_names;
+    expected_argument_names.push_back("query4");
+    expected_argument_names.push_back("deleted_leases4");
+    expected_argument_names.push_back("leases4");
+    expected_argument_names.push_back("offer_lifetime");
+    expected_argument_names.push_back("old_lease");
+
+    sort(expected_argument_names.begin(), expected_argument_names.end());
+    EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
+
+    // No allocated lease expected yet.
+    EXPECT_FALSE(callback_lease4_);
+
+    // Deleted lease must not be present.
+    EXPECT_FALSE(callback_deleted_lease4_);
+
+    // Pkt passed to a callout must be configured to copy retrieved options.
+    EXPECT_TRUE(callback_qry_options_copy_);
+
+    // Check if the callout handle state was reset after the callout.
+    checkCalloutHandleReset(client.getContext().query_);
+
+    resetCalloutBuffers();
+
+    // Renew the lease and make sure that the callout has NOT been executed.
+    client.setState(Dhcp4Client::RENEWING);
+    ASSERT_NO_THROW(client.doRequest());
+
+    // Make sure that we received a response
+    ASSERT_TRUE(client.getContext().response_);
+
+    // Make sure that the callout wasn't called.
+    EXPECT_TRUE(callback_name_.empty());
+
+    // Check if the callout handle state was reset after the callout.
+    checkCalloutHandleReset(client.getContext().query_);
+}
+
+// This test verifies that the lease4_offer hook point is not triggered
+// for the DHCPINFORM.
+TEST_F(HooksDhcpv4SrvTest, lease4OfferInform) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+        "lease4_offer", lease4_offer_callout));
+
+    Dhcp4Client client(Dhcp4Client::SELECTING);
+    client.useRelay();
+    ASSERT_NO_THROW(client.doInform());
+
+    // Make sure that we received a response
+    ASSERT_TRUE(client.getContext().response_);
+
+    // Make sure that the callout wasn't called.
+    EXPECT_TRUE(callback_name_.empty());
+
+    // Check if the callout handle state was reset after the callout.
+    checkCalloutHandleReset(client.getContext().query_);
+}
+
+// This test verifies that the lease4_offer hook point is not triggered
+// for the DHCPDECLINE.
+TEST_F(HooksDhcpv4SrvTest, lease4OfferDecline) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+        "lease4_offer", lease4_offer_callout));
+
+    Dhcp4Client client(Dhcp4Client::SELECTING);
+    client.useRelay();
+    ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
+
+    // Make sure that we received a response
+    ASSERT_TRUE(client.getContext().response_);
+
+    resetCalloutBuffers();
+
+    ASSERT_NO_THROW(client.doDecline());
+
+    // Make sure that the callout wasn't called.
+    EXPECT_TRUE(callback_name_.empty());
+
+    // Check if the callout handle state was reset after the callout.
+    checkCalloutHandleReset(client.getContext().query_);
+}
+
+// This test verifies that the lease4_offer hook point is not triggered
+// for the DHCPRELEASE.
+TEST_F(HooksDhcpv4SrvTest, lease4OfferRelease) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
+        "lease4_offer", lease4_offer_callout));
+
+    Dhcp4Client client(Dhcp4Client::SELECTING);
+    client.setIfaceName("eth1");
+    client.setIfaceIndex(ETH1_INDEX);
+    ASSERT_NO_THROW(client.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.100"))));
+
+    // Make sure that we received a response
+    ASSERT_TRUE(client.getContext().response_);
+
+    resetCalloutBuffers();
+
+    ASSERT_NO_THROW(client.doRelease());
+
+    // Make sure that the callout wasn't called.
+    EXPECT_TRUE(callback_name_.empty());
+
+    // Check if the callout handle state was reset after the callout.
+    checkCalloutHandleReset(client.getContext().query_);
+}
+
 }  // namespace