"example.com. FAKEFAKEFAKE"));
}
+// A helper callback of masterLoad() used in InMemoryZoneFinderTest.
+void
+setRRset(RRsetPtr rrset, vector<RRsetPtr*>::iterator& it) {
+ *(*it) = rrset;
+ ++it;
+}
+
+// A helper function that converts a textual form of a single RR into a
+// RRsetPtr object. If it's SOA, origin must be set to its owner name;
+// otherwise masterLoad() will reject it.
+RRsetPtr
+textToRRset(const string& text_rrset, const Name& origin = Name::ROOT_NAME()) {
+ stringstream ss(text_rrset);
+ RRsetPtr rrset;
+ vector<RRsetPtr*> rrsets;
+ rrsets.push_back(&rrset);
+ masterLoad(ss, origin, RRClass::IN(),
+ boost::bind(setRRset, _1, rrsets.begin()));
+ return (rrset);
+}
+
// This is a mock Zone Finder class for testing.
// It is a derived class of ZoneFinder for the convenient of tests.
// Its find() method emulates the common behavior of protocol compliant
// an authoritative answer, not a delegation. This is as described in
// RFC 4035, section 3.1.4.1.
-// This mock finder is used for some DS-query test(s) to check if the lookup
-// takes place at the parent zone, not at this (broken) zone.
-class BrokenChildZoneFinder : public MockZoneFinder {
+// This mock finder is used for some DS-query tests to emulate the situation
+// where the server has authority for the child side of DS. Only limited
+// methods are expected to called on this class object in these tests, which
+// are overridden below.
+class ChildZoneFinder : public MockZoneFinder {
public:
- BrokenChildZoneFinder(const Name& origin) :
+ ChildZoneFinder(const Name& origin) :
MockZoneFinder(), origin_(origin)
{}
virtual isc::dns::Name getOrigin() const { return (origin_); }
- virtual FindResult find(const isc::dns::Name&,
- const isc::dns::RRType&,
+ virtual FindResult find(const isc::dns::Name& name,
+ const isc::dns::RRType& type,
const FindOptions)
{
- isc_throw(isc::Unexpected,
- "BrokenChildZoneFinder::find shouldn't be called");
+ if (name != origin_) {
+ isc_throw(isc::Unexpected, "Non origin name is asked for "
+ "ChildZoneFinder: " << name);
+ }
+ if (type == RRType::SOA()) {
+ RRsetPtr soa = textToRRset(origin_.toText() + " 3600 IN SOA . . "
+ "0 0 0 0 0\n", origin_);
+ soa->addRRsig(RdataPtr(new generic::RRSIG(
+ getCommonRRSIGText("SOA"))));
+ return (FindResult(SUCCESS, soa));
+ }
+ if (type == RRType::DS()) {
+ RRsetPtr nsec = textToRRset(origin_.toText() + " 3600 IN NSEC " +
+ origin_.toText() + " SOA NSEC RRSIG");
+ nsec->addRRsig(RdataPtr(new generic::RRSIG(
+ getCommonRRSIGText("NSEC"))));
+ return (FindResult(NXRRSET, nsec, RESULT_NSEC_SIGNED));
+ }
+ isc_throw(isc::Unexpected, "Unexpected RR type is asked for "
+ "ChildZoneFinder: " << type);
}
private:
const Name origin_;
TEST_F(QueryTest, dsAboveDelegation) {
// Pretending to have authority for the child zone, too.
- memory_client.addZone(ZoneFinderPtr(new BrokenChildZoneFinder(
+ memory_client.addZone(ZoneFinderPtr(new ChildZoneFinder(
Name("delegation.example.com"))));
// The following will succeed only if the search goes to the parent
ns_addrs_and_sig_txt.c_str());
}
+TEST_F(QueryTest, dsAtGrandParentAndChild) {
+ // Pretending to have authority for the grandchild zone, too.
+ const Name childname("grand.delegation.example.com");
+ memory_client.addZone(ZoneFinderPtr(
+ new ChildZoneFinder(childname)));
+ Query(memory_client, childname, RRType::DS(), response, true).process();
+ responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 4, 0, NULL,
+ (childname.toText() + " 3600 IN SOA . . 0 0 0 0 0\n" +
+ childname.toText() + " 3600 IN RRSIG " +
+ getCommonRRSIGText("SOA") + "\n" +
+ childname.toText() + " 3600 IN NSEC " +
+ childname.toText() + " SOA NSEC RRSIG\n" +
+ childname.toText() + " 3600 IN RRSIG " +
+ getCommonRRSIGText("NSEC")).c_str(), NULL, childname);
+}
+
// The following are tentative tests until we really add tests for the
// query logic for these cases. At that point it's probably better to
// clean them up.