Browse Source

[2096] Test decoding

Provide three more decoders of the data, using the RdataReader. This
does not link, as the reader has no bodies of the methods.
Michal 'vorner' Vaner 12 years ago
parent
commit
256771158c

+ 5 - 1
src/lib/datasrc/memory/rdata_reader.h

@@ -138,7 +138,11 @@ public:
         /// \brief The domain label.
         ///
         /// This holds the domain label. It is only valid if type() == NAME.
-        const dns::LabelSequence& sequence;
+        const dns::LabelSequence& label() const;
+        /// \brief Is the name in label() compressible?
+        ///
+        /// This is valid only if type() == NAME.
+        bool compressible() const;
         /// \brief If there are data returned.
         ///
         /// This returns if there are any data at all returned. This is

+ 99 - 14
src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc

@@ -30,6 +30,7 @@
 
 #include <datasrc/memory/rdata_encoder.h>
 #include <datasrc/memory/rdata_field.h>
+#include <datasrc/memory/rdata_reader.h>
 
 #include <util/unittests/wiredata.h>
 
@@ -102,7 +103,7 @@ const TestRdata test_rdata_list[] = {
 // from encoded representation of each RDATA.
 void
 renderNameField(MessageRenderer* renderer, bool additional_required,
-                const LabelSequence& labels, RdataNameAttributes attributes)
+                const LabelSequence& labels, unsigned attributes)
 {
     EXPECT_EQ(additional_required,
               (attributes & NAMEATTR_ADDITIONAL) != 0);
@@ -169,6 +170,21 @@ public:
 // constant.
 const Name dummy_name2("example.com");
 
+bool
+additionalRequired(const RRType& type) {
+    // The set of RR types that require additional section processing.
+    // We'll pass it to renderNameField to check the stored attribute matches
+    // our expectation.
+    static std::set<RRType> need_additionals;
+    if (need_additionals.empty()) {
+        need_additionals.insert(RRType::NS());
+        need_additionals.insert(RRType::MX());
+        need_additionals.insert(RRType::SRV());
+    }
+
+    return (need_additionals.find(type) != need_additionals.end());
+}
+
 // A decoder that does not use RdataReader. Not recommended for use,
 // but it allows the tests to check the internals of the data.
 class ManualDecoderStyle {
@@ -282,22 +298,11 @@ public:
                                 encoded_data.end());
         }
 
-        // The set of RR types that require additional section processing.
-        // We'll pass it to renderNameField to check the stored attribute matches
-        // our expectation.
-        std::set<RRType> need_additionals;
-        need_additionals.insert(RRType::NS());
-        need_additionals.insert(RRType::MX());
-        need_additionals.insert(RRType::SRV());
-
-        const bool additional_required =
-            (need_additionals.find(rrtype) != need_additionals.end());
-
         // Create wire-format data from the encoded data
         foreachRdataField(rrclass, rrtype, rdata_count, encoded_data,
                           varlen_list,
                           boost::bind(renderNameField, &renderer,
-                                      additional_required, _1, _2),
+                                      additionalRequired(rrtype), _1, _2),
                           boost::bind(renderDataField, &renderer, _1, _2));
 
     // 2nd dummy name
@@ -308,7 +313,87 @@ public:
     }
 };
 
-typedef ::testing::Types<ManualDecoderStyle> DecoderStyles;
+// Decode using reader with the return value of next
+class NextDecoder {
+public:
+    static void decode(const isc::dns::RRClass& rrclass,
+                       const isc::dns::RRType& rrtype,
+                       size_t, size_t, size_t,
+                       const vector<uint8_t>& encoded_data,
+                       MessageRenderer& renderer)
+    {
+        RDataReader reader(rrclass, rrtype, encoded_data.size(),
+                           &encoded_data[0]);
+        RDataReader::Result field;
+        while (field = reader.next()) {
+            switch (field.type()) {
+                case RDataReader::DATA:
+                    renderer.writeData(field.data(), field.size());
+                    break;
+                case RDataReader::NAME:
+                    renderer.writeName(field.label(), field.compressible());
+                    break;
+                default:
+                    FAIL();
+            }
+        }
+
+        renderer.writeName(dummy_name2);
+
+        while (field = reader.nextSig()) {
+            switch (field.type()) {
+                case RDataReader::DATA:
+                    renderer.writeData(field.data(), field.size());
+                    break;
+                default: // There are also no NAME fields in RRSigs
+                    FAIL();
+            }
+        }
+    }
+};
+
+// Check using callbacks and calling next until the end.
+class CallbackDecoder {
+public:
+    static void decode(const isc::dns::RRClass& rrclass,
+                       const isc::dns::RRType& rrtype,
+                       size_t, size_t, size_t,
+                       const vector<uint8_t>& encoded_data,
+                       MessageRenderer& renderer)
+    {
+        RDataReader reader(rrclass, rrtype, encoded_data.size(),
+                           &encoded_data[0],
+                           boost::bind(renderNameField, &renderer,
+                                       additionalRequired(rrtype), _1, _2),
+                           boost::bind(renderDataField, &renderer, _1, _2));
+        while (reader.next()) { }
+        renderer.writeName(dummy_name2);
+        while (reader.nextSig()) { }
+    }
+};
+
+// Check using callbacks and calling iterate.
+class IterateDecoder {
+public:
+    static void decode(const isc::dns::RRClass& rrclass,
+                       const isc::dns::RRType& rrtype,
+                       size_t, size_t, size_t,
+                       const vector<uint8_t>& encoded_data,
+                       MessageRenderer& renderer)
+    {
+        RDataReader reader(rrclass, rrtype, encoded_data.size(),
+                           &encoded_data[0],
+                           boost::bind(renderNameField, &renderer,
+                                       additionalRequired(rrtype), _1, _2),
+                           boost::bind(renderDataField, &renderer, _1, _2));
+        reader.iterate();
+        renderer.writeName(dummy_name2);
+        reader.iterateSig();
+    }
+};
+
+typedef ::testing::Types<ManualDecoderStyle, NextDecoder, CallbackDecoder,
+                         IterateDecoder> DecoderStyles;
 TYPED_TEST_CASE(RdataEncodeDecodeTest, DecoderStyles);
 
 void