Parcourir la source

Add unit test code for message cache/entry.

zhanglikun il y a 14 ans
Parent
commit
ba8595ee4d

+ 1 - 5
src/lib/cache/TODO

@@ -1,8 +1,4 @@
-* Implement the TODO item for getRRsetTrustLevel() in message_entry.cc
-    
-  "TODO, according RFC2181 section 5.4.1, only the record 
-   describing that ailas is necessarily authoritative."
-
+* Revisit the algorithm used by getRRsetTrustLevel() in message_entry.cc.
 * Implement dump/load/resize interfaces of rrset/message/recursor cache.   
 * Once LRU hash table is implemented, it should be used by message/rrset cache.  
 * Once the hash/lrulist related files in /lib/nsas is moved to seperated

+ 2 - 2
src/lib/cache/message_cache.cc

@@ -22,6 +22,7 @@
 
 using namespace isc::nsas;
 using namespace isc::dns;
+using namespace std;
 
 namespace isc {
 namespace cache {
@@ -41,7 +42,6 @@ MessageCache::lookup(const isc::dns::Name& qname,
                      const isc::dns::RRType& qtype,
                      isc::dns::Message& response)
 {
-
     std::string entry_name = genCacheEntryName(qname, qtype);
     HashKey entry_key = HashKey(entry_name, RRClass(message_class_));
     MessageEntryPtr msg_entry = message_table_.get(entry_key);
@@ -71,7 +71,7 @@ MessageCache::update(const Message& msg) {
     }
 
     MessageEntryPtr msg_entry(new MessageEntry(msg, rrset_cache_));
-    message_lru_.touch(msg_entry); 
+    message_lru_.add(msg_entry); 
     return message_table_.add(msg_entry, entry_key, true); 
 }
 

+ 32 - 3
src/lib/cache/message_entry.cc

@@ -79,16 +79,45 @@ MessageEntry::genMessage(const time_t& time_now,
 
 RRsetTrustLevel
 MessageEntry::getRRsetTrustLevel(const Message& message,
-                   const isc::dns::RRset&,
+                   const isc::dns::RRsetPtr rrset,
                    const isc::dns::Message::Section& section) 
 {
     bool aa = message.getHeaderFlag(Message::HEADERFLAG_AA);
     switch(section) {
         case Message::SECTION_ANSWER: {
             if (aa) {
-                //TODO, according RFC2181 section 5.4.1, only the record 
+                // According RFC2181 section 5.4.1, only the record 
                 // describing that ailas is necessarily authoritative.
+                // If there is one or more CNAME records in answer section.
+                // CNAME records is assumed as the first rrset.
+                RRsetIterator rrset_iter = message.beginSection(section);
+                if ((*rrset_iter)->getType() == RRType("CNAME")) {
+                    if ((*rrset_iter).get() == rrset.get()) {
+                        return RRSET_TRUST_ANSWER_AA;
+                    } else {
+                        return RRSET_TRUST_ANSWER_NONAA;
+                    }
+                } 
+
+                // Here, if the first rrset is DNAME, then assume the 
+                // second rrset is synchronized CNAME record, except
+                // these two records, any other records in answer section
+                // should be treated as non-authoritative.
+                // TODO, this part logic should be revisited later,
+                // since it's not mentioned by RFC2181.
+                if ((*rrset_iter)->getType() == RRType("DNAME")) {
+                    if ((*rrset_iter).get() == rrset.get() || 
+                        ((++rrset_iter) != message.endSection(section) && 
+                                     (*rrset_iter).get() == rrset.get())) {
+
+                        return RRSET_TRUST_ANSWER_AA;
+                    } else {
+                        return RRSET_TRUST_ANSWER_NONAA;
+                    }
+                } 
+                
                 return RRSET_TRUST_ANSWER_AA;
+
             } else {
                 return RRSET_TRUST_ANSWER_NONAA;
             }
@@ -133,7 +162,7 @@ MessageEntry::parseRRset(const isc::dns::Message& msg,
         // rrset entry if the new one is more authoritative.
         //TODO set proper rrset trust level.
         RRsetPtr rrset_ptr = *iter;
-        RRsetTrustLevel level = getRRsetTrustLevel(msg, *rrset_ptr, section);
+        RRsetTrustLevel level = getRRsetTrustLevel(msg, rrset_ptr, section);
         RRsetEntryPtr rrset_entry = rrset_cache_->update(*rrset_ptr, level);
         rrsets_.push_back(rrset_entry);
         

+ 10 - 3
src/lib/cache/message_entry.h

@@ -19,6 +19,7 @@
 
 #include <vector>
 #include <dns/message.h>
+#include <dns/rrset.h>
 #include <nsas/nsas_entry.h>
 #include <nsas/fetchable.h>
 #include "rrset_entry.h"
@@ -84,12 +85,18 @@ protected:
                     uint16_t& rrset_count);
 
     /// \brief Get RRset Trust worthiness
-    /// only the rrset can be updated by the rrsets 
-    /// with higher trust level.
+    /// The algorithm refers to RFC2181 section 5.4.1
     ///
+    /// Only the rrset can be updated by the rrsets 
+    /// with higher trust level.
+    /// 
+    /// \param message Message that the rrset belongs to
+    /// \param rrset specified rrset which needs to get its 
+    ///     trust worthiness
+    /// \param section Section of the rrset
     /// \return return rrset trust level.
     RRsetTrustLevel getRRsetTrustLevel(const isc::dns::Message& message,
-                               const isc::dns::RRset& rrset,
+                               const isc::dns::RRsetPtr rrset,
                                const isc::dns::Message::Section& section);
     //@}
 private:

+ 1 - 0
src/lib/cache/tests/Makefile.am

@@ -34,6 +34,7 @@ run_unittests_SOURCES  = run_unittests.cc
 run_unittests_SOURCES  += $(top_srcdir)/src/lib/dns/tests/unittest_util.cc
 run_unittests_SOURCES  += rrset_entry_unittest.cc
 run_unittests_SOURCES  += message_cache_unittest.cc
+run_unittests_SOURCES  += message_entry_unittest.cc
 
 run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
 run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)

+ 36 - 0
src/lib/cache/tests/cache_test_util.h

@@ -0,0 +1,36 @@
+// Copyright (C) 2010  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.
+
+// $Id$
+#include <vector>
+#include <dns/tests/unittest_util.h>
+#include <dns/buffer.h>
+#include <dns/message.h>
+
+using namespace isc;
+using namespace isc::dns;
+
+namespace {
+
+void
+messageFromFile(Message& message, const char* datafile) {
+    std::vector<unsigned char> data;
+    UnitTestUtil::readWireData(datafile, data);
+
+    InputBuffer buffer(&data[0], data.size());
+    message.fromWire(buffer);
+}
+
+}   // namespace
+

+ 7 - 16
src/lib/cache/tests/message_cache_unittest.cc

@@ -16,11 +16,12 @@
 #include <config.h>
 #include <string>
 #include <gtest/gtest.h>
+#include <dns/tests/unittest_util.h>
+#include <dns/buffer.h>
 #include "../message_cache.h"
 #include "../rrset_cache.h"
 #include "../recursor_cache.h"
-#include <dns/tests/unittest_util.h>
-#include <dns/buffer.h>
+#include "cache_test_util.h"
 
 using namespace isc::cache;
 using namespace isc;
@@ -39,7 +40,7 @@ public:
     {}
 
     uint16_t messages_count() {
-        return message_table_.tableSize();
+        return message_lru_.size();
     }
 };
 
@@ -54,8 +55,6 @@ public:
                                           MESSAGE_CACHE_DEFAULT_SIZE, class_ ));
     }
 
-    void messageFromFile(Message& message, const char* datafile);
-
 protected:
     boost::shared_ptr<DerivedMessageCache> message_cache_;
     RRsetCachePtr rrset_cache_;
@@ -63,15 +62,6 @@ protected:
     Message message_render;
 };
 
-void
-MessageCacheTest::messageFromFile(Message& message, const char* datafile) {
-    std::vector<unsigned char> data;
-    UnitTestUtil::readWireData(datafile, data);
-
-    InputBuffer buffer(&data[0], data.size());
-    message.fromWire(buffer);
-}
-
 TEST_F(MessageCacheTest, testUpdate) {
     messageFromFile(message_parse, "message_fromWire1");
     EXPECT_TRUE(message_cache_->update(message_parse));
@@ -80,8 +70,9 @@ TEST_F(MessageCacheTest, testUpdate) {
     EXPECT_TRUE(message_cache_->lookup(qname, qtype, message_render));
     EXPECT_EQ(message_cache_->messages_count(), 1);
 
-    messageFromFile(message_parse, "message_fromWire2");
-    EXPECT_TRUE(message_cache_->update(message_parse));
+    Message message_net(Message::PARSE);
+    messageFromFile(message_net, "message_fromWire2");
+    EXPECT_TRUE(message_cache_->update(message_net));
     EXPECT_EQ(message_cache_->messages_count(), 2);
 
     Name qname1("test.example.net.");

+ 190 - 0
src/lib/cache/tests/message_entry_unittest.cc

@@ -0,0 +1,190 @@
+// Copyright (C) 2010  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.
+
+// $Id$
+#include <config.h>
+#include <string>
+#include <gtest/gtest.h>
+#include <dns/tests/unittest_util.h>
+#include <dns/message.h>
+#include <dns/buffer.h>
+#include "../message_entry.h"
+#include "../rrset_cache.h"
+#include "../recursor_cache.h"
+#include "cache_test_util.h"
+
+using namespace isc::cache;
+using namespace isc;
+using namespace isc::dns;
+using namespace std;
+
+static uint32_t MAX_UINT32 = numeric_limits<uint32_t>::max();    
+
+namespace {
+
+/// \brief Derived from base class to make it easy to test
+/// its internals.
+class DerivedMessageEntry: public MessageEntry {
+public:
+    DerivedMessageEntry(const isc::dns::Message& message,
+                        boost::shared_ptr<RRsetCache> rrset_cache_):
+             MessageEntry(message, rrset_cache_)
+    {}
+
+    /// \brief Wrap the protected function so that it can be tested.   
+    void parseRRsetForTest(const Message& msg,
+                           const Message::Section& section,
+                           uint32_t& smaller_ttl, 
+                           uint16_t& rrset_count)
+    {
+        parseRRset(msg, section, smaller_ttl, rrset_count);
+    }
+
+    RRsetTrustLevel getRRsetTrustLevelForTest(const Message& message,
+                                              const RRsetPtr rrset,
+                                              const Message::Section& section) 
+    {
+        return getRRsetTrustLevel(message, rrset, section);
+    }
+
+};
+
+class MessageEntryTest: public testing::Test {
+public:
+    MessageEntryTest(): class_(1),
+                        message_parse(Message::PARSE),
+                        message_render(Message::RENDER)
+    {
+        
+        rrset_cache_.reset(new RRsetCache(RRSET_CACHE_DEFAULT_SIZE, class_));
+    }
+
+protected:
+    uint16_t class_;
+    RRsetCachePtr rrset_cache_;
+    Message message_parse;
+    Message message_render;
+};
+
+TEST_F(MessageEntryTest, testParseRRset) {
+    messageFromFile(message_parse, "message_fromWire3");
+    DerivedMessageEntry message_entry(message_parse, rrset_cache_);
+    uint32_t ttl = MAX_UINT32;
+    uint16_t rrset_count = 0;
+    message_entry.parseRRsetForTest(message_parse, Message::SECTION_ANSWER, ttl, rrset_count);
+    EXPECT_EQ(ttl, 21600);
+    EXPECT_EQ(rrset_count, 1);
+
+    ttl = MAX_UINT32;
+    message_entry.parseRRsetForTest(message_parse, Message::SECTION_AUTHORITY, ttl, rrset_count);
+    EXPECT_EQ(ttl, 21600);
+    EXPECT_EQ(rrset_count, 1);
+
+    ttl = MAX_UINT32;
+    message_entry.parseRRsetForTest(message_parse, Message::SECTION_ADDITIONAL, ttl, rrset_count);
+    EXPECT_EQ(ttl, 10800);
+    EXPECT_EQ(rrset_count, 5);
+}
+
+TEST_F(MessageEntryTest, testGetRRsetTrustLevel_AA) {
+    messageFromFile(message_parse, "message_fromWire3");
+    DerivedMessageEntry message_entry(message_parse, rrset_cache_);
+    
+
+    RRsetIterator rrset_iter = message_parse.beginSection(Message::SECTION_ANSWER);
+    RRsetTrustLevel level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                                    *rrset_iter,
+                                                                    Message::SECTION_ANSWER);
+    EXPECT_EQ(level, RRSET_TRUST_ANSWER_AA);
+
+    rrset_iter = message_parse.beginSection(Message::SECTION_AUTHORITY);
+    level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                    *rrset_iter,
+                                                    Message::SECTION_AUTHORITY);
+    EXPECT_EQ(level, RRSET_TRUST_AUTHORITY_AA);
+
+    rrset_iter = message_parse.beginSection(Message::SECTION_ADDITIONAL);
+    level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                    *rrset_iter,
+                                                    Message::SECTION_ADDITIONAL);
+    EXPECT_EQ(level, RRSET_TRUST_ADDITIONAL_AA);
+}
+
+TEST_F(MessageEntryTest, testGetRRsetTrustLevel_NONAA) {
+    messageFromFile(message_parse, "message_fromWire4");
+    DerivedMessageEntry message_entry(message_parse, rrset_cache_);
+    RRsetIterator rrset_iter = message_parse.beginSection(Message::SECTION_ANSWER);
+    RRsetTrustLevel level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                                    *rrset_iter,
+                                                                    Message::SECTION_ANSWER);
+    EXPECT_EQ(level, RRSET_TRUST_ANSWER_NONAA);
+
+    rrset_iter = message_parse.beginSection(Message::SECTION_AUTHORITY);
+    level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                    *rrset_iter,
+                                                    Message::SECTION_AUTHORITY);
+    EXPECT_EQ(level, RRSET_TRUST_AUTHORITY_NONAA);
+
+    rrset_iter = message_parse.beginSection(Message::SECTION_ADDITIONAL);
+    level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                    *rrset_iter,
+                                                    Message::SECTION_ADDITIONAL);
+    EXPECT_EQ(level, RRSET_TRUST_ADDITIONAL_NONAA);
+}
+
+TEST_F(MessageEntryTest, testGetRRsetTrustLevel_CNAME) {
+    messageFromFile(message_parse, "message_fromWire5");
+    DerivedMessageEntry message_entry(message_parse, rrset_cache_);
+    RRsetIterator rrset_iter = message_parse.beginSection(Message::SECTION_ANSWER);
+    RRsetTrustLevel level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                                    *rrset_iter,
+                                                                    Message::SECTION_ANSWER);
+    EXPECT_EQ(level, RRSET_TRUST_ANSWER_AA);
+
+    ++rrset_iter; // Get the rrset after the first cname rrset.
+    level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                    *rrset_iter,
+                                                    Message::SECTION_ANSWER);
+    EXPECT_EQ(level, RRSET_TRUST_ANSWER_NONAA);
+}
+
+TEST_F(MessageEntryTest, testGetRRsetTrustLevel_DNAME) {
+    messageFromFile(message_parse, "message_fromWire6");
+    DerivedMessageEntry message_entry(message_parse, rrset_cache_);
+    RRsetIterator rrset_iter = message_parse.beginSection(Message::SECTION_ANSWER);
+    RRsetTrustLevel level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                                    *rrset_iter,
+                                                                    Message::SECTION_ANSWER);
+    EXPECT_EQ(level, RRSET_TRUST_ANSWER_AA);
+
+    ++rrset_iter; // Get the rrset after the first dname rrset.
+    level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                    *rrset_iter,
+                                                    Message::SECTION_ANSWER);
+    EXPECT_EQ(level, RRSET_TRUST_ANSWER_AA);
+
+    ++rrset_iter; // Get the second cname rrset
+    level = message_entry.getRRsetTrustLevelForTest(message_parse,
+                                                    *rrset_iter,
+                                                    Message::SECTION_ANSWER);
+    EXPECT_EQ(level, RRSET_TRUST_ANSWER_NONAA);
+}
+
+TEST_F(MessageEntryTest, testInitMessageEntry) {
+    messageFromFile(message_parse, "message_fromWire3");
+    DerivedMessageEntry message_entry(message_parse, rrset_cache_);
+}
+
+
+}   // namespace

+ 22 - 0
src/lib/cache/tests/testdata/message_fromWire2

@@ -0,0 +1,22 @@
+#
+# A simple DNS response message
+# ID = 0x1035
+# QR=1 (response), Opcode=0, AA=1, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=2, other COUNTS=0
+# Question: test.example.net. IN A
+# Answer:
+#  test.example.net. 3600 IN A 192.0.2.1
+#  test.example.net. 7200 IN A 192.0.2.2
+#
+1035 8500
+0001 0002 0000 0000
+#(4) t  e  s  t (7) e  x  a  m  p  l  e (3) n  e  t  .
+ 04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 6e 65 74 00
+0001 0001
+# same name, fully compressed
+c0 0c
+# TTL=3600, A, IN, RDLENGTH=4, RDATA
+0001 0001 00000e10 0004 c0 00 02 01
+# mostly same, with the slight difference in RDATA and TTL
+c0 0c
+0001 0001 00001c20 0004 c0 00 02 02

+ 76 - 0
src/lib/cache/tests/testdata/message_fromWire3

@@ -0,0 +1,76 @@
+#
+# A simple DNS response message
+# ID = 0x0513
+# QR=1 (response), Opcode=0, AA=1, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=1, AUTHORITY COUNT=5, ADDITIONAL COUNT=7
+# Question: example.com. IN SOA
+# ANSWER:
+#   ;; QUESTION SECTION:
+#   ;example.com.                   IN      SOA
+
+#   ;; ANSWER SECTION:
+#   example.com.            21600   IN      SOA     a.dns.example.com. root.example.com. 2009070811 7200 3600 2419200 21600
+
+#   ;; AUTHORITY SECTION:
+#   example.com.            21600   IN      NS      b.dns.example.com.
+#   example.com.            21600   IN      NS      c.dns.example.com.
+#   example.com.            21600   IN      NS      a.dns.example.com.
+#   example.com.            21600   IN      NS      e.dns.example.com.
+#   example.com.            21600   IN      NS      d.dns.example.com.
+
+#    ;; ADDITIONAL SECTION:
+#    a.dns.example.com.      21600   IN      A       1.1.1.1
+#    a.dns.example.com.      21600   IN      A       2.2.2.2
+#    b.dns.example.com.      21600   IN      A       3.3.3.3
+#    c.dns.example.com.      10800   IN      A       4.4.4.4
+#    d.dns.example.com.      43200   IN      A       5.5.5.5
+#    e.dns.example.com.      21600   IN      A       7.7.7.7
+#    e.dns.example.com.      21600   IN      A       6.6.6.6
+
+0513 8500
+0001 0001 0005 0007
+#(7) e x  a  m  p  l  e (3) c  o  m  .
+ 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0006 0001
+# same name, fully compressed
+c0 0c
+# SOA IN  TTL=6h   RDLENGTH=35 rdata
+0006 0001 00005460 0023 01 61 03 64 6e 73 c0 0c 04 72 6f 6f 74 c0 0c 77 bf fc db 00 00 1c 20 00 00 0e 10 00 24 ea 00 00 00 54 60
+#Authority section begin
+c0 0c
+# NS IN   TTL=6h   RDLENGTH=4  b.dns.example.com.
+0002 0001 00005460 0004 01 62 c0 2b
+# NS IN   TTL=6h  c.dns.example.com.
+c0 0c
+0002 0001 00005460 00 04 01 63 c0 2b
+# NS IN a.dns.example.com.
+c0 0c
+0002 0001 00005460 00 02 c0 29
+# NS IN e.dns.example.com.
+c0 0c
+0002 0001 00005460 0004 01 65 c0 2b
+# NS IN d.dns.example.com.
+c0 0c
+0002 0001 00005460 0004 01 64 c0 2b
+# additional section begin
+# a.dns.example.com. A
+c0 29
+0001 0001 00005460 0004 01 01 01 01
+# a.dns.example.com. A
+c0 29
+0001 0001 00005460 0004 02 02 02 02
+#b.dns.example.com.  A
+c0 58
+0001 0001 00002A30 0004 03 03 03 03
+#c.dns.example.com.  A
+c0 68
+0001 0001 00005460 0004 04 04 04 04
+# d.dns.example.com. A
+c0 96
+0001 0001 0000A8C0 0004 05 05 05 05
+# e.dns.example.com. A
+c0 86
+0001 0001 00005460 0004 07 07 07 07
+# e.dns.example.com. A
+c0 86
+0001 0001 00005460 0004 06 06 06 06

+ 80 - 0
src/lib/cache/tests/testdata/message_fromWire4

@@ -0,0 +1,80 @@
+# Note: This message is same with message_fromWire3, except
+#       AA bit is not set. There should be a better way to
+#       avoid the duplicated file by clear the AA bit flags
+#       after reading the message from message_fromWire4.
+# 
+# A simple DNS response message
+# ID = 0x0513
+# QR=1 (response), Opcode=0, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=1, AUTHORITY COUNT=5, ADDITIONAL COUNT=7
+# Question: example.com. IN SOA
+# ANSWER:
+#   ;; QUESTION SECTION:
+#   ;example.com.                   IN      SOA
+
+#   ;; ANSWER SECTION:
+#   example.com.            21600   IN      SOA     a.dns.example.com. root.example.com. 2009070811 7200 3600 2419200 21600
+
+#   ;; AUTHORITY SECTION:
+#   example.com.            21600   IN      NS      b.dns.example.com.
+#   example.com.            21600   IN      NS      c.dns.example.com.
+#   example.com.            21600   IN      NS      a.dns.example.com.
+#   example.com.            21600   IN      NS      e.dns.example.com.
+#   example.com.            21600   IN      NS      d.dns.example.com.
+
+#    ;; ADDITIONAL SECTION:
+#    a.dns.example.com.      21600   IN      A       1.1.1.1
+#    a.dns.example.com.      21600   IN      A       2.2.2.2
+#    b.dns.example.com.      21600   IN      A       3.3.3.3
+#    c.dns.example.com.      10800   IN      A       4.4.4.4
+#    d.dns.example.com.      43200   IN      A       5.5.5.5
+#    e.dns.example.com.      21600   IN      A       7.7.7.7
+#    e.dns.example.com.      21600   IN      A       6.6.6.6
+
+0513 8100
+0001 0001 0005 0007
+#(7) e x  a  m  p  l  e (3) c  o  m  .
+ 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+0006 0001
+# same name, fully compressed
+c0 0c
+# SOA IN  TTL=6h   RDLENGTH=35 rdata
+0006 0001 00005460 0023 01 61 03 64 6e 73 c0 0c 04 72 6f 6f 74 c0 0c 77 bf fc db 00 00 1c 20 00 00 0e 10 00 24 ea 00 00 00 54 60
+#Authority section begin
+c0 0c
+# NS IN   TTL=6h   RDLENGTH=4  b.dns.example.com.
+0002 0001 00005460 0004 01 62 c0 2b
+# NS IN   TTL=6h  c.dns.example.com.
+c0 0c
+0002 0001 00005460 00 04 01 63 c0 2b
+# NS IN a.dns.example.com.
+c0 0c
+0002 0001 00005460 00 02 c0 29
+# NS IN e.dns.example.com.
+c0 0c
+0002 0001 00005460 0004 01 65 c0 2b
+# NS IN d.dns.example.com.
+c0 0c
+0002 0001 00005460 0004 01 64 c0 2b
+# additional section begin
+# a.dns.example.com. A
+c0 29
+0001 0001 00005460 0004 01 01 01 01
+# a.dns.example.com. A
+c0 29
+0001 0001 00005460 0004 02 02 02 02
+#b.dns.example.com.  A
+c0 58
+0001 0001 00002A30 0004 03 03 03 03
+#c.dns.example.com.  A
+c0 68
+0001 0001 00005460 0004 04 04 04 04
+# d.dns.example.com. A
+c0 96
+0001 0001 0000A8C0 0004 05 05 05 05
+# e.dns.example.com. A
+c0 86
+0001 0001 00005460 0004 07 07 07 07
+# e.dns.example.com. A
+c0 86
+0001 0001 00005460 0004 06 06 06 06

+ 36 - 0
src/lib/cache/tests/testdata/message_fromWire5

@@ -0,0 +1,36 @@
+#
+# A simple DNS response message
+# ID = 0x07b2
+# QR=1 (response), Opcode=0, AA=1, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=2, other COUNTS=0
+# Question: a.example.net. IN A
+# Answer:
+#    ANSWER SECTION:
+#    a.example.com.          21600   IN      CNAME   cname.example.com.
+#    cname.example.com.      21600   IN      A       1.1.1.1
+#
+#    AUTHORITY SECTION:
+#    example.com.            21600   IN      NS      a.dns.example.com.
+#
+#    ADDITIONAL SECTION:
+#    a.dns.example.com.      21600   IN      A       1.1.1.1
+#
+07b2 8500
+0001 0002 0001 0001
+#(1) a (7)  e  x  a  m  p  l  e  (3) c o  m  .
+ 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# A  IN
+0001 0001
+#
+c0 0c
+#CNAME IN  TTL     RDATA_LEN
+0005 0001 00005460 0008 05 63 6e 61 6d 65 c0 0e
+#
+c0 2b
+0001 0001 00005460 0004 01 01 01 01
+#
+c0 0e
+0002 0001 00005460 0008 01 61 03 64 6e 73 c0 0e
+#
+c0 4f
+0001 0001 00005460 0004 01 01 01 01

+ 40 - 0
src/lib/cache/tests/testdata/message_fromWire6

@@ -0,0 +1,40 @@
+#
+# A simple DNS response message
+# ID = 0x005e
+# QR=1 (response), Opcode=0, AA=1, RD=1 (other fields are 0)
+# QDCOUNT=1, ANCOUNT=2, other COUNTS=0
+# Question: a.d.example.net. IN A
+# Answer:
+#    ;; ANSWER SECTION:
+#    d.example.com.          21600   IN      DNAME   dname.example.com.
+#    a.d.example.com.        21600   IN      CNAME   a.dname.example.com.
+#    a.dname.example.com.    21600   IN      A       1.1.1.1
+#
+#    ;; AUTHORITY SECTION:
+#    example.com.            21600   IN      NS      a.dns.example.com.
+#
+#    ;; ADDITIONAL SECTION:
+#    a.dns.example.com.      21600   IN      A       1.1.1.1
+#
+#
+005e 8500
+0001 0003 0001 0001
+#(1)a (1) b (7) e  x  a  m  p  l  e (3) c  o  m  .
+ 01 61 01 64 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# A  IN
+0001 0001
+#
+c0 0e
+0027 0001 00005460 0013 05 64 6e 61 6d 65 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
+# 
+c0 0c
+0005 0001 00005460 0004 01 61 c0 2d
+#
+c0 4c
+0001 0001 00005460 0004 01 01 01 01
+#
+c0 33
+0002 0001 00005460 0008 01 61 03 64 6e 73 c0 33
+#
+c0 6c
+0001 0001 00005460 0004 01 01 01 01