|
@@ -72,35 +72,47 @@ public:
|
|
|
};
|
|
|
class Iterator : public ZoneIterator {
|
|
|
public:
|
|
|
- Iterator(const Name& origin) :
|
|
|
+ Iterator(const Name& origin, bool include_ns) :
|
|
|
origin_(origin),
|
|
|
- finished_(false),
|
|
|
- soa_(new RRset(origin_, RRClass::IN(), RRType::SOA(), RRTTL(3600)))
|
|
|
+ soa_(new RRset(origin_, RRClass::IN(), RRType::SOA(),
|
|
|
+ RRTTL(3600)))
|
|
|
{
|
|
|
// The RData here is bogus, but it is not used to anything. There
|
|
|
// just needs to be some.
|
|
|
soa_->addRdata(rdata::generic::SOA(Name::ROOT_NAME(),
|
|
|
Name::ROOT_NAME(),
|
|
|
0, 0, 0, 0, 0));
|
|
|
+ rrsets_.push_back(soa_);
|
|
|
+
|
|
|
+ if (include_ns) {
|
|
|
+ ns_.reset(new RRset(origin_, RRClass::IN(), RRType::NS(),
|
|
|
+ RRTTL(3600)));
|
|
|
+ ns_->addRdata(rdata::generic::NS(Name::ROOT_NAME()));
|
|
|
+ rrsets_.push_back(ns_);
|
|
|
+ }
|
|
|
+ rrsets_.push_back(ConstRRsetPtr());
|
|
|
+
|
|
|
+ it_ = rrsets_.begin();
|
|
|
}
|
|
|
virtual isc::dns::ConstRRsetPtr getNextRRset() {
|
|
|
- if (finished_) {
|
|
|
- return (ConstRRsetPtr());
|
|
|
- } else {
|
|
|
- finished_ = true;
|
|
|
- return (soa_);
|
|
|
- }
|
|
|
+ ConstRRsetPtr result = *it_;
|
|
|
+ ++it_;
|
|
|
+ return (result);
|
|
|
}
|
|
|
virtual isc::dns::ConstRRsetPtr getSOA() const {
|
|
|
return (soa_);
|
|
|
}
|
|
|
private:
|
|
|
const Name origin_;
|
|
|
- bool finished_;
|
|
|
- const isc::dns::RRsetPtr soa_;
|
|
|
+ const RRsetPtr soa_;
|
|
|
+ RRsetPtr ns_;
|
|
|
+ std::vector<ConstRRsetPtr> rrsets_;
|
|
|
+ std::vector<ConstRRsetPtr>::const_iterator it_;
|
|
|
};
|
|
|
// Constructor from a list of zones.
|
|
|
- MockDataSourceClient(const char* zone_names[]) {
|
|
|
+ MockDataSourceClient(const char* zone_names[]) :
|
|
|
+ have_ns_(true), use_baditerator_(true)
|
|
|
+ {
|
|
|
for (const char** zone(zone_names); *zone; ++zone) {
|
|
|
zones.insert(Name(*zone));
|
|
|
}
|
|
@@ -110,7 +122,8 @@ public:
|
|
|
MockDataSourceClient(const string& type,
|
|
|
const ConstElementPtr& configuration) :
|
|
|
type_(type),
|
|
|
- configuration_(configuration)
|
|
|
+ configuration_(configuration),
|
|
|
+ have_ns_(true), use_baditerator_(true)
|
|
|
{
|
|
|
EXPECT_NE("MasterFiles", type) << "MasterFiles is a special case "
|
|
|
"and it never should be created as a data source client";
|
|
@@ -151,23 +164,27 @@ public:
|
|
|
isc_throw(isc::NotImplemented, "Not implemented");
|
|
|
}
|
|
|
virtual ZoneIteratorPtr getIterator(const Name& name, bool) const {
|
|
|
- if (name == Name("noiter.org")) {
|
|
|
+ if (use_baditerator_ && name == Name("noiter.org")) {
|
|
|
isc_throw(isc::NotImplemented, "Asked not to be implemented");
|
|
|
- } else if (name == Name("null.org")) {
|
|
|
+ } else if (use_baditerator_ && name == Name("null.org")) {
|
|
|
return (ZoneIteratorPtr());
|
|
|
} else {
|
|
|
FindResult result(findZone(name));
|
|
|
if (result.code == isc::datasrc::result::SUCCESS) {
|
|
|
- return (ZoneIteratorPtr(new Iterator(name)));
|
|
|
+ return (ZoneIteratorPtr(new Iterator(name, have_ns_)));
|
|
|
} else {
|
|
|
isc_throw(DataSourceError, "No such zone");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ void disableNS() { have_ns_ = false; }
|
|
|
+ void disableBadIterator() { use_baditerator_ = false; }
|
|
|
const string type_;
|
|
|
const ConstElementPtr configuration_;
|
|
|
private:
|
|
|
set<Name> zones;
|
|
|
+ bool have_ns_; // control the iterator behavior wrt whether to include NS
|
|
|
+ bool use_baditerator_; // whether to use bogus zone iterators for tests
|
|
|
};
|
|
|
|
|
|
|
|
@@ -249,22 +266,30 @@ public:
|
|
|
false, rrclass_, mem_sgmt_));
|
|
|
}
|
|
|
}
|
|
|
- void prepareCache(size_t index, const Name& zone, bool prefill = false) {
|
|
|
+
|
|
|
+ // Install a "fake" cached zone using a temporary underlying data source
|
|
|
+ // client.
|
|
|
+ void prepareCache(size_t index, const Name& zone) {
|
|
|
+ // Prepare the temporary data source client
|
|
|
+ const char* zones[2];
|
|
|
+ const std::string zonename_txt = zone.toText();
|
|
|
+ zones[0] = zonename_txt.c_str();
|
|
|
+ zones[1] = NULL;
|
|
|
+ MockDataSourceClient mock_client(zones);
|
|
|
+ // Disable some default features of the mock to distinguish the
|
|
|
+ // temporary case from normal case.
|
|
|
+ mock_client.disableNS();
|
|
|
+ mock_client.disableBadIterator();
|
|
|
+
|
|
|
+ // Create cache from the temporary data source, and push it to the
|
|
|
+ // client list.
|
|
|
const shared_ptr<InMemoryClient> cache(new InMemoryClient(mem_sgmt_,
|
|
|
rrclass_));
|
|
|
- if (prefill) {
|
|
|
- RRsetPtr soa(new RRset(zone, RRClass::IN(), RRType::SOA(),
|
|
|
- RRTTL(3600)));
|
|
|
- // The RData here is bogus, but it is not used to anything. There
|
|
|
- // just needs to be some.
|
|
|
- soa->addRdata(rdata::generic::SOA(Name::ROOT_NAME(),
|
|
|
- Name::ROOT_NAME(),
|
|
|
- 0, 0, 0, 0, 0));
|
|
|
- cache->add(zone, soa);
|
|
|
- }
|
|
|
- // If we don't do prefill, we leave the zone empty. This way,
|
|
|
- // we can check when it was reloaded.
|
|
|
- list_->getDataSources()[index].cache_ = cache;
|
|
|
+ cache->load(zone, *mock_client.getIterator(zone, false));
|
|
|
+
|
|
|
+ ConfigurableClientList::DataSourceInfo& dsrc_info =
|
|
|
+ list_->getDataSources()[index];
|
|
|
+ dsrc_info.cache_ = cache;
|
|
|
}
|
|
|
// Check the positive result is as we expect it.
|
|
|
void positiveResult(const ClientList::FindResult& result,
|
|
@@ -824,14 +849,14 @@ TEST_F(ListTest, reloadSuccess) {
|
|
|
list_->configure(config_elem_zones_, true);
|
|
|
const Name name("example.org");
|
|
|
prepareCache(0, name);
|
|
|
- // Not there yet. It would be NXDOMAIN, but it is in apex and
|
|
|
- // it returns NXRRSET instead.
|
|
|
+ // The cache currently contains a tweaked version of zone, which doesn't
|
|
|
+ // have apex NS. So the lookup should result in NXRRSET.
|
|
|
EXPECT_EQ(ZoneFinder::NXRRSET,
|
|
|
- list_->find(name).finder_->find(name, RRType::SOA())->code);
|
|
|
- // Now reload. It should be there now.
|
|
|
+ list_->find(name).finder_->find(name, RRType::NS())->code);
|
|
|
+ // Now reload the full zone. It should be there now.
|
|
|
EXPECT_EQ(ConfigurableClientList::ZONE_RELOADED, list_->reload(name));
|
|
|
EXPECT_EQ(ZoneFinder::SUCCESS,
|
|
|
- list_->find(name).finder_->find(name, RRType::SOA())->code);
|
|
|
+ list_->find(name).finder_->find(name, RRType::NS())->code);
|
|
|
}
|
|
|
|
|
|
// The cache is not enabled. The load should be rejected.
|
|
@@ -840,15 +865,14 @@ TEST_F(ListTest, reloadNotEnabled) {
|
|
|
const Name name("example.org");
|
|
|
// We put the cache in even when not enabled. This won't confuse the thing.
|
|
|
prepareCache(0, name);
|
|
|
- // Not there yet. It would be NXDOMAIN, but it is in apex and
|
|
|
- // it returns NXRRSET instead.
|
|
|
+ // See the reloadSuccess test. This should result in NXRRSET.
|
|
|
EXPECT_EQ(ZoneFinder::NXRRSET,
|
|
|
- list_->find(name).finder_->find(name, RRType::SOA())->code);
|
|
|
+ list_->find(name).finder_->find(name, RRType::NS())->code);
|
|
|
// Now reload. It should reject it.
|
|
|
EXPECT_EQ(ConfigurableClientList::CACHE_DISABLED, list_->reload(name));
|
|
|
// Nothing changed here
|
|
|
EXPECT_EQ(ZoneFinder::NXRRSET,
|
|
|
- list_->find(name).finder_->find(name, RRType::SOA())->code);
|
|
|
+ list_->find(name).finder_->find(name, RRType::NS())->code);
|
|
|
}
|
|
|
|
|
|
// Test several cases when the zone does not exist
|
|
@@ -874,10 +898,10 @@ TEST_F(ListTest, reloadNoSuchZone) {
|
|
|
list_->find(Name("example.cz")).dsrc_client_);
|
|
|
EXPECT_EQ(static_cast<isc::datasrc::DataSourceClient*>(NULL),
|
|
|
list_->find(Name("sub.example.com"), true).dsrc_client_);
|
|
|
- // Not reloaded
|
|
|
+ // Not reloaded, so NS shouldn't be visible yet.
|
|
|
EXPECT_EQ(ZoneFinder::NXRRSET,
|
|
|
list_->find(Name("example.com")).finder_->
|
|
|
- find(Name("example.com"), RRType::SOA())->code);
|
|
|
+ find(Name("example.com"), RRType::NS())->code);
|
|
|
}
|
|
|
|
|
|
// Check we gracefuly throw an exception when a zone disappeared in
|
|
@@ -888,13 +912,13 @@ TEST_F(ListTest, reloadZoneGone) {
|
|
|
// We put in a cache for non-existant zone. This emulates being loaded
|
|
|
// and then the zone disappearing. We prefill the cache, so we can check
|
|
|
// it.
|
|
|
- prepareCache(0, name, true);
|
|
|
- // The zone contains something
|
|
|
+ prepareCache(0, name);
|
|
|
+ // The (cached) zone contains zone's SOA
|
|
|
EXPECT_EQ(ZoneFinder::SUCCESS,
|
|
|
list_->find(name).finder_->find(name, RRType::SOA())->code);
|
|
|
// The zone is not there, so abort the reload.
|
|
|
EXPECT_THROW(list_->reload(name), DataSourceError);
|
|
|
- // The zone is not hurt.
|
|
|
+ // The (cached) zone is not hurt.
|
|
|
EXPECT_EQ(ZoneFinder::SUCCESS,
|
|
|
list_->find(name).finder_->find(name, RRType::SOA())->code);
|
|
|
}
|
|
@@ -903,7 +927,7 @@ TEST_F(ListTest, reloadZoneGone) {
|
|
|
TEST_F(ListTest, reloadZoneThrow) {
|
|
|
list_->configure(config_elem_zones_, true);
|
|
|
const Name name("noiter.org");
|
|
|
- prepareCache(0, name, true);
|
|
|
+ prepareCache(0, name);
|
|
|
// The zone contains stuff now
|
|
|
EXPECT_EQ(ZoneFinder::SUCCESS,
|
|
|
list_->find(name).finder_->find(name, RRType::SOA())->code);
|
|
@@ -917,7 +941,7 @@ TEST_F(ListTest, reloadZoneThrow) {
|
|
|
TEST_F(ListTest, reloadNullIterator) {
|
|
|
list_->configure(config_elem_zones_, true);
|
|
|
const Name name("null.org");
|
|
|
- prepareCache(0, name, true);
|
|
|
+ prepareCache(0, name);
|
|
|
// The zone contains stuff now
|
|
|
EXPECT_EQ(ZoneFinder::SUCCESS,
|
|
|
list_->find(name).finder_->find(name, RRType::SOA())->code);
|