Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
f164402c
Commit
f164402c
authored
Aug 20, 2013
by
Marcin Siodelski
Browse files
[master] Merge branch 'trac3105'
parents
5b38a1e7
0ece621e
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/lib/dhcpsrv/dhcp_parsers.cc
View file @
f164402c
...
...
@@ -47,37 +47,58 @@ ParserContext::ParserContext(Option::Universe universe):
string_values_
(
new
StringStorage
()),
options_
(
new
OptionStorage
()),
option_defs_
(
new
OptionDefStorage
()),
hooks_libraries_
(),
universe_
(
universe
)
{
}
ParserContext
::
ParserContext
(
const
ParserContext
&
rhs
)
:
boolean_values_
(
new
BooleanStorage
(
*
(
rhs
.
boolean_values_
))),
uint32_values_
(
new
Uint32Storage
(
*
(
rhs
.
uint32_values_
))),
string_values_
(
new
StringStorage
(
*
(
rhs
.
string_values_
))),
options_
(
new
OptionStorage
(
*
(
rhs
.
options_
))),
option_defs_
(
new
OptionDefStorage
(
*
(
rhs
.
option_defs_
))),
boolean_values_
(),
uint32_values_
(),
string_values_
(),
options_
(),
option_defs_
(),
hooks_libraries_
(),
universe_
(
rhs
.
universe_
)
{
copyContext
(
rhs
);
}
ParserContext
&
// The cppcheck version 1.56 doesn't recognize that copyContext
// copies all context fields.
// cppcheck-suppress operatorEqVarError
ParserContext
::
operator
=
(
const
ParserContext
&
rhs
)
{
if
(
this
!=
&
rhs
)
{
boolean_values_
=
BooleanStoragePtr
(
new
BooleanStorage
(
*
(
rhs
.
boolean_values_
)));
uint32_values_
=
Uint32StoragePtr
(
new
Uint32Storage
(
*
(
rhs
.
uint32_values_
)));
string_values_
=
StringStoragePtr
(
new
StringStorage
(
*
(
rhs
.
string_values_
)));
options_
=
OptionStoragePtr
(
new
OptionStorage
(
*
(
rhs
.
options_
)));
option_defs_
=
OptionDefStoragePtr
(
new
OptionDefStorage
(
*
(
rhs
.
option_defs_
)));
universe_
=
rhs
.
universe_
;
copyContext
(
rhs
);
}
return
(
*
this
);
}
void
ParserContext
::
copyContext
(
const
ParserContext
&
ctx
)
{
copyContextPointer
(
ctx
.
boolean_values_
,
boolean_values_
);
copyContextPointer
(
ctx
.
uint32_values_
,
uint32_values_
);
copyContextPointer
(
ctx
.
string_values_
,
string_values_
);
copyContextPointer
(
ctx
.
options_
,
options_
);
copyContextPointer
(
ctx
.
option_defs_
,
option_defs_
);
copyContextPointer
(
ctx
.
hooks_libraries_
,
hooks_libraries_
);
// Copy universe.
universe_
=
ctx
.
universe_
;
}
template
<
typename
T
>
void
ParserContext
::
copyContextPointer
(
const
boost
::
shared_ptr
<
T
>&
source_ptr
,
boost
::
shared_ptr
<
T
>&
dest_ptr
)
{
if
(
source_ptr
)
{
dest_ptr
.
reset
(
new
T
(
*
source_ptr
));
}
else
{
dest_ptr
.
reset
();
}
}
// **************************** DebugParser *************************
...
...
src/lib/dhcpsrv/dhcp_parsers.h
View file @
f164402c
...
...
@@ -45,7 +45,8 @@ typedef OptionSpaceContainer<Subnet::OptionContainer,
/// @brief Shared pointer to option storage.
typedef
boost
::
shared_ptr
<
OptionStorage
>
OptionStoragePtr
;
/// @brief Shared pointer to collection of hooks libraries.
typedef
boost
::
shared_ptr
<
std
::
vector
<
std
::
string
>
>
HooksLibsStoragePtr
;
/// @brief A template class that stores named elements of a given data type.
///
...
...
@@ -104,7 +105,6 @@ class ValueStorage {
values_
.
clear
();
}
private:
/// @brief An std::map of the data values, keyed by parameter names.
std
::
map
<
std
::
string
,
ValueType
>
values_
;
...
...
@@ -166,13 +166,26 @@ public:
/// the list of current names can be obtained from the HooksManager) or it
/// is non-null (this is the new list of names, reload the libraries when
/// possible).
b
oo
st
::
shared_ptr
<
std
::
vector
<
std
::
string
>
>
hooks_libraries_
;
H
oo
ksLibsStoragePtr
hooks_libraries_
;
/// @brief The parsing universe of this context.
Option
::
Universe
universe_
;
/// @brief Assignment operator
ParserContext
&
operator
=
(
const
ParserContext
&
rhs
);
/// @brief Copy the context fields.
///
/// This class method initializes the context data by copying the data
/// stored in the context instance provided as an argument. Note that
/// this function will also handle copying the NULL pointers.
///
/// @param ctx context to be copied.
void
copyContext
(
const
ParserContext
&
ctx
);
template
<
typename
T
>
void
copyContextPointer
(
const
boost
::
shared_ptr
<
T
>&
source_ptr
,
boost
::
shared_ptr
<
T
>&
dest_ptr
);
};
/// @brief Pointer to various parser context.
...
...
src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc
View file @
f164402c
...
...
@@ -397,7 +397,7 @@ public:
///
/// @return retuns 0 if the configuration parsed successfully,
/// non-zero otherwise failure.
int
parseConfiguration
(
const
std
::
string
&
config
)
{
int
parseConfiguration
(
const
std
::
string
&
config
)
{
int
rcode_
=
1
;
// Turn config into elements.
// Test json just to make sure its valid.
...
...
@@ -692,3 +692,309 @@ TEST_F(ParseConfigTest, invalidHooksLibrariesTest) {
EXPECT_FALSE
(
error_text_
.
find
(
NOT_PRESENT_LIBRARY
)
==
string
::
npos
)
<<
"Error text returned from parse failure is "
<<
error_text_
;
}
/// @brief DHCP Configuration Parser Context test fixture.
class
ParserContextTest
:
public
::
testing
::
Test
{
public:
/// @brief Constructor
ParserContextTest
()
{
}
/// @brief Check that the storages of the specific type hold the
/// same value.
///
/// This function assumes that the ref_values storage holds exactly
/// one parameter called 'foo'.
///
/// @param ref_values A storage holding reference value. In the typical
/// case it is a storage held in the original context, which is assigned
/// to another context.
/// @param values A storage holding value to be checked.
/// @tparam ContainerType A type of the storage.
/// @tparam ValueType A type of the value in the container.
template
<
typename
ContainerType
,
typename
ValueType
>
void
checkValueEq
(
const
boost
::
shared_ptr
<
ContainerType
>&
ref_values
,
const
boost
::
shared_ptr
<
ContainerType
>&
values
)
{
ValueType
param
;
ASSERT_NO_THROW
(
param
=
values
->
getParam
(
"foo"
));
EXPECT_EQ
(
ref_values
->
getParam
(
"foo"
),
param
);
}
/// @brief Check that the storages of the specific type hold different
/// value.
///
/// This function assumes that the ref_values storage holds exactly
/// one parameter called 'foo'.
///
/// @param ref_values A storage holding reference value. In the typical
/// case it is a storage held in the original context, which is assigned
/// to another context.
/// @param values A storage holding value to be checked.
/// @tparam ContainerType A type of the storage.
/// @tparam ValueType A type of the value in the container.
template
<
typename
ContainerType
,
typename
ValueType
>
void
checkValueNeq
(
const
boost
::
shared_ptr
<
ContainerType
>&
ref_values
,
const
boost
::
shared_ptr
<
ContainerType
>&
values
)
{
ValueType
param
;
ASSERT_NO_THROW
(
param
=
values
->
getParam
(
"foo"
));
EXPECT_NE
(
ref_values
->
getParam
(
"foo"
),
param
);
}
/// @brief Check that option definition storage in the context holds
/// one option definition of the specified type.
///
/// @param ctx A pointer to a context.
/// @param opt_type Expected option type.
void
checkOptionDefinitionType
(
const
ParserContext
&
ctx
,
const
uint16_t
opt_type
)
{
OptionDefContainerPtr
opt_defs
=
ctx
.
option_defs_
->
getItems
(
"option-space"
);
ASSERT_TRUE
(
opt_defs
);
OptionDefContainerTypeIndex
&
idx
=
opt_defs
->
get
<
1
>
();
OptionDefContainerTypeRange
range
=
idx
.
equal_range
(
opt_type
);
EXPECT_EQ
(
1
,
std
::
distance
(
range
.
first
,
range
.
second
));
}
/// @brief Check that option storage in the context holds one option
/// of the specified type.
///
/// @param ctx A pointer to a context.
/// @param opt_type Expected option type.
void
checkOptionType
(
const
ParserContext
&
ctx
,
const
uint16_t
opt_type
)
{
Subnet
::
OptionContainerPtr
options
=
ctx
.
options_
->
getItems
(
"option-space"
);
ASSERT_TRUE
(
options
);
Subnet
::
OptionContainerTypeIndex
&
idx
=
options
->
get
<
1
>
();
Subnet
::
OptionContainerTypeRange
range
=
idx
.
equal_range
(
opt_type
);
ASSERT_EQ
(
1
,
std
::
distance
(
range
.
first
,
range
.
second
));
}
/// @brief Test copy constructor or assignment operator when values
/// being copied are NULL.
///
/// @param copy Indicates that copy constructor should be tested
/// (if true), or assignment operator (if false).
void
testCopyAssignmentNull
(
const
bool
copy
)
{
ParserContext
ctx
(
Option
::
V6
);
// Release all pointers in the context.
ctx
.
boolean_values_
.
reset
();
ctx
.
uint32_values_
.
reset
();
ctx
.
string_values_
.
reset
();
ctx
.
options_
.
reset
();
ctx
.
option_defs_
.
reset
();
ctx
.
hooks_libraries_
.
reset
();
// Even if the fields of the context are NULL, it should get
// copied.
ParserContextPtr
ctx_new
(
new
ParserContext
(
Option
::
V6
));
if
(
copy
)
{
ASSERT_NO_THROW
(
ctx_new
.
reset
(
new
ParserContext
(
ctx
)));
}
else
{
*
ctx_new
=
ctx
;
}
// The resulting context has its fields equal to NULL.
EXPECT_FALSE
(
ctx_new
->
boolean_values_
);
EXPECT_FALSE
(
ctx_new
->
uint32_values_
);
EXPECT_FALSE
(
ctx_new
->
string_values_
);
EXPECT_FALSE
(
ctx_new
->
options_
);
EXPECT_FALSE
(
ctx_new
->
option_defs_
);
EXPECT_FALSE
(
ctx_new
->
hooks_libraries_
);
}
/// @brief Test copy constructor or assignment operator.
///
/// @param copy Indicates that copy constructor should be tested (if true),
/// or assignment operator (if false).
void
testCopyAssignment
(
const
bool
copy
)
{
// Create new context. It will be later copied/assigned to another
// context.
ParserContext
ctx
(
Option
::
V6
);
// Set boolean parameter 'foo'.
ASSERT_TRUE
(
ctx
.
boolean_values_
);
ctx
.
boolean_values_
->
setParam
(
"foo"
,
true
);
// Set uint32 parameter 'foo'.
ASSERT_TRUE
(
ctx
.
uint32_values_
);
ctx
.
uint32_values_
->
setParam
(
"foo"
,
123
);
// Ser string parameter 'foo'.
ASSERT_TRUE
(
ctx
.
string_values_
);
ctx
.
string_values_
->
setParam
(
"foo"
,
"some string"
);
// Add new option, with option code 10, to the context.
ASSERT_TRUE
(
ctx
.
options_
);
OptionPtr
opt1
(
new
Option
(
Option
::
V6
,
10
));
Subnet
::
OptionDescriptor
desc1
(
opt1
,
false
);
std
::
string
option_space
=
"option-space"
;
ASSERT_TRUE
(
desc1
.
option
);
ctx
.
options_
->
addItem
(
desc1
,
option_space
);
// Add new option definition, with option code 123.
OptionDefinitionPtr
def1
(
new
OptionDefinition
(
"option-foo"
,
123
,
"string"
));
ctx
.
option_defs_
->
addItem
(
def1
,
option_space
);
// Allocate container for hooks libraries and add one library name.
ctx
.
hooks_libraries_
.
reset
(
new
std
::
vector
<
std
::
string
>
());
ctx
.
hooks_libraries_
->
push_back
(
"library1"
);
// We will use ctx_new to assign another context to it or copy
// construct.
ParserContextPtr
ctx_new
(
new
ParserContext
(
Option
::
V4
));;
if
(
copy
)
{
ctx_new
.
reset
(
new
ParserContext
(
ctx
));
}
else
{
*
ctx_new
=
ctx
;
}
// New context has the same boolean value.
ASSERT_TRUE
(
ctx_new
->
boolean_values_
);
{
SCOPED_TRACE
(
"Check that boolean values are equal in both"
" contexts"
);
checkValueEq
<
BooleanStorage
,
bool
>
(
ctx
.
boolean_values_
,
ctx_new
->
boolean_values_
);
}
// New context has the same uint32 value.
ASSERT_TRUE
(
ctx_new
->
uint32_values_
);
{
SCOPED_TRACE
(
"Check that uint32_t values are equal in both"
" contexts"
);
checkValueEq
<
Uint32Storage
,
uint32_t
>
(
ctx
.
uint32_values_
,
ctx_new
->
uint32_values_
);
}
// New context has the same string value.
ASSERT_TRUE
(
ctx_new
->
string_values_
);
{
SCOPED_TRACE
(
"Check that string values are equal in both contexts"
);
checkValueEq
<
StringStorage
,
std
::
string
>
(
ctx
.
string_values_
,
ctx_new
->
string_values_
);
}
// New context has the same option.
ASSERT_TRUE
(
ctx_new
->
options_
);
{
SCOPED_TRACE
(
"Check that the option values are equal in both"
" contexts"
);
checkOptionType
(
*
ctx_new
,
10
);
}
// New context has the same option definition.
ASSERT_TRUE
(
ctx_new
->
option_defs_
);
{
SCOPED_TRACE
(
"check that the option definition is equal in both"
" contexts"
);
checkOptionDefinitionType
(
*
ctx_new
,
123
);
}
// New context has the same hooks library.
ASSERT_TRUE
(
ctx_new
->
hooks_libraries_
);
{
ASSERT_EQ
(
1
,
ctx_new
->
hooks_libraries_
->
size
());
EXPECT_EQ
(
"library1"
,
(
*
ctx_new
->
hooks_libraries_
)[
0
]);
}
// New context has the same universe.
EXPECT_EQ
(
ctx
.
universe_
,
ctx_new
->
universe_
);
// Change the value of the boolean parameter. This should not affect the
// corresponding value in the new context.
{
SCOPED_TRACE
(
"Check that boolean value isn't changed when original"
" value is changed"
);
ctx
.
boolean_values_
->
setParam
(
"foo"
,
false
);
checkValueNeq
<
BooleanStorage
,
bool
>
(
ctx
.
boolean_values_
,
ctx_new
->
boolean_values_
);
}
// Change the value of the uint32_t parameter. This should not affect
// the corresponding value in the new context.
{
SCOPED_TRACE
(
"Check that uint32_t value isn't changed when original"
" value is changed"
);
ctx
.
uint32_values_
->
setParam
(
"foo"
,
987
);
checkValueNeq
<
Uint32Storage
,
uint32_t
>
(
ctx
.
uint32_values_
,
ctx_new
->
uint32_values_
);
}
// Change the value of the string parameter. This should not affect the
// corresponding value in the new context.
{
SCOPED_TRACE
(
"Check that string value isn't changed when original"
" value is changed"
);
ctx
.
string_values_
->
setParam
(
"foo"
,
"different string"
);
checkValueNeq
<
StringStorage
,
std
::
string
>
(
ctx
.
string_values_
,
ctx_new
->
string_values_
);
}
// Change the option. This should not affect the option instance in the
// new context.
{
SCOPED_TRACE
(
"Check that option remains the same in the new context"
" when the option in the original context is changed"
);
ctx
.
options_
->
clearItems
();
Subnet
::
OptionDescriptor
desc
(
OptionPtr
(
new
Option
(
Option
::
V6
,
100
)),
false
);
ASSERT_TRUE
(
desc
.
option
);
ctx
.
options_
->
addItem
(
desc
,
"option-space"
);
checkOptionType
(
*
ctx_new
,
10
);
}
// Change the option definition. This should not affect the option
// definition in the new context.
{
SCOPED_TRACE
(
"Check that option definition remains the same in"
" the new context when the option definition in the"
" original context is changed"
);
ctx
.
option_defs_
->
clearItems
();
OptionDefinitionPtr
def
(
new
OptionDefinition
(
"option-foo"
,
234
,
"string"
));
ctx
.
option_defs_
->
addItem
(
def
,
option_space
);
checkOptionDefinitionType
(
*
ctx_new
,
123
);
}
// Change the list of libraries. this should not affect the list in the
// new context.
ctx
.
hooks_libraries_
->
clear
();
ctx
.
hooks_libraries_
->
push_back
(
"library2"
);
ASSERT_EQ
(
1
,
ctx_new
->
hooks_libraries_
->
size
());
EXPECT_EQ
(
"library1"
,
(
*
ctx_new
->
hooks_libraries_
)[
0
]);
// Change the universe. This should not affect the universe value in the
// new context.
ctx
.
universe_
=
Option
::
V4
;
EXPECT_EQ
(
Option
::
V6
,
ctx_new
->
universe_
);
}
};
// Check that the assignment operator of the ParserContext class copies all
// fields correctly.
TEST_F
(
ParserContextTest
,
assignment
)
{
testCopyAssignment
(
false
);
}
// Check that the assignment operator of the ParserContext class copies all
// fields correctly when these fields are NULL.
TEST_F
(
ParserContextTest
,
assignmentNull
)
{
testCopyAssignmentNull
(
false
);
}
// Check that the context is copy constructed correctly.
TEST_F
(
ParserContextTest
,
copyConstruct
)
{
testCopyAssignment
(
true
);
}
// Check that the context is copy constructed correctly, when context fields
// are NULL.
TEST_F
(
ParserContextTest
,
copyConstructNull
)
{
testCopyAssignmentNull
(
true
);
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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