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
0140368e
Commit
0140368e
authored
Dec 13, 2012
by
Stephen Morris
Browse files
[2546] Merge branch 'master' into trac2546
parents
fecfe82b
ce492ecf
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
doc/Doxyfile
View file @
0140368e
This diff is collapsed.
Click to expand it.
src/lib/datasrc/Makefile.am
View file @
0140368e
...
...
@@ -38,6 +38,7 @@ libb10_datasrc_la_SOURCES += client_list.h client_list.cc
libb10_datasrc_la_SOURCES
+=
memory_datasrc.h memory_datasrc.cc
libb10_datasrc_la_SOURCES
+=
master_loader_callbacks.h
libb10_datasrc_la_SOURCES
+=
master_loader_callbacks.cc
libb10_datasrc_la_SOURCES
+=
zone_loader.h zone_loader.cc
nodist_libb10_datasrc_la_SOURCES
=
datasrc_messages.h datasrc_messages.cc
libb10_datasrc_la_LDFLAGS
=
-no-undefined
-version-info
1:0:1
...
...
src/lib/datasrc/master_loader_callbacks.cc
View file @
0140368e
...
...
@@ -48,6 +48,19 @@ logWarning(const isc::dns::Name& name, const isc::dns::RRClass& rrclass,
arg
(
name
).
arg
(
rrclass
).
arg
(
reason
);
}
void
addRR
(
const
isc
::
dns
::
Name
&
name
,
const
isc
::
dns
::
RRClass
&
rrclass
,
const
isc
::
dns
::
RRType
&
type
,
const
isc
::
dns
::
RRTTL
&
ttl
,
const
isc
::
dns
::
rdata
::
RdataPtr
&
data
,
ZoneUpdater
*
updater
)
{
// We get description of one RR. The updater takes RRset, so we
// wrap it up and push there. It should collate the RRsets of the
// same name and type together, since the addRRset should "merge".
isc
::
dns
::
BasicRRset
rrset
(
name
,
rrclass
,
type
,
ttl
);
rrset
.
addRdata
(
data
);
updater
->
addRRset
(
rrset
);
}
}
isc
::
dns
::
MasterLoaderCallbacks
...
...
@@ -61,12 +74,9 @@ createMasterLoaderCallbacks(const isc::dns::Name& name,
rrclass
,
_1
,
_2
,
_3
)));
}
isc
::
dns
::
AddRR
set
Callback
isc
::
dns
::
AddRRCallback
createMasterLoaderAddCallback
(
ZoneUpdater
&
updater
)
{
return
(
boost
::
bind
(
&
ZoneUpdater
::
addRRset
,
&
updater
,
// The callback provides a shared pointer, we
// need the object. This bind unpacks the object.
boost
::
bind
(
&
isc
::
dns
::
RRsetPtr
::
operator
*
,
_1
)));
return
(
boost
::
bind
(
addRR
,
_1
,
_2
,
_3
,
_4
,
_5
,
&
updater
));
}
}
...
...
src/lib/datasrc/master_loader_callbacks.h
View file @
0140368e
...
...
@@ -58,7 +58,7 @@ createMasterLoaderCallbacks(const isc::dns::Name& name,
/// \param updater The zone updater to use.
/// \return The callback to be passed to MasterLoader.
/// \throw std::bad_alloc when allocation fails.
isc
::
dns
::
AddRR
set
Callback
isc
::
dns
::
AddRRCallback
createMasterLoaderAddCallback
(
ZoneUpdater
&
updater
);
}
...
...
src/lib/datasrc/memory/memory_client.cc
View file @
0140368e
...
...
@@ -209,14 +209,20 @@ private:
RdataIteratorPtr
rdata_iterator_
;
bool
separate_rrs_
;
bool
ready_
;
bool
examined_rrsigs_
;
// In case there's nsec3 namespace in the zone, it is represented the same
// way as the usual namespace. So we reuse the iterator implementation for
// it.
ZoneIteratorPtr
nsec3_namespace_
;
public:
MemoryIterator
(
const
RRClass
&
rrclass
,
const
ZoneTree
&
tree
,
const
N
ame
&
origin
,
bool
separate_rrs
)
:
const
ZoneTree
&
tree
,
const
N
SEC3Data
*
nsec3_data
,
const
Name
&
origin
,
bool
separate_rrs
)
:
rrclass_
(
rrclass
),
tree_
(
tree
),
separate_rrs_
(
separate_rrs
),
ready_
(
true
)
ready_
(
true
),
examined_rrsigs_
(
false
)
{
// Find the first node (origin) and preserve the node chain for future
// searches
...
...
@@ -235,10 +241,25 @@ public:
rdata_iterator_
=
rrset_
->
getRdataIterator
();
}
}
// If we have the NSEC3 namespace, get an iterator for it so we can
// delegate to it later.
if
(
nsec3_data
!=
NULL
)
{
nsec3_namespace_
=
ZoneIteratorPtr
(
new
MemoryIterator
(
rrclass
,
nsec3_data
->
getNSEC3Tree
(),
NULL
,
origin
,
separate_rrs
));
}
}
virtual
ConstRRsetPtr
getNextRRset
()
{
if
(
!
ready_
)
{
// We are done iterating. But in case there's the nsec3 one,
// iterate through that one.
if
(
nsec3_namespace_
!=
ZoneIteratorPtr
())
{
return
(
nsec3_namespace_
->
getNextRRset
());
}
isc_throw
(
Unexpected
,
"Iterating past the zone end"
);
}
/*
...
...
@@ -259,13 +280,19 @@ public:
rrset_
.
reset
(
new
TreeNodeRRset
(
rrclass_
,
node_
,
set_node_
,
true
));
rdata_iterator_
=
rrset_
->
getRdataIterator
();
examined_rrsigs_
=
false
;
}
}
}
if
(
node_
==
NULL
)
{
// That's all, folks
ready_
=
false
;
return
(
ConstRRsetPtr
());
if
(
nsec3_namespace_
!=
ZoneIteratorPtr
())
{
// In case we have the NSEC3 namespace, get one from there.
return
(
nsec3_namespace_
->
getNextRRset
());
}
else
{
return
(
ConstRRsetPtr
());
}
}
if
(
separate_rrs_
)
{
...
...
@@ -273,10 +300,24 @@ public:
// 'current' rdata
RRsetPtr
result
(
new
RRset
(
rrset_
->
getName
(),
rrset_
->
getClass
(),
rrset_
->
getType
(),
// If we are looking into the signature,
// we need to adjust the type too.
examined_rrsigs_
?
RRType
::
RRSIG
()
:
rrset_
->
getType
(),
rrset_
->
getTTL
()));
result
->
addRdata
(
rdata_iterator_
->
getCurrent
());
rdata_iterator_
->
next
();
if
(
!
examined_rrsigs_
&&
rdata_iterator_
->
isLast
())
{
// We got to the last RR of the RRset, but we need to look at
// the signatures too, if there are any.
examined_rrsigs_
=
true
;
const
ConstRRsetPtr
rrsig
=
rrset_
->
getRRsig
();
if
(
rrsig
!=
ConstRRsetPtr
())
{
rrset_
=
rrsig
;
rdata_iterator_
=
rrsig
->
getRdataIterator
();
}
// else - no RRSIG. rdata_iterator_ stays at last, next
// condition applies
}
if
(
rdata_iterator_
->
isLast
())
{
// all used up, next.
set_node_
=
set_node_
->
getNext
();
...
...
@@ -286,6 +327,7 @@ public:
rrset_
.
reset
(
new
TreeNodeRRset
(
rrclass_
,
node_
,
set_node_
,
true
));
rdata_iterator_
=
rrset_
->
getRdataIterator
();
examined_rrsigs_
=
false
;
}
}
return
(
result
);
...
...
@@ -317,7 +359,8 @@ InMemoryClient::getIterator(const Name& name, bool separate_rrs) const {
return
(
ZoneIteratorPtr
(
new
MemoryIterator
(
getClass
(),
result
.
zone_data
->
getZoneTree
(),
name
,
result
.
zone_data
->
getZoneTree
(),
result
.
zone_data
->
getNSEC3Data
(),
name
,
separate_rrs
)));
}
...
...
src/lib/datasrc/tests/Makefile.am
View file @
0140368e
...
...
@@ -60,6 +60,7 @@ run_unittests_SOURCES += zone_finder_context_unittest.cc
run_unittests_SOURCES
+=
faked_nsec3.h faked_nsec3.cc
run_unittests_SOURCES
+=
client_list_unittest.cc
run_unittests_SOURCES
+=
master_loader_callbacks_test.cc
run_unittests_SOURCES
+=
zone_loader_unittest.cc
# We need the actual module implementation in the tests (they are not part
# of libdatasrc)
...
...
src/lib/datasrc/tests/master_loader_callbacks_test.cc
View file @
0140368e
...
...
@@ -18,6 +18,9 @@
#include
<dns/rrset.h>
#include
<dns/rrclass.h>
#include
<dns/rrttl.h>
#include
<dns/rdata.h>
#include
<testutils/dnsmessage_test.h>
#include
<exceptions/exceptions.h>
...
...
@@ -40,8 +43,21 @@ public:
// the correct ones, according to a predefined set in a list.
virtual
void
addRRset
(
const
isc
::
dns
::
AbstractRRset
&
rrset
)
{
ASSERT_FALSE
(
expected_rrsets_
.
empty
());
// In our tests, pointer equality is enough.
EXPECT_EQ
(
expected_rrsets_
.
front
().
get
(),
&
rrset
);
// As the rrsetCheck requires a shared pointer, we need to create
// a copy.
isc
::
dns
::
RRsetPtr
copy
(
new
isc
::
dns
::
BasicRRset
(
rrset
.
getName
(),
rrset
.
getClass
(),
rrset
.
getType
(),
rrset
.
getTTL
()));
EXPECT_FALSE
(
rrset
.
getRRsig
())
<<
"Unexpected RRSIG on rrset, not "
"copying. Following check will likely fail as a result."
;
for
(
isc
::
dns
::
RdataIteratorPtr
it
(
rrset
.
getRdataIterator
());
!
it
->
isLast
();
it
->
next
())
{
copy
->
addRdata
(
it
->
getCurrent
());
}
isc
::
testutils
::
rrsetCheck
(
expected_rrsets_
.
front
(),
copy
);
// And remove this RRset, as it has been used.
expected_rrsets_
.
pop_front
();
}
...
...
@@ -67,14 +83,22 @@ protected:
isc
::
dns
::
RRClass
::
IN
(),
&
ok_
))
{}
// Generate a new RRset, put it to the updater and return it.
isc
::
dns
::
RRsetPtr
generateRRset
(
)
{
void
generateRRset
(
isc
::
dns
::
AddRRCallback
callback
)
{
const
isc
::
dns
::
RRsetPtr
result
(
new
isc
::
dns
::
RRset
(
isc
::
dns
::
Name
(
"example.org"
),
isc
::
dns
::
RRClass
::
IN
(),
isc
::
dns
::
RRType
::
A
(),
isc
::
dns
::
RRTTL
(
3600
)));
const
isc
::
dns
::
rdata
::
RdataPtr
data
(
isc
::
dns
::
rdata
::
createRdata
(
isc
::
dns
::
RRType
::
A
(),
isc
::
dns
::
RRClass
::
IN
(),
"192.0.2.1"
));
result
->
addRdata
(
data
);
updater_
.
expected_rrsets_
.
push_back
(
result
);
return
(
result
);
callback
(
result
->
getName
(),
result
->
getClass
(),
result
->
getType
(),
result
->
getTTL
(),
data
);
}
// An updater to be passed to the context
MockUpdater
updater_
;
...
...
@@ -112,11 +136,11 @@ TEST_F(MasterLoaderCallbackTest, callbacks) {
// Try adding some RRsets.
TEST_F
(
MasterLoaderCallbackTest
,
addRRset
)
{
isc
::
dns
::
AddRR
set
Callback
isc
::
dns
::
AddRRCallback
callback
(
createMasterLoaderAddCallback
(
updater_
));
// Put some of them in.
EXPECT_NO_THROW
(
callback
(
generateRRset
(
)
));
EXPECT_NO_THROW
(
callback
(
generateRRset
(
)
));
EXPECT_NO_THROW
(
generateRRset
(
callback
));
EXPECT_NO_THROW
(
generateRRset
(
callback
));
// They all get pushed there right away, so there are none in the queue
EXPECT_TRUE
(
updater_
.
expected_rrsets_
.
empty
());
}
...
...
src/lib/datasrc/tests/memory/memory_client_unittest.cc
View file @
0140368e
...
...
@@ -690,6 +690,25 @@ TEST_F(MemoryClientTest, getIteratorSeparateRRs) {
EXPECT_EQ
(
ConstRRsetPtr
(),
iterator2
->
getNextRRset
());
}
// Test we get RRSIGs and NSEC3s too for iterating with separate RRs
TEST_F
(
MemoryClientTest
,
getIteratorSeparateSigned
)
{
client_
->
load
(
Name
(
"example.org"
),
TEST_DATA_DIR
"/example.org-nsec3-signed.zone"
);
ZoneIteratorPtr
iterator
(
client_
->
getIterator
(
Name
(
"example.org"
),
true
));
bool
seen_rrsig
=
false
,
seen_nsec3
=
false
;
for
(
ConstRRsetPtr
rrset
=
iterator
->
getNextRRset
();
rrset
!=
ConstRRsetPtr
();
rrset
=
iterator
->
getNextRRset
())
{
if
(
rrset
->
getType
()
==
RRType
::
RRSIG
())
{
seen_rrsig
=
true
;
}
else
if
(
rrset
->
getType
()
==
RRType
::
NSEC3
())
{
seen_nsec3
=
true
;
}
}
EXPECT_TRUE
(
seen_rrsig
);
EXPECT_TRUE
(
seen_nsec3
);
}
TEST_F
(
MemoryClientTest
,
getIteratorGetSOAThrowsNotImplemented
)
{
client_
->
load
(
Name
(
"example.org"
),
TEST_DATA_DIR
"/example.org-empty.zone"
);
ZoneIteratorPtr
iterator
(
client_
->
getIterator
(
Name
(
"example.org"
)));
...
...
src/lib/datasrc/tests/zone_loader_unittest.cc
0 → 100644
View file @
0140368e
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include
<datasrc/zone_loader.h>
#include
<datasrc/data_source.h>
#include
<datasrc/memory/zone_table_segment.h>
#include
<datasrc/memory/memory_client.h>
#include
<dns/rrclass.h>
#include
<dns/name.h>
#include
<dns/rrset.h>
#include
<util/memory_segment_local.h>
#include
<exceptions/exceptions.h>
#include
<gtest/gtest.h>
#include
<boost/shared_ptr.hpp>
#include
<string>
#include
<vector>
using
isc
::
dns
::
RRClass
;
using
isc
::
dns
::
Name
;
using
isc
::
dns
::
RRType
;
using
isc
::
dns
::
ConstRRsetPtr
;
using
std
::
string
;
using
std
::
vector
;
using
boost
::
shared_ptr
;
using
namespace
isc
::
datasrc
;
namespace
{
class
MockClient
:
public
DataSourceClient
{
public:
MockClient
()
:
commit_called_
(
false
),
missing_zone_
(
false
),
rrclass_
(
RRClass
::
IN
())
{}
virtual
FindResult
findZone
(
const
Name
&
)
const
{
isc_throw
(
isc
::
NotImplemented
,
"Method not used in tests"
);
};
virtual
std
::
pair
<
ZoneJournalReader
::
Result
,
ZoneJournalReaderPtr
>
getJournalReader
(
const
Name
&
,
uint32_t
,
uint32_t
)
const
{
isc_throw
(
isc
::
NotImplemented
,
"Method not used in tests"
);
}
virtual
ZoneUpdaterPtr
getUpdater
(
const
Name
&
name
,
bool
replace
,
bool
journaling
)
const
;
// We store some information about what was happening here.
// It is publicly accessible, since this is private testing class
// anyway, so no need to dress it fancy into getters. Some are mutable,
// since many client methods are const, but we still want to know they
// were called.
mutable
vector
<
Name
>
provided_updaters_
;
// We store string representations of the RRsets. This is simpler than
// copying them and we can't really put them into shared pointers, because
// we get them as references.
vector
<
string
>
rrsets_
;
bool
commit_called_
;
// If set to true, getUpdater returns NULL
bool
missing_zone_
;
// The pretended class of the client. Usualy IN, but can be overriden.
RRClass
rrclass_
;
};
// The updater isn't really correct according to the API. For example,
// the whole client can be committed only once in its lifetime. The
// updaters would influence each other if there were more. But we
// don't need more updaters in the same test, so it doesn't matter
// and this way, it is much simpler.
class
Updater
:
public
ZoneUpdater
{
public:
Updater
(
MockClient
*
client
)
:
client_
(
client
),
finder_
(
client_
->
rrclass_
)
{}
virtual
ZoneFinder
&
getFinder
()
{
return
(
finder_
);
}
virtual
void
addRRset
(
const
isc
::
dns
::
AbstractRRset
&
rrset
)
{
if
(
client_
->
commit_called_
)
{
isc_throw
(
DataSourceError
,
"Add after commit"
);
}
client_
->
rrsets_
.
push_back
(
rrset
.
toText
());
}
virtual
void
deleteRRset
(
const
isc
::
dns
::
AbstractRRset
&
)
{
isc_throw
(
isc
::
NotImplemented
,
"Method not used in tests"
);
}
virtual
void
commit
()
{
client_
->
commit_called_
=
true
;
}
private:
MockClient
*
client_
;
class
Finder
:
public
ZoneFinder
{
public:
Finder
(
const
RRClass
&
rrclass
)
:
class_
(
rrclass
)
{}
virtual
RRClass
getClass
()
const
{
return
(
class_
);
}
virtual
Name
getOrigin
()
const
{
isc_throw
(
isc
::
NotImplemented
,
"Method not used in tests"
);
}
virtual
shared_ptr
<
Context
>
find
(
const
Name
&
,
const
RRType
&
,
const
FindOptions
)
{
isc_throw
(
isc
::
NotImplemented
,
"Method not used in tests"
);
}
virtual
shared_ptr
<
Context
>
findAll
(
const
Name
&
,
vector
<
ConstRRsetPtr
>&
,
const
FindOptions
)
{
isc_throw
(
isc
::
NotImplemented
,
"Method not used in tests"
);
}
virtual
FindNSEC3Result
findNSEC3
(
const
Name
&
,
bool
)
{
isc_throw
(
isc
::
NotImplemented
,
"Method not used in tests"
);
}
private:
const
RRClass
class_
;
}
finder_
;
};
ZoneUpdaterPtr
MockClient
::
getUpdater
(
const
Name
&
name
,
bool
replace
,
bool
journaling
)
const
{
if
(
missing_zone_
)
{
return
(
ZoneUpdaterPtr
());
}
EXPECT_TRUE
(
replace
);
EXPECT_FALSE
(
journaling
);
provided_updaters_
.
push_back
(
name
);
// const_cast is bad. But the const on getUpdater seems wrong in the first
// place, since updater will be modifying the data there. And the updater
// wants to store data into the client so we can examine it later.
return
(
ZoneUpdaterPtr
(
new
Updater
(
const_cast
<
MockClient
*>
(
this
))));
}
class
ZoneLoaderTest
:
public
::
testing
::
Test
{
protected:
ZoneLoaderTest
()
:
rrclass_
(
RRClass
::
IN
()),
ztable_segment_
(
memory
::
ZoneTableSegment
::
create
(
isc
::
data
::
NullElement
(),
rrclass_
)),
source_client_
(
ztable_segment_
,
rrclass_
)
{}
void
prepareSource
(
const
Name
&
zone
,
const
char
*
filename
)
{
// TODO:
// Currently, load uses an urelated implementation. In the long term,
// the method will probably be deprecated. At that time, we should
// probably prepare the data in some other way (using sqlite3 or
// something). This is simpler for now.
source_client_
.
load
(
zone
,
string
(
TEST_DATA_DIR
)
+
"/"
+
filename
);
}
private:
const
RRClass
rrclass_
;
// This is because of the in-memory client. We use it to read data
// from. It is still easier than setting up sqlite3 client, since
// we have this one in the linked library.
// FIXME: We should be destroying it by ZoneTableSegment::destroy.
// But the shared pointer won't let us, will it?
shared_ptr
<
memory
::
ZoneTableSegment
>
ztable_segment_
;
protected:
memory
::
InMemoryClient
source_client_
;
// This one is mocked. It will help us see what is happening inside.
// Also, mocking it is simpler than setting up an sqlite3 client.
MockClient
destination_client_
;
};
// Use the loader to load an unsigned zone.
TEST_F
(
ZoneLoaderTest
,
copyUnsigned
)
{
prepareSource
(
Name
::
ROOT_NAME
(),
"root.zone"
);
ZoneLoader
loader
(
destination_client_
,
Name
::
ROOT_NAME
(),
source_client_
);
// It gets the updater directly in the constructor
ASSERT_EQ
(
1
,
destination_client_
.
provided_updaters_
.
size
());
EXPECT_EQ
(
Name
::
ROOT_NAME
(),
destination_client_
.
provided_updaters_
[
0
]);
// Now load the whole zone
loader
.
load
();
EXPECT_TRUE
(
destination_client_
.
commit_called_
);
// We don't check the whole zone. We check the first and last and the
// count, which should be enough.
// The count is 34 because we expect the RRs to be separated.
EXPECT_EQ
(
34
,
destination_client_
.
rrsets_
.
size
());
// Ensure known order.
std
::
sort
(
destination_client_
.
rrsets_
.
begin
(),
destination_client_
.
rrsets_
.
end
());
EXPECT_EQ
(
". 518400 IN NS a.root-servers.net.
\n
"
,
destination_client_
.
rrsets_
.
front
());
EXPECT_EQ
(
"m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
\n
"
,
destination_client_
.
rrsets_
.
back
());
// It isn't possible to try again now
EXPECT_THROW
(
loader
.
load
(),
isc
::
InvalidOperation
);
EXPECT_THROW
(
loader
.
loadIncremental
(
1
),
isc
::
InvalidOperation
);
// Even 0, which should load nothing, returns the error
EXPECT_THROW
(
loader
.
loadIncremental
(
0
),
isc
::
InvalidOperation
);
}
// Try loading incrementally.
TEST_F
(
ZoneLoaderTest
,
copyUnsignedIncremental
)
{
prepareSource
(
Name
::
ROOT_NAME
(),
"root.zone"
);
ZoneLoader
loader
(
destination_client_
,
Name
::
ROOT_NAME
(),
source_client_
);
// Try loading few RRs first.
loader
.
loadIncremental
(
10
);
// We should get the 10 we asked for
EXPECT_EQ
(
10
,
destination_client_
.
rrsets_
.
size
());
// Not committed yet, we didn't complete the loading
EXPECT_FALSE
(
destination_client_
.
commit_called_
);
// This is unusual, but allowed. Check it doesn't do anything
loader
.
loadIncremental
(
0
);
EXPECT_EQ
(
10
,
destination_client_
.
rrsets_
.
size
());
EXPECT_FALSE
(
destination_client_
.
commit_called_
);
// We can finish the rest
loader
.
loadIncremental
(
30
);
EXPECT_EQ
(
34
,
destination_client_
.
rrsets_
.
size
());
EXPECT_TRUE
(
destination_client_
.
commit_called_
);
// No more loading now
EXPECT_THROW
(
loader
.
load
(),
isc
::
InvalidOperation
);
EXPECT_THROW
(
loader
.
loadIncremental
(
1
),
isc
::
InvalidOperation
);
EXPECT_THROW
(
loader
.
loadIncremental
(
0
),
isc
::
InvalidOperation
);
}
// Check we can load RRSIGs and NSEC3 (which could break due to them being
// in separate namespace)
TEST_F
(
ZoneLoaderTest
,
copySigned
)
{
prepareSource
(
Name
(
"example.org"
),
"example.org.nsec3-signed"
);
ZoneLoader
loader
(
destination_client_
,
Name
(
"example.org"
),
source_client_
);
loader
.
load
();
// All the RRs are there, including the ones in NSEC3 namespace
EXPECT_EQ
(
14
,
destination_client_
.
rrsets_
.
size
());
EXPECT_TRUE
(
destination_client_
.
commit_called_
);
// Same trick with sorting to know where they are
std
::
sort
(
destination_client_
.
rrsets_
.
begin
(),
destination_client_
.
rrsets_
.
end
());
// Due to the R at the beginning, this one should be last
EXPECT_EQ
(
"09GM5T42SMIMT7R8DF6RTG80SFMS1NLU.example.org. 1200 IN NSEC3 "
"1 0 10 AABBCCDD RKOF8QMFRB5F2V9EJHFBVB2JPVSA0DJD A RRSIG
\n
"
,
destination_client_
.
rrsets_
[
0
]);
EXPECT_EQ
(
"09GM5T42SMIMT7R8DF6RTG80SFMS1NLU.example.org. 1200 IN RRSIG "
"NSEC3 7 3 1200 20120301040838 20120131040838 19562 example.org."
" EdwMeepLf//lV+KpCAN+213Scv1rrZyj4i2OwoCP4XxxS3CWGSuvYuKOyfZc8w"
"KRcrD/4YG6nZVXE0s5O8NahjBJmDIyVt4WkfZ6QthxGg8ggLVvcD3dFksPyiKHf"
"/WrTOZPSsxvN5m/i1Ey6+YWS01Gf3WDCMWDauC7Nmh3CTM=
\n
"
,
destination_client_
.
rrsets_
[
1
]);
}
// If the destination zone does not exist, it throws
TEST_F
(
ZoneLoaderTest
,
copyMissingDestination
)
{
destination_client_
.
missing_zone_
=
true
;
prepareSource
(
Name
::
ROOT_NAME
(),
"root.zone"
);
EXPECT_THROW
(
ZoneLoader
(
destination_client_
,
Name
::
ROOT_NAME
(),
source_client_
),
DataSourceError
);
}
// If the source zone does not exist, it throws
TEST_F
(
ZoneLoaderTest
,
copyMissingSource
)
{
EXPECT_THROW
(
ZoneLoader
(
destination_client_
,
Name
::
ROOT_NAME
(),
source_client_
),
DataSourceError
);
}
// The class of the source and destination are different
TEST_F
(
ZoneLoaderTest
,
classMismatch
)
{
destination_client_
.
rrclass_
=
RRClass
::
CH
();
prepareSource
(
Name
::
ROOT_NAME
(),
"root.zone"
);
EXPECT_THROW
(
ZoneLoader
(
destination_client_
,
Name
::
ROOT_NAME
(),
source_client_
),
isc
::
InvalidParameter
);
}
// Load an unsigned zone, all at once
TEST_F
(
ZoneLoaderTest
,
loadUnsigned
)
{
ZoneLoader
loader
(
destination_client_
,
Name
::
ROOT_NAME
(),
TEST_DATA_DIR
"/root.zone"
);
// It gets the updater directly in the constructor
ASSERT_EQ
(
1
,
destination_client_
.
provided_updaters_
.
size
());
EXPECT_EQ
(
Name
::
ROOT_NAME
(),
destination_client_
.
provided_updaters_
[
0
]);
// Now load the whole zone
loader
.
load
();
EXPECT_TRUE
(
destination_client_
.
commit_called_
);
// We don't check the whole zone. We check the first and last and the
// count, which should be enough.
// The count is 34 because we expect the RRs to be separated.
EXPECT_EQ
(
34
,
destination_client_
.
rrsets_
.
size
());
// Ensure known order.
std
::
sort
(
destination_client_
.
rrsets_
.
begin
(),
destination_client_
.
rrsets_
.
end
());
EXPECT_EQ
(
". 518400 IN NS a.root-servers.net.
\n
"
,
destination_client_
.
rrsets_
.
front
());
EXPECT_EQ
(
"m.root-servers.net. 3600000 IN AAAA 2001:dc3::35
\n
"
,
destination_client_
.
rrsets_
.
back
());
// It isn't possible to try again now
EXPECT_THROW
(
loader
.
load
(),
isc
::
InvalidOperation
);
EXPECT_THROW
(
loader
.
loadIncremental
(
1
),
isc
::
InvalidOperation
);
// Even 0, which should load nothing, returns the error
EXPECT_THROW
(
loader
.
loadIncremental
(
0
),
isc
::
InvalidOperation
);
}
// Try loading from master file incrementally.
TEST_F
(
ZoneLoaderTest
,
loadUnsignedIncremental
)
{