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());
}
}
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());
}
}
/// (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
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.
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());
}
}
#endif
#include <log/logger_support.h>
+#include <testutils/test_to_element.h>
#include <util/stopwatch.h>
#include <boost/pointer_cast.hpp>
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using namespace isc::hooks;
+using namespace isc::test;
namespace {
///
/// Exposes internal fields and installs stub implementation of the
/// @c CBControlDHCPv4 object.
-class NakedControlledDhcpv4Srv: public ControlledDhcpv4Srv {
+class NakedControlledDhcpv4Srv : public ControlledDhcpv4Srv {
public:
/// @brief Constructor.
// 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
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
LeaseMgrFactory::instance().getType());
}
-
// This test verifies that backend specification can be added on
// server reconfiguration.
TEST_F(JSONFileBackendMySQLTest, reconfigureBackendUndefinedToMySQL) {
#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
/// (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
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.
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());
}
}
#endif
#include <log/logger_support.h>
+#include <testutils/test_to_element.h>
#include <util/stopwatch.h>
#include <boost/pointer_cast.hpp>
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using namespace isc::hooks;
+using namespace isc::test;
namespace {
///
/// Exposes internal fields and installs stub implementation of the
/// @c CBControlDHCPv6 object.
-class NakedControlledDhcpv6Srv: public ControlledDhcpv6Srv {
+class NakedControlledDhcpv6Srv : public ControlledDhcpv6Srv {
public:
/// @brief Constructor.
// 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() {
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
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.
LeaseMgrFactory::instance().getType());
}
-
// This test verifies that backend specification can be added on
// server reconfiguration.
TEST_F(JSONFileBackendMySQLTest, reconfigureBackendUndefinedToMySQL) {
#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
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());
}
}
.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") {
(keyword == "host") ||
(keyword == "name") ||
(keyword == "on-fail") ||
- (keyword == "retry-on-startup") ||
(keyword == "trust-anchor") ||
(keyword == "cert-file") ||
(keyword == "key-file") ||
"\"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"