summaryrefslogtreecommitdiffstats
path: root/src/lib/dns/tests/rdata_unittest.cc
diff options
context:
space:
mode:
authorJeremy C. Reed <jreed@isc.org>2010-03-05 05:31:28 +0100
committerJeremy C. Reed <jreed@isc.org>2010-03-05 05:31:28 +0100
commit2e119c7e2290889e6d4fc0ee48ece416d8e2ad8a (patch)
treec0f79971ea76ee3615cfc52144ce1f3832b987c5 /src/lib/dns/tests/rdata_unittest.cc
parent- made AuthSrv construction exception-safe (diff)
downloadkea-2e119c7e2290889e6d4fc0ee48ece416d8e2ad8a.tar.xz
kea-2e119c7e2290889e6d4fc0ee48ece416d8e2ad8a.zip
Restructure trunk again.
This is based on ideas done in experiments/jreed-layout, but I manually did this again. Moved around directory structures. A single python subdirectory under src/lib for single "isc" module. No "cpp" directories. No pyshared or includes symlink trees. I tested running the c++ tests and python tests. I tested running run_bind10.sh from source tree (with nothing installed). I tested running bind10 from installed (after moving source). git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1120 e5f2f494-b856-4b98-b285-d166d9295462
Diffstat (limited to 'src/lib/dns/tests/rdata_unittest.cc')
-rw-r--r--src/lib/dns/tests/rdata_unittest.cc314
1 files changed, 314 insertions, 0 deletions
diff --git a/src/lib/dns/tests/rdata_unittest.cc b/src/lib/dns/tests/rdata_unittest.cc
new file mode 100644
index 0000000000..1173b7c060
--- /dev/null
+++ b/src/lib/dns/tests/rdata_unittest.cc
@@ -0,0 +1,314 @@
+// Copyright (C) 2010 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.
+
+// $Id$
+
+#include <vector>
+#include <string>
+#include <sstream>
+
+#include <dns/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 "unittest_util.h"
+#include "rdata_unittest.h"
+
+using isc::UnitTestUtil;
+using namespace std;
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+RdataTest::RdataTest() :
+ obuffer(0), renderer(obuffer),
+ rdata_nomatch(createRdata(RRType(0), RRClass(1), "\\# 0"))
+{}
+
+RdataPtr
+RdataTest::rdataFactoryFromFile(const RRType& rrtype, const RRClass& rrclass,
+ const char* datafile, size_t position)
+{
+ std::vector<unsigned char> data;
+ UnitTestUtil::readWireData(datafile, data);
+
+ InputBuffer buffer(&data[0], data.size());
+ buffer.setPosition(position);
+
+ uint16_t rdlen = buffer.readUint16();
+ return (createRdata(rrtype, rrclass, buffer, rdlen));
+}
+}
+}
+}
+
+namespace {
+class Rdata_Unknown_Test : public RdataTest {
+protected:
+ static string getLongestRdataTxt();
+ static void getLongestRdataWire(vector<uint8_t>& v);
+};
+
+string
+Rdata_Unknown_Test::getLongestRdataTxt()
+{
+ ostringstream oss;
+
+ oss << "\\# " << MAX_RDLENGTH << " ";
+ oss.fill('0');
+ oss << right << hex;
+ for (int i = 0; i < MAX_RDLENGTH; i++) {
+ oss << setw(2) << (i & 0xff);
+ }
+
+ return (oss.str());
+}
+
+void
+Rdata_Unknown_Test::getLongestRdataWire(vector<uint8_t>& v)
+{
+ unsigned char ch = 0;
+ for (int i = 0; i < MAX_RDLENGTH; ++i, ++ch) {
+ v.push_back(ch);
+ }
+}
+
+const string rdata_unknowntxt("\\# 4 a1b2c30d");
+const generic::Generic rdata_unknown(rdata_unknowntxt);
+// Wire-format data correspond to rdata_unknown. Note that it doesn't include
+// RDLENGTH
+const uint8_t wiredata_unknown[] = { 0xa1, 0xb2, 0xc3, 0x0d };
+
+// "Unknown" RR Type used for the test cases below. If/when we use this
+// type number as a "well-known" (probably experimental) type, we'll need to
+// renumber it.
+const RRType unknown_rrtype = RRType("TYPE65000");
+
+TEST_F(Rdata_Unknown_Test, createFromText)
+{
+ // valid construction. This also tests a normal case of "FromWire".
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1b2c30d").compare(
+ *rdataFactoryFromFile(unknown_rrtype, RRClass("IN"),
+ "testdata/rdata_unknown_fromWire")));
+ // upper case hexadecimal digits should also be okay.
+ EXPECT_EQ(0, generic::Generic("\\# 4 A1B2C30D").compare(
+ *rdataFactoryFromFile(unknown_rrtype, RRClass("IN"),
+ "testdata/rdata_unknown_fromWire")));
+ // 0-length RDATA should be accepted
+ EXPECT_EQ(0, generic::Generic("\\# 0").compare(
+ *rdataFactoryFromFile(unknown_rrtype, RRClass("IN"),
+ "testdata/rdata_unknown_fromWire", 6)));
+ // hex encoding can be space-separated
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1 b2c30d").compare(rdata_unknown));
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1b2 c30d").compare(rdata_unknown));
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1 b2 c3 0d").compare(rdata_unknown));
+ EXPECT_EQ(0, generic::Generic("\\# 4 a1\tb2c3 0d").compare(rdata_unknown));
+
+ // Max-length RDATA
+ vector<uint8_t> v;
+ getLongestRdataWire(v);
+ InputBuffer ibuffer(&v[0], v.size());
+ EXPECT_EQ(0, generic::Generic(getLongestRdataTxt()).compare(
+ generic::Generic(ibuffer, v.size())));
+
+ // the length field must match the encoding data length.
+ EXPECT_THROW(generic::Generic("\\# 4 1080c0ff00"), InvalidRdataLength);
+ EXPECT_THROW(generic::Generic("\\# 5 1080c0ff"), InvalidRdataLength);
+ // RDATA encoding part must consist of an even number of hex digits.
+ EXPECT_THROW(generic::Generic("\\# 1 1"), InvalidRdataText);
+ EXPECT_THROW(generic::Generic("\\# 1 ax"), InvalidRdataText);
+ // the length should be 16-bit unsigned integer
+ EXPECT_THROW(generic::Generic("\\# 65536 a1b2c30d"), InvalidRdataLength);
+ EXPECT_THROW(generic::Generic("\\# -1 a1b2c30d"), InvalidRdataLength);
+ EXPECT_THROW(generic::Generic("\\# 1.1 a1"), InvalidRdataText);
+ EXPECT_THROW(generic::Generic("\\# 0a 00010203040506070809"),
+ InvalidRdataText);
+ // should reject if the special token is missing.
+ EXPECT_THROW(generic::Generic("4 a1b2c30d"), InvalidRdataText);
+ // the special token, the RDLENGTH and the data must be space separated.
+ EXPECT_THROW(generic::Generic("\\#0"), InvalidRdataText);
+ EXPECT_THROW(generic::Generic("\\# 1ff"), InvalidRdataText);
+}
+
+TEST_F(Rdata_Unknown_Test, createFromWire)
+{
+ // normal case (including 0-length data) is covered in createFromText.
+
+ // buffer too short. the error should be detected in buffer read
+ EXPECT_THROW(rdataFactoryFromFile(unknown_rrtype, RRClass("IN"),
+ "testdata/rdata_unknown_fromWire", 8),
+ InvalidBufferPosition);
+
+ // too large data
+ vector<uint8_t> v;
+ getLongestRdataWire(v);
+ v.push_back(0); // making it too long
+ InputBuffer ibuffer(&v[0], v.size());
+ EXPECT_THROW(generic::Generic(ibuffer, v.size()), InvalidRdataLength);
+}
+
+// The following 3 sets of tests check the behavior of createRdata() variants
+// with the "unknown" RRtype. The result should be RRclass independent.
+TEST_F(Rdata_Unknown_Test, createRdataFromString)
+{
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("IN"),
+ rdata_unknowntxt)));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("CH"),
+ rdata_unknowntxt)));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("CLASS65000"),
+ rdata_unknowntxt)));
+}
+
+TEST_F(Rdata_Unknown_Test, createRdataFromWire)
+{
+ InputBuffer ibuffer(wiredata_unknown, sizeof(wiredata_unknown));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("IN"),
+ ibuffer, sizeof(wiredata_unknown))));
+
+ InputBuffer ibuffer2(wiredata_unknown, sizeof(wiredata_unknown));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("CH"),
+ ibuffer2, sizeof(wiredata_unknown))));
+
+ InputBuffer ibuffer3(wiredata_unknown, sizeof(wiredata_unknown));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("CLASS65000"),
+ ibuffer3, sizeof(wiredata_unknown))));
+}
+
+TEST_F(Rdata_Unknown_Test, createRdataByCopy)
+{
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("IN"), rdata_unknown)));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("CH"), rdata_unknown)));
+ EXPECT_EQ(0, rdata_unknown.compare(
+ *createRdata(unknown_rrtype, RRClass("CLASS65000"),
+ rdata_unknown)));
+}
+
+TEST_F(Rdata_Unknown_Test, copyConstruct)
+{
+ generic::Generic copy(rdata_unknown);
+ EXPECT_EQ(0, copy.compare(rdata_unknown));
+
+ // Check the copied data is valid even after the original is deleted
+ generic::Generic* copy2 = new generic::Generic(rdata_unknown);
+ generic::Generic copy3(*copy2);
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_unknown));
+}
+
+TEST_F(Rdata_Unknown_Test, assignment)
+{
+ generic::Generic copy("\\# 1 10");
+ copy = rdata_unknown;
+ EXPECT_EQ(0, copy.compare(rdata_unknown));
+
+ // Check if the copied data is valid even after the original is deleted
+ generic::Generic* copy2 = new generic::Generic(rdata_unknown);
+ generic::Generic copy3("\\# 1 10");
+ copy3 = *copy2;
+ delete copy2;
+ EXPECT_EQ(0, copy3.compare(rdata_unknown));
+
+ // Self assignment
+ copy = copy;
+ EXPECT_EQ(0, copy.compare(rdata_unknown));
+}
+
+TEST_F(Rdata_Unknown_Test, toText)
+{
+ EXPECT_EQ(rdata_unknowntxt, rdata_unknown.toText());
+ EXPECT_EQ(getLongestRdataTxt(),
+ generic::Generic(getLongestRdataTxt()).toText());
+}
+
+TEST_F(Rdata_Unknown_Test, toWireBuffer)
+{
+ rdata_unknown.toWire(obuffer);
+ EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+ obuffer.getData(), obuffer.getLength(),
+ wiredata_unknown, sizeof(wiredata_unknown));
+}
+
+TEST_F(Rdata_Unknown_Test, toWireRenderer)
+{
+ rdata_unknown.toWire(renderer);
+ EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+ obuffer.getData(), obuffer.getLength(),
+ wiredata_unknown, sizeof(wiredata_unknown));
+}
+
+TEST_F(Rdata_Unknown_Test, compare)
+{
+ // comparison as left-justified unsigned octet sequences:
+ EXPECT_EQ(0, rdata_unknown.compare(rdata_unknown));
+
+ generic::Generic rdata_unknown_small("\\# 4 00b2c3ff");
+ EXPECT_GT(0, rdata_unknown_small.compare(rdata_unknown));
+ EXPECT_LT(0, rdata_unknown.compare(rdata_unknown_small));
+
+ generic::Generic rdata_unknown_large("\\# 4 ffb2c300");
+ EXPECT_LT(0, rdata_unknown_large.compare(rdata_unknown));
+ EXPECT_GT(0, rdata_unknown.compare(rdata_unknown_large));
+
+ // the absence of an octet sorts before a zero octet.
+ generic::Generic rdata_unknown_short("\\# 3 a1b2c3");
+ EXPECT_GT(0, rdata_unknown_short.compare(rdata_unknown));
+ EXPECT_LT(0, rdata_unknown.compare(rdata_unknown_short));
+}
+
+TEST_F(Rdata_Unknown_Test, LeftShiftOperator)
+{
+ ostringstream oss;
+ oss << rdata_unknown;
+ EXPECT_EQ(rdata_unknown.toText(), oss.str());
+}
+
+//
+// Tests for global utility functions
+//
+TEST_F(RdataTest, compareNames)
+{
+ Name small("a.example");
+ Name large("example");
+
+ // Check the case where the order is different from the owner name
+ // comparison:
+ EXPECT_EQ(true, small > large);
+ EXPECT_EQ(-1, compareNames(small, large));
+ EXPECT_EQ(1, compareNames(large, small));
+
+ // Check case insensitive comparison:
+ Name small_upper("A.EXAMPLE");
+ EXPECT_EQ(0, compareNames(small, small_upper));
+
+ // the absence of an octet sorts before a zero octet.
+ Name large2("a.example2");
+ EXPECT_EQ(-1, compareNames(small, large2));
+ EXPECT_EQ(1, compareNames(large2, small));
+}
+}