Commit 2a9fd6c6 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[2463] Reset configuration after each unit test.

parent 03e57865
......@@ -505,7 +505,8 @@ public:
///
/// Class constructor.
OptionDataParser(const std::string&)
: options_(NULL) { }
: options_(NULL),
option_descriptor_(OptionPtr(), false) { }
/// @brief Parses the single option data.
///
......@@ -570,33 +571,31 @@ public:
/// already present in the storage they will be replaced if options with
/// the same code are present in the intermediate storage.
///
/// @throw isc::InvalidOperation if failed to set pointer to storage
/// prior to calling commit. If that happens the data in the storage remain
/// not modified.
/// @throw isc::InvalidOperation if failed to set pointer to storage failed
/// to call build() prior to commit. If that happens the data in the storage
/// remain not modified.
virtual void commit() {
if (options_ == NULL) {
isc_throw(isc::InvalidOperation, "Parser logic error: storage must be set before "
"commiting option data.");
} else if (!option_descriptor_.option) {
// Before we can commit the new option should be configured. If it is not
// than somebody must have called commit() before build().
isc_throw(isc::InvalidOperation, "Parser logic error: no option has been configured and"
" thus there is nothing to commit. Has build() been called?");
}
// Get all new options from the intermediate storage. Note that it holds
// all options configured since last commit.
BOOST_FOREACH(Subnet::OptionDescriptor desc, intermediate_storage_) {
uint16_t opt_type = desc.option->getType();
Subnet::OptionContainerTypeIndex& idx = options_->get<1>();
// Try to find options with the particular option code in the main
// storage. If found, remove these options because they will be
// replaced with new ones.
Subnet::OptionContainerTypeRange range =
idx.equal_range(opt_type);
if (std::distance(range.first, range.second) > 0) {
idx.erase(range.first, range.second);
}
uint16_t opt_type = option_descriptor_.option->getType();
Subnet::OptionContainerTypeIndex& idx = options_->get<1>();
// Try to find options with the particular option code in the main
// storage. If found, remove these options because they will be
// replaced with new one.
Subnet::OptionContainerTypeRange range =
idx.equal_range(opt_type);
if (std::distance(range.first, range.second) > 0) {
idx.erase(range.first, range.second);
}
// Append all options from the intermediate storage to the
// main storage.
options_->insert(options_->end(),
intermediate_storage_.begin(),
intermediate_storage_.end());
// Append new option to the main storage.
options_->push_back(option_descriptor_);
}
/// @brief Set storage for the parser.
......@@ -688,14 +687,11 @@ private:
// if definition does not exist.
OptionPtr option(new Option(Option::V6, static_cast<uint16_t>(option_code),
binary));
// The intermerdiate storage is used here because it is
// reset for each new parser created. Thus it collects only new
// options and can be later used to merge new options with
// options configured earlier (replace those that have the same
// option code and add new to storage). Merge is performed in
// commit stage.
Subnet::OptionDescriptor desc(option, false);
intermediate_storage_.push_back(desc);
// Created option is stored in option_descriptor_ class member until commit
// stage when it inserted into the main storage. If option with the same
// code exists in main storage already it replaces old option.
option_descriptor_.option = option;
option_descriptor_.persistent = false;
} else {
// We have exactly one option definition for the particular option code.
// use it to create option instance.
......@@ -706,7 +702,8 @@ private:
try {
OptionPtr option = factory(Option::V6, option_code, binary);
Subnet::OptionDescriptor desc(option, false);
intermediate_storage_.push_back(desc);
option_descriptor_.option = option;
option_descriptor_.persistent = false;
} catch (const isc::Exception& ex) {
isc_throw(Dhcp6ConfigError, "Parser error: option data does not match"
<< " option definition (code " << option_code << "): "
......@@ -748,9 +745,8 @@ private:
/// Pointer to options storage. This storage is provided by
/// the calling class and is shared by all OptionDataParser objects.
OptionStorage* options_;
/// Intermediate option storage. It holds all newly configured
/// option values.
OptionStorage intermediate_storage_;
/// Option descriptor holds newly configured option.
Subnet::OptionDescriptor option_descriptor_;
};
/// @brief Parser for option data values with ina subnet.
......@@ -768,7 +764,7 @@ public:
/// a global option containers (option_default). That storage location
/// is overriden on a subnet basis.
OptionDataListParser(const std::string&)
: options_(&option_defaults) { }
: options_(&option_defaults), local_options_() { }
/// @brief Parses entries that define options' data for a subnet.
///
......@@ -782,8 +778,8 @@ public:
boost::shared_ptr<OptionDataParser> parser(new OptionDataParser("option-data"));
// options_ member will hold instances of all options thus
// each OptionDataParser takes it as a storage.
parser->setStorage(options_);
// Build the instance of a singkle option.
parser->setStorage(&local_options_);
// Build the instance of a single option.
parser->build(option_value);
// Store a parser as it will be used to commit.
parsers_.push_back(parser);
......@@ -805,6 +801,7 @@ public:
BOOST_FOREACH(ParserPtr parser, parsers_) {
parser->commit();
}
std::swap(local_options_, *options_);
}
/// @brief Create DhcpDataListParser object
......@@ -816,6 +813,8 @@ public:
return (new OptionDataListParser(param_name));
}
/// Intermediate option storage
OptionStorage local_options_;
/// Pointer to options instances storage.
OptionStorage* options_;
/// Collection of parsers;
......
......@@ -54,6 +54,8 @@ public:
}
~Dhcp6ParserTest() {
// Reset configuration database after each test.
resetConfiguration();
delete srv_;
};
......@@ -118,6 +120,51 @@ public:
return (stream.str());
}
/// @brief Reset configuration database.
///
/// This function resets configuration data base by
/// removing all subnets and option-data. Reset must
/// be performed after each test to make sure that
/// contents of the database do not affect result of
/// subsequent tests.
void resetConfiguration() {
ConstElementPtr status;
string config = "{ \"interface\": [ \"all\" ],"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"valid-lifetime\": 4000, "
"\"subnet6\": [ ], "
"\"option-data\": [ ] }";
try {
ElementPtr json = Element::fromJSON(config);
status = configureDhcp6Server(*srv_, json);
} catch (const std::exception& ex) {
FAIL() << "Fatal error: unable to reset configuration database"
<< " after the test. The following configuration was used"
<< " to reset database: " << std::endl
<< config << std::endl
<< " and the following error message was returned:"
<< ex.what() << std::endl;
}
// returned value should be 0 (configuration success)
if (!status) {
FAIL() << "Fatal error: unable to reset configuration database"
<< " after the test. Configuration function returned"
<< " NULL pointer" << std::endl;
}
comment_ = parseAnswer(rcode_, status);
if (rcode_ != 0) {
FAIL() << "Fatal error: unable to reset configuration database"
<< " after the test. Configuration function returned"
<< " error code " << rcode_ << std::endl;
}
}
/// @brief Test invalid option parameter value.
///
/// This test function constructs the simple configuration
......@@ -693,7 +740,7 @@ TEST_F(Dhcp6ParserTest, stdOptionData) {
// Option code 3 means OPTION_IA_NA.
params["code"] = "3";
params["data"] = "ABCDEF01 02030405 06070809";
std::string config = createConfigWithOption(params);
ElementPtr json = Element::fromJSON(config);
......
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