Commit d1a0a7fa authored by Thomas Markwalder's avatar Thomas Markwalder
Browse files

[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.
parent c2b4e255
......@@ -349,7 +349,8 @@ TSIGKeyInfoParser::build(isc::data::ConstElementPtr key_config) {
// data to the parser's local storage.
BOOST_FOREACH (config_pair, key_config->mapValue()) {
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
config_pair.second->getPosition()));
config_pair.second->
getPosition()));
parser->build(config_pair.second);
parser->commit();
}
......@@ -387,8 +388,7 @@ TSIGKeyInfoParser::build(isc::data::ConstElementPtr key_config) {
try {
TSIGKeyInfo::stringToAlgorithmName(algorithm);
} catch (const std::exception& ex) {
isc_throw(D2CfgError, "TSIG key invalid algorithm : "
<< algorithm << " : " << pos[1]);
isc_throw(D2CfgError, "TSIG key : " << ex.what() << " : " << pos[1]);
}
// Secret cannot be blank.
......@@ -513,7 +513,8 @@ DnsServerInfoParser::build(isc::data::ConstElementPtr server_config) {
// data to the parser's local storage.
BOOST_FOREACH (config_pair, server_config->mapValue()) {
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
config_pair.second->getPosition()));
config_pair.second->
getPosition()));
parser->build(config_pair.second);
parser->commit();
}
......@@ -682,7 +683,8 @@ DdnsDomainParser::build(isc::data::ConstElementPtr domain_config) {
isc::dhcp::ConfigPair config_pair;
BOOST_FOREACH(config_pair, domain_config->mapValue()) {
isc::dhcp::ParserPtr parser(createConfigParser(config_pair.first,
config_pair.second->getPosition()));
config_pair.second->
getPosition()));
parser->build(config_pair.second);
parser->commit();
}
......@@ -838,7 +840,9 @@ DdnsDomainListMgrParser::build(isc::data::ConstElementPtr domain_config) {
// data to the parser's local storage.
isc::dhcp::ConfigPair config_pair;
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->commit();
}
......@@ -848,7 +852,9 @@ DdnsDomainListMgrParser::build(isc::data::ConstElementPtr domain_config) {
}
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;
if (config_id == "ddns_domains") {
// 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_);
} else {
isc_throw(NotImplemented, "parser error: "
"DdnsDomainListMgr parameter not supported: " << config_id);
"DdnsDomainListMgr parameter not supported: " << config_id
<< " : " << pos);
}
// Return the new domain parser instance.
......
......@@ -1145,10 +1145,16 @@ public:
///
/// @param config_id is the "item_name" for a specific member element of
/// 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.
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
/// 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 += d2_process_tests.sh.in
EXTRA_DIST += testdata/d2_cfg_tests.json
# Explicitly specify paths to dynamic libraries required by loadable python
# 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);
}
std::string testDataFile(const std::string& name) {
return (std::string(D2_TEST_DATA_DIR) + "/" + name);
}
/// @brief Test fixture class for testing D2CfgMgr class.
/// It maintains an member instance of D2CfgMgr and provides methods for
/// converting JSON strings to configuration element sets, checking parse
......@@ -1564,4 +1568,101 @@ TEST_F(D2CfgMgrTest, matchReverse) {
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
......@@ -15,3 +15,4 @@
/// @brief Path to D2 source dir so tests against the dhcp-ddns.spec file
/// can find it reliably.
#define D2_SRC_DIR "@abs_top_srcdir@/src/bin/d2"
#define D2_TEST_DATA_DIR "@abs_top_srcdir@/src/bin/d2/tests/testdata"
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment