]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3144] added more unit tests
authorRazvan Becheriu <razvan@isc.org>
Fri, 15 May 2026 18:56:07 +0000 (21:56 +0300)
committerRazvan Becheriu <razvan@isc.org>
Mon, 18 May 2026 11:22:02 +0000 (14:22 +0300)
doc/sphinx/arm/ctrl-channel.rst
src/lib/dhcp/iface_mgr.h
src/lib/dhcp/tests/iface_mgr_unittest.cc
src/lib/dhcpsrv/tests/srv_config_unittest.cc

index 28a8ef7f75511434cc676ade64fced3e42907403..cd3d56933eebfd7a6b684ddaf9613e01a841b125 100644 (file)
@@ -422,11 +422,11 @@ outcome:
 
 ::
 
-       {"result": 0, "text": "Configuration seems sane..." }
+       { "result": 0, "text": "Configuration seems sane..." }
 
        or
 
-       {"result": 1, "text": "unsupported parameter: BOGUS (<string>:16:26)" }
+       { "result": 1, "text": "unsupported parameter: BOGUS (<string>:16:26)" }
 
 .. isccmd:: config-write
 .. _command-config-write:
@@ -613,11 +613,11 @@ string, ``text``, describing the outcome:
 
 ::
 
-       {"result": 0, "text": "Configuration successful." }
+       { "result": 0, "text": "Configuration successful." }
 
        or
 
-       {"result": 1, "text": "unsupported parameter: BOGUS (<string>:16:26)" }
+       { "result": 1, "text": "unsupported parameter: BOGUS (<string>:16:26)" }
 
 In Kea 2.4.0 and later, the successful response from a DHCPv4, DHCPv6, or DHCP-DDNS daemon
 also contains a SHA-256 digest of the newly set configuration. The digest can be used to easily
index 9a48fac82bb588dcce45b5fb1357360be6f3c80e..0f640f0d3ee786b464f4ecd2186256e043c889c8 100644 (file)
@@ -465,7 +465,7 @@ public:
     /// @return the list of messages
     ErrorBuffer const& getErrors() const;
 
-    /// @brief Unparse a configuration object
+    /// @brief Unparse a configuration object.
     ///
     /// Returns an element which must parse into the same object, i.e.
     /// @code
index 105e413acc66f69c96a4a4b2400c96b8d2dacd8b..0939882c8961d3e22b0d9bcb810d2d9e69a2af36 100644 (file)
@@ -389,6 +389,7 @@ public:
     /// @brief Constructor.
     IfaceMgrTest()
         : errors_count_(0), kea_event_handler_type_("KEA_EVENT_HANDLER_TYPE") {
+        IfaceMgr::instance().setFamily(AF_INET);
         struct rlimit limit;
         getrlimit(RLIMIT_NOFILE, &limit_);
         limit.rlim_cur = 16 * FD_SETSIZE;
@@ -406,6 +407,7 @@ public:
         IfaceMgr::instance().setPacketFilter(PktFilter6Ptr(new PktFilterInet6()));
         IfaceMgr::instance().configureDHCPPacketQueue(AF_INET, data::ConstElementPtr());
         IfaceMgr::instance().configureDHCPPacketQueue(AF_INET6, data::ConstElementPtr());
+        IfaceMgr::instance().setFamily(AF_INET);
     }
 
     /// @brief Tests the number of IPv6 sockets on interface
@@ -4708,11 +4710,19 @@ TEST_F(IfaceMgrTest, configureDHCPPacketQueueTest4) {
     EXPECT_TRUE(ifacemgr->getPacketQueue4());
     ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
 
+    const isc::asiolink::IOAddress addr("::");
+    const uint16_t port = 0;
+    Pkt4Ptr pkt;
+    SocketInfo si(addr, port, 0);
+    ifacemgr->getPacketQueue4()->enqueuePacket(pkt, si);
+    ASSERT_FALSE(ifacemgr->getPacketQueue4()->empty());
+
     // Now let's stop stop the thread.
     ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
     ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
     // Stopping the thread should not destroy the queue.
     ASSERT_TRUE(ifacemgr->getPacketQueue4());
+    ASSERT_TRUE(ifacemgr->getPacketQueue4()->empty());
 
     // Reconfigure with the queue turned off.  We should have neither queue nor thread.
     ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET, queue_control));
@@ -4777,11 +4787,19 @@ TEST_F(IfaceMgrTest, configureDHCPPacketQueueTest6) {
     EXPECT_TRUE(ifacemgr->getPacketQueue6());
     ASSERT_TRUE(ifacemgr->isDHCPReceiverRunning());
 
+    const isc::asiolink::IOAddress addr("::");
+    const uint16_t port = 0;
+    Pkt6Ptr pkt;
+    SocketInfo si(addr, port, 0);
+    ifacemgr->getPacketQueue6()->enqueuePacket(pkt, si);
+    ASSERT_FALSE(ifacemgr->getPacketQueue6()->empty());
+
     // Now let's stop stop the thread.
     ASSERT_NO_THROW(ifacemgr->stopDHCPReceiver());
     ASSERT_FALSE(ifacemgr->isDHCPReceiverRunning());
     // Stopping the thread should not destroy the queue.
     ASSERT_TRUE(ifacemgr->getPacketQueue6());
+    ASSERT_TRUE(ifacemgr->getPacketQueue6()->empty());
 
     // Reconfigure with the queue turned off.  We should have neither queue nor thread.
     ASSERT_NO_THROW(queue_enabled = ifacemgr->configureDHCPPacketQueue(AF_INET6, queue_control));
@@ -4821,26 +4839,71 @@ TEST_F(IfaceMgrTest, indirectReceive6RotateIfaces) {
     testReceive6RotateIfaces(false);
 }
 
-TEST_F(IfaceMgrTest, receiverCS) {
+TEST_F(IfaceMgrTest, receiverCS4) {
+    const isc::asiolink::IOAddress addr("::");
+    const uint16_t port = 0;
+    Pkt4Ptr pkt;
+    SocketInfo si(addr, port, 0);
+    ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4());
     ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
     {
         ReceiverCriticalSection rcs(IfaceMgr::instance());
         ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+        ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4());
     }
     ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+    ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4());
     bool queue_enabled = false;
     data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr4::DEFAULT_QUEUE_TYPE4, 500);
     ASSERT_NO_THROW(queue_enabled = IfaceMgr::instance().configureDHCPPacketQueue(AF_INET, config));
     ASSERT_TRUE(queue_enabled);
+    IfaceMgr::instance().getPacketQueue4()->enqueuePacket(pkt, si);
 
     // Thread should only start when there is a packet queue.
     ASSERT_NO_THROW(IfaceMgr::instance().startDHCPReceiver(AF_INET));
     ASSERT_TRUE(IfaceMgr::instance().isDHCPReceiverRunning());
+    ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4()->empty());
+    {
+        ReceiverCriticalSection rcs(IfaceMgr::instance());
+        ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+        ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4()->empty());
+    }
+    ASSERT_TRUE(IfaceMgr::instance().isDHCPReceiverRunning());
+    ASSERT_FALSE(IfaceMgr::instance().getPacketQueue4()->empty());
+}
+
+TEST_F(IfaceMgrTest, receiverCS6) {
+    IfaceMgr::instance().setFamily(AF_INET6);
+    const isc::asiolink::IOAddress addr("::");
+    const uint16_t port = 0;
+    Pkt6Ptr pkt;
+    SocketInfo si(addr, port, 0);
+    ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6());
+    ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+    {
+        ReceiverCriticalSection rcs(IfaceMgr::instance());
+        ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+        ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6());
+    }
+    ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+    ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6());
+    bool queue_enabled = false;
+    data::ConstElementPtr config = makeQueueConfig(PacketQueueMgr6::DEFAULT_QUEUE_TYPE6, 500);
+    ASSERT_NO_THROW(queue_enabled = IfaceMgr::instance().configureDHCPPacketQueue(AF_INET6, config));
+    ASSERT_TRUE(queue_enabled);
+    IfaceMgr::instance().getPacketQueue6()->enqueuePacket(pkt, si);
+
+    // Thread should only start when there is a packet queue.
+    ASSERT_NO_THROW(IfaceMgr::instance().startDHCPReceiver(AF_INET6));
+    ASSERT_TRUE(IfaceMgr::instance().isDHCPReceiverRunning());
+    ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6()->empty());
     {
         ReceiverCriticalSection rcs(IfaceMgr::instance());
         ASSERT_FALSE(IfaceMgr::instance().isDHCPReceiverRunning());
+        ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6()->empty());
     }
     ASSERT_TRUE(IfaceMgr::instance().isDHCPReceiverRunning());
+    ASSERT_FALSE(IfaceMgr::instance().getPacketQueue6()->empty());
 }
 
 }
index 7fc4e27afe642d577ceb3b314c4c365457ec7cd8..16089f8b3bca055ea39ccbbe9603129903d32f50 100644 (file)
@@ -9,6 +9,7 @@
 #include <dhcp/testutils/iface_mgr_test_config.h>
 #include <dhcpsrv/cfgmgr.h>
 #include <dhcpsrv/client_class_def.h>
+#include <dhcpsrv/parsers/ifaces_config_parser.h>
 #include <dhcpsrv/srv_config.h>
 #include <dhcpsrv/subnet.h>
 #include <process/logging_info.h>
 #include <gtest/gtest.h>
 
 using namespace isc::asiolink;
+using namespace isc::data;
 using namespace isc::dhcp_ddns;
 using namespace isc::dhcp;
-using namespace isc::data;
+using namespace isc::dhcp::test;
 using namespace isc::process;
 using namespace isc::util;
 
@@ -2305,6 +2307,53 @@ TEST_F(SrvConfigTest, sanityChecksDdnsTtlParameters) {
     }
 }
 
+TEST_F(SrvConfigTest, update) {
+    CfgIfacePtr running_cfg(new CfgIface());
+    {
+        std::string config =
+            "{ \"user-context\": { \"foo\": \"bar\" }, "
+            "  \"interfaces\": [ \"eth0/10.0.0.1\", \"lo\", \"eth1961/198.51.100.1\" ], "
+            "  \"dhcp-socket-type\": \"udp\","
+            "  \"outbound-interface\": \"use-routing\", "
+            "  \"re-detect\": false }";
+        ElementPtr config_element = Element::fromJSON(config);
+        IfacesConfigParser parser(AF_INET, true);
+        parser.parse(running_cfg, config_element);
+    }
+    std::string expected = "{ "
+            "\"dhcp-socket-type\": \"udp\", "
+            "\"interfaces\": [ \"lo\", \"eth0/10.0.0.1\", \"eth1961/198.51.100.1\" ], "
+            "\"outbound-interface\": \"use-routing\", "
+            "\"re-detect\": false, "
+            "\"user-context\": { \"foo\": \"bar\" } }";
+    ASSERT_EQ(expected, running_cfg->toElement()->str());
+    CfgIfacePtr cfg_iface(new CfgIface());
+    {
+        std::string config =
+            "{ \"user-context\": { \"black\": \"sheep\" }, "
+            "  \"interfaces\": [ \"eth1/192.0.2.3\", \"eth1/192.0.2.5\", \"*\" ], "
+            "  \"dhcp-socket-type\": \"raw\","
+            "  \"outbound-interface\": \"same-as-inbound\", "
+            "  \"re-detect\": true }";
+        ElementPtr config_element = Element::fromJSON(config);
+        IfacesConfigParser parser(AF_INET, true);
+        parser.parse(cfg_iface, config_element);
+    }
+    expected = "{ "
+            "\"interfaces\": [ \"*\", \"eth1/192.0.2.3\", \"eth1/192.0.2.5\" ], "
+            "\"re-detect\": true, "
+            "\"user-context\": { \"black\": \"sheep\" } }";
+    ASSERT_EQ(expected, cfg_iface->toElement()->str());
+    running_cfg->update(*cfg_iface);
+    expected = "{ "
+            "\"dhcp-socket-type\": \"udp\", "
+            "\"interfaces\": [ \"*\", \"eth1/192.0.2.3\", \"eth1/192.0.2.5\" ], "
+            "\"outbound-interface\": \"use-routing\", "
+            "\"re-detect\": false, "
+            "\"user-context\": { \"foo\": \"bar\" } }";
+    ASSERT_EQ(expected, running_cfg->toElement()->str());
+}
+
 /// @brief Class for DdnsParams class.
 class DdnsParamsTest : public testing::Test {
 public: