diff options
Diffstat (limited to 'src/lib/dns/tests/rdata_sshfp_unittest.cc')
-rw-r--r-- | src/lib/dns/tests/rdata_sshfp_unittest.cc | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/src/lib/dns/tests/rdata_sshfp_unittest.cc b/src/lib/dns/tests/rdata_sshfp_unittest.cc new file mode 100644 index 0000000..2bf88f3 --- /dev/null +++ b/src/lib/dns/tests/rdata_sshfp_unittest.cc @@ -0,0 +1,311 @@ +// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <algorithm> +#include <string> + +#include <util/buffer.h> +#include <dns/messagerenderer.h> +#include <dns/rdata.h> +#include <dns/rdataclass.h> +#include <dns/rrclass.h> +#include <dns/rrtype.h> + +#include <gtest/gtest.h> + +#include <dns/tests/unittest_util.h> +#include <dns/tests/rdata_unittest.h> +#include <util/unittests/wiredata.h> + +#include <boost/algorithm/string.hpp> + +using namespace std; +using namespace isc; +using namespace isc::dns; +using namespace isc::util; +using namespace isc::dns::rdata; +using isc::UnitTestUtil; +using isc::util::unittests::matchWireData; + +namespace { +class Rdata_SSHFP_Test : public RdataTest { +protected: + Rdata_SSHFP_Test() : + sshfp_txt("2 1 123456789abcdef67890123456789abcdef67890"), + rdata_sshfp(sshfp_txt) + {} + + void checkFromText_None(const string& rdata_str) { + checkFromText<generic::SSHFP, isc::Exception, isc::Exception>( + rdata_str, rdata_sshfp, false, false); + } + + void checkFromText_InvalidText(const string& rdata_str) { + checkFromText<generic::SSHFP, InvalidRdataText, InvalidRdataText>( + rdata_str, rdata_sshfp, true, true); + } + + void checkFromText_LexerError(const string& rdata_str) { + checkFromText + <generic::SSHFP, InvalidRdataText, MasterLexer::LexerError>( + rdata_str, rdata_sshfp, true, true); + } + + void checkFromText_BadString(const string& rdata_str) { + checkFromText + <generic::SSHFP, InvalidRdataText, isc::Exception>( + rdata_str, rdata_sshfp, true, false); + } + + const string sshfp_txt; + const generic::SSHFP rdata_sshfp; +}; + +const uint8_t rdata_sshfp_wiredata[] = { + // algorithm + 0x02, + // fingerprint type + 0x01, + // fingerprint + 0x12, 0x34, 0x56, 0x78, + 0x9a, 0xbc, 0xde, 0xf6, + 0x78, 0x90, 0x12, 0x34, + 0x56, 0x78, 0x9a, 0xbc, + 0xde, 0xf6, 0x78, 0x90 +}; + +TEST_F(Rdata_SSHFP_Test, createFromText) { + // Basic test + checkFromText_None(sshfp_txt); + + // With different spacing + checkFromText_None("2 1 123456789abcdef67890123456789abcdef67890"); + + // Combination of lowercase and uppercase + checkFromText_None("2 1 123456789ABCDEF67890123456789abcdef67890"); + + // spacing in the fingerprint field + checkFromText_None("2 1 123456789abcdef67890 123456789abcdef67890"); + + // multi-line fingerprint field + checkFromText_None("2 1 ( 123456789abcdef67890\n 123456789abcdef67890 )"); + + // string constructor throws if there's extra text, + // but lexer constructor doesn't + checkFromText_BadString(sshfp_txt + "\n" + sshfp_txt); +} + +TEST_F(Rdata_SSHFP_Test, algorithmTypes) { + // Some of these may not be RFC conformant, but we relax the check + // in our code to work with algorithm and fingerprint types that may + // show up in the future. + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 1 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("2 1 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("3 1 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("128 1 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("255 1 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 1 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 2 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 3 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 128 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 255 12ab")); + + // 0 is reserved, but we allow that too + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("0 1 12ab")); + EXPECT_NO_THROW(const generic::SSHFP rdata_sshfp("1 0 12ab")); + + // > 255 would be broken + EXPECT_THROW(const generic::SSHFP rdata_sshfp("256 1 12ab"), + InvalidRdataText); + EXPECT_THROW(const generic::SSHFP rdata_sshfp("2 256 12ab"), + InvalidRdataText); +} + +TEST_F(Rdata_SSHFP_Test, badText) { + checkFromText_LexerError("1"); + checkFromText_LexerError("ONE 2 123456789abcdef67890123456789abcdef67890"); + checkFromText_LexerError("1 TWO 123456789abcdef67890123456789abcdef67890"); + checkFromText_InvalidText("1 2 BUCKLEMYSHOE"); + checkFromText_InvalidText(sshfp_txt + " extra text"); + + // yes, these are redundant to the last test cases in algorithmTypes + checkFromText_InvalidText( + "2345 1 123456789abcdef67890123456789abcdef67890"); + checkFromText_InvalidText( + "2 1234 123456789abcdef67890123456789abcdef67890"); + + // negative values are trapped in the lexer rather than the constructor + checkFromText_LexerError("-2 1 123456789abcdef67890123456789abcdef67890"); + checkFromText_LexerError("2 -1 123456789abcdef67890123456789abcdef67890"); +} + +TEST_F(Rdata_SSHFP_Test, copyAndAssign) { + // Copy construct + generic::SSHFP rdata_sshfp2(rdata_sshfp); + EXPECT_EQ(0, rdata_sshfp.compare(rdata_sshfp2)); + + // Assignment, mainly to confirm it doesn't cause disruption. + rdata_sshfp2 = rdata_sshfp; + EXPECT_EQ(0, rdata_sshfp.compare(rdata_sshfp2)); +} + +TEST_F(Rdata_SSHFP_Test, createFromWire) { + // Basic test + EXPECT_EQ(0, rdata_sshfp.compare( + *rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire"))); + // Combination of lowercase and uppercase + EXPECT_EQ(0, rdata_sshfp.compare( + *rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire2"))); + // algorithm=1, fingerprint=1 + EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire3.wire")); + + // algorithm=255, fingerprint=1 + EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire4.wire")); + + // algorithm=0, fingerprint=1 + EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire5.wire")); + + // algorithm=5, fingerprint=0 + EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire6.wire")); + + // algorithm=255, fingerprint=255 + EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire7.wire")); + + // short fingerprint data + EXPECT_NO_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire8.wire")); + + // fingerprint is shorter than rdata len + EXPECT_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire9"), + InvalidBufferPosition); + + // fingerprint is missing + EXPECT_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire10"), + InvalidBufferPosition); + + // all rdata is missing + EXPECT_THROW(rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire11"), + InvalidBufferPosition); +} + +TEST_F(Rdata_SSHFP_Test, createFromParams) { + const generic::SSHFP rdata_sshfp2( + 2, 1, "123456789abcdef67890123456789abcdef67890"); + EXPECT_EQ(0, rdata_sshfp2.compare(rdata_sshfp)); +} + +TEST_F(Rdata_SSHFP_Test, toText) { + EXPECT_TRUE(boost::iequals(sshfp_txt, rdata_sshfp.toText())); + + const string sshfp_txt2("2 1"); + const generic::SSHFP rdata_sshfp2(sshfp_txt2); + EXPECT_TRUE(boost::iequals(sshfp_txt2, rdata_sshfp2.toText())); + + const generic::SSHFP rdata_sshfp3("2 1 "); + EXPECT_TRUE(boost::iequals(sshfp_txt2, rdata_sshfp3.toText())); +} + +TEST_F(Rdata_SSHFP_Test, toWire) { + this->obuffer.clear(); + rdata_sshfp.toWire(this->obuffer); + + EXPECT_EQ(sizeof (rdata_sshfp_wiredata), + this->obuffer.getLength()); + + matchWireData(rdata_sshfp_wiredata, sizeof(rdata_sshfp_wiredata), + obuffer.getData(), obuffer.getLength()); +} + +TEST_F(Rdata_SSHFP_Test, compare) { + const generic::SSHFP rdata_sshfp2("2 1"); + EXPECT_EQ(-1, rdata_sshfp2.compare(rdata_sshfp)); + EXPECT_EQ(1, rdata_sshfp.compare(rdata_sshfp2)); +} + +TEST_F(Rdata_SSHFP_Test, getAlgorithmNumber) { + EXPECT_EQ(2, rdata_sshfp.getAlgorithmNumber()); +} + +TEST_F(Rdata_SSHFP_Test, getFingerprintType) { + EXPECT_EQ(1, rdata_sshfp.getFingerprintType()); +} + +TEST_F(Rdata_SSHFP_Test, getFingerprint) { + const std::vector<uint8_t>& fingerprint = + rdata_sshfp.getFingerprint(); + + EXPECT_EQ(rdata_sshfp.getFingerprintLength(), + fingerprint.size()); + for (size_t i = 0; i < fingerprint.size(); ++i) { + EXPECT_EQ(rdata_sshfp_wiredata[i + 2], + fingerprint.at(i)); + } +} + +TEST_F(Rdata_SSHFP_Test, getFingerprintLength) { + EXPECT_EQ(20, rdata_sshfp.getFingerprintLength()); +} + +TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromWire) { + const uint8_t rdf_wiredata[] = { + // algorithm + 0x04, + // fingerprint type + 0x09 + }; + + const generic::SSHFP rdf = + dynamic_cast<const generic::SSHFP&> + (*rdataFactoryFromFile(RRType("SSHFP"), RRClass("IN"), + "rdata_sshfp_fromWire12")); + + EXPECT_EQ(4, rdf.getAlgorithmNumber()); + EXPECT_EQ(9, rdf.getFingerprintType()); + EXPECT_EQ(0, rdf.getFingerprintLength()); + + this->obuffer.clear(); + rdf.toWire(this->obuffer); + + EXPECT_EQ(2, this->obuffer.getLength()); + + matchWireData(rdf_wiredata, sizeof(rdf_wiredata), + obuffer.getData(), obuffer.getLength()); +} + +TEST_F(Rdata_SSHFP_Test, emptyFingerprintFromString) { + const generic::SSHFP rdata_sshfp2("5 6"); + const uint8_t rdata_sshfp2_wiredata[] = { + // algorithm + 0x05, + // fingerprint type + 0x06 + }; + + EXPECT_EQ(5, rdata_sshfp2.getAlgorithmNumber()); + EXPECT_EQ(6, rdata_sshfp2.getFingerprintType()); + EXPECT_EQ(0, rdata_sshfp2.getFingerprintLength()); + + this->obuffer.clear(); + rdata_sshfp2.toWire(this->obuffer); + + EXPECT_EQ(2, this->obuffer.getLength()); + + matchWireData(rdata_sshfp2_wiredata, sizeof(rdata_sshfp2_wiredata), + obuffer.getData(), obuffer.getLength()); +} +} |