Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
ca368d00
Commit
ca368d00
authored
Feb 09, 2011
by
JINMEI Tatuya
Browse files
[master] Merge branch 'trac550' with resolving conflicts.
parents
7356673c
1d018cd8
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/lib/datasrc/memory_datasrc.cc
View file @
ca368d00
...
...
@@ -36,7 +36,7 @@ struct MemoryZone::MemoryZoneImpl {
// Constructor
MemoryZoneImpl
(
const
RRClass
&
zone_class
,
const
Name
&
origin
)
:
zone_class_
(
zone_class
),
origin_
(
origin
),
origin_data_
(
NULL
),
domains_
(
true
)
domains_
(
true
)
{
// We create the node for origin (it needs to exist anyway in future)
domains_
.
insert
(
origin
,
&
origin_data_
);
...
...
@@ -62,6 +62,7 @@ struct MemoryZone::MemoryZoneImpl {
// The tree stores domains
typedef
RBTree
<
Domain
>
DomainTree
;
typedef
RBNode
<
Domain
>
DomainNode
;
static
const
DomainNode
::
Flags
DOMAINFLAG_WILD
=
DomainNode
::
FLAG_USER1
;
// Information about the zone
RRClass
zone_class_
;
...
...
@@ -72,6 +73,47 @@ struct MemoryZone::MemoryZoneImpl {
// The actual zone data
DomainTree
domains_
;
// Add the necessary magic for any wildcard contained in 'name'
// (including itself) to be found in the zone.
//
// In order for wildcard matching to work correctly in find(),
// we must ensure that a node for the wildcarding level exists in the
// backend RBTree.
// E.g. if the wildcard name is "*.sub.example." then we must ensure
// that "sub.example." exists and is marked as a wildcard level.
// Note: the "wildcarding level" is for the parent name of the wildcard
// name (such as "sub.example.").
//
// We also perform the same trick for empty wild card names possibly
// contained in 'name' (e.g., '*.foo.example' in 'bar.*.foo.example').
void
addWildcards
(
DomainTree
&
domains
,
const
Name
&
name
)
{
Name
wname
(
name
);
const
unsigned
int
labels
(
wname
.
getLabelCount
());
const
unsigned
int
origin_labels
(
origin_
.
getLabelCount
());
for
(
unsigned
int
l
=
labels
;
l
>
origin_labels
;
--
l
,
wname
=
wname
.
split
(
1
))
{
if
(
wname
.
isWildcard
())
{
// Ensure a separate level exists for the wildcard name.
// Note: for 'name' itself we do this later anyway, but the
// overhead should be marginal because wildcard names should
// be rare.
DomainNode
*
node
;
DomainTree
::
Result
result
(
domains
.
insert
(
wname
.
split
(
1
),
&
node
));
assert
(
result
==
DomainTree
::
SUCCESS
||
result
==
DomainTree
::
ALREADYEXISTS
);
// Ensure a separate level exists for the "wildcarding" name,
// and mark the node as "wild".
result
=
domains
.
insert
(
wname
,
&
node
);
assert
(
result
==
DomainTree
::
SUCCESS
||
result
==
DomainTree
::
ALREADYEXISTS
);
node
->
setFlag
(
DOMAINFLAG_WILD
);
}
}
}
/*
* Does some checks in context of the data that are already in the zone.
* Currently checks for forbidden combinations of RRsets in the same
...
...
@@ -114,13 +156,10 @@ struct MemoryZone::MemoryZoneImpl {
}
}
/*
* Implementation of longer methods. We put them here, because the
* access is without the impl_-> and it will get inlined anyway.
*/
// Implementation of MemoryZone::add
result
::
Result
add
(
const
ConstRRsetPtr
&
rrset
,
DomainTree
*
domains
)
{
// Sanitize input
// Validate rrset before adding it to the zone. If something is wrong
// it throws an exception. It doesn't modify the zone, and provides
// the strong exception guarantee.
void
addValidation
(
const
ConstRRsetPtr
rrset
)
{
if
(
!
rrset
)
{
isc_throw
(
NullRRset
,
"The rrset provided is NULL"
);
}
...
...
@@ -137,26 +176,55 @@ struct MemoryZone::MemoryZoneImpl {
<<
rrset
->
getName
());
}
Name
name
(
rrset
->
getName
());
NameComparisonResult
compare
(
origin_
.
compare
(
name
));
NameComparisonResult
compare
(
origin_
.
compare
(
rrset
->
getName
()));
if
(
compare
.
getRelation
()
!=
NameComparisonResult
::
SUPERDOMAIN
&&
compare
.
getRelation
()
!=
NameComparisonResult
::
EQUAL
)
{
isc_throw
(
OutOfZone
,
"The name "
<<
n
ame
<<
isc_throw
(
OutOfZone
,
"The name "
<<
rrset
->
getN
ame
()
<<
" is not contained in zone "
<<
origin_
);
}
// Some RR types do not really work well with a wildcard.
// Even though the protocol specifically doesn't completely ban such
// usage, we refuse to load a zone containing such RR in order to
// keep the lookup logic simpler and more predictable.
// See RFC4592 and (for DNAME) draft-ietf-dnsext-rfc2672bis-dname
// for more technical background. Note also that BIND 9 refuses
// NS at a wildcard, so in that sense we simply provide compatible
// behavior.
if
(
rrset
->
getName
().
isWildcard
())
{
if
(
rrset
->
getType
()
==
RRType
::
NS
())
{
isc_throw
(
AddError
,
"Invalid NS owner name (wildcard): "
<<
rrset
->
getName
());
}
if
(
rrset
->
getType
()
==
RRType
::
DNAME
())
{
isc_throw
(
AddError
,
"Invalid DNAME owner name (wildcard): "
<<
rrset
->
getName
());
}
}
}
/*
* Implementation of longer methods. We put them here, because the
* access is without the impl_-> and it will get inlined anyway.
*/
// Implementation of MemoryZone::add
result
::
Result
add
(
const
ConstRRsetPtr
&
rrset
,
DomainTree
*
domains
)
{
// Sanitize input
addValidation
(
rrset
);
// Add wildcards possibly contained in the owner name to the domain
// tree.
// Note: this can throw an exception, breaking strong exception
// guarantee. (see also the note for contextCheck() below).
addWildcards
(
*
domains
,
rrset
->
getName
());
// Get the node
DomainNode
*
node
;
switch
(
domains
->
insert
(
name
,
&
node
))
{
// Just check it returns reasonable results
case
DomainTree
::
SUCCESS
:
case
DomainTree
::
ALREADYEXISTS
:
break
;
// Something odd got out
default:
assert
(
0
);
}
assert
(
node
!=
NULL
);
DomainTree
::
Result
result
=
domains
->
insert
(
rrset
->
getName
(),
&
node
);
// Just check it returns reasonable results
assert
((
result
==
DomainTree
::
SUCCESS
||
result
==
DomainTree
::
ALREADYEXISTS
)
&&
node
!=
NULL
);
// Now get the domain
DomainPtr
domain
;
...
...
@@ -183,10 +251,10 @@ struct MemoryZone::MemoryZoneImpl {
// indicating the need for callback in find().
if
(
rrset
->
getType
()
==
RRType
::
NS
()
&&
rrset
->
getName
()
!=
origin_
)
{
node
->
enableCallback
(
);
node
->
setFlag
(
DomainNode
::
FLAG_CALLBACK
);
// If it is DNAME, we have a callback as well here
}
else
if
(
rrset
->
getType
()
==
RRType
::
DNAME
())
{
node
->
enableCallback
(
);
node
->
setFlag
(
DomainNode
::
FLAG_CALLBACK
);
}
return
(
result
::
SUCCESS
);
...
...
@@ -349,7 +417,7 @@ struct MemoryZone::MemoryZoneImpl {
// If the node callback is enabled, this may be a zone cut. If it
// has a NS RR, we should return a delegation, but not in the apex.
if
(
node
->
isCallbackEnabled
(
)
&&
node
!=
origin_data_
)
{
if
(
node
->
getFlag
(
DomainNode
::
FLAG_CALLBACK
)
&&
node
!=
origin_data_
)
{
found
=
node
->
getData
()
->
find
(
RRType
::
NS
());
if
(
found
!=
node
->
getData
()
->
end
())
{
return
(
FindResult
(
DELEGATION
,
found
->
second
));
...
...
src/lib/datasrc/rbtree.h
View file @
ca368d00
...
...
@@ -23,6 +23,8 @@
/// issue, the design and interface are not fixed, and RBTree isn't ready
/// to be used as a base data structure by other modules.
#include <exceptions/exceptions.h>
#include <dns/name.h>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
...
...
@@ -110,6 +112,29 @@ public:
/// \brief Alias for shared pointer to the data.
typedef
boost
::
shared_ptr
<
T
>
NodeDataPtr
;
/// Node flags.
///
/// Each flag value defines a non default property for a specific node.
/// These are defined as bitmask type values for the convenience of
/// internal implementation, but applications are expected to use
/// each flag separately via the enum definitions.
///
/// All (settable) flags are off by default; they must be explicitly
/// set to on by the \c setFlag() method.
enum
Flags
{
FLAG_CALLBACK
=
1
,
///< Callback enabled. See \ref callback
FLAG_USER1
=
0x8000000U
///< Application specific flag
};
private:
// Some flag values are expected to be used for internal purposes
// (e.g., representing the node color) in future versions, so we
// limit the settable flags via the \c setFlag() method to those
// explicitly defined in \c Flags. This constant represents all
// such flags.
static
const
uint32_t
SETTABLE_FLAGS
=
(
FLAG_CALLBACK
|
FLAG_USER1
);
public:
/// \brief Destructor
///
/// It might seem strange that constructors are private and destructor
...
...
@@ -153,6 +178,52 @@ public:
void
setData
(
const
NodeDataPtr
&
data
)
{
data_
=
data
;
}
//@}
/// \name Node flag manipulation methods
//@{
/// Get the status of a node flag.
///
/// This method returns whether the given node flag is set (enabled)
/// on the node. The \c flag parameter is expected to be one of the
/// defined \c Flags constants. For simplicity, the method interface
/// does not prohibit passing an undefined flag or combined flags, but
/// the return value in such a case will be meaningless for the caller
/// (an application would have to use an ugly cast for such an unintended
/// form of call, which will hopefully avoid accidental misuse).
///
/// \exception None
/// \param flag The flag to be tested.
/// \return \c true if the \c flag is set; \c false otherwise.
bool
getFlag
(
Flags
flag
)
const
{
return
((
flags_
&
flag
)
!=
0
);
}
/// Set or clear a node flag.
///
/// This method changes the status of the specified node flag to either
/// "on" (enabled) or "off" (disabled). The new status is specified by
/// the \c on parameter.
/// Like the \c getFlag() method, \c flag is expected to be one of the
/// defined \c Flags constants. If an undefined or unsettable flag is
/// specified, \c isc::InvalidParameter exception will be thrown.
///
/// \exception isc::InvalidParameter Unsettable flag is specified
/// \exception None otherwise
/// \param flag The node flag to be changed.
/// \on If \c true, set the flag to on; otherwise set it to off.
void
setFlag
(
Flags
flag
,
bool
on
=
true
)
{
if
((
flag
&
~
SETTABLE_FLAGS
)
!=
0
)
{
isc_throw
(
isc
::
InvalidParameter
,
"Unsettable RBTree flag is being set"
);
}
if
(
on
)
{
flags_
|=
flag
;
}
else
{
flags_
&=
~
flag
;
}
}
//@}
private:
/// \name Callback related methods
///
/// See the description of \c RBTree<T>::find() about callbacks.
...
...
@@ -160,16 +231,8 @@ public:
/// These methods never throw an exception.
//@{
/// Return if callback is enabled at the node.
bool
isCallbackEnabled
()
const
{
return
(
callback_required_
);
}
/// Enable callback at the node.
void
enableCallback
()
{
callback_required_
=
true
;
}
/// Disable callback at the node.
void
disableCallback
()
{
callback_required_
=
false
;
}
//@}
private:
/// \brief Define rbnode color
enum
RBNodeColor
{
BLACK
,
RED
};
...
...
@@ -224,7 +287,7 @@ private:
/// RBTree::find().
///
/// \todo It might be needed to put it into more general attributes field.
bool
callback_required
_
;
uint32_t
flags
_
;
};
...
...
@@ -238,7 +301,7 @@ RBNode<T>::RBNode() :
// dummy name, the value doesn't matter:
name_
(
isc
::
dns
::
Name
::
ROOT_NAME
()),
down_
(
this
),
callback_required_
(
false
)
flags_
(
0
)
{
}
...
...
@@ -250,7 +313,7 @@ RBNode<T>::RBNode(const isc::dns::Name& name) :
color_
(
RED
),
name_
(
name
),
down_
(
NULL_NODE
()),
callback_required_
(
false
)
flags_
(
0
)
{
}
...
...
@@ -650,7 +713,7 @@ public:
///
/// This version of \c find() calls the callback whenever traversing (on
/// the way from root down the tree) a marked node on the way down through
/// the domain namespace (see RBNode::enableCallback and related
/// the domain namespace (see
\c
RBNode::enableCallback and related
/// functions).
///
/// If you return true from the callback, the search is stopped and a
...
...
@@ -944,7 +1007,8 @@ RBTree<T>::find(const isc::dns::Name& target_name,
if
(
needsReturnEmptyNode_
||
!
node
->
isEmpty
())
{
ret
=
PARTIALMATCH
;
*
target
=
node
;
if
(
callback
!=
NULL
&&
node
->
callback_required_
)
{
if
(
callback
!=
NULL
&&
node
->
getFlag
(
RBNode
<
T
>::
FLAG_CALLBACK
))
{
if
((
callback
)(
*
node
,
callback_arg
))
{
break
;
}
...
...
@@ -1096,7 +1160,7 @@ RBTree<T>::nodeFission(RBNode<T>& node, const isc::dns::Name& base_name) {
// consistent behavior (i.e., a weak form of strong exception guarantee)
// even if code after the call to this function throws an exception.
std
::
swap
(
node
.
data_
,
down_node
->
data_
);
std
::
swap
(
node
.
callback_required_
,
down_node
->
callback_required
_
);
std
::
swap
(
node
.
flags_
,
down_node
->
flags
_
);
down_node
->
down_
=
node
.
down_
;
node
.
down_
=
down_node
.
get
();
// root node of sub tree, the initial color is BLACK
...
...
src/lib/datasrc/tests/memory_datasrc_unittest.cc
View file @
ca368d00
...
...
@@ -13,8 +13,14 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <sstream>
#include <vector>
#include <boost/bind.hpp>
#include <exceptions/exceptions.h>
#include <dns/masterload.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
...
...
@@ -27,6 +33,7 @@
#include <gtest/gtest.h>
using
namespace
std
;
using
namespace
isc
::
dns
;
using
namespace
isc
::
dns
::
rdata
;
using
namespace
isc
::
datasrc
;
...
...
@@ -140,62 +147,86 @@ TEST_F(MemoryDataSrcTest, getZoneCount) {
EXPECT_EQ
(
2
,
memory_datasrc
.
getZoneCount
());
}
// A helper callback of masterLoad() used in MemoryZoneTest.
void
setRRset
(
RRsetPtr
rrset
,
vector
<
RRsetPtr
*>::
iterator
&
it
)
{
*
(
*
it
)
=
rrset
;
++
it
;
}
/// \brief Test fixture for the MemoryZone class
class
MemoryZoneTest
:
public
::
testing
::
Test
{
// A straightforward pair of textual RR(set) and a RRsetPtr variable
// to store the RRset. Used to build test data below.
struct
RRsetData
{
const
char
*
const
text
;
// textual representation of an RRset
RRsetPtr
*
rrset
;
};
public:
MemoryZoneTest
()
:
class_
(
RRClass
::
IN
()),
origin_
(
"example.org"
),
ns_name_
(
"ns.example.org"
),
cname_name_
(
"cname.example.org"
),
dname_name_
(
"dname.example.org"
),
child_ns_name_
(
"child.example.org"
),
child_glue_name_
(
"ns.child.example.org"
),
grandchild_ns_name_
(
"grand.child.example.org"
),
grandchild_glue_name_
(
"ns.grand.child.example.org"
),
child_dname_name_
(
"dname.child.example.org"
),
zone_
(
class_
,
origin_
),
rr_out_
(
new
RRset
(
Name
(
"example.com"
),
class_
,
RRType
::
A
(),
RRTTL
(
300
))),
rr_ns_
(
new
RRset
(
origin_
,
class_
,
RRType
::
NS
(),
RRTTL
(
300
))),
rr_ns_a_
(
new
RRset
(
ns_name_
,
class_
,
RRType
::
A
(),
RRTTL
(
300
))),
rr_ns_aaaa_
(
new
RRset
(
ns_name_
,
class_
,
RRType
::
AAAA
(),
RRTTL
(
300
))),
rr_a_
(
new
RRset
(
origin_
,
class_
,
RRType
::
A
(),
RRTTL
(
300
))),
rr_cname_
(
new
RRset
(
cname_name_
,
class_
,
RRType
::
CNAME
(),
RRTTL
(
300
))),
rr_cname_a_
(
new
RRset
(
cname_name_
,
class_
,
RRType
::
A
(),
RRTTL
(
300
))),
rr_dname_
(
new
RRset
(
dname_name_
,
class_
,
RRType
::
DNAME
(),
RRTTL
(
300
))),
rr_dname_a_
(
new
RRset
(
dname_name_
,
class_
,
RRType
::
A
(),
RRTTL
(
300
))),
rr_dname_ns_
(
new
RRset
(
dname_name_
,
class_
,
RRType
::
NS
(),
RRTTL
(
300
))),
rr_dname_apex_
(
new
RRset
(
origin_
,
class_
,
RRType
::
DNAME
(),
RRTTL
(
300
))),
rr_child_ns_
(
new
RRset
(
child_ns_name_
,
class_
,
RRType
::
NS
(),
RRTTL
(
300
))),
rr_child_glue_
(
new
RRset
(
child_glue_name_
,
class_
,
RRType
::
A
(),
RRTTL
(
300
))),
rr_grandchild_ns_
(
new
RRset
(
grandchild_ns_name_
,
class_
,
RRType
::
NS
(),
RRTTL
(
300
))),
rr_grandchild_glue_
(
new
RRset
(
grandchild_glue_name_
,
class_
,
RRType
::
AAAA
(),
RRTTL
(
300
))),
rr_child_dname_
(
new
RRset
(
child_dname_name_
,
class_
,
RRType
::
DNAME
(),
RRTTL
(
300
)))
zone_
(
class_
,
origin_
)
{
// Build test RRsets. Below, we construct an RRset for
// each textual RR(s) of zone_data, and assign it to the corresponding
// rr_xxx.
const
RRsetData
zone_data
[]
=
{
{
"example.org. 300 IN NS ns.example.org."
,
&
rr_ns_
},
{
"example.org. 300 IN A 192.0.2.1"
,
&
rr_a_
},
{
"ns.example.org. 300 IN A 192.0.2.2"
,
&
rr_ns_a_
},
{
"ns.example.org. 300 IN AAAA 2001:db8::2"
,
&
rr_ns_aaaa_
},
{
"cname.example.org. 300 IN CNAME canonical.example.org"
,
&
rr_cname_
},
{
"cname.example.org. 300 IN A 192.0.2.3"
,
&
rr_cname_a_
},
{
"dname.example.org. 300 IN DNAME target.example.org."
,
&
rr_dname_
},
{
"dname.example.org. 300 IN A 192.0.2.39"
,
&
rr_dname_a_
},
{
"dname.example.org. 300 IN NS ns.dname.example.org."
,
&
rr_dname_ns_
},
{
"example.org. 300 IN DNAME example.com."
,
&
rr_dname_apex_
},
{
"child.example.org. 300 IN NS ns.child.example.org."
,
&
rr_child_ns_
},
{
"ns.child.example.org. 300 IN A 192.0.2.153"
,
&
rr_child_glue_
},
{
"grand.child.example.org. 300 IN NS ns.grand.child.example.org."
,
&
rr_grandchild_ns_
},
{
"ns.grand.child.example.org. 300 IN AAAA 2001:db8::253"
,
&
rr_grandchild_glue_
},
{
"dname.child.example.org. 300 IN DNAME example.com."
,
&
rr_child_dname_
},
{
"example.com. 300 IN A 192.0.2.10"
,
&
rr_out_
},
{
"*.wild.example.org. 300 IN A 192.0.2.1"
,
&
rr_wild_
},
{
"wild.*.foo.example.org. 300 IN A 192.0.2.1"
,
&
rr_emptywild_
},
{
"wild.*.foo.*.bar.example.org. 300 IN A 192.0.2.1"
,
&
rr_nested_emptywild_
},
{
"*.nswild.example.org. 300 IN NS nswild.example."
,
&
rr_nswild_
},
{
"*.dnamewild.example.org. 300 IN DNAME dnamewild.example."
,
&
rr_dnamewild_
},
{
NULL
,
NULL
}
};
stringstream
zone_data_stream
;
vector
<
RRsetPtr
*>
rrsets
;
for
(
unsigned
int
i
=
0
;
zone_data
[
i
].
text
!=
NULL
;
++
i
)
{
zone_data_stream
<<
zone_data
[
i
].
text
<<
"
\n
"
;
rrsets
.
push_back
(
zone_data
[
i
].
rrset
);
}
vector
<
RRsetPtr
*>::
iterator
it
=
rrsets
.
begin
();
masterLoad
(
zone_data_stream
,
Name
::
ROOT_NAME
(),
class_
,
boost
::
bind
(
setRRset
,
_1
,
it
));
}
// Some data to test with
const
RRClass
class_
;
const
Name
origin_
,
ns_name_
,
cname_name_
,
dname_name_
,
child_ns_name_
,
child_glue_name_
,
grandchild_ns_name_
,
grandchild_glue_name_
,
child_dname_name_
;
const
Name
origin_
;
// The zone to torture by tests
MemoryZone
zone_
;
/*
* Some RRsets to put inside the zone.
* They are empty, but the MemoryZone does not have a reason to look
* inside anyway. We will check it finds them and does not change
* the pointer.
*/
Const
RRsetPtr
RRsetPtr
// Out of zone RRset
rr_out_
,
// NS of example.org
...
...
@@ -207,16 +238,20 @@ public:
// A of example.org
rr_a_
;
RRsetPtr
rr_cname_
;
// CNAME in example.org (RDATA will be added)
Const
RRsetPtr
rr_cname_a_
;
// for mixed CNAME + A case
RRsetPtr
rr_cname_a_
;
// for mixed CNAME + A case
RRsetPtr
rr_dname_
;
// DNAME in example.org (RDATA will be added)
ConstRRsetPtr
rr_dname_a_
;
// for mixed DNAME + A case
ConstRRsetPtr
rr_dname_ns_
;
// for mixed DNAME + NS case
ConstRRsetPtr
rr_dname_apex_
;
// for mixed DNAME + NS case in the apex
ConstRRsetPtr
rr_child_ns_
;
// NS of a child domain (for delegation)
ConstRRsetPtr
rr_child_glue_
;
// glue RR of the child domain
ConstRRsetPtr
rr_grandchild_ns_
;
// NS below a zone cut (unusual)
ConstRRsetPtr
rr_grandchild_glue_
;
// glue RR below a deeper zone cut
ConstRRsetPtr
rr_child_dname_
;
// A DNAME under NS
RRsetPtr
rr_dname_a_
;
// for mixed DNAME + A case
RRsetPtr
rr_dname_ns_
;
// for mixed DNAME + NS case
RRsetPtr
rr_dname_apex_
;
// for mixed DNAME + NS case in the apex
RRsetPtr
rr_child_ns_
;
// NS of a child domain (for delegation)
RRsetPtr
rr_child_glue_
;
// glue RR of the child domain
RRsetPtr
rr_grandchild_ns_
;
// NS below a zone cut (unusual)
RRsetPtr
rr_grandchild_glue_
;
// glue RR below a deeper zone cut
RRsetPtr
rr_child_dname_
;
// A DNAME under NS
RRsetPtr
rr_wild_
;
RRsetPtr
rr_emptywild_
;
RRsetPtr
rr_nested_emptywild_
;
RRsetPtr
rr_nswild_
,
rr_dnamewild_
;
/**
* \brief Test one find query to the zone.
...
...
@@ -292,33 +327,30 @@ TEST_F(MemoryZoneTest, add) {
}
TEST_F
(
MemoryZoneTest
,
addMultipleCNAMEs
)
{
rr_cname_
->
addRdata
(
generic
::
CNAME
(
"canonical1.example.org."
));
rr_cname_
->
addRdata
(
generic
::
CNAME
(
"canonical2.example.org."
));
EXPECT_THROW
(
zone_
.
add
(
rr_cname_
),
MemoryZone
::
AddError
);
}
TEST_F
(
MemoryZoneTest
,
addCNAMEThenOther
)
{
rr_cname_
->
addRdata
(
generic
::
CNAME
(
"canonical.example.org."
));
EXPECT_EQ
(
SUCCESS
,
zone_
.
add
(
rr_cname_
));
EXPECT_THROW
(
zone_
.
add
(
rr_cname_a_
),
MemoryZone
::
AddError
);
}
TEST_F
(
MemoryZoneTest
,
addOtherThenCNAME
)
{
rr_cname_
->
addRdata
(
generic
::
CNAME
(
"canonical.example.org."
));
EXPECT_EQ
(
SUCCESS
,
zone_
.
add
(
rr_cname_a_
));
EXPECT_THROW
(
zone_
.
add
(
rr_cname_
),
MemoryZone
::
AddError
);
}
TEST_F
(
MemoryZoneTest
,
findCNAME
)
{
// install CNAME RR
rr_cname_
->
addRdata
(
generic
::
CNAME
(
"canonical.example.org."
));
EXPECT_EQ
(
SUCCESS
,
zone_
.
add
(
rr_cname_
));
// Find A RR of the same. Should match the CNAME
findTest
(
cname_
n
ame
_
,
RRType
::
NS
(),
Zone
::
CNAME
,
true
,
rr_cname_
);
findTest
(
rr_
cname_
->
getN
ame
()
,
RRType
::
NS
(),
Zone
::
CNAME
,
true
,
rr_cname_
);
// Find the CNAME itself. Should result in normal SUCCESS
findTest
(
cname_name_
,
RRType
::
CNAME
(),
Zone
::
SUCCESS
,
true
,
rr_cname_
);
findTest
(
rr_cname_
->
getName
(),
RRType
::
CNAME
(),
Zone
::
SUCCESS
,
true
,
rr_cname_
);
}
TEST_F
(
MemoryZoneTest
,
findCNAMEUnderZoneCut
)
{
...
...
@@ -339,8 +371,7 @@ TEST_F(MemoryZoneTest, findCNAMEUnderZoneCut) {
// Having a CNAME there is disallowed too, but it is tested by
// addOtherThenCNAME and addCNAMEThenOther.
TEST_F
(
MemoryZoneTest
,
addMultipleDNAMEs
)
{
rr_dname_
->
addRdata
(
generic
::
DNAME
(
"dname1.example.org."
));
rr_dname_
->
addRdata
(
generic
::
DNAME
(
"dname2.example.org."
));
rr_dname_
->
addRdata
(
generic
::
DNAME
(
"target2.example.org."
));
EXPECT_THROW
(
zone_
.
add
(
rr_dname_
),
MemoryZone
::
AddError
);
}
...
...
@@ -366,7 +397,8 @@ TEST_F(MemoryZoneTest, DNAMEAndNSAtApex) {
// The NS should be possible to be found, below should be DNAME, not
// delegation
findTest
(
origin_
,
RRType
::
NS
(),
Zone
::
SUCCESS
,
true
,
rr_ns_
);
findTest
(
child_ns_name_
,
RRType
::
A
(),
Zone
::
DNAME
,
true
,
rr_dname_apex_
);
findTest
(
rr_child_ns_
->
getName
(),
RRType
::
A
(),
Zone
::
DNAME
,
true
,
rr_dname_apex_
);
}
TEST_F
(
MemoryZoneTest
,
NSAndDNAMEAtApex
)
{
...
...
@@ -379,7 +411,6 @@ TEST_F(MemoryZoneTest, NSAndDNAMEAtApex) {
// Search under a DNAME record. It should return the DNAME
TEST_F
(
MemoryZoneTest
,
findBelowDNAME
)
{
rr_dname_
->
addRdata
(
generic
::
DNAME
(
"target.example.org."
));
EXPECT_NO_THROW
(
EXPECT_EQ
(
SUCCESS
,
zone_
.
add
(
rr_dname_
)));
findTest
(
Name
(
"below.dname.example.org"
),
RRType
::
A
(),
Zone
::
DNAME
,
true
,
rr_dname_
);
...
...
@@ -388,13 +419,13 @@ TEST_F(MemoryZoneTest, findBelowDNAME) {
// Search at the domain with DNAME. It should act as DNAME isn't there, DNAME
// influences only the data below (see RFC 2672, section 3)
TEST_F
(
MemoryZoneTest
,
findAtDNAME
)
{
rr_dname_
->
addRdata
(
generic
::
DNAME
(
"target.example.org."
));
EXPECT_NO_THROW
(
EXPECT_EQ
(
SUCCESS
,
zone_
.
add
(
rr_dname_
)));
EXPECT_NO_THROW
(
EXPECT_EQ
(
SUCCESS
,
zone_
.
add
(
rr_dname_a_
)));
findTest
(
dname_name_
,
RRType
::
A
(),
Zone
::
SUCCESS
,
true
,
rr_dname_a_
);
findTest
(
dname_name_
,
RRType
::
DNAME
(),
Zone
::
SUCCESS
,
true
,
rr_dname_
);
findTest
(
dname_name_
,
RRType
::
TXT
(),
Zone
::
NXRRSET
,
true
);
const
Name
dname_name
(
rr_dname_
->
getName
());
findTest
(
dname_name
,
RRType
::
A
(),
Zone
::
SUCCESS
,
true
,
rr_dname_a_
);
findTest
(
dname_name
,
RRType
::
DNAME
(),
Zone
::
SUCCESS
,
true
,
rr_dname_
);
findTest
(
dname_name
,
RRType
::
TXT
(),
Zone
::
NXRRSET
,
true
);
}
// Try searching something that is both under NS and DNAME, without and with
...
...
@@ -458,7 +489,7 @@ TEST_F(MemoryZoneTest, findAny) {
EXPECT_EQ
(
0
,
out_rrsets
.
size
());
RRsetList
glue_child_rrsets
;
findTest
(
child_glue_
n
ame
_
,
RRType
::
ANY
(),
Zone
::
SUCCESS
,
true
,
findTest
(
rr_
child_glue_
->
getN
ame
()
,
RRType
::
ANY
(),
Zone
::
SUCCESS
,
true
,
ConstRRsetPtr
(),
&
glue_child_rrsets
);
EXPECT_EQ
(
rr_child_glue_
,
glue_child_rrsets
.
findRRset
(
RRType
::
A
(),
RRClass
::
IN
()));
...
...
@@ -472,13 +503,13 @@ TEST_F(MemoryZoneTest, findAny) {
// zone cut
RRsetList
child_rrsets
;
findTest
(
child_ns_
n
ame
_
,
RRType
::
ANY
(),
Zone
::
DELEGATION
,
true
,
findTest
(
rr_
child_ns_
->
getN
ame
()
,
RRType
::
ANY
(),
Zone
::
DELEGATION
,
true
,
rr_child_ns_
,
&
child_rrsets
);
EXPECT_EQ
(
0
,
child_rrsets
.
size
());
// glue for this zone cut
RRsetList
new_glue_child_rrsets
;
findTest
(
child_glue_
n
ame
_
,
RRType
::
ANY
(),
Zone
::
DELEGATION
,
true
,
findTest
(
rr_
child_glue_
->
getN
ame
()
,
RRType
::
ANY
(),
Zone
::
DELEGATION
,
true
,