diff options
Diffstat (limited to 'src/lib/dns/tests/rrset_collection_unittest.cc')
-rw-r--r-- | src/lib/dns/tests/rrset_collection_unittest.cc | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/src/lib/dns/tests/rrset_collection_unittest.cc b/src/lib/dns/tests/rrset_collection_unittest.cc new file mode 100644 index 0000000..be16ab5 --- /dev/null +++ b/src/lib/dns/tests/rrset_collection_unittest.cc @@ -0,0 +1,240 @@ +// 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 <dns/rrset_collection.h> +#include <dns/rrttl.h> +#include <dns/rdataclass.h> + +#include <gtest/gtest.h> + +#include <list> +#include <fstream> + +using namespace isc::dns; +using namespace isc::dns::rdata; +using namespace std; + +namespace { + +class RRsetCollectionTest : public ::testing::Test { +public: + RRsetCollectionTest() : + rrclass("IN"), + origin("example.org"), + collection(TEST_DATA_SRCDIR "/example.org", origin, rrclass) + {} + + const RRClass rrclass; + const Name origin; + RRsetCollection collection; +}; + +TEST_F(RRsetCollectionTest, istreamConstructor) { + std::ifstream fs(TEST_DATA_SRCDIR "/example.org"); + RRsetCollection collection2(fs, origin, rrclass); + + RRsetCollectionBase::Iterator iter = collection.begin(); + RRsetCollectionBase::Iterator iter2 = collection2.begin(); + while (iter != collection.end()) { + ASSERT_TRUE(iter2 != collection2.end()); + EXPECT_EQ((*iter).toText(), (*iter2).toText()); + ++iter; + ++iter2; + } + ASSERT_TRUE(iter2 == collection2.end()); +} + +template <typename T, typename TP> +void doFind(T& collection, const RRClass& rrclass) { + // Test the find() that returns ConstRRsetPtr + TP rrset = collection.find(Name("www.example.org"), rrclass, RRType::A()); + EXPECT_TRUE(rrset); + EXPECT_EQ(RRType::A(), rrset->getType()); + EXPECT_EQ(RRTTL(3600), rrset->getTTL()); + EXPECT_EQ(RRClass("IN"), rrset->getClass()); + EXPECT_EQ(Name("www.example.org"), rrset->getName()); + + // foo.example.org doesn't exist + rrset = collection.find(Name("foo.example.org"), rrclass, RRType::A()); + EXPECT_FALSE(rrset); + + // www.example.org exists, but not with MX + rrset = collection.find(Name("www.example.org"), rrclass, RRType::MX()); + EXPECT_FALSE(rrset); + + // www.example.org exists, with AAAA + rrset = collection.find(Name("www.example.org"), rrclass, RRType::AAAA()); + EXPECT_TRUE(rrset); + + // www.example.org with AAAA does not exist in RRClass::CH() + rrset = collection.find(Name("www.example.org"), RRClass::CH(), + RRType::AAAA()); + EXPECT_FALSE(rrset); +} + +TEST_F(RRsetCollectionTest, findConst) { + // Test the find() that returns ConstRRsetPtr + const RRsetCollection& ccln = collection; + doFind<const RRsetCollection, ConstRRsetPtr>(ccln, rrclass); +} + +TEST_F(RRsetCollectionTest, find) { + // Test the find() that returns RRsetPtr + doFind<RRsetCollection, RRsetPtr>(collection, rrclass); +} + +void +doAddAndRemove(RRsetCollection& collection, const RRClass& rrclass) { + // foo.example.org/A doesn't exist + RRsetPtr rrset_found = collection.find(Name("foo.example.org"), rrclass, + RRType::A()); + EXPECT_FALSE(rrset_found); + + // Add foo.example.org/A + RRsetPtr rrset(new BasicRRset(Name("foo.example.org"), rrclass, RRType::A(), + RRTTL(7200))); + rrset->addRdata(in::A("192.0.2.1")); + collection.addRRset(rrset); + + // foo.example.org/A should now exist + rrset_found = collection.find(Name("foo.example.org"), rrclass, + RRType::A()); + EXPECT_TRUE(rrset_found); + EXPECT_EQ(RRType::A(), rrset_found->getType()); + EXPECT_EQ(RRTTL(7200), rrset_found->getTTL()); + EXPECT_EQ(RRClass("IN"), rrset_found->getClass()); + EXPECT_EQ(Name("foo.example.org"), rrset_found->getName()); + + // The collection must not be empty. + EXPECT_TRUE(collection.end() != collection.begin()); + + // Adding a duplicate RRset must throw. + EXPECT_THROW({ + collection.addRRset(rrset); + }, isc::InvalidParameter); + + // Remove foo.example.org/A, which should pass + EXPECT_TRUE(collection.removeRRset(Name("foo.example.org"), + rrclass, RRType::A())); + // foo.example.org/A should not exist now + rrset_found = collection.find(Name("foo.example.org"), rrclass, + RRType::A()); + EXPECT_FALSE(rrset_found); + + // Removing foo.example.org/A should fail now + EXPECT_FALSE(collection.removeRRset(Name("foo.example.org"), + rrclass, RRType::A())); +} + +TEST_F(RRsetCollectionTest, addAndRemove) { + doAddAndRemove(collection, rrclass); +} + +TEST_F(RRsetCollectionTest, empty) { + RRsetCollection cln; + + // Here, cln is empty. + EXPECT_TRUE(cln.end() == cln.begin()); + + doAddAndRemove(cln, rrclass); + + // cln should be empty again here, after the add and remove + // operations. + EXPECT_TRUE(cln.end() == cln.begin()); +} + +TEST_F(RRsetCollectionTest, iteratorTest) { + // The collection must not be empty. + EXPECT_TRUE(collection.end() != collection.begin()); + + // Here, we just count the records and do some basic tests on them. + size_t count = 0; + for (RRsetCollection::Iterator it = collection.begin(); + it != collection.end(); ++it) { + ++count; + const AbstractRRset& rrset = *it; + EXPECT_EQ(rrclass, rrset.getClass()); + EXPECT_EQ(RRTTL(3600), rrset.getTTL()); + } + + // example.org master file has SOA, NS, A, AAAA + EXPECT_EQ(4, count); +} + +// This is a dummy class which is used in iteratorCompareDifferent test +// to compare iterators from different RRsetCollectionBase +// implementations. +class MyRRsetCollection : public RRsetCollectionBase { +public: + MyRRsetCollection() + {} + + virtual isc::dns::ConstRRsetPtr find(const isc::dns::Name&, + const isc::dns::RRClass&, + const isc::dns::RRType&) const { + return (ConstRRsetPtr()); + } + + typedef std::list<isc::dns::RRset> MyCollection; + +protected: + class MyIter : public RRsetCollectionBase::Iter { + public: + MyIter(MyCollection::iterator& iter) : + iter_(iter) + {} + + virtual const isc::dns::AbstractRRset& getValue() { + return (*iter_); + } + + virtual IterPtr getNext() { + MyCollection::iterator it = iter_; + ++it; + return (RRsetCollectionBase::IterPtr(new MyIter(it))); + } + + virtual bool equals(Iter& other) { + const MyIter* other_real = dynamic_cast<MyIter*>(&other); + if (other_real == NULL) { + return (false); + } + return (iter_ == other_real->iter_); + } + + private: + MyCollection::iterator iter_; + }; + + virtual RRsetCollectionBase::IterPtr getBeginning() { + MyCollection::iterator it = dummy_list_.begin(); + return (RRsetCollectionBase::IterPtr(new MyIter(it))); + } + + virtual RRsetCollectionBase::IterPtr getEnd() { + MyCollection::iterator it = dummy_list_.end(); + return (RRsetCollectionBase::IterPtr(new MyIter(it))); + } + +private: + MyCollection dummy_list_; +}; + +TEST_F(RRsetCollectionTest, iteratorCompareDifferent) { + // Create objects of two different RRsetCollectionBase + // implementations. + RRsetCollection cln1; + MyRRsetCollection cln2; + + // Comparing two iterators from different RRsetCollectionBase + // implementations must not throw. + EXPECT_TRUE(cln2.begin() != cln1.begin()); + EXPECT_TRUE(cln1.end() != cln2.end()); +} + +} // namespace |