]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3578] added load write and reload test
authorRazvan Becheriu <razvan@isc.org>
Wed, 25 Sep 2024 19:55:24 +0000 (22:55 +0300)
committerRazvan Becheriu <razvan@isc.org>
Mon, 30 Sep 2024 09:13:35 +0000 (12:13 +0300)
src/bin/agent/parser_context.cc
src/bin/d2/parser_context.cc
src/bin/dhcp4/ctrl_dhcp4_srv.h
src/bin/dhcp4/parser_context.cc
src/bin/dhcp4/tests/kea_controller_unittest.cc
src/bin/dhcp6/ctrl_dhcp6_srv.h
src/bin/dhcp6/parser_context.cc
src/bin/dhcp6/tests/kea_controller_unittest.cc
src/bin/netconf/parser_context.cc
src/lib/database/database_connection.cc
src/lib/database/tests/database_connection_unittest.cc

index 7c18e034e3cba783577ec0c88ca5230a3ab27609..675fda3db67e3b89d6517eced3f8ed66be400883 100644 (file)
@@ -57,15 +57,14 @@ ParserContext::parseCommon() {
             isc_throw(ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index d70212e2fab39e76303bc039140869dedf7e6e41..d71ea40d28ee7dd5bd1ce322b95a5abed1ec7d69 100644 (file)
@@ -57,15 +57,14 @@ D2ParserContext::parseCommon() {
             isc_throw(D2ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(D2ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(D2ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index 1c8e6dc8adbe8bbb42e20c97e881ef54f05684f9..8464ae245d42a90976b044bb88f453b71b66010b 100644 (file)
@@ -124,6 +124,7 @@ private:
     /// (that was sent from some yet unspecified sender).
     static void sessionReader(void);
 
+protected:
     /// @brief Handler for processing 'shutdown' command
     ///
     /// This handler processes shutdown command, which initializes shutdown
@@ -342,6 +343,7 @@ private:
     commandStatisticSetMaxSampleAgeAllHandler(const std::string& command,
                                               isc::data::ConstElementPtr args);
 
+private:
     /// @brief Reclaims expired IPv4 leases and reschedules timer.
     ///
     /// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases4.
index c0156c79bfb3272fa55a56acf1c72250ea78e555..daca1e7022d91b38909c666a35f71b460f4ff49e 100644 (file)
@@ -55,15 +55,14 @@ Parser4Context::parseCommon() {
             isc_throw(Dhcp4ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(Dhcp4ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(Dhcp4ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index c636be1238919529b3aff71cd76ce6ded87c1981..f61c90f58ecc4ec182b5e552636021f894415698 100644 (file)
@@ -27,6 +27,7 @@
 #endif
 
 #include <log/logger_support.h>
+#include <testutils/test_to_element.h>
 #include <util/stopwatch.h>
 
 #include <boost/pointer_cast.hpp>
@@ -55,6 +56,7 @@ using namespace isc::db::test;
 using namespace isc::dhcp;
 using namespace isc::dhcp::test;
 using namespace isc::hooks;
+using namespace isc::test;
 
 namespace {
 
@@ -176,7 +178,7 @@ typedef boost::shared_ptr<TestCBControlDHCPv4> TestCBControlDHCPv4Ptr;
 ///
 /// Exposes internal fields and installs stub implementation of the
 /// @c CBControlDHCPv4 object.
-class NakedControlledDhcpv4Srv: public ControlledDhcpv4Srv {
+class NakedControlledDhcpv4Srv : public ControlledDhcpv4Srv {
 public:
 
     /// @brief Constructor.
@@ -185,7 +187,14 @@ public:
         // We're replacing the @c CBControlDHCPv4 instance with our
         // stub implementation used in tests.
         cb_control_.reset(new TestCBControlDHCPv4());
+
+        CfgMgr::instance().setFamily(AF_INET);
     }
+
+    using ControlledDhcpv4Srv::commandConfigGetHandler;
+    using ControlledDhcpv4Srv::commandConfigSetHandler;
+    using ControlledDhcpv4Srv::commandConfigReloadHandler;
+    using ControlledDhcpv4Srv::commandConfigWriteHandler;
 };
 
 /// @brief test class for Kea configuration backend
@@ -301,7 +310,6 @@ public:
         EXPECT_EQ(0, cb_control->getDatabaseCurrentConfigFetchCalls());
         EXPECT_EQ(1, cb_control->getDatabaseStagingConfigFetchCalls());
 
-
         if (call_command) {
             // The case where there is no backend is tested in the
             // controlled server tests so we have only to verify
@@ -1079,7 +1087,6 @@ testBackendReconfiguration(const std::string& backend_first,
               LeaseMgrFactory::instance().getType());
 }
 
-
 // This test verifies that backend specification can be added on
 // server reconfiguration.
 TEST_F(JSONFileBackendMySQLTest, reconfigureBackendUndefinedToMySQL) {
@@ -1100,4 +1107,94 @@ TEST_F(JSONFileBackendMySQLTest, reconfigureBackendMemfileToMySQL) {
 
 #endif
 
+/// @brief Test that all-keys.json config file can be loaded, written to disk
+/// and reloaded.
+TEST_F(JSONFileBackendTest, DISABLED_loadWriteReloadTest) {
+
+    // Create server first.
+    boost::scoped_ptr<NakedControlledDhcpv4Srv> srv;
+    ASSERT_NO_THROW(
+        srv.reset(new NakedControlledDhcpv4Srv());
+    );
+
+    try {
+        srv->init(CFG_EXAMPLES"/all-keys.json");
+    } catch (const std::exception& ex) {
+        ADD_FAILURE() << "Exception thrown on load: " << ex.what() << endl;
+    }
+
+    // Save initial configuration.
+    // ConstElementPtr expected_json;
+
+    // Read contents of the file and parse it as JSON.
+    // {
+    //     Parser4Context parser;
+    //     expected_json = parser.parseFile(CFG_EXAMPLES"/all-keys.json", Parser4Context::PARSER_DHCP4);
+    //     if (!expected_json) {
+    //         ADD_FAILURE() << "Invalid configuration in " << CFG_EXAMPLES"/all-keys.json" << endl;
+    //     }
+    // }
+
+    // Set test file used write and reload configuration.
+    srv->setConfigFile(TEST_FILE);
+
+    // Save initial configuration to check it with the reloaded configuration.
+    // ConstElementPtr expected;
+    // try {
+    //     expected = srv->commandConfigGetHandler("", ConstElementPtr());
+    // } catch (const std::exception& ex) {
+    //     ADD_FAILURE() << "Exception thrown on get: " << ex.what() << endl;
+    // }
+
+    ConstElementPtr result;
+    int rcode;
+
+    // Configuration is written to test file.
+    try {
+        result = srv->commandConfigWriteHandler("", ConstElementPtr());
+        result = parseAnswerText(rcode, result);
+    } catch (const std::exception& ex) {
+        ADD_FAILURE() << "Exception thrown on write: " << ex.what() << endl;
+    }
+
+    ASSERT_EQ(CONTROL_RESULT_SUCCESS, rcode);
+    ASSERT_EQ("Configuration written to test-config.json successful", result->stringValue());
+
+    // Save written configuration.
+    // ConstElementPtr actual_json;
+
+    // {
+    //     Parser4Context parser;
+    //     actual_json = parser.parseFile(TEST_FILE, Parser4Context::PARSER_DHCP4);
+    //     if (!actual_json) {
+    //         ADD_FAILURE() << "Invalid configuration in written file " << TEST_FILE << endl;
+    //     }
+    // }
+
+    // Configuration is reloaded from test file.
+    try {
+        result = srv->commandConfigReloadHandler("", ConstElementPtr());
+        result = parseAnswerText(rcode, result);
+    }  catch (const std::exception& ex) {
+        ADD_FAILURE() << "Exception thrown on reload: " << ex.what() << endl;
+    }
+
+    ASSERT_EQ(CONTROL_RESULT_SUCCESS, rcode);
+    ASSERT_EQ("Configuration successful.", result->stringValue());
+
+    // Save reloaded configuration.
+    // ConstElementPtr actual;
+    // try {
+    //     expected = srv->commandConfigGetHandler("", ConstElementPtr());
+    // } catch (const std::exception& ex) {
+    //     ADD_FAILURE() << "Exception thrown on get after reload: " << ex.what() << endl;
+    // }
+
+    // Check initial configuration with reloaded configuration.
+    // expectEqWithDiff(expected_json, actual_json);
+
+    // Check initial configuration with reloaded configuration.
+    // expectEqWithDiff(expected, actual);
+}
+
 } // End of anonymous namespace
index 3d75bae6f9d1a00e6e5985cf776472bc9d6d0644..b86e9bf7ac1b584bc582f1d23a54be5045832796 100644 (file)
@@ -124,6 +124,7 @@ private:
     /// (that was sent from some yet unspecified sender).
     static void sessionReader(void);
 
+protected:
     /// @brief Handler for processing 'shutdown' command
     ///
     /// This handler processes shutdown command, which initializes shutdown
@@ -342,6 +343,7 @@ private:
     commandStatisticSetMaxSampleAgeAllHandler(const std::string& command,
                                               isc::data::ConstElementPtr args);
 
+private:
     /// @brief Reclaims expired IPv6 leases and reschedules timer.
     ///
     /// This is a wrapper method for @c AllocEngine::reclaimExpiredLeases6.
index 04124a35b500d38f1ec992d9c049d060887fa477..97a62c26367f32a51599cae564b683927cc7633b 100644 (file)
@@ -55,15 +55,14 @@ Parser6Context::parseCommon() {
             isc_throw(Dhcp6ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(Dhcp6ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(Dhcp6ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index 9ec596040e18fe7c214c4b59e98511480a600b25..08693ce6f85264155868dc5be84daf38d1af825c 100644 (file)
@@ -25,6 +25,7 @@
 #endif
 
 #include <log/logger_support.h>
+#include <testutils/test_to_element.h>
 #include <util/stopwatch.h>
 
 #include <boost/pointer_cast.hpp>
@@ -52,6 +53,7 @@ using namespace isc::db::test;
 using namespace isc::dhcp;
 using namespace isc::dhcp::test;
 using namespace isc::hooks;
+using namespace isc::test;
 
 namespace {
 
@@ -173,7 +175,7 @@ typedef boost::shared_ptr<TestCBControlDHCPv6> TestCBControlDHCPv6Ptr;
 ///
 /// Exposes internal fields and installs stub implementation of the
 /// @c CBControlDHCPv6 object.
-class NakedControlledDhcpv6Srv: public ControlledDhcpv6Srv {
+class NakedControlledDhcpv6Srv : public ControlledDhcpv6Srv {
 public:
 
     /// @brief Constructor.
@@ -182,10 +184,22 @@ public:
         // We're replacing the @c CBControlDHCPv6 instance with our
         // stub implementation used in tests.
         cb_control_.reset(new TestCBControlDHCPv6());
+
+        CfgMgr::instance().setFamily(AF_INET6);
     }
-};
 
+    using ControlledDhcpv6Srv::commandConfigGetHandler;
+    using ControlledDhcpv6Srv::commandConfigSetHandler;
+    using ControlledDhcpv6Srv::commandConfigReloadHandler;
+    using ControlledDhcpv6Srv::commandConfigWriteHandler;
+};
 
+/// @brief test class for Kea configuration backend
+///
+/// This class is used for testing Kea configuration backend.
+/// It is very simple and currently focuses on reading
+/// config file from disk. It is expected to be expanded in the
+/// near future.
 class JSONFileBackendTest : public dhcp::test::BaseServerTest {
 public:
     JSONFileBackendTest() {
@@ -286,7 +300,6 @@ public:
         EXPECT_EQ(0, cb_control->getDatabaseCurrentConfigFetchCalls());
         EXPECT_EQ(1, cb_control->getDatabaseStagingConfigFetchCalls());
 
-
         if (call_command) {
             // The case where there is no backend is tested in the
             // controlled server tests so we have only to verify
@@ -796,7 +809,6 @@ TEST_F(JSONFileBackendTest, timers) {
                                        duid_expired, 1, 50, 60, SubnetID(1)));
     lease_expired->cltt_ = time(NULL) - 100;
 
-
     // Create expired-reclaimed lease. The lease has expired 1000 - 60 seconds
     // ago. It should be removed from the lease database when the "flush" timer
     // goes off.
@@ -1062,7 +1074,6 @@ testBackendReconfiguration(const std::string& backend_first,
               LeaseMgrFactory::instance().getType());
 }
 
-
 // This test verifies that backend specification can be added on
 // server reconfiguration.
 TEST_F(JSONFileBackendMySQLTest, reconfigureBackendUndefinedToMySQL) {
@@ -1083,4 +1094,94 @@ TEST_F(JSONFileBackendMySQLTest, reconfigureBackendMemfileToMySQL) {
 
 #endif
 
+/// @brief Test that all-keys.json config file can be loaded, written to disk
+/// and reloaded.
+TEST_F(JSONFileBackendTest, DISABLED_loadWriteReloadTest) {
+
+    // Create server first.
+    boost::scoped_ptr<NakedControlledDhcpv6Srv> srv;
+    ASSERT_NO_THROW(
+        srv.reset(new NakedControlledDhcpv6Srv());
+    );
+
+    try {
+        srv->init(CFG_EXAMPLES"/all-keys.json");
+    } catch (const std::exception& ex) {
+        ADD_FAILURE() << "Exception thrown on load: " << ex.what() << endl;
+    }
+
+    // Save initial configuration.
+    // ConstElementPtr expected_json;
+
+    // Read contents of the file and parse it as JSON.
+    // {
+    //     Parser6Context parser;
+    //     expected_json = parser.parseFile(CFG_EXAMPLES"/all-keys.json", Parser6Context::PARSER_DHCP6);
+    //     if (!expected_json) {
+    //         ADD_FAILURE() << "Invalid configuration in " << CFG_EXAMPLES"/all-keys.json" << endl;
+    //     }
+    // }
+
+    // Set test file used write and reload configuration.
+    srv->setConfigFile(TEST_FILE);
+
+    // Save initial configuration to check it with the reloaded configuration.
+    // ConstElementPtr expected;
+    // try {
+    //     expected = srv->commandConfigGetHandler("", ConstElementPtr());
+    // } catch (const std::exception& ex) {
+    //     ADD_FAILURE() << "Exception thrown on get: " << ex.what() << endl;
+    // }
+
+    ConstElementPtr result;
+    int rcode;
+
+    // Configuration is written to test file.
+    try {
+        result = srv->commandConfigWriteHandler("", ConstElementPtr());
+        result = parseAnswerText(rcode, result);
+    } catch (const std::exception& ex) {
+        ADD_FAILURE() << "Exception thrown on write: " << ex.what() << endl;
+    }
+
+    ASSERT_EQ(CONTROL_RESULT_SUCCESS, rcode);
+    ASSERT_EQ("Configuration written to test-config.json successful", result->stringValue());
+
+    // Save written configuration.
+    // ConstElementPtr actual_json;
+
+    // {
+    //     Parser6Context parser;
+    //     actual_json = parser.parseFile(TEST_FILE, Parser6Context::PARSER_DHCP6);
+    //     if (!actual_json) {
+    //         ADD_FAILURE() << "Invalid configuration in written file " << TEST_FILE << endl;
+    //     }
+    // }
+
+    // Configuration is reloaded from test file.
+    try {
+        result = srv->commandConfigReloadHandler("", ConstElementPtr());
+        result = parseAnswerText(rcode, result);
+    }  catch (const std::exception& ex) {
+        ADD_FAILURE() << "Exception thrown on reload: " << ex.what() << endl;
+    }
+
+    ASSERT_EQ(CONTROL_RESULT_SUCCESS, rcode);
+    ASSERT_EQ("Configuration successful.", result->stringValue());
+
+    // Save reloaded configuration.
+    // ConstElementPtr actual;
+    // try {
+    //     expected = srv->commandConfigGetHandler("", ConstElementPtr());
+    // } catch (const std::exception& ex) {
+    //     ADD_FAILURE() << "Exception thrown on get after reload: " << ex.what() << endl;
+    // }
+
+    // Check initial configuration with reloaded configuration.
+    // expectEqWithDiff(expected_json, actual_json);
+
+    // Check initial configuration with reloaded configuration.
+    // expectEqWithDiff(expected, actual);
+}
+
 } // End of anonymous namespace
index d0e20fc11176a48ebab9dc90cdbf02e9714db236..3e57c51e9fa661a66c9bb982777b65dfccd62195 100644 (file)
@@ -57,15 +57,14 @@ ParserContext::parseCommon() {
             isc_throw(ParseError, "Parser abort");
         }
         scanEnd();
-    }
-    catch (...) {
+    } catch (...) {
         scanEnd();
         throw;
     }
     if (stack_.size() == 1) {
         return (stack_[0]);
     } else {
-        isc_throw(ParseError, "Expected exactly one terminal Element expected, found "
+        isc_throw(ParseError, "Expected exactly one terminal Element, found "
                   << stack_.size());
     }
 }
index 29f99f6ec1028bd7c46208f8947efc353de6630d..99a0bdf7b071c9f18744a97774af6235c85542ad 100644 (file)
@@ -241,7 +241,8 @@ DatabaseConnection::toElement(const ParameterMap& params) {
                     .arg(keyword).arg(value);
             }
         } else if ((keyword == "persist") ||
-                   (keyword == "readonly")) {
+                   (keyword == "readonly") ||
+                   (keyword == "retry-on-startup")) {
             if (value == "true") {
                 result->set(keyword, isc::data::Element::create(true));
             } else if (value == "false") {
@@ -256,7 +257,6 @@ DatabaseConnection::toElement(const ParameterMap& params) {
                    (keyword == "host") ||
                    (keyword == "name") ||
                    (keyword == "on-fail") ||
-                   (keyword == "retry-on-startup") ||
                    (keyword == "trust-anchor") ||
                    (keyword == "cert-file") ||
                    (keyword == "key-file") ||
index a0ee38ae0254396b7e9e3382ab618c2927c6495b..de1ae2d72d5ec2eb2c96b4db37dddb70c0aa01f5 100644 (file)
@@ -536,6 +536,7 @@ TEST(DatabaseConnection, toElementDbAccessStringValid) {
         "\"port\" : 300, \n"
         "\"readonly\" : false, \n"
         "\"reconnect-wait-time\": 99, \n"
+        "\"retry-on-startup\" : true, \n"
         "\"type\": \"memfile\", \n"
         "\"user\": \"user_str\", \n"
         "\"max-row-errors\": 50, \n"