Browse Source

[trac493] Add more unit tests for negative cache

Ocean Wang 14 years ago
parent
commit
21d48af75c

+ 10 - 8
src/lib/cache/message_entry.cc

@@ -229,7 +229,7 @@ MessageEntry::parseSection(const isc::dns::Message& msg,
 
 
 void
 void
 MessageEntry::parseNegativeResponseAuthoritySection(const isc::dns::Message& msg,
 MessageEntry::parseNegativeResponseAuthoritySection(const isc::dns::Message& msg,
-        uint32_t& soa_ttl,
+        uint32_t& min_ttl,
         uint16_t& rrset_count)
         uint16_t& rrset_count)
 {
 {
 
 
@@ -240,15 +240,20 @@ MessageEntry::parseNegativeResponseAuthoritySection(const isc::dns::Message& msg
             ++iter){
             ++iter){
         RRsetPtr rrset_ptr = *iter;
         RRsetPtr rrset_ptr = *iter;
         RRsetTrustLevel level = getRRsetTrustLevel(msg, rrset_ptr, Message::SECTION_AUTHORITY);
         RRsetTrustLevel level = getRRsetTrustLevel(msg, rrset_ptr, Message::SECTION_AUTHORITY);
+        uint32_t rrset_ttl = 0;
         if (rrset_ptr->getType() == RRType::SOA()){
         if (rrset_ptr->getType() == RRType::SOA()){
-            soa_ttl = rrset_ptr->getTTL().getValue();
             RRsetEntryPtr rrset_entry = negative_soa_cache_->update(*rrset_ptr, level);
             RRsetEntryPtr rrset_entry = negative_soa_cache_->update(*rrset_ptr, level);
             rrsets_.push_back(RRsetRef(rrset_ptr->getName(), rrset_ptr->getType(), negative_soa_cache_));
             rrsets_.push_back(RRsetRef(rrset_ptr->getName(), rrset_ptr->getType(), negative_soa_cache_));
+            rrset_ttl = rrset_entry->getTTL();
         } else {
         } else {
             RRsetEntryPtr rrset_entry = rrset_cache_->update(*rrset_ptr, level);
             RRsetEntryPtr rrset_entry = rrset_cache_->update(*rrset_ptr, level);
             rrsets_.push_back(RRsetRef(rrset_ptr->getName(), rrset_ptr->getType(), rrset_cache_));
             rrsets_.push_back(RRsetRef(rrset_ptr->getName(), rrset_ptr->getType(), rrset_cache_));
+            rrset_ttl = rrset_entry->getTTL();
         }
         }
 
 
+        if (min_ttl > rrset_ttl) {
+            min_ttl = rrset_ttl;
+        }
         ++count;
         ++count;
     }
     }
 
 
@@ -269,15 +274,12 @@ MessageEntry::initMessageEntry(const isc::dns::Message& msg) {
     query_type_ = (*iter)->getType().getCode();
     query_type_ = (*iter)->getType().getCode();
     query_class_ = (*iter)->getClass().getCode();
     query_class_ = (*iter)->getClass().getCode();
 
 
+    uint32_t min_ttl = MAX_UINT32;
     if (!isNegativeResponse(msg)){
     if (!isNegativeResponse(msg)){
-        uint32_t min_ttl = MAX_UINT32;
         parseSection(msg, Message::SECTION_ANSWER, min_ttl, answer_count_);
         parseSection(msg, Message::SECTION_ANSWER, min_ttl, answer_count_);
         parseSection(msg, Message::SECTION_AUTHORITY, min_ttl, authority_count_);
         parseSection(msg, Message::SECTION_AUTHORITY, min_ttl, authority_count_);
         parseSection(msg, Message::SECTION_ADDITIONAL, min_ttl, additional_count_);
         parseSection(msg, Message::SECTION_ADDITIONAL, min_ttl, additional_count_);
-        expire_time_ = time(NULL) + min_ttl;
     } else {
     } else {
-        uint32_t min_ttl = MAX_UINT32;
-        uint32_t soa_ttl = MAX_UINT32;
         uint16_t rrset_count = 0;
         uint16_t rrset_count = 0;
 
 
         // For negative response, if no soa RRset is found in authority section, dont cache it
         // For negative response, if no soa RRset is found in authority section, dont cache it
@@ -285,14 +287,14 @@ MessageEntry::initMessageEntry(const isc::dns::Message& msg) {
             return;
             return;
         }
         }
 
 
-        parseNegativeResponseAuthoritySection(msg, soa_ttl, rrset_count);
+        parseNegativeResponseAuthoritySection(msg, min_ttl, rrset_count);
 
 
         authority_count_ = rrset_count;
         authority_count_ = rrset_count;
         parseSection(msg, Message::SECTION_ANSWER, min_ttl, answer_count_);
         parseSection(msg, Message::SECTION_ANSWER, min_ttl, answer_count_);
         parseSection(msg, Message::SECTION_ADDITIONAL, min_ttl, additional_count_);
         parseSection(msg, Message::SECTION_ADDITIONAL, min_ttl, additional_count_);
 
 
-        expire_time_ = time(NULL) + soa_ttl;
     }
     }
+    expire_time_ = time(NULL) + min_ttl;
 
 
 }
 }
 
 

+ 2 - 2
src/lib/cache/message_entry.h

@@ -122,10 +122,10 @@ protected:
     ///        negative response. The SOA RRset need to be located and
     ///        negative response. The SOA RRset need to be located and
     ///        stored in a seperate cache
     ///        stored in a seperate cache
     /// \param msg The message to parse the RRsets from
     /// \param msg The message to parse the RRsets from
-    /// \param soa_ttl Get the ttl of soa rrset in the authority section
+    /// \param min_ttl Get the minimum ttl of rrset in the authority section
     /// \param rrset_count the rrset count of the authority section
     /// \param rrset_count the rrset count of the authority section
     void parseNegativeResponseAuthoritySection(const isc::dns::Message& msg,
     void parseNegativeResponseAuthoritySection(const isc::dns::Message& msg,
-            uint32_t& soa_ttl,
+            uint32_t& min_ttl,
             uint16_t& rrset_count);
             uint16_t& rrset_count);
 
 
     /// \brief Get RRset Trustworthiness
     /// \brief Get RRset Trustworthiness

+ 33 - 0
src/lib/cache/tests/negative_cache_unittest.cc

@@ -17,6 +17,7 @@
 #include <string>
 #include <string>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <dns/rrset.h>
 #include <dns/rrset.h>
+#include <dns/rcode.h>
 #include "resolver_cache.h"
 #include "resolver_cache.h"
 #include "cache_test_messagefromfile.h"
 #include "cache_test_messagefromfile.h"
 
 
@@ -115,6 +116,23 @@ TEST_F(NegativeCacheTest, testNXDOMAINWithoutSOA){
     EXPECT_FALSE(cache->lookup(non_exist_qname, RRType::A(), RRClass::IN(), msg_nxdomain));
     EXPECT_FALSE(cache->lookup(non_exist_qname, RRType::A(), RRClass::IN(), msg_nxdomain));
 }
 }
 
 
+TEST_F(NegativeCacheTest, testNXDOMAINCname){
+    // a.example.org points to b.example.org
+    // b.example.org points to c.example.org
+    // c.example.org does not exist
+    Message msg_nxdomain_cname(Message::PARSE);
+    messageFromFile(msg_nxdomain_cname, "message_nxdomain_cname.wire");
+    cache->update(msg_nxdomain_cname);
+
+    msg_nxdomain_cname.makeResponse();
+
+    Name a_example_org("a.example.org.");
+    // The message should be cached
+    EXPECT_TRUE(cache->lookup(a_example_org, RRType::A(), RRClass::IN(), msg_nxdomain_cname));
+
+    EXPECT_EQ(msg_nxdomain_cname.getRcode().getCode(), Rcode::NXDOMAIN().getCode());
+}
+
 TEST_F(NegativeCacheTest, testNoerrorNodata){
 TEST_F(NegativeCacheTest, testNoerrorNodata){
     // NODATA/NOERROR response for MX type query of example.com
     // NODATA/NOERROR response for MX type query of example.com
     Message msg_nodata(Message::PARSE);
     Message msg_nodata(Message::PARSE);
@@ -164,4 +182,19 @@ TEST_F(NegativeCacheTest, testNoerrorNodata){
     EXPECT_EQ(nodata_ttl2.getValue(), 86400);
     EXPECT_EQ(nodata_ttl2.getValue(), 86400);
 }
 }
 
 
+TEST_F(NegativeCacheTest, testReferralResponse){
+    // CNAME exist, but it points to out of zone data, so the server give some reference data
+    Message msg_cname_referral(Message::PARSE);
+    messageFromFile(msg_cname_referral, "message_cname_referral.wire");
+    cache->update(msg_cname_referral);
+
+    msg_cname_referral.makeResponse();
+
+    Name x_example_org("x.example.org.");
+    EXPECT_TRUE(cache->lookup(x_example_org, RRType::A(), RRClass::IN(), msg_cname_referral));
+
+    // The Rcode should be NOERROR
+    EXPECT_EQ(msg_cname_referral.getRcode().getCode(), Rcode::NOERROR().getCode());
+}
+
 }
 }

+ 3 - 1
src/lib/cache/tests/testdata/message_cname_referral.wire

@@ -1,6 +1,6 @@
 #
 #
 # Request A record for x.example.org, the CNAME record exist for x.example.org
 # Request A record for x.example.org, the CNAME record exist for x.example.org
-# it poinst to x.example.net, but the server have no idea whether x.example.net exist
+# it poinst to x.example.net, but the server has no idea whether x.example.net exist
 # so it give some NS records for reference
 # so it give some NS records for reference
 #
 #
 # Transaction ID: 0xaf71
 # Transaction ID: 0xaf71
@@ -19,12 +19,14 @@ af71 8480
 ## Answer
 ## Answer
 ##
 ##
 # x.example.org: type CNAME, class IN, cname x.example.net
 # x.example.org: type CNAME, class IN, cname x.example.net
+# TTL: 360s
 01 78 07 65 78 61 6d 70 6c 65 03 6f 72 67 00 00 01 00 01
 01 78 07 65 78 61 6d 70 6c 65 03 6f 72 67 00 00 01 00 01
 c0 0c 00 05 00 01 00 00 0e 10 00 0f 01 78 07 65 78
 c0 0c 00 05 00 01 00 00 0e 10 00 0f 01 78 07 65 78
 61 6d 70 6c 65 03 6e 65 74 00
 61 6d 70 6c 65 03 6e 65 74 00
 ##
 ##
 ## Authority
 ## Authority
 ##
 ##
+# TTL:518400
 # <Root>: type NS, class IN, ns G.ROOT-SERVERS.net
 # <Root>: type NS, class IN, ns G.ROOT-SERVERS.net
 # <Root>: type NS, class IN, ns E.ROOT-SERVERS.net
 # <Root>: type NS, class IN, ns E.ROOT-SERVERS.net
 # <Root>: type NS, class IN, ns J.ROOT-SERVERS.net
 # <Root>: type NS, class IN, ns J.ROOT-SERVERS.net