mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-01 06:25:34 +00:00
[3436] Added configuration permutations test from file to D2
Added the unit test D2CfgMgrTest.configPermutations to d2_cfg_mgr_unittests.cc. This test iterates through the list of test configurations defined in a specialzed JSON data file. It provides a relatively painless way to test a large number configurations without hard-coding them. Added the test data file: It currently contains over sixty tests. The vast majority of these tests are invalid content tests.
This commit is contained in:
@@ -349,7 +349,8 @@ TSIGKeyInfoParser::build(isc::data::ConstElementPtr key_config) {
|
|||||||
// data to the parser's local storage.
|
// data to the parser's local storage.
|
||||||
BOOST_FOREACH (config_pair, key_config->mapValue()) {
|
BOOST_FOREACH (config_pair, key_config->mapValue()) {
|
||||||
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
|
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
|
||||||
config_pair.second->getPosition()));
|
config_pair.second->
|
||||||
|
getPosition()));
|
||||||
parser->build(config_pair.second);
|
parser->build(config_pair.second);
|
||||||
parser->commit();
|
parser->commit();
|
||||||
}
|
}
|
||||||
@@ -387,8 +388,7 @@ TSIGKeyInfoParser::build(isc::data::ConstElementPtr key_config) {
|
|||||||
try {
|
try {
|
||||||
TSIGKeyInfo::stringToAlgorithmName(algorithm);
|
TSIGKeyInfo::stringToAlgorithmName(algorithm);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
isc_throw(D2CfgError, "TSIG key invalid algorithm : "
|
isc_throw(D2CfgError, "TSIG key : " << ex.what() << " : " << pos[1]);
|
||||||
<< algorithm << " : " << pos[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Secret cannot be blank.
|
// Secret cannot be blank.
|
||||||
@@ -513,7 +513,8 @@ DnsServerInfoParser::build(isc::data::ConstElementPtr server_config) {
|
|||||||
// data to the parser's local storage.
|
// data to the parser's local storage.
|
||||||
BOOST_FOREACH (config_pair, server_config->mapValue()) {
|
BOOST_FOREACH (config_pair, server_config->mapValue()) {
|
||||||
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
|
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
|
||||||
config_pair.second->getPosition()));
|
config_pair.second->
|
||||||
|
getPosition()));
|
||||||
parser->build(config_pair.second);
|
parser->build(config_pair.second);
|
||||||
parser->commit();
|
parser->commit();
|
||||||
}
|
}
|
||||||
@@ -682,7 +683,8 @@ DdnsDomainParser::build(isc::data::ConstElementPtr domain_config) {
|
|||||||
isc::dhcp::ConfigPair config_pair;
|
isc::dhcp::ConfigPair config_pair;
|
||||||
BOOST_FOREACH(config_pair, domain_config->mapValue()) {
|
BOOST_FOREACH(config_pair, domain_config->mapValue()) {
|
||||||
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
|
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
|
||||||
config_pair.second->getPosition()));
|
config_pair.second->
|
||||||
|
getPosition()));
|
||||||
parser->build(config_pair.second);
|
parser->build(config_pair.second);
|
||||||
parser->commit();
|
parser->commit();
|
||||||
}
|
}
|
||||||
@@ -838,7 +840,9 @@ DdnsDomainListMgrParser::build(isc::data::ConstElementPtr domain_config) {
|
|||||||
// data to the parser's local storage.
|
// data to the parser's local storage.
|
||||||
isc::dhcp::ConfigPair config_pair;
|
isc::dhcp::ConfigPair config_pair;
|
||||||
BOOST_FOREACH(config_pair, domain_config->mapValue()) {
|
BOOST_FOREACH(config_pair, domain_config->mapValue()) {
|
||||||
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first));
|
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
|
||||||
|
config_pair.second->
|
||||||
|
getPosition()));
|
||||||
parser->build(config_pair.second);
|
parser->build(config_pair.second);
|
||||||
parser->commit();
|
parser->commit();
|
||||||
}
|
}
|
||||||
@@ -848,7 +852,9 @@ DdnsDomainListMgrParser::build(isc::data::ConstElementPtr domain_config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isc::dhcp::ParserPtr
|
isc::dhcp::ParserPtr
|
||||||
DdnsDomainListMgrParser::createConfigParser(const std::string& config_id) {
|
DdnsDomainListMgrParser::createConfigParser(const std::string& config_id,
|
||||||
|
const isc::data::Element::
|
||||||
|
Position& pos) {
|
||||||
DhcpConfigParser* parser = NULL;
|
DhcpConfigParser* parser = NULL;
|
||||||
if (config_id == "ddns_domains") {
|
if (config_id == "ddns_domains") {
|
||||||
// Domain list parser is given our local domain storage. It will pass
|
// Domain list parser is given our local domain storage. It will pass
|
||||||
@@ -857,7 +863,8 @@ DdnsDomainListMgrParser::createConfigParser(const std::string& config_id) {
|
|||||||
parser = new DdnsDomainListParser(config_id, local_domains_, keys_);
|
parser = new DdnsDomainListParser(config_id, local_domains_, keys_);
|
||||||
} else {
|
} else {
|
||||||
isc_throw(NotImplemented, "parser error: "
|
isc_throw(NotImplemented, "parser error: "
|
||||||
"DdnsDomainListMgr parameter not supported: " << config_id);
|
"DdnsDomainListMgr parameter not supported: " << config_id
|
||||||
|
<< " : " << pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the new domain parser instance.
|
// Return the new domain parser instance.
|
||||||
|
@@ -1145,10 +1145,16 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param config_id is the "item_name" for a specific member element of
|
/// @param config_id is the "item_name" for a specific member element of
|
||||||
/// the manager specification.
|
/// the manager specification.
|
||||||
|
/// @param pos position within the configuration text (or file) of element
|
||||||
|
/// to be parsed. This is passed for error messaging.
|
||||||
///
|
///
|
||||||
/// @return returns a pointer to newly created parser.
|
/// @return returns a pointer to newly created parser.
|
||||||
virtual isc::dhcp::ParserPtr createConfigParser(const std::string&
|
///
|
||||||
config_id);
|
/// @throw D2CfgError if configuration contains an unknown parameter
|
||||||
|
virtual isc::dhcp::ParserPtr
|
||||||
|
createConfigParser(const std::string& config_id,
|
||||||
|
const isc::data::Element::Position& pos =
|
||||||
|
isc::data::Element::ZERO_POSITION());
|
||||||
|
|
||||||
/// @brief Commits the configured DdsnDomainListMgr
|
/// @brief Commits the configured DdsnDomainListMgr
|
||||||
/// Currently this method is a NOP, as the manager instance is created
|
/// Currently this method is a NOP, as the manager instance is created
|
||||||
|
@@ -12,6 +12,7 @@ noinst_SCRIPTS = d2_process_tests.sh
|
|||||||
|
|
||||||
EXTRA_DIST = $(PYTESTS)
|
EXTRA_DIST = $(PYTESTS)
|
||||||
EXTRA_DIST += d2_process_tests.sh.in
|
EXTRA_DIST += d2_process_tests.sh.in
|
||||||
|
EXTRA_DIST += testdata/d2_cfg_tests.json
|
||||||
|
|
||||||
# Explicitly specify paths to dynamic libraries required by loadable python
|
# Explicitly specify paths to dynamic libraries required by loadable python
|
||||||
# modules. That is required on Mac OS systems. Otherwise we will get exception
|
# modules. That is required on Mac OS systems. Otherwise we will get exception
|
||||||
|
@@ -32,6 +32,10 @@ std::string specfile(const std::string& name) {
|
|||||||
return (std::string(D2_SRC_DIR) + "/" + name);
|
return (std::string(D2_SRC_DIR) + "/" + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string testDataFile(const std::string& name) {
|
||||||
|
return (std::string(D2_TEST_DATA_DIR) + "/" + name);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Test fixture class for testing D2CfgMgr class.
|
/// @brief Test fixture class for testing D2CfgMgr class.
|
||||||
/// It maintains an member instance of D2CfgMgr and provides methods for
|
/// It maintains an member instance of D2CfgMgr and provides methods for
|
||||||
/// converting JSON strings to configuration element sets, checking parse
|
/// converting JSON strings to configuration element sets, checking parse
|
||||||
@@ -1564,4 +1568,101 @@ TEST_F(D2CfgMgrTest, matchReverse) {
|
|||||||
ASSERT_THROW(cfg_mgr_->matchReverse("", match), D2CfgError);
|
ASSERT_THROW(cfg_mgr_->matchReverse("", match), D2CfgError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Tests D2 config parsing against a wide range of config permutations.
|
||||||
|
/// It iterates over all of the test configurations described in given file.
|
||||||
|
/// The file content is JSON specialized to this test. The format of the file
|
||||||
|
/// is:
|
||||||
|
///
|
||||||
|
/// @code
|
||||||
|
/// # The file must open with a list. It's name is arbitrary.
|
||||||
|
///
|
||||||
|
/// { "test_list" :
|
||||||
|
/// [
|
||||||
|
///
|
||||||
|
/// # Test one starts here:
|
||||||
|
/// {
|
||||||
|
///
|
||||||
|
/// # Each test has:
|
||||||
|
/// # 1. description - optional text description
|
||||||
|
/// # 2. should_fail - bool indicator if parsing is expected to file
|
||||||
|
/// # (defaults to false)
|
||||||
|
/// # 3. data - configuration text to parse
|
||||||
|
/// #
|
||||||
|
/// "description" : "<text describing test>",
|
||||||
|
/// "should_fail" : <true|false> ,
|
||||||
|
/// "data" :
|
||||||
|
/// {
|
||||||
|
/// # configuration elements here
|
||||||
|
/// "bool_val" : false,
|
||||||
|
/// "some_map" : {}
|
||||||
|
/// # :
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// # Next test would start here
|
||||||
|
/// ,
|
||||||
|
/// {
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// ]}
|
||||||
|
///
|
||||||
|
/// @endcode
|
||||||
|
///
|
||||||
|
/// (The file supports comments per Element::fromJSONFile())
|
||||||
|
///
|
||||||
|
TEST_F(D2CfgMgrTest, configPermutations) {
|
||||||
|
std::string test_file = testDataFile("d2_cfg_tests.json");
|
||||||
|
isc::data::ConstElementPtr tests;
|
||||||
|
|
||||||
|
// Read contents of the file and parse it as JSON. Note it must contain
|
||||||
|
// all valid JSON, we aren't testing JSON parsing.
|
||||||
|
try {
|
||||||
|
tests = isc::data::Element::fromJSONFile(test_file, true);
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
FAIL() << "ERROR parsing file : " << test_file << " : " << ex.what();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read in each test For each test, read:
|
||||||
|
// 1. description - optional text description
|
||||||
|
// 2. should_fail - bool indicator if parsing is expected to file (defaults
|
||||||
|
// to false
|
||||||
|
// 3. data - configuration text to parse
|
||||||
|
//
|
||||||
|
// Next attempt to parse the configuration by passing it into
|
||||||
|
// D2CfgMgr::parseConfig(). Then check the parsing outcome against the
|
||||||
|
// expected outcome as given by should_fail.
|
||||||
|
isc::data::ConstElementPtr test;
|
||||||
|
BOOST_FOREACH(test, tests->get("test_list")->listValue()) {
|
||||||
|
|
||||||
|
// Grab the description.
|
||||||
|
std::string description = "<no desc>";
|
||||||
|
isc::data::ConstElementPtr elem = test->get("description");
|
||||||
|
if (elem) {
|
||||||
|
elem->getValue(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the outcome flag, should_fail, defaults to false if it's
|
||||||
|
// not specified.
|
||||||
|
bool should_fail = false;
|
||||||
|
elem = test->get("should_fail");
|
||||||
|
if (elem) {
|
||||||
|
elem->getValue(should_fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the test's configuration data.
|
||||||
|
isc::data::ConstElementPtr data = test->get("data");
|
||||||
|
ASSERT_TRUE(data) << "No data for test: "
|
||||||
|
<< " : " << test->getPosition();
|
||||||
|
|
||||||
|
// Verify that we can parse the configuration.
|
||||||
|
answer_ = cfg_mgr_->parseConfig(data);
|
||||||
|
if (checkAnswer(!should_fail)) {
|
||||||
|
ADD_FAILURE() << "Parsing should have "
|
||||||
|
<< (should_fail ? "failed" : "passed")
|
||||||
|
<< " for : " << description
|
||||||
|
<< " : " << test->getPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
@@ -15,3 +15,4 @@
|
|||||||
/// @brief Path to D2 source dir so tests against the dhcp-ddns.spec file
|
/// @brief Path to D2 source dir so tests against the dhcp-ddns.spec file
|
||||||
/// can find it reliably.
|
/// can find it reliably.
|
||||||
#define D2_SRC_DIR "@abs_top_srcdir@/src/bin/d2"
|
#define D2_SRC_DIR "@abs_top_srcdir@/src/bin/d2"
|
||||||
|
#define D2_TEST_DATA_DIR "@abs_top_srcdir@/src/bin/d2/tests/testdata"
|
||||||
|
1273
src/bin/d2/tests/testdata/d2_cfg_tests.json
vendored
Normal file
1273
src/bin/d2/tests/testdata/d2_cfg_tests.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user