Browse Source

[2094] complete test cases. added a couple of RR types.

JINMEI Tatuya 12 years ago
parent
commit
73d54f8cb7

+ 93 - 12
src/lib/datasrc/memory/rdata_encoder.cc

@@ -12,14 +12,22 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
+#include <dns/name.h>
+#include <dns/labelsequence.h>
+#include <dns/rdata.h>
 #include <dns/rrclass.h>
 #include <dns/rrclass.h>
 #include <dns/rrtype.h>
 #include <dns/rrtype.h>
 
 
+#include <util/buffer.h>        // for test functions
+
 #include "rdata_encoder.h"
 #include "rdata_encoder.h"
 
 
+#include <vector>
+
 #include <stdint.h>
 #include <stdint.h>
 
 
 using namespace isc::dns;
 using namespace isc::dns;
+using std::vector;
 
 
 namespace isc {
 namespace isc {
 namespace datasrc {
 namespace datasrc {
@@ -63,22 +71,34 @@ const uint16_t NAMEATTR_ADDITIONAL_INITIALIZER =
 const uint16_t NAMEATTR_COMPADDITIONAL_INITIALIZER =
 const uint16_t NAMEATTR_COMPADDITIONAL_INITIALIZER =
     static_cast<uint16_t>(NAMEATTR_COMPRESSIBLE | NAMEATTR_ADDITIONAL);
     static_cast<uint16_t>(NAMEATTR_COMPRESSIBLE | NAMEATTR_ADDITIONAL);
 
 
+// TBD
 const RdataFieldSpec generic_data_fields[] = {
 const RdataFieldSpec generic_data_fields[] = {
     {RdataFieldSpec::VARLEN_DATA, {0}}
     {RdataFieldSpec::VARLEN_DATA, {0}}
 };
 };
 const uint16_t generic_data_fields_count =
 const uint16_t generic_data_fields_count =
     sizeof(generic_data_fields) / sizeof(RdataFieldSpec);
     sizeof(generic_data_fields) / sizeof(RdataFieldSpec);
 
 
+// TBD
+const RdataFieldSpec single_ipv4_fields[] = {
+    {RdataFieldSpec::FIXEDLEN_DATA, {sizeof(uint32_t)}}
+};
+const uint16_t single_ipv4_fields_count =
+    sizeof(single_ipv4_fields) / sizeof(RdataFieldSpec);
+
+// TBD
 const RdataFieldSpec generic_single_name_fields[] = {
 const RdataFieldSpec generic_single_name_fields[] = {
-    {RdataFieldSpec::VARLEN_DATA, {NAMEATTR_COMPADDITIONAL_INITIALIZER}}
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_COMPADDITIONAL_INITIALIZER}}
 };
 };
+const uint16_t generic_single_name_fields_count =
+    sizeof(generic_single_name_fields) / sizeof(RdataFieldSpec);
 
 
 // Class IN encode specs
 // Class IN encode specs
 const RdataEncodeSpec encode_spec_list_in[] = {
 const RdataEncodeSpec encode_spec_list_in[] = {
-    {generic_data_fields_count, 0, 0, generic_data_fields} // type #0
+    {generic_data_fields_count, 0, 0, generic_data_fields}, // #0
+    {single_ipv4_fields_count, 0, 0, single_ipv4_fields},   // #1: A
+    {generic_single_name_fields_count, 0, 0, generic_single_name_fields} // NS
 };
 };
 
 
-#ifdef notyet
 inline
 inline
 const RdataEncodeSpec&
 const RdataEncodeSpec&
 getRdataEncodeSpec(RRClass rrclass, RRType rrtype) {
 getRdataEncodeSpec(RRClass rrclass, RRType rrtype) {
@@ -87,23 +107,84 @@ getRdataEncodeSpec(RRClass rrclass, RRType rrtype) {
     }
     }
     return (encode_spec_list_in[0]);
     return (encode_spec_list_in[0]);
 }
 }
-#endif
 } // end of unnamed namespace
 } // end of unnamed namespace
 
 
-#ifdef notyet
 void
 void
-testRdataEncoder(const Rdata& rdata, RRClass rrclass, RRType rrtype,
-                 vector<uint8_t>& result)
+encodeRdata(const rdata::Rdata& rdata, RRClass rrclass, RRType rrtype,
+            vector<uint8_t>& data_result, vector<uint16_t>& /*len_result*/)
 {
 {
+    util::OutputBuffer buffer(0);
+    rdata.toWire(buffer);
+    util::InputBuffer ibuffer(buffer.getData(), buffer.getLength());
+    vector<uint8_t> tmp;        // used as temporary placeholder below
+
     const RdataEncodeSpec& encode_spec = getRdataEncodeSpec(rrclass, rrtype);
     const RdataEncodeSpec& encode_spec = getRdataEncodeSpec(rrclass, rrtype);
     for (size_t i = 0; i < encode_spec.field_count; ++i) {
     for (size_t i = 0; i < encode_spec.field_count; ++i) {
-        const RdataFieldSpec& field_spec = *encode_spec.fields[i];
-        if (field_spec.type == RdataFieldSpec::FIXEDLEN_DATA)
-        assert(encode_spec.fields[i] != NULL);
-        
+        const RdataFieldSpec& field_spec = encode_spec.fields[i];
+        switch (field_spec.type) {
+        case RdataFieldSpec::FIXEDLEN_DATA:
+            tmp.resize(field_spec.fixeddata_len);
+            ibuffer.readData(&tmp[0], tmp.size());
+            data_result.insert(data_result.end(), tmp.begin(), tmp.end());
+            break;
+        case RdataFieldSpec::DOMAIN_NAME:
+        {
+            const Name name(ibuffer);
+            const LabelSequence labels(name);
+            size_t nlen;
+            const uint8_t* ndata = labels.getData(&nlen);
+            size_t olen;
+            uint8_t offset_holder[Name::MAX_LABELS];
+            labels.getOffsetData(&olen, offset_holder);
+            data_result.push_back(nlen);
+            data_result.push_back(olen);
+            data_result.insert(data_result.end(), ndata, ndata + nlen);
+            data_result.insert(data_result.end(), offset_holder,
+                               offset_holder + olen);
+            break;
+        }
+        default:
+            assert(false);
+        }
+    }
+}
+
+void
+foreachRdataField(RRClass rrclass, RRType rrtype,
+                  const vector<uint8_t>& encoded_data,
+                  const vector<uint16_t>& /*varlen_list*/,
+                  NameCallback name_callback, DataCallback data_callback)
+{
+    const RdataEncodeSpec& encode_spec = getRdataEncodeSpec(rrclass, rrtype);
+
+    size_t off = 0;
+    for (size_t i = 0; i < encode_spec.field_count; ++i) {
+        const RdataFieldSpec& field_spec = encode_spec.fields[i];
+        switch (field_spec.type) {
+        case RdataFieldSpec::FIXEDLEN_DATA:
+            if (data_callback) {
+                data_callback(&encoded_data[off], field_spec.fixeddata_len);
+            }
+            off += field_spec.fixeddata_len;
+            break;
+        case RdataFieldSpec::DOMAIN_NAME:
+        {
+            const uint8_t nlen = encoded_data.at(off);
+            const uint8_t olen = encoded_data.at(off + 1);
+            if (name_callback) {
+                const uint8_t* ndata = &encoded_data.at(off + 2);
+                const uint8_t* odata = &encoded_data.at(off + 2 + nlen);
+                name_callback(LabelSequence(ndata, odata, olen),
+                              field_spec.name_attributes);
+            }
+            off += (2 + nlen + olen);
+            break;
+        }
+        default:
+            assert(false);
+        }
     }
     }
 }
 }
-#endif
 
 
 } // namespace memory
 } // namespace memory
 } // namespace datasrc
 } // namespace datasrc

+ 22 - 0
src/lib/datasrc/memory/rdata_encoder.h

@@ -15,6 +15,15 @@
 #ifndef DATASRC_MEMORY_RDATA_ENCODER_H
 #ifndef DATASRC_MEMORY_RDATA_ENCODER_H
 #define DATASRC_MEMORY_RDATA_ENCODER_H 1
 #define DATASRC_MEMORY_RDATA_ENCODER_H 1
 
 
+#include <dns/labelsequence.h>
+#include <dns/rdata.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <boost/function.hpp>
+
+#include <vector>
+
 namespace isc {
 namespace isc {
 namespace datasrc {
 namespace datasrc {
 namespace memory {
 namespace memory {
@@ -24,6 +33,19 @@ enum RdataNameAttributes {
     NAMEATTR_ADDITIONAL = (NAMEATTR_COMPRESSIBLE << 1)
     NAMEATTR_ADDITIONAL = (NAMEATTR_COMPRESSIBLE << 1)
 };
 };
 
 
+void encodeRdata(const dns::rdata::Rdata& rdata, dns::RRClass rrclass,
+                 dns::RRType rrtype, std::vector<uint8_t>& data_result,
+                 std::vector<uint16_t>& len_result);
+
+typedef boost::function<void(const dns::LabelSequence&,
+                             RdataNameAttributes)> NameCallback;
+typedef boost::function<void(const uint8_t*, size_t)> DataCallback;
+
+void foreachRdataField(dns::RRClass rrclass, dns::RRType rrtype,
+                       const std::vector<uint8_t>& encoded_data,
+                       const std::vector<uint16_t>& varlen_list,
+                       NameCallback name_callback, DataCallback data_callback);
+
 } // namespace memory
 } // namespace memory
 } // namespace datasrc
 } // namespace datasrc
 } // namespace isc
 } // namespace isc

+ 87 - 5
src/lib/datasrc/memory/tests/rdata_encoder_unittest.cc

@@ -12,20 +12,102 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
+#include <dns/name.h>
+#include <dns/labelsequence.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
 #include <datasrc/memory/rdata_encoder.h>
 #include <datasrc/memory/rdata_encoder.h>
 
 
+#include <util/unittests/wiredata.h>
+
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 
 
+#include <boost/bind.hpp>
+
+#include <set>
+#include <string>
+#include <vector>
+
+using namespace isc::dns;
+using namespace isc::dns::rdata;
 using namespace isc::datasrc::memory;
 using namespace isc::datasrc::memory;
 
 
+using isc::util::unittests::matchWireData;
+using std::string;
+using std::vector;
+
 namespace {
 namespace {
-class RdataEncoderTest : public ::testing::Test {
-protected:
-    RdataEncoderTest() {}
+struct TestRdata {
+    const char* const rrclass;
+    const char* const rrtype;
+    const char* const rdata;
 };
 };
+const TestRdata test_rdata_list[] = {
+    {"IN", "A", "192.0.2.1"},
+    {"IN", "NS", "ns.example.com"},
+    {NULL, NULL, NULL}
+};
+
+void
+renderNameField(MessageRenderer* renderer, bool additional_required,
+                const LabelSequence& labels, RdataNameAttributes attributes)
+{
+    EXPECT_EQ(additional_required,
+              (attributes & NAMEATTR_ADDITIONAL) != 0);
+    renderer->writeName(labels, (attributes & NAMEATTR_COMPRESSIBLE) != 0);
+}
+
+void
+renderDataField(MessageRenderer* renderer, const uint8_t* data,
+                size_t data_len)
+{
+    renderer->writeData(data, data_len);
+}
+
+TEST(RdataFieldSpec, checkData) {
+    const Name dummy_name("example.com");
+    MessageRenderer expected_renderer, actual_renderer;
+    vector<uint8_t> encoded_data;
+    vector<uint16_t> varlen_list;
+
+    std::set<RRType> need_additionals;
+    need_additionals.insert(RRType::NS());
+    need_additionals.insert(RRType::MX());
+    need_additionals.insert(RRType::SRV());
+
+    for (size_t i = 1; test_rdata_list[i].rrclass != NULL; ++i) {
+        SCOPED_TRACE(string(test_rdata_list->rrclass) + "/" +
+                     test_rdata_list->rrtype);
+
+        expected_renderer.clear();
+        actual_renderer.clear();
+        expected_renderer.writeName(dummy_name);
+        actual_renderer.writeName(dummy_name);
+
+        const RRClass rrclass(test_rdata_list[i].rrclass);
+        const RRType rrtype(test_rdata_list[i].rrtype);
+        const ConstRdataPtr rdata = createRdata(rrtype, rrclass,
+                                                test_rdata_list[i].rdata);
+        rdata->toWire(expected_renderer);
+
+        const bool additional_required =
+            (need_additionals.find(rrtype) != need_additionals.end());
+
+        encodeRdata(*rdata, rrclass, rrtype, encoded_data, varlen_list);
+        foreachRdataField(rrclass, rrtype, encoded_data, varlen_list,
+                          boost::bind(renderNameField, &actual_renderer,
+                                      additional_required, _1, _2),
+                          boost::bind(renderDataField, &actual_renderer,
+                                      _1, _2));
 
 
-TEST_F(RdataEncoderTest, test1) {
-    EXPECT_NE(NAMEATTR_COMPRESSIBLE, NAMEATTR_ADDITIONAL);
+        matchWireData(expected_renderer.getData(),
+                      expected_renderer.getLength(),
+                      actual_renderer.getData(),
+                      actual_renderer.getLength());
+    }
 }
 }
 
 
 }
 }