Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Adam Osuchowski
Kea
Commits
4114ac95
Commit
4114ac95
authored
Dec 18, 2012
by
Marcin Siodelski
Browse files
[2544] Added test cases covering per subnet option value configuration.
parent
16bdc389
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp4/tests/config_parser_unittest.cc
View file @
4114ac95
...
...
@@ -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
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment