123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- // Copyright (C) 2011 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/tests/unittest_util.h>
- #include <dns/exceptions.h>
- #include <dns/rdata.h>
- #include <dns/rdataclass.h>
- #include <dns/rrclass.h>
- #include <dns/rrtype.h>
- #include <gtest/gtest.h>
- #include <dns/tests/rdata_unittest.h>
- #include <boost/lexical_cast.hpp>
- #include <string>
- #include <vector>
- using namespace std;
- using boost::lexical_cast;
- using isc::UnitTestUtil;
- using namespace isc::dns;
- using namespace isc::dns::rdata;
- namespace {
- // Template for shared tests for NSEC and NSEC3 bitmaps
- template <typename RDATA_TYPE>
- class NSECLikeBitmapTest : public RdataTest {
- protected:
- RDATA_TYPE fromText(const string& rdata_text) {
- return (RDATA_TYPE(rdata_text));
- }
- vector<RDATA_TYPE> compare_set; // used in compare() tests
- void compareCheck() const {
- typename vector<RDATA_TYPE>::const_iterator it;
- typename vector<RDATA_TYPE>::const_iterator const it_end =
- compare_set.end();
- for (it = compare_set.begin(); it != it_end - 1; ++it) {
- SCOPED_TRACE("compare " + it->toText() + " to " +
- (it + 1)->toText());
- EXPECT_GT(0, (*it).compare(*(it + 1)));
- EXPECT_LT(0, (*(it + 1)).compare(*it));
- }
- }
- // These depend on the specific RR type. We use specialized methods
- // for them.
- static RRType getType(); // return either RRType::NSEC() or NSEC3()
- static string getWireFilePrefix();
- static string getCommonText(); // commonly used part of textual form
- };
- // Instantiate specific typed tests
- typedef ::testing::Types<generic::NSEC, generic::NSEC3> TestRdataTypes;
- TYPED_TEST_CASE(NSECLikeBitmapTest, TestRdataTypes);
- // NSEC and NSEC3 bitmaps have some subtle differences, in which case we
- // need to test them separately. Using these typedef type names with TEST_F
- // will do the trick.
- typedef NSECLikeBitmapTest<generic::NSEC3> NSEC3BitmapTest;
- typedef NSECLikeBitmapTest<generic::NSEC> NSECBitmapTest;
- template <>
- string
- NSECLikeBitmapTest<generic::NSEC>::getWireFilePrefix() {
- return ("rdata_nsec_");
- }
- template <>
- RRType
- NSECLikeBitmapTest<generic::NSEC>::getType() {
- return (RRType::NSEC());
- }
- template <>
- string
- NSECLikeBitmapTest<generic::NSEC3>::getWireFilePrefix() {
- return ("rdata_nsec3_");
- }
- template <>
- RRType
- NSECLikeBitmapTest<generic::NSEC3>::getType() {
- return (RRType::NSEC3());
- }
- template <>
- string
- NSECLikeBitmapTest<generic::NSEC>::getCommonText() {
- return ("next. ");
- }
- template <>
- string
- NSECLikeBitmapTest<generic::NSEC3>::getCommonText() {
- return ("1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR ");
- }
- // Tests against various types of bogus NSEC/NSEC3 type bitmaps.
- // The syntax and semantics are common for both RR types, and our
- // implementation of that part is shared, so in theory it should be sufficient
- // to test for only one RR type. But we check for both just in case.
- TYPED_TEST(NSECLikeBitmapTest, createFromWire) {
- // A malformed NSEC bitmap length field that could cause overflow.
- EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
- (this->getWireFilePrefix() +
- "fromWire4.wire").c_str()),
- DNSMessageFORMERR);
- // The bitmap field is incomplete (only the first byte is included)
- EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
- (this->getWireFilePrefix() +
- "fromWire5.wire").c_str()),
- DNSMessageFORMERR);
- // Bitmap length is 0, which is invalid.
- EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
- (this->getWireFilePrefix() +
- "fromWire6.wire").c_str()),
- DNSMessageFORMERR);
- // Too large bitmap length with a short buffer.
- EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
- (this->getWireFilePrefix() +
- "fromWire3").c_str()),
- DNSMessageFORMERR);
- // A boundary case: longest possible bitmaps (32 maps). This should be
- // accepted.
- EXPECT_NO_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
- (this->getWireFilePrefix() +
- "fromWire7.wire").c_str()));
- // Another boundary condition: 33 bitmaps, which should be rejected.
- EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
- (this->getWireFilePrefix() +
- "fromWire8.wire").c_str()),
- DNSMessageFORMERR);
- // Disordered bitmap window blocks.
- EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
- (this->getWireFilePrefix() +
- "fromWire9.wire").c_str()),
- DNSMessageFORMERR);
- // Bitmap ending with all-zero bytes. Not necessarily harmful except
- // the additional overhead of parsing, but invalid according to the
- // spec anyway.
- EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
- (this->getWireFilePrefix() +
- "fromWire10.wire").c_str()),
- DNSMessageFORMERR);
- }
- TYPED_TEST(NSECLikeBitmapTest, badText) {
- // redundant space after the sequence
- EXPECT_THROW(this->fromText(this->getCommonText() + "A "),
- InvalidRdataText);
- }
- // This tests the result of toText() with various kinds of NSEC/NSEC3 bitmaps.
- // It also tests the "from text" constructor as a result.
- TYPED_TEST(NSECLikeBitmapTest, toText) {
- // A simple case (some commonly seen RR types in NSEC(3) bitmaps)
- string rdata_text = this->getCommonText() + "NS SOA RRSIG DNSKEY";
- EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
- // Similar to above, but involves more than one bitmap window blocks.
- rdata_text = this->getCommonText() + "NS DLV";
- EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
- // Make sure all possible bits in a one-octet bitmap field are handled
- // correctly.
- // We use the range around 1024 (reasonably higher number) so it's
- // unlikely that they have predefined mnemonic and can be safely converted
- // to TYPEnnnn by toText().
- for (unsigned int i = 1024; i < 1032; ++i) {
- rdata_text = this->getCommonText() + "TYPE" + lexical_cast<string>(i);
- EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
- }
- // Make sure all possible 32 octets in a longest possible block are
- // handled correctly.
- for (unsigned int i = 1024; i < 1024 + 256; i += 8) {
- rdata_text = this->getCommonText() + "TYPE" + lexical_cast<string>(i);
- EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
- }
- // Check for the highest window block.
- rdata_text = this->getCommonText() + "TYPE65535";
- EXPECT_EQ(rdata_text, this->fromText(rdata_text).toText());
- }
- TYPED_TEST(NSECLikeBitmapTest, compare) {
- // Bit map: [win=0][len=1] 00000010
- this->compare_set.push_back(this->fromText(this->getCommonText() + "SOA"));
- // Bit map: [win=0][len=1] 00000010, [win=4][len=1] 10000000
- this->compare_set.push_back(this->fromText(this->getCommonText() +
- "SOA TYPE1024"));
- // Bit map: [win=0][len=1] 00100000
- this->compare_set.push_back(this->fromText(this->getCommonText() + "NS"));
- // Bit map: [win=0][len=1] 00100010
- this->compare_set.push_back(this->fromText(this->getCommonText() +
- "NS SOA"));
- // Bit map: [win=0][len=2] 00100000, 00000001
- this->compare_set.push_back(this->fromText(this->getCommonText() +
- "NS MX"));
- // Bit map: [win=4][len=1] 10000000
- this->compare_set.push_back(this->fromText(this->getCommonText() +
- "TYPE1024"));
- this->compareCheck();
- }
- // NSEC bitmaps must not be empty
- TEST_F(NSECBitmapTest, emptyMap) {
- EXPECT_THROW(this->fromText("next.example").toText(), InvalidRdataText);
- EXPECT_THROW(this->rdataFactoryFromFile(this->getType(), RRClass::IN(),
- (this->getWireFilePrefix() +
- "fromWire16.wire").c_str()),
- DNSMessageFORMERR);
- }
- // NSEC3 bitmaps can be empty
- TEST_F(NSEC3BitmapTest, emptyMap) {
- // Read wire data wit an empty NSEC3 bitmap. This should succeed.
- vector<uint8_t> data;
- UnitTestUtil::readWireData((this->getWireFilePrefix() +
- "fromWire16.wire").c_str(), data);
- InputBuffer buffer(&data[0], data.size());
- const uint16_t rdlen = buffer.readUint16();
- const generic::NSEC3 empty_nsec3 =
- dynamic_cast<const generic::NSEC3&>(*createRdata(
- RRType::NSEC3(), RRClass::IN(),
- buffer, rdlen));
- // Check the toText() result.
- EXPECT_EQ("1 0 1 7373737373 D1K6GQ38D1K6GQ38D1K6GQ38D1K6GQ38",
- empty_nsec3.toText());
- // Check the toWire() result.
- OutputBuffer obuffer(0);
- obuffer.writeUint16(rdlen);
- empty_nsec3.toWire(obuffer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, obuffer.getData(),
- obuffer.getLength(), &data[0], data.size());
- // Same for MessageRenderer.
- obuffer.clear();
- MessageRenderer renderer;
- renderer.writeUint16(rdlen);
- empty_nsec3.toWire(renderer);
- EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, renderer.getData(),
- renderer.getLength(), &data[0], data.size());
- }
- }
|