Commit 4114ac95 authored by Marcin Siodelski's avatar Marcin Siodelski

[2544] Added test cases covering per subnet option value configuration.

parent 16bdc389
......@@ -74,6 +74,7 @@ public:
}
~Dhcp4ParserTest() {
resetConfiguration();
delete srv_;
};
......@@ -117,6 +118,50 @@ public:
EXPECT_TRUE(memcmp(expected_data, data, expected_data_len));
}
/// @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\" ],"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"valid-lifetime\": 4000, "
"\"subnet4\": [ ], "
"\"option-data\": [ ] }";
try {
ElementPtr json = Element::fromJSON(config);
status = configureDhcp4Server(*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;
}
}
Dhcpv4Srv* srv_;
int rcode_;
......@@ -299,12 +344,12 @@ TEST_F(Dhcp4ParserTest, optionDataDefaults) {
"\"renew-timer\": 1000,"
"\"option-data\": [ {"
" \"name\": \"option_foo\","
" \"code\": 100,"
" \"code\": 56,"
" \"data\": \"AB CDEF0105\""
" },"
" {"
" \"name\": \"option_foo2\","
" \"code\": 101,"
" \"code\": 23,"
" \"data\": \"01\""
" } ],"
"\"subnet4\": [ { "
......@@ -333,30 +378,164 @@ TEST_F(Dhcp4ParserTest, optionDataDefaults) {
// code so we get the range.
std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
Subnet::OptionContainerTypeIndex::const_iterator> range =
idx.equal_range(100);
// Expect single option with the code equal to 100.
idx.equal_range(56);
// Expect single option with the code equal to 56.
ASSERT_EQ(1, std::distance(range.first, range.second));
const uint8_t foo_expected[] = {
0xAB, 0xCD, 0xEF, 0x01, 0x05
};
// Check if option is valid in terms of code and carried data.
testOption(*range.first, 100, foo_expected, sizeof(foo_expected));
testOption(*range.first, 56, foo_expected, sizeof(foo_expected));
range = idx.equal_range(101);
range = idx.equal_range(23);
ASSERT_EQ(1, std::distance(range.first, range.second));
// Do another round of testing with second option.
const uint8_t foo2_expected[] = {
0x01
};
testOption(*range.first, 101, foo2_expected, sizeof(foo2_expected));
testOption(*range.first, 23, foo2_expected, sizeof(foo2_expected));
}
// Check that options with other option codes are not returned.
for (uint16_t code = 102; code < 110; ++code) {
range = idx.equal_range(code);
EXPECT_EQ(0, std::distance(range.first, range.second));
}
// Goal of this test is to verify options configuration
// for a single subnet. In particular this test checks
// that local options configuration overrides global
// option setting.
TEST_F(Dhcp4ParserTest, optionDataInSingleSubnet) {
ConstElementPtr x;
string config = "{ \"interface\": [ \"all\" ],"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"option-data\": [ {"
" \"name\": \"option_foo\","
" \"code\": 56,"
" \"data\": \"AB\""
" } ],"
"\"subnet4\": [ { "
" \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ],"
" \"subnet\": \"192.0.2.0/24\", "
" \"option-data\": [ {"
" \"name\": \"option_foo\","
" \"code\": 56,"
" \"data\": \"AB CDEF0105\""
" },"
" {"
" \"name\": \"option_foo2\","
" \"code\": 23,"
" \"data\": \"01\""
" } ]"
" } ],"
"\"valid-lifetime\": 4000 }";
ElementPtr json = Element::fromJSON(config);
EXPECT_NO_THROW(x = configureDhcp4Server(*srv_, json));
ASSERT_TRUE(x);
comment_ = parseAnswer(rcode_, x);
ASSERT_EQ(0, rcode_);
Subnet4Ptr subnet = CfgMgr::instance().getSubnet4(IOAddress("192.0.2.24"));
ASSERT_TRUE(subnet);
const Subnet::OptionContainer& options = subnet->getOptions();
ASSERT_EQ(2, options.size());
// Get the search index. Index #1 is to search using option code.
const Subnet::OptionContainerTypeIndex& idx = options.get<1>();
// Get the options for specified index. Expecting one option to be
// returned but in theory we may have multiple options with the same
// code so we get the range.
std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
Subnet::OptionContainerTypeIndex::const_iterator> range =
idx.equal_range(56);
// Expect single option with the code equal to 100.
ASSERT_EQ(1, std::distance(range.first, range.second));
const uint8_t foo_expected[] = {
0xAB, 0xCD, 0xEF, 0x01, 0x05
};
// Check if option is valid in terms of code and carried data.
testOption(*range.first, 56, foo_expected, sizeof(foo_expected));
range = idx.equal_range(23);
ASSERT_EQ(1, std::distance(range.first, range.second));
// Do another round of testing with second option.
const uint8_t foo2_expected[] = {
0x01
};
testOption(*range.first, 23, foo2_expected, sizeof(foo2_expected));
}
// Goal of this test is to verify options configuration
// for multiple subnets.
TEST_F(Dhcp4ParserTest, optionDataInMultipleSubnets) {
ConstElementPtr x;
string config = "{ \"interface\": [ \"all\" ],"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
" \"pool\": [ \"192.0.2.1 - 192.0.2.100\" ],"
" \"subnet\": \"192.0.2.0/24\", "
" \"option-data\": [ {"
" \"name\": \"option_foo\","
" \"code\": 56,"
" \"data\": \"0102030405060708090A\""
" } ]"
" },"
" {"
" \"pool\": [ \"192.0.3.101 - 192.0.3.150\" ],"
" \"subnet\": \"192.0.3.0/24\", "
" \"option-data\": [ {"
" \"name\": \"option_foo2\","
" \"code\": 23,"
" \"data\": \"FF\""
" } ]"
" } ],"
"\"valid-lifetime\": 4000 }";
ElementPtr json = Element::fromJSON(config);
EXPECT_NO_THROW(x = configureDhcp4Server(*srv_, json));
ASSERT_TRUE(x);
comment_ = parseAnswer(rcode_, x);
ASSERT_EQ(0, rcode_);
Subnet4Ptr subnet1 = CfgMgr::instance().getSubnet4(IOAddress("192.0.2.100"));
ASSERT_TRUE(subnet1);
const Subnet::OptionContainer& options1 = subnet1->getOptions();
ASSERT_EQ(1, options1.size());
// Get the search index. Index #1 is to search using option code.
const Subnet::OptionContainerTypeIndex& idx1 = options1.get<1>();
// Get the options for specified index. Expecting one option to be
// returned but in theory we may have multiple options with the same
// code so we get the range.
std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
Subnet::OptionContainerTypeIndex::const_iterator> range1 =
idx1.equal_range(56);
// Expect single option with the code equal to 56.
ASSERT_EQ(1, std::distance(range1.first, range1.second));
const uint8_t foo_expected[] = {
0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x0A
};
// Check if option is valid in terms of code and carried data.
testOption(*range1.first, 56, foo_expected, sizeof(foo_expected));
// Test another subnet in the same way.
Subnet4Ptr subnet2 = CfgMgr::instance().getSubnet4(IOAddress("192.0.3.102"));
ASSERT_TRUE(subnet2);
const Subnet::OptionContainer& options2 = subnet2->getOptions();
ASSERT_EQ(1, options2.size());
const Subnet::OptionContainerTypeIndex& idx2 = options2.get<1>();
std::pair<Subnet::OptionContainerTypeIndex::const_iterator,
Subnet::OptionContainerTypeIndex::const_iterator> range2 =
idx2.equal_range(23);
ASSERT_EQ(1, std::distance(range2.first, range2.second));
const uint8_t foo2_expected[] = { 0xFF };
testOption(*range2.first, 23, foo2_expected, sizeof(foo2_expected));
}
/// This test checks if Uint32Parser can really parse the whole range
/// and properly err of out of range values. As we can't call Uint32Parser
......
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