|
@@ -12,10 +12,6 @@
|
|
// 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.
|
|
|
|
|
|
-// Note: This file tests both the rdata_encoder and rdata_reader. They are
|
|
|
|
-// tested together because they form kind the oposite sides of the same
|
|
|
|
-// functionality.
|
|
|
|
-
|
|
|
|
#include <exceptions/exceptions.h>
|
|
#include <exceptions/exceptions.h>
|
|
|
|
|
|
#include <util/buffer.h>
|
|
#include <util/buffer.h>
|
|
@@ -28,9 +24,7 @@
|
|
#include <dns/rrclass.h>
|
|
#include <dns/rrclass.h>
|
|
#include <dns/rrtype.h>
|
|
#include <dns/rrtype.h>
|
|
|
|
|
|
-#include <datasrc/memory/rdata_encoder.h>
|
|
|
|
-#include <datasrc/memory/rdata_field.h>
|
|
|
|
-#include <datasrc/memory/rdata_reader.h>
|
|
|
|
|
|
+#include <datasrc/memory/rdata_serialization.h>
|
|
|
|
|
|
#include <util/unittests/wiredata.h>
|
|
#include <util/unittests/wiredata.h>
|
|
|
|
|
|
@@ -52,6 +46,18 @@ using isc::util::unittests::matchWireData;
|
|
using std::string;
|
|
using std::string;
|
|
using std::vector;
|
|
using std::vector;
|
|
|
|
|
|
|
|
+// A trick to steal some private definitions of the implementation we use here
|
|
|
|
+
|
|
|
|
+namespace isc {
|
|
|
|
+namespace datasrc{
|
|
|
|
+namespace memory {
|
|
|
|
+
|
|
|
|
+#include "../rdata_serialization_priv.cc"
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+}
|
|
|
|
+}
|
|
|
|
+
|
|
namespace {
|
|
namespace {
|
|
// This defines a tuple of test data used in test_rdata_list below.
|
|
// This defines a tuple of test data used in test_rdata_list below.
|
|
struct TestRdata {
|
|
struct TestRdata {
|
|
@@ -102,24 +108,21 @@ const TestRdata test_rdata_list[] = {
|
|
// from encoded representation of each RDATA.
|
|
// from encoded representation of each RDATA.
|
|
void
|
|
void
|
|
renderNameField(MessageRenderer* renderer, bool additional_required,
|
|
renderNameField(MessageRenderer* renderer, bool additional_required,
|
|
- const LabelSequence& labels, unsigned attributes)
|
|
|
|
|
|
+ const LabelSequence& labels, RdataNameAttributes attributes)
|
|
{
|
|
{
|
|
- EXPECT_EQ(additional_required,
|
|
|
|
- (attributes & NAMEATTR_ADDITIONAL) != 0);
|
|
|
|
|
|
+ EXPECT_EQ(additional_required, (attributes & NAMEATTR_ADDITIONAL) != 0);
|
|
renderer->writeName(labels, (attributes & NAMEATTR_COMPRESSIBLE) != 0);
|
|
renderer->writeName(labels, (attributes & NAMEATTR_COMPRESSIBLE) != 0);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
void
|
|
-renderDataField(MessageRenderer* renderer, const uint8_t* data,
|
|
|
|
- size_t data_len)
|
|
|
|
-{
|
|
|
|
|
|
+renderDataField(MessageRenderer* renderer, const void* data, size_t data_len) {
|
|
renderer->writeData(data, data_len);
|
|
renderer->writeData(data, data_len);
|
|
}
|
|
}
|
|
|
|
|
|
class RdataSerializationTest : public ::testing::Test {
|
|
class RdataSerializationTest : public ::testing::Test {
|
|
protected:
|
|
protected:
|
|
RdataSerializationTest() : a_rdata_(createRdata(RRType::A(), RRClass::IN(),
|
|
RdataSerializationTest() : a_rdata_(createRdata(RRType::A(), RRClass::IN(),
|
|
- "192.0.2.53")),
|
|
|
|
|
|
+ "192.0.2.53")),
|
|
aaaa_rdata_(createRdata(RRType::AAAA(), RRClass::IN(),
|
|
aaaa_rdata_(createRdata(RRType::AAAA(), RRClass::IN(),
|
|
"2001:db8::53")),
|
|
"2001:db8::53")),
|
|
rrsig_rdata_(createRdata(
|
|
rrsig_rdata_(createRdata(
|
|
@@ -151,7 +154,7 @@ protected:
|
|
template<class DecoderStyle>
|
|
template<class DecoderStyle>
|
|
class RdataEncodeDecodeTest : public RdataSerializationTest {
|
|
class RdataEncodeDecodeTest : public RdataSerializationTest {
|
|
public:
|
|
public:
|
|
- // This helper test method constructs encodes the given list of RDATAs
|
|
|
|
|
|
+ // This helper test method encodes the given list of RDATAs
|
|
// (in rdata_list), and then iterates over the data, rendering the fields
|
|
// (in rdata_list), and then iterates over the data, rendering the fields
|
|
// in the wire format. It then compares the wire data with the one
|
|
// in the wire format. It then compares the wire data with the one
|
|
// generated by the normal libdns++ interface to see the encoding/decoding
|
|
// generated by the normal libdns++ interface to see the encoding/decoding
|
|
@@ -168,13 +171,16 @@ public:
|
|
|
|
|
|
// Used across more classes and scopes. But it's just uninteresting
|
|
// Used across more classes and scopes. But it's just uninteresting
|
|
// constant.
|
|
// constant.
|
|
-const Name dummy_name2("example.com");
|
|
|
|
|
|
+const Name& dummyName2() {
|
|
|
|
+ static const Name result("example.com");
|
|
|
|
+ return (result);
|
|
|
|
+}
|
|
|
|
|
|
bool
|
|
bool
|
|
additionalRequired(const RRType& type) {
|
|
additionalRequired(const RRType& type) {
|
|
// The set of RR types that require additional section processing.
|
|
// The set of RR types that require additional section processing.
|
|
- // We'll pass it to renderNameField to check the stored attribute matches
|
|
|
|
- // our expectation.
|
|
|
|
|
|
+ // We'll use it to determine what value should the renderNameField get
|
|
|
|
+ // and, if the stored attributes are as expected.
|
|
static std::set<RRType> need_additionals;
|
|
static std::set<RRType> need_additionals;
|
|
if (need_additionals.empty()) {
|
|
if (need_additionals.empty()) {
|
|
need_additionals.insert(RRType::NS());
|
|
need_additionals.insert(RRType::NS());
|
|
@@ -286,8 +292,8 @@ public:
|
|
encoded_data.end());
|
|
encoded_data.end());
|
|
}
|
|
}
|
|
|
|
|
|
- // If RRSIGs are given, we need to extract the list of the RRSIG lengths
|
|
|
|
- // and adjust encoded_data_ further.
|
|
|
|
|
|
+ // If RRSIGs are given, we need to extract the list of the RRSIG
|
|
|
|
+ // lengths and adjust encoded_data_ further.
|
|
vector<uint16_t> rrsiglen_list;
|
|
vector<uint16_t> rrsiglen_list;
|
|
if (rrsig_count > 0) {
|
|
if (rrsig_count > 0) {
|
|
const size_t rrsig_len_size = rrsig_count * sizeof(uint16_t);
|
|
const size_t rrsig_len_size = rrsig_count * sizeof(uint16_t);
|
|
@@ -305,16 +311,16 @@ public:
|
|
additionalRequired(rrtype), _1, _2),
|
|
additionalRequired(rrtype), _1, _2),
|
|
boost::bind(renderDataField, &renderer, _1, _2));
|
|
boost::bind(renderDataField, &renderer, _1, _2));
|
|
|
|
|
|
- // 2nd dummy name
|
|
|
|
- renderer.writeName(dummy_name2);
|
|
|
|
- // Finally, dump any RRSIGs in wire format.
|
|
|
|
- foreachRRSig(encoded_data, rrsiglen_list,
|
|
|
|
- boost::bind(renderDataField, &renderer, _1, _2));
|
|
|
|
|
|
+ // 2nd dummy name
|
|
|
|
+ renderer.writeName(dummyName2());
|
|
|
|
+ // Finally, dump any RRSIGs in wire format.
|
|
|
|
+ foreachRRSig(encoded_data, rrsiglen_list,
|
|
|
|
+ boost::bind(renderDataField, &renderer, _1, _2));
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
-// Decode using reader with the return value of next
|
|
|
|
-class NextDecoder {
|
|
|
|
|
|
+// Check using callbacks and calling next until the end.
|
|
|
|
+class CallbackDecoder {
|
|
public:
|
|
public:
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
const isc::dns::RRType& rrtype,
|
|
const isc::dns::RRType& rrtype,
|
|
@@ -323,38 +329,18 @@ public:
|
|
MessageRenderer& renderer)
|
|
MessageRenderer& renderer)
|
|
{
|
|
{
|
|
RdataReader reader(rrclass, rrtype, &encoded_data[0], rdata_count,
|
|
RdataReader reader(rrclass, rrtype, &encoded_data[0], rdata_count,
|
|
- sig_count);
|
|
|
|
- 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();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ sig_count,
|
|
|
|
+ boost::bind(renderNameField, &renderer,
|
|
|
|
+ additionalRequired(rrtype), _1, _2),
|
|
|
|
+ boost::bind(renderDataField, &renderer, _1, _2));
|
|
|
|
+ while (reader.next() != RdataReader::RRSET_BOUNDARY) {}
|
|
|
|
+ renderer.writeName(dummyName2());
|
|
|
|
+ while (reader.nextSig() != RdataReader::RRSET_BOUNDARY) {}
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
-// Decode using reader with the return value of next, but after the reader
|
|
|
|
-// was used and rewund.
|
|
|
|
-class RewundDecoder {
|
|
|
|
|
|
+// Check using callbacks and calling iterate.
|
|
|
|
+class IterateDecoder {
|
|
public:
|
|
public:
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
const isc::dns::RRType& rrtype,
|
|
const isc::dns::RRType& rrtype,
|
|
@@ -362,42 +348,46 @@ public:
|
|
const vector<uint8_t>& encoded_data, size_t,
|
|
const vector<uint8_t>& encoded_data, size_t,
|
|
MessageRenderer& renderer)
|
|
MessageRenderer& renderer)
|
|
{
|
|
{
|
|
- RdataReader reader(rrclass, rrtype, &encoded_data[0], rdata_count,
|
|
|
|
- sig_count);
|
|
|
|
- // Use the reader first and rewind it
|
|
|
|
- reader.iterateSig();
|
|
|
|
|
|
+ RdataReader reader(rrclass, rrtype, &encoded_data[0],
|
|
|
|
+ rdata_count, sig_count,
|
|
|
|
+ boost::bind(renderNameField, &renderer,
|
|
|
|
+ additionalRequired(rrtype), _1, _2),
|
|
|
|
+ boost::bind(renderDataField, &renderer, _1, _2));
|
|
reader.iterate();
|
|
reader.iterate();
|
|
- reader.rewind();
|
|
|
|
- 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(dummyName2());
|
|
|
|
+ reader.iterateAllSigs();
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
|
|
- renderer.writeName(dummy_name2);
|
|
|
|
|
|
+namespace {
|
|
|
|
|
|
- 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();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+// Render the data to renderer, if one is set, or put it inside
|
|
|
|
+// a data buffer.
|
|
|
|
+void
|
|
|
|
+appendOrRenderData(vector<uint8_t>* where, MessageRenderer** renderer,
|
|
|
|
+ const void* data, size_t size)
|
|
|
|
+{
|
|
|
|
+ if (*renderer != NULL) {
|
|
|
|
+ (*renderer)->writeData(data, size);
|
|
|
|
+ } else {
|
|
|
|
+ where->insert(where->end(), reinterpret_cast<const uint8_t*>(data),
|
|
|
|
+ reinterpret_cast<const uint8_t*>(data) + size);
|
|
}
|
|
}
|
|
-};
|
|
|
|
|
|
+}
|
|
|
|
|
|
-// Check using callbacks and calling next until the end.
|
|
|
|
-class CallbackDecoder {
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Similar to IterateDecoder, but it first iterates a little and rewinds
|
|
|
|
+// before actual rendering.
|
|
|
|
+class RewindAndDecode {
|
|
|
|
+private:
|
|
|
|
+ static void writeName(MessageRenderer** renderer,
|
|
|
|
+ const LabelSequence& labels,
|
|
|
|
+ RdataNameAttributes attributes)
|
|
|
|
+ {
|
|
|
|
+ (*renderer)->writeName(labels,
|
|
|
|
+ (attributes & NAMEATTR_COMPRESSIBLE) != 0);
|
|
|
|
+ }
|
|
public:
|
|
public:
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
const isc::dns::RRType& rrtype,
|
|
const isc::dns::RRType& rrtype,
|
|
@@ -405,19 +395,30 @@ public:
|
|
const vector<uint8_t>& encoded_data, size_t,
|
|
const vector<uint8_t>& encoded_data, size_t,
|
|
MessageRenderer& renderer)
|
|
MessageRenderer& renderer)
|
|
{
|
|
{
|
|
- RdataReader reader(rrclass, rrtype, &encoded_data[0], rdata_count,
|
|
|
|
- sig_count,
|
|
|
|
- boost::bind(renderNameField, &renderer,
|
|
|
|
- additionalRequired(rrtype), _1, _2),
|
|
|
|
- boost::bind(renderDataField, &renderer, _1, _2));
|
|
|
|
- while (reader.next()) { }
|
|
|
|
- renderer.writeName(dummy_name2);
|
|
|
|
- while (reader.nextSig()) { }
|
|
|
|
|
|
+ MessageRenderer dump; // A place to dump the extra data from before
|
|
|
|
+ // actual rendering.
|
|
|
|
+ MessageRenderer* current = &dump;
|
|
|
|
+ vector<uint8_t> placeholder; // boost::bind does not like NULL
|
|
|
|
+ RdataReader reader(rrclass, rrtype, &encoded_data[0],
|
|
|
|
+ rdata_count, sig_count,
|
|
|
|
+ boost::bind(writeName, ¤t, _1, _2),
|
|
|
|
+ boost::bind(appendOrRenderData, &placeholder,
|
|
|
|
+ ¤t, _1, _2));
|
|
|
|
+ // Iterate a little and rewind
|
|
|
|
+ reader.next();
|
|
|
|
+ reader.nextSig();
|
|
|
|
+ reader.rewind();
|
|
|
|
+ // Do the actual rendering
|
|
|
|
+ current = &renderer;
|
|
|
|
+ reader.iterate();
|
|
|
|
+ renderer.writeName(dummyName2());
|
|
|
|
+ reader.iterateAllSigs();
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
-// Check using callbacks and calling iterate.
|
|
|
|
-class IterateDecoder {
|
|
|
|
|
|
+// Decode using the iteration over one rdata each time.
|
|
|
|
+// We also count there's the correct count of Rdatas.
|
|
|
|
+class SingleIterateDecoder {
|
|
public:
|
|
public:
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
const isc::dns::RRType& rrtype,
|
|
const isc::dns::RRType& rrtype,
|
|
@@ -430,9 +431,17 @@ public:
|
|
boost::bind(renderNameField, &renderer,
|
|
boost::bind(renderNameField, &renderer,
|
|
additionalRequired(rrtype), _1, _2),
|
|
additionalRequired(rrtype), _1, _2),
|
|
boost::bind(renderDataField, &renderer, _1, _2));
|
|
boost::bind(renderDataField, &renderer, _1, _2));
|
|
- reader.iterate();
|
|
|
|
- renderer.writeName(dummy_name2);
|
|
|
|
- reader.iterateSig();
|
|
|
|
|
|
+ size_t actual_count = 0;
|
|
|
|
+ while (reader.iterateRdata()) {
|
|
|
|
+ ++actual_count;
|
|
|
|
+ }
|
|
|
|
+ EXPECT_EQ(rdata_count, actual_count);
|
|
|
|
+ actual_count = 0;
|
|
|
|
+ renderer.writeName(dummyName2());
|
|
|
|
+ while (reader.iterateSingleSig()) {
|
|
|
|
+ ++actual_count;
|
|
|
|
+ }
|
|
|
|
+ EXPECT_EQ(sig_count, actual_count);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
@@ -442,19 +451,6 @@ public:
|
|
// of rendering.
|
|
// of rendering.
|
|
template<bool start_data, bool start_sig>
|
|
template<bool start_data, bool start_sig>
|
|
class HybridDecoder {
|
|
class HybridDecoder {
|
|
-private:
|
|
|
|
- // Append data either to the renderer or to the vector passed.
|
|
|
|
- // The double pointer is there so we can change the renderer to NULL
|
|
|
|
- // and back during the test.
|
|
|
|
- static void appendData(vector<uint8_t>* where, MessageRenderer** renderer,
|
|
|
|
- const uint8_t* data, size_t size)
|
|
|
|
- {
|
|
|
|
- if (*renderer != NULL) {
|
|
|
|
- (*renderer)->writeData(data, size);
|
|
|
|
- } else {
|
|
|
|
- where->insert(where->end(), data, data + size);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
public:
|
|
public:
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
static void decode(const isc::dns::RRClass& rrclass,
|
|
const isc::dns::RRType& rrtype,
|
|
const isc::dns::RRType& rrtype,
|
|
@@ -469,7 +465,8 @@ public:
|
|
rdata_count, sig_count,
|
|
rdata_count, sig_count,
|
|
boost::bind(renderNameField, &renderer,
|
|
boost::bind(renderNameField, &renderer,
|
|
additionalRequired(rrtype), _1, _2),
|
|
additionalRequired(rrtype), _1, _2),
|
|
- boost::bind(appendData, &data, ¤t, _1, _2));
|
|
|
|
|
|
+ boost::bind(appendOrRenderData, &data, ¤t, _1,
|
|
|
|
+ _2));
|
|
// The size matches
|
|
// The size matches
|
|
EXPECT_EQ(encoded_data_len, reader.getSize());
|
|
EXPECT_EQ(encoded_data_len, reader.getSize());
|
|
if (start_sig) {
|
|
if (start_sig) {
|
|
@@ -485,28 +482,35 @@ public:
|
|
// Now, we let all sigs to be copied to data. We disable the
|
|
// Now, we let all sigs to be copied to data. We disable the
|
|
// renderer for this.
|
|
// renderer for this.
|
|
current = NULL;
|
|
current = NULL;
|
|
- reader.iterateSig();
|
|
|
|
|
|
+ reader.iterateAllSigs();
|
|
// Now return the renderer and render the rest of the data
|
|
// Now return the renderer and render the rest of the data
|
|
current = &renderer;
|
|
current = &renderer;
|
|
reader.iterate();
|
|
reader.iterate();
|
|
// Now, this should not break anything and should be valid, but should
|
|
// Now, this should not break anything and should be valid, but should
|
|
// return ends.
|
|
// return ends.
|
|
- EXPECT_FALSE(reader.next());
|
|
|
|
- EXPECT_FALSE(reader.nextSig());
|
|
|
|
|
|
+ EXPECT_EQ(RdataReader::RRSET_BOUNDARY, reader.next());
|
|
|
|
+ EXPECT_EQ(RdataReader::RRSET_BOUNDARY, reader.nextSig());
|
|
// Render the name and the sigs
|
|
// Render the name and the sigs
|
|
- renderer.writeName(dummy_name2);
|
|
|
|
|
|
+ renderer.writeName(dummyName2());
|
|
renderer.writeData(&data[0], data.size());
|
|
renderer.writeData(&data[0], data.size());
|
|
// The size matches even after use
|
|
// The size matches even after use
|
|
EXPECT_EQ(encoded_data_len, reader.getSize());
|
|
EXPECT_EQ(encoded_data_len, reader.getSize());
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
-typedef ::testing::Types<ManualDecoderStyle, NextDecoder, RewundDecoder,
|
|
|
|
- CallbackDecoder, IterateDecoder,
|
|
|
|
|
|
+typedef ::testing::Types<ManualDecoderStyle,
|
|
|
|
+ CallbackDecoder, IterateDecoder, SingleIterateDecoder,
|
|
HybridDecoder<true, true>, HybridDecoder<true, false>,
|
|
HybridDecoder<true, true>, HybridDecoder<true, false>,
|
|
HybridDecoder<false, true>,
|
|
HybridDecoder<false, true>,
|
|
HybridDecoder<false, false> >
|
|
HybridDecoder<false, false> >
|
|
DecoderStyles;
|
|
DecoderStyles;
|
|
|
|
+// Each decoder style must contain a decode() method. Such method is expected
|
|
|
|
+// to decode the passed data, first render the Rdata into the passed renderer,
|
|
|
|
+// then write the dummyName2() there and write the RRSig data after that.
|
|
|
|
+// It may do other checks too.
|
|
|
|
+//
|
|
|
|
+// There are some slight differences to how to do the decoding, that's why we
|
|
|
|
+// have the typed test.
|
|
TYPED_TEST_CASE(RdataEncodeDecodeTest, DecoderStyles);
|
|
TYPED_TEST_CASE(RdataEncodeDecodeTest, DecoderStyles);
|
|
|
|
|
|
void
|
|
void
|
|
@@ -536,8 +540,8 @@ checkEncode(RRClass rrclass, RRType rrtype,
|
|
// These two names will be rendered before and after the test RDATA,
|
|
// 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
|
|
// to check in case the RDATA contain a domain name whether it's
|
|
// compressed or not correctly. The names in the RDATA should basically
|
|
// 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
|
|
|
|
|
|
+ // a subdomain of example.com, so it can be compressed due to dummyName2().
|
|
|
|
+ // Likewise, dummyName2() should be able to be fully compressed due to
|
|
// the name in the RDATA.
|
|
// the name in the RDATA.
|
|
const Name dummy_name("com");
|
|
const Name dummy_name("com");
|
|
|
|
|
|
@@ -550,7 +554,7 @@ checkEncode(RRClass rrclass, RRType rrtype,
|
|
BOOST_FOREACH(const ConstRdataPtr& rdata, rdata_list) {
|
|
BOOST_FOREACH(const ConstRdataPtr& rdata, rdata_list) {
|
|
rdata->toWire(expected_renderer_);
|
|
rdata->toWire(expected_renderer_);
|
|
}
|
|
}
|
|
- expected_renderer_.writeName(dummy_name2);
|
|
|
|
|
|
+ expected_renderer_.writeName(dummyName2());
|
|
BOOST_FOREACH(const ConstRdataPtr& rdata, rrsig_list) {
|
|
BOOST_FOREACH(const ConstRdataPtr& rdata, rrsig_list) {
|
|
rdata->toWire(expected_renderer_);
|
|
rdata->toWire(expected_renderer_);
|
|
}
|
|
}
|
|
@@ -601,7 +605,7 @@ addRdataCommon(const vector<ConstRdataPtr>& rrsigs) {
|
|
|
|
|
|
TYPED_TEST(RdataEncodeDecodeTest, addRdata) {
|
|
TYPED_TEST(RdataEncodeDecodeTest, addRdata) {
|
|
vector<ConstRdataPtr> rrsigs;
|
|
vector<ConstRdataPtr> rrsigs;
|
|
- this->addRdataCommon(rrsigs); // basic tests without RRSIGs (empty vector)
|
|
|
|
|
|
+ this->addRdataCommon(rrsigs); // basic tests without RRSIGs (empty vector)
|
|
|
|
|
|
// Test with RRSIGs (covered type doesn't always match, but the encoder
|
|
// Test with RRSIGs (covered type doesn't always match, but the encoder
|
|
// doesn't check that)
|
|
// doesn't check that)
|
|
@@ -654,6 +658,22 @@ addRdataMultiCommon(const vector<ConstRdataPtr>& rrsigs) {
|
|
checkEncode(RRClass::IN(), RRType::NAPTR(), rdata_list_, 1, rrsigs);
|
|
checkEncode(RRClass::IN(), RRType::NAPTR(), rdata_list_, 1, rrsigs);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void ignoreName(const LabelSequence&, unsigned) {
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+checkLargeData(const in::DHCID* decoded, bool* called, const void* encoded,
|
|
|
|
+ size_t length)
|
|
|
|
+{
|
|
|
|
+ EXPECT_FALSE(*called); // Called exactly once
|
|
|
|
+ *called = true;
|
|
|
|
+
|
|
|
|
+ // Reconstruct the Rdata and check it.
|
|
|
|
+ isc::util::InputBuffer ib(encoded, length);
|
|
|
|
+ const in::DHCID reconstructed(ib, ib.getLength());
|
|
|
|
+ EXPECT_EQ(0, reconstructed.compare(*decoded));
|
|
|
|
+}
|
|
|
|
+
|
|
TEST_F(RdataSerializationTest, encodeLargeRdata) {
|
|
TEST_F(RdataSerializationTest, encodeLargeRdata) {
|
|
// There should be no reason for a large RDATA to fail in encoding,
|
|
// There should be no reason for a large RDATA to fail in encoding,
|
|
// but we check such a case explicitly.
|
|
// but we check such a case explicitly.
|
|
@@ -667,10 +687,15 @@ TEST_F(RdataSerializationTest, encodeLargeRdata) {
|
|
encodeWrapper(encoder_.getStorageLength());
|
|
encodeWrapper(encoder_.getStorageLength());
|
|
|
|
|
|
// The encoded data should be identical to the original one.
|
|
// The encoded data should be identical to the original one.
|
|
- ASSERT_LT(sizeof(uint16_t), encoder_.getStorageLength());
|
|
|
|
- isc::util::InputBuffer ib(&encoded_data_[2], encoded_data_.size() - 2);
|
|
|
|
- const in::DHCID encoded_dhcid(ib, ib.getLength());
|
|
|
|
- EXPECT_EQ(0, encoded_dhcid.compare(large_dhcid));
|
|
|
|
|
|
+ bool called = false;
|
|
|
|
+ RdataReader reader(RRClass::IN(), RRType::DHCID(), &encoded_data_[0], 1, 0,
|
|
|
|
+ ignoreName, boost::bind(checkLargeData, &large_dhcid,
|
|
|
|
+ &called, _1, _2));
|
|
|
|
+ reader.iterate();
|
|
|
|
+ EXPECT_TRUE(called);
|
|
|
|
+ called = false;
|
|
|
|
+ reader.iterateAllSigs();
|
|
|
|
+ EXPECT_FALSE(called);
|
|
}
|
|
}
|
|
|
|
|
|
TYPED_TEST(RdataEncodeDecodeTest, addRdataMulti) {
|
|
TYPED_TEST(RdataEncodeDecodeTest, addRdataMulti) {
|
|
@@ -763,6 +788,19 @@ TEST_F(RdataSerializationTest, badAddRdata) {
|
|
isc::BadValue);
|
|
isc::BadValue);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void
|
|
|
|
+checkSigData(const ConstRdataPtr& decoded, bool* called, const void* encoded,
|
|
|
|
+ size_t length)
|
|
|
|
+{
|
|
|
|
+ EXPECT_FALSE(*called); // Called exactly once
|
|
|
|
+ *called = true;
|
|
|
|
+
|
|
|
|
+ // Reconstruct the RRSig and check it.
|
|
|
|
+ isc::util::InputBuffer ib(encoded, length);
|
|
|
|
+ const generic::RRSIG reconstructed(ib, ib.getLength());
|
|
|
|
+ EXPECT_EQ(0, reconstructed.compare(*decoded));
|
|
|
|
+}
|
|
|
|
+
|
|
TEST_F(RdataSerializationTest, addSIGRdataOnly) {
|
|
TEST_F(RdataSerializationTest, addSIGRdataOnly) {
|
|
// Encoded data that only contain RRSIGs. Mostly useless, but can happen
|
|
// Encoded data that only contain RRSIGs. Mostly useless, but can happen
|
|
// (in a partially broken zone) and it's accepted.
|
|
// (in a partially broken zone) and it's accepted.
|
|
@@ -771,10 +809,14 @@ TEST_F(RdataSerializationTest, addSIGRdataOnly) {
|
|
encodeWrapper(encoder_.getStorageLength());
|
|
encodeWrapper(encoder_.getStorageLength());
|
|
ASSERT_LT(sizeof(uint16_t), encoder_.getStorageLength());
|
|
ASSERT_LT(sizeof(uint16_t), encoder_.getStorageLength());
|
|
|
|
|
|
- // The encoded data should be identical to the given one.
|
|
|
|
- isc::util::InputBuffer ib(&encoded_data_[2], encoded_data_.size() - 2);
|
|
|
|
- const generic::RRSIG encoded_sig(ib, ib.getLength());
|
|
|
|
- EXPECT_EQ(0, encoded_sig.compare(*rrsig_rdata_));
|
|
|
|
|
|
+ bool called = false;
|
|
|
|
+ RdataReader reader(RRClass::IN(), RRType::A(), &encoded_data_[0], 0, 1,
|
|
|
|
+ ignoreName, boost::bind(checkSigData, rrsig_rdata_,
|
|
|
|
+ &called, _1, _2));
|
|
|
|
+ reader.iterate();
|
|
|
|
+ EXPECT_FALSE(called);
|
|
|
|
+ reader.iterateAllSigs();
|
|
|
|
+ EXPECT_TRUE(called);
|
|
}
|
|
}
|
|
|
|
|
|
TEST_F(RdataSerializationTest, badAddSIGRdata) {
|
|
TEST_F(RdataSerializationTest, badAddSIGRdata) {
|
|
@@ -794,46 +836,4 @@ TEST_F(RdataSerializationTest, badAddSIGRdata) {
|
|
encoder_.start(RRClass::IN(), RRType::A());
|
|
encoder_.start(RRClass::IN(), RRType::A());
|
|
EXPECT_THROW(encoder_.addSIGRdata(big_sigrdata), RdataEncodingError);
|
|
EXPECT_THROW(encoder_.addSIGRdata(big_sigrdata), RdataEncodingError);
|
|
}
|
|
}
|
|
-
|
|
|
|
-// Test the result returns what it was constructed with.
|
|
|
|
-TEST_F(RdataSerializationTest, readerResult) {
|
|
|
|
- // Default constructor
|
|
|
|
- RdataReader::Result empty;
|
|
|
|
- // Everything should be at the "empty" values, type END
|
|
|
|
- EXPECT_EQ(RdataReader::END, empty.type());
|
|
|
|
- EXPECT_EQ(NULL, empty.data());
|
|
|
|
- EXPECT_EQ(0, empty.size());
|
|
|
|
- EXPECT_TRUE(empty.label().equals(LabelSequence(Name::ROOT_NAME())));
|
|
|
|
- EXPECT_FALSE(empty);
|
|
|
|
- EXPECT_FALSE(empty.compressible());
|
|
|
|
- EXPECT_FALSE(empty.additional());
|
|
|
|
- // Constructor from label sequence
|
|
|
|
- LabelSequence seq(Name("example.org"));
|
|
|
|
- RdataReader::Result compressible(seq, NAMEATTR_COMPRESSIBLE);
|
|
|
|
- EXPECT_EQ(RdataReader::NAME, compressible.type());
|
|
|
|
- EXPECT_EQ(NULL, compressible.data());
|
|
|
|
- EXPECT_EQ(0, compressible.size());
|
|
|
|
- EXPECT_TRUE(compressible.label().equals(seq));
|
|
|
|
- EXPECT_TRUE(compressible);
|
|
|
|
- EXPECT_TRUE(compressible.compressible());
|
|
|
|
- EXPECT_FALSE(compressible.additional());
|
|
|
|
- RdataReader::Result incompressible(seq, NAMEATTR_ADDITIONAL);
|
|
|
|
- EXPECT_EQ(RdataReader::NAME, incompressible.type());
|
|
|
|
- EXPECT_EQ(NULL, incompressible.data());
|
|
|
|
- EXPECT_EQ(0, incompressible.size());
|
|
|
|
- EXPECT_TRUE(incompressible.label().equals(seq));
|
|
|
|
- EXPECT_TRUE(incompressible);
|
|
|
|
- EXPECT_FALSE(incompressible.compressible());
|
|
|
|
- EXPECT_TRUE(incompressible.additional());
|
|
|
|
- // Constructor from data
|
|
|
|
- uint8_t byte;
|
|
|
|
- RdataReader::Result data(&byte, 1);
|
|
|
|
- EXPECT_EQ(RdataReader::DATA, data.type());
|
|
|
|
- EXPECT_EQ(&byte, data.data());
|
|
|
|
- EXPECT_EQ(1, data.size());
|
|
|
|
- EXPECT_TRUE(data.label().equals(LabelSequence(Name::ROOT_NAME())));
|
|
|
|
- EXPECT_TRUE(data);
|
|
|
|
- EXPECT_FALSE(data.compressible());
|
|
|
|
- EXPECT_FALSE(data.additional());
|
|
|
|
-}
|
|
|
|
}
|
|
}
|