// 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 #include #include #include #include #include #include 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 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(ccln, rrclass); } TEST_F(RRsetCollectionTest, find) { // Test the find() that returns RRsetPtr doFind(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 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(&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