Commit 76263303 authored by Stephen Morris's avatar Stephen Morris

[1605] Added basic class and tests (all of which fail)

Currently no RRSIG-related methods added yet.
parent aacfc3fe
......@@ -21,6 +21,7 @@ libdatasrc_la_SOURCES += static_datasrc.h static_datasrc.cc
libdatasrc_la_SOURCES += sqlite3_datasrc.h sqlite3_datasrc.cc
libdatasrc_la_SOURCES += query.h query.cc
libdatasrc_la_SOURCES += cache.h cache.cc
libdatasrc_la_SOURCES += rbnode_rrset.h
libdatasrc_la_SOURCES += rbtree.h
libdatasrc_la_SOURCES += zonetable.h zonetable.cc
libdatasrc_la_SOURCES += zone.h
......
// Copyright (C) 2012 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.
#ifndef __RBNODE_RRSET_H
#define __RBNODE_RRSET_H
#include <dns/messagerenderer.h>
#include <dns/name.h>
#include <dns/rrclass.h>
#include <dns/rrset.h>
#include <dns/rrttl.h>
#include <dns/rrtype.h>
#include <util/buffer.h>
#include <string>
namespace isc {
namespace datasrc {
/// \brief Special RRset for optimiing memory datasource requirement
///
/// To speed up the performance of the in-memory data source, at load time
/// associate relevant "additional section" data with each RRset in the
/// data source.
///
/// This class, derived from AbstractRRset, holds a "const" pointer to the
/// underlying RRset object. All calls to methods on the class are passed to
/// the underlying object. However, there are some restrictions:
///
/// - Calls to methods that change attributes of the underlying RRset (such as
/// TTL or Name) cause an exception to be thrown. The in-memory data source
/// does not allow modification of these attributes.
/// - Calls that modify the associated RRSIGs of the RRset are allowed (even
/// though the pointer is to a "const" object). The reason here is because
/// RRSIGs are added to the in-memory data source after the RBNodeRRset
/// objects have been created. Thus there has to be the capability of
/// modifying this information.
///
/// The class is not derived from RRset itself to simplify coding: part of the
/// loading of the memory data source is handled in the BIND 10 "libdns++"
/// code, which creates RRsets and passes them to the data source code. This
/// does not have to be altered if encapsulation, rather than inheritcance, is
/// used.
// Note: non-Doxygen-documented methods are documented in the base class.
class RBNodeRRset : public isc::dns::AbstractRRset {
private:
// Note: The copy constructor and the assignment operator are intentionally
// defined as private as we would normally not duplicate a RBNodeRRset.
RBNodeRRset(const RBNodeRRset& source);
RBNodeRRset& operator=(const RBNodeRRset& source);
public:
/// \brief Usual Constructor
///
/// Creates an RBNodeRRset from the pointer to the RRset passed to it.
RBNodeRRset(const isc::dns::ConstRRsetPtr& rrset) : rrset_(rrset),
n("a.com"), c("HS"), t("A"), ttl(0) {}
/// \brief Destructor
virtual ~RBNodeRRset() {}
// Getter and Setter Methods
//
// The getter methods pass the call through to the underlying RRset. The
// setter methods thrown an exception - this specialisation of the RRset
// object does not expect the underlying RRset to be modified.
virtual unsigned int getRdataCount() const {
return (0);
}
virtual const isc::dns::Name& getName() const {
return (n);
}
virtual const isc::dns::RRClass& getClass() const {
return (c);
}
virtual const isc::dns::RRType& getType() const {
return (t);
}
virtual const isc::dns::RRTTL& getTTL() const {
return (ttl);
}
virtual void setName(const isc::dns::Name&) {
}
virtual void setTTL(const isc::dns::RRTTL&) {
}
virtual std::string toText() const {
return (std::string());
}
virtual unsigned int toWire(isc::dns::AbstractMessageRenderer& /*renderer*/) const {
return (-1);
}
virtual unsigned int toWire(isc::util::OutputBuffer& /*buffer*/) const {
return (-1);
}
virtual void addRdata(isc::dns::rdata::ConstRdataPtr) {
}
virtual void addRdata(const isc::dns::rdata::Rdata&) {
}
virtual isc::dns::RdataIteratorPtr getRdataIterator() const {
isc::dns::BasicRRset b(isc::dns::Name("example.com"),
isc::dns::RRClass("IN"),
isc::dns::RRType("A"),
isc::dns::RRTTL(1));
return (b.getRdataIterator());
}
virtual isc::dns::RRsetPtr getRRsig() const {
return (isc::dns::RRsetPtr());
}
virtual void addRRsig(const isc::dns::rdata::ConstRdataPtr& /*rdata*/) {
}
virtual void addRRsig(const isc::dns::rdata::RdataPtr& /*rdata*/) {
}
virtual void addRRsig(const AbstractRRset& /*sigs*/) {
}
virtual void addRRsig(const isc::dns::ConstRRsetPtr& /*sigs*/) {
}
virtual void addRRsig(const isc::dns::RRsetPtr& /*sigs*/) {
}
virtual void removeRRsig() {
}
/// \brief Return underlying RRset pointer
virtual isc::dns::ConstRRsetPtr getUnderlyingRRset() const {
return rrset_;
}
private:
isc::dns::ConstRRsetPtr rrset_; ///< Underlying RRset
isc::dns::Name n;
isc::dns::RRClass c;
isc::dns::RRType t;
isc::dns::RRTTL ttl;
};
} // namespace datasrc
} // namespace isc
#endif // __RBNODE_RRSET_H
......@@ -79,6 +79,7 @@ run_unittests_sqlite3_LDADD = $(common_ldadd)
# In-memory datasource tests
run_unittests_memory_SOURCES = $(common_sources)
run_unittests_memory_SOURCES += memory_datasrc_unittest.cc
run_unittests_memory_SOURCES += rbnode_rrset_unittest.cc
run_unittests_memory_SOURCES += $(top_srcdir)/src/lib/datasrc/memory_datasrc.cc
run_unittests_memory_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
......@@ -109,19 +110,21 @@ endif
endif
EXTRA_DIST = testdata/brokendb.sqlite3
EXTRA_DIST += testdata/diffs.sqlite3
EXTRA_DIST += testdata/example2.com
EXTRA_DIST += testdata/example2.com.sqlite3
EXTRA_DIST += testdata/example.com.signed
EXTRA_DIST += testdata/example.org
EXTRA_DIST += testdata/example.org.nsec3-signed
EXTRA_DIST += testdata/example.org.nsec3-signed-noparam
EXTRA_DIST += testdata/example.org.sqlite3
EXTRA_DIST += testdata/example2.com
EXTRA_DIST += testdata/example2.com.sqlite3
EXTRA_DIST += testdata/mkbrokendb.c
EXTRA_DIST += testdata/root.zone
EXTRA_DIST += testdata/rrset_toWire1
EXTRA_DIST += testdata/rrset_toWire2
EXTRA_DIST += testdata/rwtest.sqlite3
EXTRA_DIST += testdata/sql1.example.com.signed
EXTRA_DIST += testdata/sql2.example.com.signed
EXTRA_DIST += testdata/test-root.sqlite3
EXTRA_DIST += testdata/test.sqlite3
EXTRA_DIST += testdata/test.sqlite3.nodiffs
EXTRA_DIST += testdata/rwtest.sqlite3
EXTRA_DIST += testdata/diffs.sqlite3
// Copyright (C) 2012 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 <stdexcept>
#include <exceptions/exceptions.h>
#include <dns/rdataclass.h>
#include <datasrc/rbnode_rrset.h>
#include <gtest/gtest.h>
#include <dns/tests/unittest_util.h>
using isc::UnitTestUtil;
using namespace std;
using namespace isc;
using namespace isc::datasrc;
using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace isc::util;
// These tests are very similar to those for RRset - indeed, the files was
// created from those tests. However, the significant difference in behaviour
// between RRset and RBNodeRRset - that the "set" methods in the latter mostly
// result in exceptions being thrown - preclude use of full type
// parameterisation of the tests.
namespace {
class RBNodeRRsetTest : public ::testing::Test {
protected:
RBNodeRRsetTest() :
buffer(0), renderer(buffer),
test_name("test.example.com"),
test_domain("example.com"),
test_nsname("ns.example.com"),
rrset_a(ConstRRsetPtr(new RRset(
test_name, RRClass::IN(), RRType::A(), RRTTL(3600)))),
rrset_a_empty(ConstRRsetPtr(new RRset(
test_name, RRClass::IN(), RRType::A(), RRTTL(3600)))),
rrset_ns(ConstRRsetPtr(new RRset(
test_domain, RRClass::IN(), RRType::NS(), RRTTL(86400)))),
rrset_ch_txt(ConstRRsetPtr(new RRset(
test_domain, RRClass::CH(), RRType::TXT(), RRTTL(0))))
{
// Add a couple of Rdata elements to an RRset. The easiest way to
// do this is to override the "const" restrictions. As this is a test,
// we don't feel too bad about doing so.
AbstractRRset* rrset =
const_cast<AbstractRRset*>(rrset_a.getUnderlyingRRset().get());
rrset->addRdata(in::A("192.0.2.1"));
rrset->addRdata(in::A("192.0.2.2"));
}
OutputBuffer buffer;
MessageRenderer renderer;
Name test_name;
Name test_domain;
Name test_nsname;
RBNodeRRset rrset_a;
RBNodeRRset rrset_a_empty;
RBNodeRRset rrset_ns;
RBNodeRRset rrset_ch_txt;
std::vector<unsigned char> wiredata;
// max number of Rdata objects added to a test RRset object.
// this is an arbitrary chosen limit, but should be sufficiently large
// in practice and reasonable even as an extreme test case.
static const int MAX_RDATA_COUNT = 100;
};
TEST_F(RBNodeRRsetTest, getRdataCount) {
EXPECT_EQ(0, rrset_a_empty.getRdataCount());
EXPECT_EQ(2, rrset_a.getRdataCount());
}
TEST_F(RBNodeRRsetTest, getName) {
EXPECT_EQ(test_name, rrset_a.getName());
EXPECT_EQ(test_domain, rrset_ns.getName());
}
TEST_F(RBNodeRRsetTest, getClass) {
EXPECT_EQ(RRClass("IN"), rrset_a.getClass());
EXPECT_EQ(RRClass("CH"), rrset_ch_txt.getClass());
}
TEST_F(RBNodeRRsetTest, getType) {
EXPECT_EQ(RRType("A"), rrset_a.getType());
EXPECT_EQ(RRType("NS"), rrset_ns.getType());
EXPECT_EQ(RRType("TXT"), rrset_ch_txt.getType());
}
TEST_F(RBNodeRRsetTest, getTTL) {
EXPECT_EQ(RRTTL(3600), rrset_a.getTTL());
EXPECT_EQ(RRTTL(86400), rrset_ns.getTTL());
EXPECT_EQ(RRTTL(0), rrset_ch_txt.getTTL());
}
TEST_F(RBNodeRRsetTest, setName) {
EXPECT_THROW(rrset_a.setName(test_nsname), NotImplemented);
}
TEST_F(RBNodeRRsetTest, setTTL) {
EXPECT_THROW(rrset_a.setTTL(RRTTL(86400)), NotImplemented);
}
TEST_F(RBNodeRRsetTest, toText) {
EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n"
"test.example.com. 3600 IN A 192.0.2.2\n",
rrset_a.toText());
// toText() cannot be performed for an empty RRset.
EXPECT_THROW(rrset_a_empty.toText(), EmptyRRset);
}
TEST_F(RBNodeRRsetTest, toWireRenderer) {
rrset_ns.addRdata(generic::NS(test_nsname));
rrset_a.toWire(renderer);
rrset_ns.toWire(renderer);
UnitTestUtil::readWireData("rrset_toWire2", wiredata);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
buffer.getLength(), &wiredata[0], wiredata.size());
// toWire() cannot be performed for an empty RRset.
renderer.clear();
EXPECT_THROW(rrset_a_empty.toWire(renderer), EmptyRRset);
}
TEST_F(RBNodeRRsetTest, toWireBuffer) {
rrset_a.toWire(buffer);
UnitTestUtil::readWireData("rrset_toWire1", wiredata);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData, buffer.getData(),
buffer.getLength(), &wiredata[0], wiredata.size());
// toWire() cannot be performed for an empty RRset.
buffer.clear();
EXPECT_THROW(rrset_a_empty.toWire(buffer), EmptyRRset);
}
TEST_F(RBNodeRRsetTest, addRdata) {
EXPECT_THROW(rrset_a.addRdata(in::A("192.0.2.3")), NotImplemented);
// Check the same goes for tryin g to add the wrong type of data
EXPECT_THROW(rrset_a.addRdata(generic::NS(test_nsname)), NotImplemented);
}
TEST_F(RBNodeRRsetTest, addRdataPtr) {
EXPECT_THROW(rrset_a_empty.addRdata(createRdata(rrset_a_empty.getType(),
rrset_a_empty.getClass(),
"192.0.2.1")),
NotImplemented);
}
TEST_F(RBNodeRRsetTest, getRDataIterator) {
RdataIteratorPtr it = rrset_a.getRdataIterator();
for (int i = 0; i < 2; ++i) {
ASSERT_FALSE(it->isLast());
ASSERT_EQ(0, it->getCurrent().compare(in::A("192.0.2.1")));
it->next();
ASSERT_FALSE(it->isLast());
ASSERT_EQ(0, it->getCurrent().compare(in::A("192.0.2.2")));
it->next();
ASSERT_TRUE(it->isLast());
// Should be able repeat the iteration by calling first().
it->first();
}
}
// test operator<<. We simply confirm it appends the result of toText().
TEST_F(RBNodeRRsetTest, LeftShiftOperator) {
ostringstream oss;
oss << rrset_a;
EXPECT_EQ("test.example.com. 3600 IN A 192.0.2.1\n"
"test.example.com. 3600 IN A 192.0.2.2\n", oss.str());
}
} // Anonymous namespace
#
# Rendering an IN/A RRset containing 2 RRs:
# test.example.com. 3600 IN A 192.0.2.1
# test.example.com. 3600 IN A 192.0.2.2
#
#(4) t e s t (7) e x a m p l e (3) c o m .
04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
# type/class: A = 1, IN = 1
00 01 00 01
# TTL: 3600
00 00 0e 10
#6 7
# RDLENGTH: 4
00 04
# RDATA: 192.0.2.1
c0 00 02 01
#
# 2nd RR: mostly the same except the RDATA
04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
00 01 00 01
00 00 0e 10
00 04
c0 00 02 02
#
# Rendering an IN/A RRset and NS RRset as follows:
# test.example.com. 3600 IN A 192.0.2.1
# test.example.com. 3600 IN A 192.0.2.2
# example.com. 1D IN NS ns.example.com.
# Names will be compressed when possible.
#
# 0 1 2 3 4 5
#(4) t e s t (7) e x a m p l e (3) c o m .
04 74 65 73 74 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
# type/class: A = 1, IN = 1
00 01 00 01
# TTL: 3600
00 00 0e 10
#6 7
# RDLENGTH: 4
00 04
# RDATA: 192.0.2.1
c0 00 02 01
#
# 2nd RR: the owner name is compresed
c0 00
00 01 00 01
00 00 0e 10
00 04
c0 00 02 02
# 3rd RR: the owner name and NS name are compressed
# pointing to the 5th octet of the owner name of the 1st RR
c0 05
# type/class: NS = 2, IN = 1
00 02 00 01
# TTL: 1D = 86400sec = 0x15180
00 01 51 80
# RDLENGTH: 5 octets
00 05
# NSDNAME: "ns." + compression pointer
#(2) n s
02 6e 73 c0 05
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment