Browse Source

Started work with address store, another test

While working on the internal part, another opportunity for testcase
appeared.

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac408@3479 e5f2f494-b856-4b98-b285-d166d9295462
Michal Vaner 14 years ago
parent
commit
36a9f6f87f

+ 52 - 4
src/lib/nsas/nameserver_address_store.cc

@@ -47,12 +47,60 @@ NameserverAddressStore::NameserverAddressStore(ResolverInterface& resolver,
 {
 }
 
+namespace {
+
+// Often used types
+typedef shared_ptr<ZoneEntry> ZonePtr;
+typedef shared_ptr<NameserverEntry> NameserverPtr;
+typedef shared_ptr<AddressRequestCallback> CallbackPtr;
+
+// One function to call new on both ZoneEntry and NameserverEntry
+template<class T>
+shared_ptr<T>
+newT(const std::string& zone, uint16_t class_code) {
+    return (shared_ptr<T>(new T(zone, class_code)));
+}
+
+}
+
 void
-NameserverAddressStore::lookup(const std::string& , uint16_t ,
-    const AbstractRRset& , const vector<AbstractRRset>& ,
-    shared_ptr<AddressRequestCallback> )
+NameserverAddressStore::lookup(const std::string& zone, uint16_t class_code,
+    const AbstractRRset& authority, const vector<AbstractRRset>& ,
+    CallbackPtr callback)
 {
-    // TODO Implement
+    // Try to look up the entry
+    pair<bool, ZonePtr> zone_lookup(
+        zone_hash_.getOrAdd(HashKey(zone, class_code),
+        bind(newT<ZoneEntry>, zone, class_code)));
+    ZonePtr zone_ptr(zone_lookup.second);
+    if (zone_lookup.first) { // New value
+        zone_lru_.add(zone_ptr);
+        // Sanitize the authority section and put the data there
+        if (authority.getClass().getCode() != class_code) {
+            isc_throw(InconsistentZone,
+                "Authority section is for different class, expected: " <<
+                RRClass(class_code).toText() << ", got: " <<
+                authority.getClass().toText());
+        }
+        if (authority.getName() != Name(zone)) {
+            isc_throw(InconsistentZone,
+                "Authority section is for different zone, expected: " <<
+                zone << ", got: " << authority.getName().toText());
+        }
+        if (authority.getType() != RRType::NS()) {
+            isc_throw(NotNS, "Authority section with non-NS RR type: " <<
+                authority.getType().toText());
+        }
+    } else { // Was already here
+        zone_lru_.touch(zone_ptr);
+        // TODO Do we update the TTL and nameservers here?
+    }
+    zone_ptr->addCallback(callback);
+    processZone(zone_ptr);
+}
+
+void NameserverAddressStore::processZone(ZonePtr) {
+
 }
 
 } // namespace nsas

+ 37 - 0
src/lib/nsas/nameserver_address_store.h

@@ -32,6 +32,32 @@
 namespace isc {
 namespace nsas {
 
+/**
+ * \short Invalid referral information passed.
+ *
+ * This is thrown if the referral passed to NameserverAddressStore::lookup is
+ * wrong. Has subexceptions for specific conditions.
+ */
+struct InvalidReferral : public isc::BadValue {
+    InvalidReferral(const char *file, size_t line, const char *what) :
+        BadValue(file, line, what)
+    { }
+};
+
+/// \short The referral is not for this zone.
+struct InconsistentZone : public InvalidReferral {
+    InconsistentZone(const char *file, size_t line, const char *what) :
+        InvalidReferral(file, line, what)
+    { }
+};
+
+/// \short The authority zone contains something else than NS
+struct NotNS : public InvalidReferral {
+    NotNS(const char *file, size_t line, const char *what) :
+        InvalidReferral(file, line, what)
+    { }
+};
+
 /// \brief Nameserver Address Store
 ///
 /// This class implements the bare bones of the nameserver address store - the
@@ -104,6 +130,17 @@ protected:
     //}@
 private:
     ResolverInterface& resolver_;
+    /**
+     * \short Find if any callbacks may be called.
+     *
+     * This is called when new callback or new data arrive to a zone. In both
+     * cases this may trigger executing some of the callbacks or additional
+     * lookups.
+     * \param zone Which zone to process
+     * \todo Should this be part of the zone entry possibly?
+     * \todo Pass some of the referral stuff there?
+     */
+    void processZone(boost::shared_ptr<ZoneEntry> zone);
 };
 
 } // namespace nsas

+ 29 - 6
src/lib/nsas/tests/nameserver_address_store_unittest.cc

@@ -164,6 +164,10 @@ protected:
                     asiolink::IOAddress("0.0.0.0")));
             }
     };
+
+    boost::shared_ptr<AddressRequestCallback> getCallback() {
+        return (boost::shared_ptr<AddressRequestCallback>(new NSASCallback));
+    }
 };
 
 vector<NameserverAddressStoreTest::NSASCallback::Result>
@@ -238,24 +242,21 @@ TEST_F(NameserverAddressStoreTest, emptyLookup) {
     DerivedNsas nsas(defaultTestResolver, 10, 10);
     // Ask it a question
     nsas.lookup("example.net.", RRClass::IN().getCode(), *authority_,
-        vector<AbstractRRset>(), boost::shared_ptr<AddressRequestCallback>(
-        new NSASCallback));
+        vector<AbstractRRset>(), getCallback());
     // It should ask for IP addresses for example.com.
     ASSERT_EQ(2, defaultTestResolver.requests.size());
     asksIPs(Name("example.com."), 0, 1);
 
     // Ask another question for the same zone
     nsas.lookup("example.net.", RRClass::IN().getCode(), *authority_,
-        vector<AbstractRRset>(), boost::shared_ptr<AddressRequestCallback>(
-        new NSASCallback));
+        vector<AbstractRRset>(), getCallback());
     // It should ask no more questions now
     EXPECT_EQ(2, defaultTestResolver.requests.size());
 
     // Ask another question with different zone but the same nameserver
     authority_->setName(Name("example.com."));
     nsas.lookup("example.com.", RRClass::IN().getCode(), *authority_,
-        vector<AbstractRRset>(), boost::shared_ptr<AddressRequestCallback>(
-        new NSASCallback));
+        vector<AbstractRRset>(), getCallback());
     // It still should ask nothing
     EXPECT_EQ(2, defaultTestResolver.requests.size());
 
@@ -276,5 +277,27 @@ TEST_F(NameserverAddressStoreTest, emptyLookup) {
     }
 }
 
+/// \short Test invalid authority section.
+TEST_F(NameserverAddressStoreTest, invalidAuthority) {
+    DerivedNsas nsas(defaultTestResolver, 2, 2);
+    EXPECT_THROW(nsas.lookup("example.net.", RRClass::CH().getCode(),
+        *authority_, vector<AbstractRRset>(), getCallback()),
+        InconsistentZone);
+    EXPECT_EQ(0, defaultTestResolver.requests.size());
+    EXPECT_EQ(0, NSASCallback::results.size());
+    EXPECT_THROW(nsas.lookup("example.com.", RRClass::IN().getCode(),
+        *authority_, vector<AbstractRRset>(), getCallback()),
+        InconsistentZone);
+    EXPECT_EQ(0, defaultTestResolver.requests.size());
+    EXPECT_EQ(0, NSASCallback::results.size());
+    BasicRRset aAuthority(Name("example.net."), RRClass::IN(), RRType::A(),
+            RRTTL(128));
+    EXPECT_THROW(nsas.lookup("example.net.", RRClass::IN().getCode(),
+        aAuthority, vector<AbstractRRset>(),
+        getCallback()), NotNS);
+    EXPECT_EQ(0, defaultTestResolver.requests.size());
+    EXPECT_EQ(0, NSASCallback::results.size());
+}
+
 } // namespace nsas
 } // namespace isc