BIND 10 master, updated. df5d7b6c42ea160ddc0ba30af632cc092d3b9f07 [master] Merge branch 'trac2094'

BIND 10 source code commits bind10-changes at lists.isc.org
Mon Jul 23 17:24:06 UTC 2012


The branch, master has been updated
       via  df5d7b6c42ea160ddc0ba30af632cc092d3b9f07 (commit)
       via  e6d33997df8c251b29a0cb6d574b9fcd3791f66f (commit)
       via  3df27b54faaac4ba46116b4820aa5ceb3563fb31 (commit)
       via  af5673b049f1d31ccacda2652e824588d0da7262 (commit)
       via  1d950e29cae11777bc459fcb930acd0a10d0be11 (commit)
       via  2cc12f1554c816f6da1a5802e17a5bf6fd13c1f5 (commit)
       via  a47e80cd13b156f8e3f04e044bc11e8789392136 (commit)
       via  04698fa05e0944068aa171762a1ae117f547ee60 (commit)
       via  fc772a408baf60d2fa4b53e370c7cc8cb1c59e9f (commit)
       via  2d291f69d89c4b966776124a8bddc1b77d2ae48f (commit)
       via  5e84742d029495596793b806b40e4a272d2c2a22 (commit)
       via  f2b0b4fd969eeb08158d370daadd4607ec4dd11f (commit)
       via  7e1561912cd9c52694558f6b4ffc67bee5b8d31b (commit)
       via  eec907bdcb0e3d1ca8164edfbd78019c76f7e226 (commit)
       via  73d54f8cb72bbefe66ec44ed3d5d4a6417e25332 (commit)
       via  220170cd0ea975cf86174d5bea6b256c814e27e0 (commit)
       via  69d485056646364cfa661b0b2e6f465b7710687d (commit)
       via  49a8bcbf81bbb4feafc569793797b5ce3d5fbfce (commit)
       via  02e3688018188f871ca2f40e46fa185cc917cfe9 (commit)
      from  7f881cb954516c9f0b146c4f3bf35b296b102c4a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit df5d7b6c42ea160ddc0ba30af632cc092d3b9f07
Merge: 7f881cb e6d3399
Author: JINMEI Tatuya <jinmei at isc.org>
Date:   Mon Jul 23 10:07:37 2012 -0700

    [master] Merge branch 'trac2094'

-----------------------------------------------------------------------

Summary of changes:
 configure.ac                                       |    2 +
 src/lib/datasrc/Makefile.am                        |    3 +-
 src/lib/datasrc/memory/Makefile.am                 |   12 +
 src/lib/datasrc/memory/rdata_encoder.cc            |  383 ++++++++++++++++++++
 src/lib/datasrc/memory/rdata_encoder.h             |   88 +++++
 .../{bench => datasrc/memory}/tests/Makefile.am    |   21 +-
 .../datasrc/memory/tests/rdata_encoder_unittest.cc |  172 +++++++++
 .../memory}/tests/run_unittests.cc                 |    2 +-
 src/lib/dns/labelsequence.h                        |   34 +-
 src/lib/dns/rdata/generic/dname_39.cc              |    4 +-
 src/lib/dns/rdata/generic/naptr_35.cc              |    5 +
 src/lib/dns/rdata/generic/naptr_35.h               |    2 -
 src/lib/dns/rdata/generic/nsec_47.cc               |    4 +-
 src/lib/dns/tests/rdata_dname_unittest.cc          |    8 +-
 src/lib/util/unittests/Makefile.am                 |    1 +
 src/lib/util/unittests/fork.h                      |    4 +-
 src/lib/util/unittests/newhook.h                   |    4 +-
 src/lib/util/unittests/testdata.h                  |    4 +-
 src/lib/util/unittests/textdata.h                  |    4 +-
 src/lib/util/unittests/wiredata.cc                 |   52 +++
 src/lib/util/unittests/{resource.h => wiredata.h}  |   34 +-
 21 files changed, 786 insertions(+), 57 deletions(-)
 create mode 100644 src/lib/datasrc/memory/Makefile.am
 create mode 100644 src/lib/datasrc/memory/rdata_encoder.cc
 create mode 100644 src/lib/datasrc/memory/rdata_encoder.h
 copy src/lib/{bench => datasrc/memory}/tests/Makefile.am (58%)
 create mode 100644 src/lib/datasrc/memory/tests/rdata_encoder_unittest.cc
 copy src/lib/{cryptolink => datasrc/memory}/tests/run_unittests.cc (93%)
 create mode 100644 src/lib/util/unittests/wiredata.cc
 copy src/lib/util/unittests/{resource.h => wiredata.h} (56%)

-----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index af350a8..352c5c9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1101,6 +1101,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/exceptions/Makefile
                  src/lib/exceptions/tests/Makefile
                  src/lib/datasrc/Makefile
+                 src/lib/datasrc/memory/Makefile
+                 src/lib/datasrc/memory/tests/Makefile
                  src/lib/datasrc/tests/Makefile
                  src/lib/datasrc/tests/testdata/Makefile
                  src/lib/xfr/Makefile
diff --git a/src/lib/datasrc/Makefile.am b/src/lib/datasrc/Makefile.am
index 5359c09..defc7ac 100644
--- a/src/lib/datasrc/Makefile.am
+++ b/src/lib/datasrc/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = . tests
+SUBDIRS = memory . tests
 
 AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
@@ -64,6 +64,7 @@ libdatasrc_la_LIBADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
 libdatasrc_la_LIBADD += $(top_builddir)/src/lib/dns/libdns++.la
 libdatasrc_la_LIBADD += $(top_builddir)/src/lib/log/liblog.la
 libdatasrc_la_LIBADD += $(top_builddir)/src/lib/cc/libcc.la
+libdatasrc_la_LIBADD += memory/libdatasrc_memory.la # convenience library
 libdatasrc_la_LIBADD += $(SQLITE_LIBS)
 
 BUILT_SOURCES = datasrc_config.h datasrc_messages.h datasrc_messages.cc
diff --git a/src/lib/datasrc/memory/Makefile.am b/src/lib/datasrc/memory/Makefile.am
new file mode 100644
index 0000000..0b061b6
--- /dev/null
+++ b/src/lib/datasrc/memory/Makefile.am
@@ -0,0 +1,12 @@
+SUBDIRS = . tests
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+CLEANFILES = *.gcno *.gcda datasrc_messages.h datasrc_messages.cc
+
+noinst_LTLIBRARIES = libdatasrc_memory.la
+libdatasrc_memory_la_SOURCES = rdata_encoder.h rdata_encoder.cc
diff --git a/src/lib/datasrc/memory/rdata_encoder.cc b/src/lib/datasrc/memory/rdata_encoder.cc
new file mode 100644
index 0000000..6a32ce9
--- /dev/null
+++ b/src/lib/datasrc/memory/rdata_encoder.cc
@@ -0,0 +1,383 @@
+// Copyright (C) 2012  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.
+
+#include <dns/name.h>
+#include <dns/labelsequence.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>     // for a test function
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <util/buffer.h>        // for test functions
+
+#include "rdata_encoder.h"
+
+#include <boost/static_assert.hpp>
+
+#include <cassert>
+#include <vector>
+
+#include <stdint.h>
+
+using namespace isc::dns;
+using std::vector;
+
+namespace isc {
+namespace datasrc {
+namespace memory {
+
+namespace {
+/// Specification of a single RDATA field in terms of internal encoding.
+struct RdataFieldSpec {
+    enum FieldType {
+        FIXEDLEN_DATA = 0,      // fixed-length data field
+        VARLEN_DATA,            // variable-length data field
+        DOMAIN_NAME             // domain name
+    };
+
+    const FieldType type;       // field type
+
+    // type specific data.  We use a union so it'll be clear only one of them
+    // (determined by the type) is valid.  Since we want to make it as
+    // lightweight as possible, we use a relatively lower-level primitives
+    // here.
+    union {
+        // The length of fixed-length data field.  Only valid for FIXEDLEN_DATA
+        const uint16_t fixeddata_len;
+
+        // Attributes of the name.  Only valid for DOMAIN_NAME.
+        const RdataNameAttributes name_attributes;
+    };
+};
+
+/// Specification of RDATA in terms of internal encoding.
+struct RdataEncodeSpec {
+    const uint16_t field_count; // total number of fields (# of fields member)
+    const uint16_t name_count;  // number of domain name fields
+    const uint16_t varlen_count; // number of variable-length data fields
+    const RdataFieldSpec* const fields; // list of field specs
+};
+
+// These constants are convenient shortcut to initialize the name_attributes
+// member of RdataFieldSpec (since it's a union, we can only directly
+// initialize fixeddata_len member, so we need to convert it to its type).
+// These are essentially small integers, so the cast should be safe.
+const uint16_t NAMEATTR_NOATTRIBUTE_INITIALIZER = static_cast<uint16_t>(0);
+const uint16_t NAMEATTR_COMPRESSIBLE_INITIALIZER =
+    static_cast<uint16_t>(NAMEATTR_COMPRESSIBLE);
+const uint16_t NAMEATTR_ADDITIONAL_INITIALIZER =
+    static_cast<uint16_t>(NAMEATTR_ADDITIONAL);
+const uint16_t NAMEATTR_COMPADDITIONAL_INITIALIZER =
+    static_cast<uint16_t>(NAMEATTR_COMPRESSIBLE | NAMEATTR_ADDITIONAL);
+
+// Many types of RDATA can be treated as a single-field, variable length
+// field (in terms of our encoding).  The following define such most general
+// form of field spec.
+const RdataFieldSpec generic_data_fields[] = {
+    {RdataFieldSpec::VARLEN_DATA, {0}}
+};
+const uint16_t n_generic_data_fields =
+    sizeof(generic_data_fields) / sizeof(RdataFieldSpec);
+const RdataEncodeSpec generic_data_spec = {
+    n_generic_data_fields, 0, 1, generic_data_fields
+};
+
+// RDATA consist of a single IPv4 address field.
+const RdataFieldSpec single_ipv4_fields[] = {
+    {RdataFieldSpec::FIXEDLEN_DATA, {sizeof(uint32_t)}}
+};
+const uint16_t n_ipv4_fields =
+    sizeof(single_ipv4_fields) / sizeof(RdataFieldSpec);
+
+// RDATA consist of a single IPv6 address field.
+const RdataFieldSpec single_ipv6_fields[] = {
+    {RdataFieldSpec::FIXEDLEN_DATA, {16}} // 128bits = 16 bytes
+};
+const uint16_t n_ipv6_fields =
+    sizeof(single_ipv6_fields) / sizeof(RdataFieldSpec);
+
+// There are several RR types that consist of a single domain name.
+const RdataFieldSpec single_noattr_name_fields[] = {
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_NOATTRIBUTE_INITIALIZER}}
+};
+const RdataFieldSpec single_compressible_name_fields[] = {
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_COMPRESSIBLE_INITIALIZER}}
+};
+const RdataFieldSpec single_compadditional_name_fields[] = {
+    {RdataFieldSpec::DOMAIN_NAME,
+     {NAMEATTR_COMPRESSIBLE_INITIALIZER|NAMEATTR_COMPADDITIONAL_INITIALIZER}}
+};
+const uint16_t n_single_name_fields =
+    sizeof(single_noattr_name_fields) / sizeof(RdataFieldSpec);
+
+// RDATA consisting of two names.  There are some of this type.
+const RdataFieldSpec double_compressible_name_fields[] = {
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_COMPRESSIBLE_INITIALIZER}},
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_COMPRESSIBLE_INITIALIZER}}
+};
+const RdataFieldSpec double_noattr_name_fields[] = {
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_NOATTRIBUTE_INITIALIZER}},
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_NOATTRIBUTE_INITIALIZER}}
+};
+const uint16_t n_double_name_fields =
+    sizeof(double_compressible_name_fields) / sizeof(RdataFieldSpec);
+
+// SOA specific: two compressible names + 5*32-bit data
+const RdataFieldSpec soa_fields[] = {
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_COMPRESSIBLE_INITIALIZER}},
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_COMPRESSIBLE_INITIALIZER}},
+    {RdataFieldSpec::FIXEDLEN_DATA, {sizeof(uint32_t) * 5}}
+};
+const uint16_t n_soa_fields = sizeof(soa_fields) / sizeof(RdataFieldSpec);
+
+// MX specific: 16-bit data + compressible/additional name
+const RdataFieldSpec mx_fields[] = {
+    {RdataFieldSpec::FIXEDLEN_DATA, {sizeof(uint16_t)}},
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_COMPADDITIONAL_INITIALIZER}}
+};
+const uint16_t n_mx_fields = sizeof(mx_fields) / sizeof(RdataFieldSpec);
+
+// AFSDB specific: 16-bit data + no-attribute name
+const RdataFieldSpec afsdb_fields[] = {
+    {RdataFieldSpec::FIXEDLEN_DATA, {sizeof(uint16_t)}},
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_NOATTRIBUTE_INITIALIZER}}
+};
+const uint16_t n_afsdb_fields = sizeof(afsdb_fields) / sizeof(RdataFieldSpec);
+
+// SRV specific: 3*16-bit data + additional name
+const RdataFieldSpec srv_fields[] = {
+    {RdataFieldSpec::FIXEDLEN_DATA, {sizeof(uint16_t) * 3}},
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_ADDITIONAL_INITIALIZER}}
+};
+const uint16_t n_srv_fields = sizeof(srv_fields) / sizeof(RdataFieldSpec);
+
+// NAPTR specific: (multi-field) variable data + (additional) name
+// NAPTR requires complicated additional section handling; for now, we skip
+// the additional handling completely.
+const RdataFieldSpec naptr_fields[] = {
+    {RdataFieldSpec::VARLEN_DATA, {0}},
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_NOATTRIBUTE_INITIALIZER}}
+};
+const uint16_t n_naptr_fields = sizeof(naptr_fields) / sizeof(RdataFieldSpec);
+
+// NSEC specific: no-attribute name + varlen data
+const RdataFieldSpec nsec_fields[] = {
+    {RdataFieldSpec::DOMAIN_NAME, {NAMEATTR_NOATTRIBUTE_INITIALIZER}},
+    {RdataFieldSpec::VARLEN_DATA, {0}}
+};
+const uint16_t n_nsec_fields = sizeof(nsec_fields) / sizeof(RdataFieldSpec);
+
+// Class IN encode specs.  This gives a shortcut to the encode spec for
+// some well-known types of RDATA specific to class IN (most of which are
+// generic and can be used for other classes).  The array index is the
+// RR type code.
+const RdataEncodeSpec encode_spec_list_in[] = {
+    generic_data_spec,                         // #0: (NONE)
+    {n_ipv4_fields, 0, 0, single_ipv4_fields},   // #1: A
+    {n_single_name_fields, 1, 0, single_compadditional_name_fields}, // #2: NS
+    generic_data_spec,          // #3
+    generic_data_spec,          // #4
+    {n_single_name_fields, 1, 0, single_compressible_name_fields}, // #5: CNAME
+    {n_soa_fields, 2, 0, soa_fields}, // #6: SOA
+    generic_data_spec,                // #7
+    generic_data_spec,                // #8
+    generic_data_spec,                // #9
+    generic_data_spec,                // #10
+    generic_data_spec,                // #11
+    {n_single_name_fields, 1, 0, single_compressible_name_fields}, // #12: PTR
+    generic_data_spec,          // #13: HINFO
+    {n_double_name_fields, 2, 0, double_compressible_name_fields}, // #14:HINFO
+    {n_mx_fields, 1, 0, mx_fields}, // #15: MX
+    generic_data_spec, // #16: TXT
+    {n_double_name_fields, 2, 0, double_noattr_name_fields}, // 17: RP
+    {n_afsdb_fields, 1, 0, afsdb_fields}, // #18: AFSDB
+    // #19-#26
+    generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
+    generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
+    generic_data_spec,                // #27
+    {n_ipv6_fields, 0, 0, single_ipv6_fields},   // #28: AAAA
+    // #29-#32
+    generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
+    {n_srv_fields, 1, 0, srv_fields},   // #33: SRV
+    generic_data_spec,                  // #34
+    {n_naptr_fields, 1, 1, naptr_fields}, // #35: NAPTR
+    generic_data_spec,                  // #36
+    generic_data_spec,                  // #37
+    generic_data_spec,                  // #38
+    {n_single_name_fields, 1, 0, single_noattr_name_fields}, // #39 DNAME
+    generic_data_spec,                  // #40
+    generic_data_spec,                  // #41 (OPT)
+    generic_data_spec,                  // #42
+    generic_data_spec, // #43: DS (this is opaque for encoding purposes)
+    generic_data_spec, // #44: SSHFP (this is opaque for encoding purposes)
+    generic_data_spec,                  // #45
+    generic_data_spec, // #46: RRSIG (this is opaque for encoding purposes)
+    {n_nsec_fields, 1, 1, nsec_fields} // #47: NSEC
+
+    // All others can be treated as single-field variable length data, at
+    // least for currently supported RR types.
+};
+
+// # of entries in encode_spec_list_in
+const size_t encode_spec_list_in_size =
+    sizeof(encode_spec_list_in) / sizeof(encode_spec_list_in[0]);
+BOOST_STATIC_ASSERT(encode_spec_list_in_size == 48);
+
+inline
+const RdataEncodeSpec&
+getRdataEncodeSpec(RRClass rrclass, RRType rrtype) {
+    // Special case: for classes other than IN, we treat RDATA of RR types
+    // that are class-IN specific as generic opaque data.
+    if (rrclass != RRClass::IN() &&
+        (rrtype == RRType::A() || rrtype == RRType::AAAA() ||
+         rrtype == RRType::SRV())) {
+        return (generic_data_spec);
+    }
+
+    // Otherwise, if the type is in the pre-defined range, we use the defined
+    // spec; otherwise we treat it as opaque data.
+    const uint16_t typecode = rrtype.getCode();
+    if (typecode < encode_spec_list_in_size) {
+        return (encode_spec_list_in[rrtype.getCode()]);
+    }
+    return (generic_data_spec);
+}
+
+// A temporary helper of temporary encodeRdata(): it calculates the length
+// of the data portion of a NAPTR RDATA (i.e., the RDATA fields before the
+// "replacement" name).
+size_t
+getNAPTRDataLen(const rdata::Rdata& rdata) {
+    const rdata::generic::NAPTR& naptr_rdata =
+        dynamic_cast<const rdata::generic::NAPTR&>(rdata);
+
+    util::OutputBuffer buffer(0);
+    rdata.toWire(buffer);
+    return (buffer.getLength() - naptr_rdata.getReplacement().getLength());
+}
+} // end of unnamed namespace
+
+namespace testing {
+void
+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);
+    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:
+            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::VARLEN_DATA:
+        {
+            // In the vast majority cases of our supported RR types,
+            // variable-length data fields are placed at the end of RDATA,
+            // so the length of the field should be the remaining length
+            // of the output buffer.  The only exception is NAPTR, for which
+            // we use an ad hoc workaround (remember this function is for
+            // initial testing only, and will be cleaned up eventually).
+            const size_t pos = ibuffer.getPosition();
+            const size_t data_len = rrtype == RRType::NAPTR() ?
+                getNAPTRDataLen(rdata) : (ibuffer.getLength() - pos);
+            tmp.resize(data_len);
+            ibuffer.readData(&tmp[0], tmp.size());
+            data_result.insert(data_result.end(), tmp.begin(), tmp.end());
+            len_result.push_back(data_len);
+            break;
+        }
+        case RdataFieldSpec::DOMAIN_NAME:
+        {
+            const Name name(ibuffer);
+            const LabelSequence labels(name);
+            size_t nlen;
+            const uint8_t* ndata = labels.getData(&nlen);
+            assert(nlen < 256); // nlen should fit in 8 bits
+            size_t olen;
+            uint8_t offset_holder[Name::MAX_LABELS];
+            labels.getOffsetData(&olen, offset_holder);
+            assert(olen < 256); // olen should fit in 8 bits
+            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;
+        }
+        }
+    }
+}
+
+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;
+    size_t varlen_count = 0;
+    size_t name_count = 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.at(off), field_spec.fixeddata_len);
+            }
+            off += field_spec.fixeddata_len;
+            break;
+        case RdataFieldSpec::VARLEN_DATA:
+        {
+            const size_t varlen = varlen_list.at(varlen_count);
+            if (data_callback && varlen > 0) {
+                data_callback(&encoded_data.at(off), varlen);
+            }
+            off += varlen;
+            ++varlen_count;
+            break;
+        }
+        case RdataFieldSpec::DOMAIN_NAME:
+        {
+            ++name_count;
+            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;
+        }
+        }
+    }
+
+    assert(name_count == encode_spec.name_count);
+    assert(varlen_count == encode_spec.varlen_count);
+}
+} // namespace testing
+
+} // namespace memory
+} // namespace datasrc
+} // datasrc isc
diff --git a/src/lib/datasrc/memory/rdata_encoder.h b/src/lib/datasrc/memory/rdata_encoder.h
new file mode 100644
index 0000000..39fe873
--- /dev/null
+++ b/src/lib/datasrc/memory/rdata_encoder.h
@@ -0,0 +1,88 @@
+// Copyright (C) 2012  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.
+
+#ifndef DATASRC_MEMORY_RDATA_ENCODER_H
+#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 datasrc {
+namespace memory {
+
+/// \brief Attributes of domain name fields of encoded RDATA.
+///
+/// The enum values define special traits of the name that can affect how
+/// it should be handled in rendering or query processing.
+enum RdataNameAttributes {
+    NAMEATTR_COMPRESSIBLE = 1,  ///< Name should be compressed when rendered
+    NAMEATTR_ADDITIONAL = (NAMEATTR_COMPRESSIBLE << 1) ///< Name requires
+                                                      ///< Additional section
+                                                      ///< handling
+};
+
+// We use the following quick-hack version of encoder and "foreach"
+// operator until we implement the complete versions.  The plan is to
+// update the test cases that use these functions with the complete
+// functions/classes, and then remove the entire namespace.
+namespace testing {
+// "Encode" given RDATA of given RR class and type.
+//
+// Fixed/variable-length data fields are encoded in their wire-format;
+// domain names are encoded in the form of:
+//  - nlen: name data length (1 byte)
+//  - olen: offset data length (1 byte)
+//  - name data (nlen bytes)
+//  - offset data (olen bytes)
+//
+// The encoded results are appended to data_result.
+// If the RDATA contain variable-length data fields, the lengths of the
+// these fields will be appended in len_result, in the order of appearance.
+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);
+
+// Callbacks used in foreachRdataField.
+typedef boost::function<void(const dns::LabelSequence&,
+                             RdataNameAttributes)> NameCallback;
+typedef boost::function<void(const uint8_t*, size_t)> DataCallback;
+
+// Iterate over each RDATA field (in terms of the internal encoding) stored
+// in encoded_data, and call the given callback for each data (for
+// domain name fields, name_callback will be called; for normal data fields
+// data_callback will be called).  If the encoded data contain variable-length
+// data fields, varlen_list should store a sequence of their lengths, in the
+// of the appearance.
+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 datasrc
+} // namespace isc
+
+#endif // DATASRC_MEMORY_RDATA_ENCODER_H
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/datasrc/memory/tests/Makefile.am b/src/lib/datasrc/memory/tests/Makefile.am
new file mode 100644
index 0000000..473bff5
--- /dev/null
+++ b/src/lib/datasrc/memory/tests/Makefile.am
@@ -0,0 +1,33 @@
+AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
+AM_CPPFLAGS += -I$(top_builddir)/src/lib/dns -I$(top_srcdir)/src/lib/dns
+AM_CPPFLAGS += $(BOOST_INCLUDES)
+
+AM_CXXFLAGS = $(B10_CXXFLAGS)
+
+if USE_STATIC_LINK
+AM_LDFLAGS = -static
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+TESTS_ENVIRONMENT = \
+	$(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
+
+TESTS =
+if HAVE_GTEST
+TESTS += run_unittests
+
+run_unittests_SOURCES = run_unittests.cc
+run_unittests_SOURCES += rdata_encoder_unittest.cc
+
+run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
+run_unittests_LDFLAGS  = $(AM_LDFLAGS)  $(GTEST_LDFLAGS)
+
+run_unittests_LDADD = $(builddir)/../libdatasrc_memory.la
+run_unittests_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
+run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
+run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
+run_unittests_LDADD += $(GTEST_LDADD)
+endif
+
+noinst_PROGRAMS = $(TESTS)
diff --git a/src/lib/datasrc/memory/tests/rdata_encoder_unittest.cc b/src/lib/datasrc/memory/tests/rdata_encoder_unittest.cc
new file mode 100644
index 0000000..33c09af
--- /dev/null
+++ b/src/lib/datasrc/memory/tests/rdata_encoder_unittest.cc
@@ -0,0 +1,172 @@
+// Copyright (C) 2012  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.
+
+#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 <util/unittests/wiredata.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::testing;
+
+using isc::util::unittests::matchWireData;
+using std::string;
+using std::vector;
+
+namespace {
+// This defines a tuple of test data used in test_rdata_list below.
+struct TestRdata {
+    const char* const rrclass;  // RR class, textual form
+    const char* const rrtype;   // RR type, textual form
+    const char* const rdata;    // textual RDATA
+    const size_t n_varlen_fields; // expected # of variable-len fields
+};
+
+// This test data consist of all supported types of RDATA (+ some
+// unusual and corner cases).  We'll construct corresponding Rdata
+// object from this, and compare its wire format data both generated
+// by normal libdns++ interface and via encoding conversion.
+const TestRdata test_rdata_list[] = {
+    {"IN", "A", "192.0.2.1", 0},
+    {"IN", "NS", "ns.example.com", 0},
+    {"IN", "CNAME", "cname.example.com", 0},
+    {"IN", "SOA", "ns.example.com root.example.com 0 0 0 0 0", 0},
+    {"IN", "PTR", "reverse.example.com", 0},
+    {"IN", "HINFO", "\"cpu-info\" \"OS-info\"", 1},
+    {"IN", "MINFO", "root.example.com mbox.example.com", 0},
+    {"IN", "MX", "10 mx.example.com", 0},
+    {"IN", "TXT", "\"test1\" \"test 2\"", 1},
+    {"IN", "RP", "root.example.com. rp-text.example.com", 0},
+    {"IN", "AFSDB", "1 afsdb.example.com", 0},
+    {"IN", "AAAA", "2001:db8::1", 0},
+    {"IN", "SRV", "1 0 10 target.example.com", 0},
+    {"IN", "NAPTR", "100 50 \"s\" \"http\" \"\" _http._tcp.example.com", 1},
+    {"IN", "DNAME", "dname.example.com", 0},
+    {"IN", "DS", "12892 5 2 5F0EB5C777586DE18DA6B5", 1},
+    {"IN", "SSHFP", "1 1 dd465c09cfa51fb45020cc83316fff", 1},
+    // Note: in our implementation RRSIG is treated as opaque data (including
+    // the signer name).  We use "com" for signer so it won't be a compress
+    // target in the test.
+    {"IN", "RRSIG", "SOA 5 2 3600 20120814220826 20120715220826 12345 "
+     "com. FAKEFAKEFAKE", 1},
+    {"IN", "NSEC", "next.example.com. A AAAA NSEC RRSIG", 1},
+    {"IN", "DNSKEY", "256 3 5 FAKEFAKE", 1},
+    {"IN", "DHCID", "FAKEFAKE", 1},
+    {"IN", "NSEC3", "1 1 12 AABBCCDD FAKEFAKE A RRSIG", 1},
+    {"IN", "NSEC3PARAM", "1 0 12 AABBCCDD", 1},
+    {"IN", "SPF", "v=spf1 +mx a:colo.example.com/28 -all", 1},
+    {"IN", "DLV", "12892 5 2 5F0EB5C777586DE18DA6B5", 1},
+    {"IN", "TYPE65000", "\\# 3 010203", 1}, // some "custom" type
+    {"IN", "TYPE65535", "\\# 0", 1},        // max RR type, 0-length RDATA
+    {"CH", "A", "\\# 2 0102", 1}, // A RR for non-IN class; varlen data
+    {"CH", "NS", "ns.example.com", 0}, // class CH, generic data
+    {"CH", "TXT", "BIND10", 1},        // ditto
+    {"HS", "A", "\\# 5 0102030405", 1}, // A RR for non-IN class; varlen data
+    {NULL, NULL, NULL, 0}
+};
+
+// The following two functions will be used to generate wire format data
+// from encoded representation of each RDATA.
+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) {
+    // These two names will be rendered before and after the test RDATA,
+    // to check in case the RDATA contain a domain name whether it's
+    // compressed or not correctly.  The names in the RDATA should basically
+    // a subdomain of example.com, so it can be compressed due to dummy_name.
+    // Likewise, dummy_name2 should be able to be fully compressed due to
+    // the name in the RDATA.
+    const Name dummy_name("com");
+    const Name dummy_name2("example.com");
+
+    MessageRenderer expected_renderer, actual_renderer;
+    vector<uint8_t> encoded_data;
+    vector<uint16_t> varlen_list;
+
+    // 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());
+
+    for (size_t i = 1; test_rdata_list[i].rrclass != NULL; ++i) {
+        SCOPED_TRACE(string(test_rdata_list[i].rrclass) + "/" +
+                     test_rdata_list[i].rrtype);
+
+        expected_renderer.clear();
+        actual_renderer.clear();
+        expected_renderer.writeName(dummy_name);
+        actual_renderer.writeName(dummy_name);
+        encoded_data.clear();
+        varlen_list.clear();
+
+        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);
+        expected_renderer.writeName(dummy_name2);
+
+        const bool additional_required =
+            (need_additionals.find(rrtype) != need_additionals.end());
+
+        encodeRdata(*rdata, rrclass, rrtype, encoded_data, varlen_list);
+        EXPECT_EQ(varlen_list.size(), test_rdata_list[i].n_varlen_fields);
+        foreachRdataField(rrclass, rrtype, encoded_data, varlen_list,
+                          boost::bind(renderNameField, &actual_renderer,
+                                      additional_required, _1, _2),
+                          boost::bind(renderDataField, &actual_renderer,
+                                      _1, _2));
+
+        actual_renderer.writeName(dummy_name2);
+        matchWireData(expected_renderer.getData(),
+                      expected_renderer.getLength(),
+                      actual_renderer.getData(),
+                      actual_renderer.getLength());
+    }
+}
+
+}
diff --git a/src/lib/datasrc/memory/tests/run_unittests.cc b/src/lib/datasrc/memory/tests/run_unittests.cc
new file mode 100644
index 0000000..998667c
--- /dev/null
+++ b/src/lib/datasrc/memory/tests/run_unittests.cc
@@ -0,0 +1,23 @@
+// Copyright (C) 2012  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.
+
+#include <gtest/gtest.h>
+#include <util/unittests/run_all.h>
+
+int
+main(int argc, char* argv[]) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    return (isc::util::unittests::run_all());
+}
diff --git a/src/lib/dns/labelsequence.h b/src/lib/dns/labelsequence.h
index 48f3241..d6f02c9 100644
--- a/src/lib/dns/labelsequence.h
+++ b/src/lib/dns/labelsequence.h
@@ -46,23 +46,6 @@ class LabelSequence {
     friend std::string Name::toText(bool) const;
 
 public:
-    /// \brief Constructs a LabelSequence for the given label sequence
-    ///
-    /// \note The associated data MUST remain in scope during the lifetime
-    /// of this LabelSequence, since only the pointers are copied.
-    ///
-    /// \note No validation is done on the given data upon construction;
-    ///       use with care.
-    ///
-    /// \param ls The LabelSequence to construct a LabelSequence from
-    explicit LabelSequence(const LabelSequence& ls):
-                                     data_(ls.data_),
-                                     offsets_(ls.offsets_),
-                                     offsets_size_(ls.offsets_size_),
-                                     first_label_(ls.first_label_),
-                                     last_label_(ls.last_label_)
-    {}
-
     /// \brief Constructs a LabelSequence for the given name
     ///
     /// \note The associated Name MUST remain in scope during the lifetime
@@ -98,6 +81,23 @@ public:
                   const uint8_t* offsets,
                   size_t offsets_size);
 
+    /// \brief Copy constructor.
+    ///
+    /// \note The associated data MUST remain in scope during the lifetime
+    /// of this LabelSequence, since only the pointers are copied.
+    ///
+    /// \note No validation is done on the given data upon construction;
+    ///       use with care.
+    ///
+    /// \param ls The LabelSequence to construct a LabelSequence from
+    LabelSequence(const LabelSequence& ls):
+                                     data_(ls.data_),
+                                     offsets_(ls.offsets_),
+                                     offsets_size_(ls.offsets_size_),
+                                     first_label_(ls.first_label_),
+                                     last_label_(ls.last_label_)
+    {}
+
     /// \brief Return the wire-format data for this LabelSequence
     ///
     /// The data is returned as a pointer to (the part of) the original
diff --git a/src/lib/dns/rdata/generic/dname_39.cc b/src/lib/dns/rdata/generic/dname_39.cc
index 165c4a6..a22fcc3 100644
--- a/src/lib/dns/rdata/generic/dname_39.cc
+++ b/src/lib/dns/rdata/generic/dname_39.cc
@@ -54,7 +54,9 @@ DNAME::toWire(OutputBuffer& buffer) const {
 
 void
 DNAME::toWire(AbstractMessageRenderer& renderer) const {
-    renderer.writeName(dname_);
+    // Type DNAME is not "well-known", and name compression must be disabled
+    // per RFC3597.
+    renderer.writeName(dname_, false);
 }
 
 string
diff --git a/src/lib/dns/rdata/generic/naptr_35.cc b/src/lib/dns/rdata/generic/naptr_35.cc
index 129bf6c..957cb72 100644
--- a/src/lib/dns/rdata/generic/naptr_35.cc
+++ b/src/lib/dns/rdata/generic/naptr_35.cc
@@ -125,11 +125,16 @@ NAPTR::NAPTR(const NAPTR& naptr):
 void
 NAPTR::toWire(OutputBuffer& buffer) const {
     toWireHelper(buffer);
+    replacement_.toWire(buffer);
+
 }
 
 void
 NAPTR::toWire(AbstractMessageRenderer& renderer) const {
     toWireHelper(renderer);
+    // Type NAPTR is not "well-known", and name compression must be disabled
+    // per RFC3597.
+    renderer.writeName(replacement_, false);
 }
 
 string
diff --git a/src/lib/dns/rdata/generic/naptr_35.h b/src/lib/dns/rdata/generic/naptr_35.h
index ca16b3c..c82ef87 100644
--- a/src/lib/dns/rdata/generic/naptr_35.h
+++ b/src/lib/dns/rdata/generic/naptr_35.h
@@ -62,8 +62,6 @@ private:
 
         outputer.writeUint8(regexp_.size());
         outputer.writeData(regexp_.c_str(), regexp_.size());
-
-        replacement_.toWire(outputer);
     }
 
     uint16_t order_;
diff --git a/src/lib/dns/rdata/generic/nsec_47.cc b/src/lib/dns/rdata/generic/nsec_47.cc
index aeb6da8..b21a87d 100644
--- a/src/lib/dns/rdata/generic/nsec_47.cc
+++ b/src/lib/dns/rdata/generic/nsec_47.cc
@@ -124,7 +124,9 @@ NSEC::toWire(OutputBuffer& buffer) const {
 
 void
 NSEC::toWire(AbstractMessageRenderer& renderer) const {
-    impl_->nextname_.toWire(renderer);
+    // Type NSEC is not "well-known", and name compression must be disabled
+    // per RFC3597.
+    renderer.writeName(impl_->nextname_, false);
     renderer.writeData(&impl_->typebits_[0], impl_->typebits_.size());
 }
 
diff --git a/src/lib/dns/tests/rdata_dname_unittest.cc b/src/lib/dns/tests/rdata_dname_unittest.cc
index cf3001c..eb221d8 100644
--- a/src/lib/dns/tests/rdata_dname_unittest.cc
+++ b/src/lib/dns/tests/rdata_dname_unittest.cc
@@ -45,9 +45,11 @@ const uint8_t wiredata_dname2[] = {
     // first name: dn.example.com.
     0x02, 0x64, 0x6e, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
     0x63, 0x6f, 0x6d, 0x00,
-    // second name: dn2.example.com.  all labels except the first should be
-    // compressed.
-    0x03, 0x64, 0x6e, 0x32, 0xc0, 0x03 };
+    // second name: dn2.example.com.  The "example.com" shouldn't be compressed
+    // because DNAME is not a well know type per RFC3597.
+    0x03, 0x64, 0x6e, 0x32,
+    0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03,
+    0x63, 0x6f, 0x6d, 0x00 };
 
 TEST_F(Rdata_DNAME_Test, createFromText) {
     EXPECT_EQ(0, rdata_dname.compare(generic::DNAME("dn.example.com")));
diff --git a/src/lib/util/unittests/Makefile.am b/src/lib/util/unittests/Makefile.am
index 3007a83..39fbf88 100644
--- a/src/lib/util/unittests/Makefile.am
+++ b/src/lib/util/unittests/Makefile.am
@@ -9,6 +9,7 @@ if HAVE_GTEST
 libutil_unittests_la_SOURCES += resource.h resource.cc
 libutil_unittests_la_SOURCES += run_all.h run_all.cc
 libutil_unittests_la_SOURCES += textdata.h
+libutil_unittests_la_SOURCES += wiredata.h wiredata.cc
 endif
 
 # For now, this isn't needed for libutil_unittests
diff --git a/src/lib/util/unittests/fork.h b/src/lib/util/unittests/fork.h
index 3331cfa..2d27a11 100644
--- a/src/lib/util/unittests/fork.h
+++ b/src/lib/util/unittests/fork.h
@@ -18,8 +18,8 @@
 #include <unistd.h>
 
 /**
- * @file fork.h
- * @short Help functions to fork the test case process.
+ * \file fork.h
+ * \brief Help functions to fork the test case process.
  * Various functions to fork a process and feed some data to pipe, check
  * its output and such lives here.
  */
diff --git a/src/lib/util/unittests/newhook.h b/src/lib/util/unittests/newhook.h
index 7eb8ade..c90751e 100644
--- a/src/lib/util/unittests/newhook.h
+++ b/src/lib/util/unittests/newhook.h
@@ -16,8 +16,8 @@
 #define __UTIL_UNITTESTS_NEWHOOK_H 1
 
 /**
- * @file newhook.h
- * @short Enable the use of special operator new that throws for testing.
+ * \file newhook.h
+ * \brief Enable the use of special operator new that throws for testing.
  *
  * This small utility allows a test case to force the global operator new
  * to throw for a given size to test a case where memory allocation fails
diff --git a/src/lib/util/unittests/testdata.h b/src/lib/util/unittests/testdata.h
index 03bd83a..a452dc6 100644
--- a/src/lib/util/unittests/testdata.h
+++ b/src/lib/util/unittests/testdata.h
@@ -16,8 +16,8 @@
 #define __UTIL_UNITTESTS_TESTDATA_H 1
 
 /**
- * @file testdata.h
- * @short Manipulating test data files.
+ * \file testdata.h
+ * \brief Manipulating test data files.
  *
  * This utility defines functions that help test case handle test data
  * stored in a file.
diff --git a/src/lib/util/unittests/textdata.h b/src/lib/util/unittests/textdata.h
index 3e9b1aa..3e5fe0f 100644
--- a/src/lib/util/unittests/textdata.h
+++ b/src/lib/util/unittests/textdata.h
@@ -22,8 +22,8 @@
 #define __UTIL_UNITTESTS_TEXTDATA_H 1
 
 /**
- * @file textdata.h
- * @short Utilities for tests with text data.
+ * \file textdata.h
+ * \brief Utilities for tests with text data.
  *
  * This utility provides convenient helper functions for unit tests using
  * textual data.
diff --git a/src/lib/util/unittests/wiredata.cc b/src/lib/util/unittests/wiredata.cc
new file mode 100644
index 0000000..f24176d
--- /dev/null
+++ b/src/lib/util/unittests/wiredata.cc
@@ -0,0 +1,52 @@
+// Copyright (C) 2012  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.
+
+#include "wiredata.h"
+
+#include <gtest/gtest.h>
+
+#include <algorithm>            // for std::min
+#include <stdint.h>
+
+using namespace std;
+
+namespace isc {
+namespace util {
+namespace unittests {
+
+void
+matchWireData(const void* expected_data, size_t expected_len,
+              const void* actual_data, size_t actual_len)
+{
+    const size_t cmplen = std::min(expected_len, actual_len);
+
+    for (size_t i = 0; i < cmplen; ++i) {
+        const int ebyte = static_cast<const uint8_t*>(expected_data)[i];
+        const int abyte = static_cast<const uint8_t*>(actual_data)[i];
+        // Once we find a mismatch, it's quite likely that there will be many
+        // mismatches after this point.  So we stop here by using ASSERT not
+        // to be too noisy.
+        ASSERT_EQ(ebyte, abyte) << "Wire data mismatch at " << i << "th byte\n"
+                                << "  Actual: " << abyte << "\n"
+                                << "Expected: " << ebyte << "\n";
+    }
+    EXPECT_EQ(expected_len, actual_len)
+        << "Wire data mismatch in length:\n"
+        << "  Actual: " << actual_len << "\n"
+        << "Expected: " << expected_len << "\n";
+}
+
+} // unittests
+} // util
+} // isc
diff --git a/src/lib/util/unittests/wiredata.h b/src/lib/util/unittests/wiredata.h
new file mode 100644
index 0000000..8f1385d
--- /dev/null
+++ b/src/lib/util/unittests/wiredata.h
@@ -0,0 +1,45 @@
+// Copyright (C) 2012  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.
+
+#ifndef __UTIL_UNITTESTS_WIREDATA_H
+#define __UTIL_UNITTESTS_WIREDATA_H 1
+
+#include <cstddef>
+
+/// \file wiredata.h
+/// \brief Utilities for tests with wire data.
+///
+/// This utility provides convenient helper functions for unit tests using
+/// wire (binary) data.
+
+namespace isc {
+namespace util {
+namespace unittests {
+
+/// \brief Compare two sets of binary data in a google test.
+///
+/// This method checks if the expected and actual data have the same length
+/// and all bytes are the same.  If not, it reports the point of mismatch in
+/// the google test format.
+void matchWireData(const void* expected_data, size_t expected_len,
+                   const void* actual_data, size_t actual_len);
+}
+}
+}
+
+#endif // __UTIL_UNITTESTS_WIREDATA_H
+
+// Local Variables:
+// mode: c++
+// End:



More information about the bind10-changes mailing list