From: Michal 'vorner' Vaner Date: Fri, 10 Aug 2012 10:58:00 +0000 (+0200) Subject: [2096] Further RdataReader tests X-Git-Tag: trac2351_base~114^2~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6bcd73aa1c0ef3f2ea13b6aa87f003db437d55f0;p=thirdparty%2Fkea.git [2096] Further RdataReader tests Testing rewinding it and accessing the stuff out of the usual order (intermixing iteration of Rdata and the signatures). --- diff --git a/src/lib/datasrc/memory/rdata_reader.cc b/src/lib/datasrc/memory/rdata_reader.cc index eb57b9e207..1a6e5b9d4b 100644 --- a/src/lib/datasrc/memory/rdata_reader.cc +++ b/src/lib/datasrc/memory/rdata_reader.cc @@ -83,21 +83,23 @@ RdataReader::rewind() { } RdataReader::Result -RdataReader::next() { +RdataReader::nextInternal(const NameAction& name_action, + const DataAction& data_action) +{ if (spec_pos_ < spec_count_) { const RdataFieldSpec& spec(spec_.fields[(spec_pos_ ++) % spec_.field_count]); if (spec.type == RdataFieldSpec::DOMAIN_NAME) { const LabelSequence sequence(data_ + data_pos_); data_pos_ += sequence.getSerializedLength(); - name_action_(sequence, spec.name_attributes); + name_action(sequence, spec.name_attributes); return (Result(sequence, spec.name_attributes)); } else { const size_t length(spec.type == RdataFieldSpec::FIXEDLEN_DATA ? spec.fixeddata_len : lengths_[length_pos_ ++]); Result result(data_ + data_pos_, length); data_pos_ += length; - data_action_(result.data(), result.size()); + data_action(result.data(), result.size()); return (result); } } else { @@ -106,6 +108,11 @@ RdataReader::next() { } } +RdataReader::Result +RdataReader::next() { + return (nextInternal(name_action_, data_action_)); +} + RdataReader::Result RdataReader::nextSig() { if (sig_pos_ < sig_count_) { @@ -117,7 +124,7 @@ RdataReader::nextSig() { size_t spec_pos = spec_pos_; size_t length_pos = length_pos_; // When the next() gets to the last item, it sets the sigs_ - iterate(); + while (nextInternal(emptyNameAction, emptyDataAction)) {} assert(sigs_ != NULL); // Return the state data_pos_ = data_pos; diff --git a/src/lib/datasrc/memory/rdata_reader.h b/src/lib/datasrc/memory/rdata_reader.h index 6134120b38..ff631028ec 100644 --- a/src/lib/datasrc/memory/rdata_reader.h +++ b/src/lib/datasrc/memory/rdata_reader.h @@ -269,6 +269,8 @@ private: // The positions in data. size_t data_pos_, spec_pos_, length_pos_; size_t sig_pos_, sig_data_pos_; + Result nextInternal(const NameAction& name_action, + const DataAction& data_action); }; } diff --git a/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc b/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc index 3ecf935581..6f0e8a5848 100644 --- a/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc +++ b/src/lib/datasrc/memory/tests/rdata_serialization_unittest.cc @@ -351,6 +351,50 @@ public: } }; +// Decode using reader with the return value of next, but after the reader +// was used and rewund. +class RewundDecoder { +public: + static void decode(const isc::dns::RRClass& rrclass, + const isc::dns::RRType& rrtype, + size_t rdata_count, size_t sig_count, size_t, + const vector& encoded_data, + MessageRenderer& renderer) + { + RdataReader reader(rrclass, rrtype, encoded_data.size(), + &encoded_data[0], rdata_count, sig_count); + // Use the reader first and rewind it + reader.iterateSig(); + 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(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: @@ -391,8 +435,72 @@ public: } }; -typedef ::testing::Types DecoderStyles; +// This one does not adhere to the usual way the reader is used, trying +// to confuse it. It iterates part of the data manually and then reads +// the rest through iterate. It also reads the signatures in the middle +// of rendering. +template +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* 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: + static void decode(const isc::dns::RRClass& rrclass, + const isc::dns::RRType& rrtype, + size_t rdata_count, size_t sig_count, size_t, + const vector& encoded_data, + MessageRenderer& renderer) + { + vector data; + MessageRenderer* current; + RdataReader reader(rrclass, rrtype, encoded_data.size(), + &encoded_data[0], rdata_count, sig_count, + boost::bind(renderNameField, &renderer, + additionalRequired(rrtype), _1, _2), + boost::bind(appendData, &data, ¤t, _1, _2)); + if (start_sig) { + current = NULL; + reader.nextSig(); + } + // Render first part of data. If there's none, return empty Result and + // do nothing. + if (start_data) { + current = &renderer; + reader.next(); + } + // Now, we let all sigs to be copied to data. We disable the + // renderer for this. + current = NULL; + reader.iterateSig(); + // Now return the renderer and render the rest of the data + current = &renderer; + reader.iterate(); + // Now, this should not break anything and should be valid, but should + // return ends. + EXPECT_FALSE(reader.next()); + EXPECT_FALSE(reader.nextSig()); + // Render the name and the sigs + renderer.writeName(dummy_name2); + renderer.writeData(&data[0], data.size()); + } +}; + +typedef ::testing::Types, HybridDecoder, + HybridDecoder, + HybridDecoder > + DecoderStyles; TYPED_TEST_CASE(RdataEncodeDecodeTest, DecoderStyles); void