Commit 0aeb26af authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[2107merge] Merge branch 'trac2107' into trac2107merge with fixing conflicts.

Conflict resolution is mostly straightforward adujstment for the latest
interface, but it's not super trivial and should be reviewed.
parents 73270385 558b2dbe
......@@ -10,10 +10,9 @@ CLEANFILES = *.gcno *.gcda datasrc_messages.h datasrc_messages.cc
noinst_LTLIBRARIES = libdatasrc_memory.la
libdatasrc_memory_la_SOURCES = \
rdataset.h rdataset.cc \
rdata_serialization.h rdata_serialization.cc \
domaintree.h
libdatasrc_memory_la_SOURCES += zone_data.h
libdatasrc_memory_la_SOURCES = domaintree.h
libdatasrc_memory_la_SOURCES += rdataset.h rdataset.cc
libdatasrc_memory_la_SOURCES += rdata_serialization.h rdata_serialization.cc
libdatasrc_memory_la_SOURCES += zone_data.h zone_data.cc
libdatasrc_memory_la_SOURCES += zone_table.h zone_table.cc
EXTRA_DIST = rdata_serialization_priv.cc
This diff is collapsed.
......@@ -194,6 +194,43 @@ public:
static void destroy(util::MemorySegment& mem_sgmt, dns::RRClass rrclass,
RdataSet* rdataset);
/// \brief Find \c RdataSet of given RR type from a list (const version).
///
/// This function is a convenient shortcut for commonly used operation of
/// finding a given type of \c RdataSet from a linked list of them.
///
/// It follows the linked list of \c RdataSet objects (via their \c next
/// member) starting the given head, until it finds an object of the
/// given RR type. If found, it returns a (bare) pointer to the object;
/// if not found in the entire list, it returns NULL. The head pointer
/// can be NULL, in which case this function will simply return NULL.
///
/// \note This function is defined as a (static) class method to
/// clarify its an operation for \c RdataSet objects and to make the
/// name shorter. But its implementation does not depend on private
/// members of the class, and it should be kept if and when this method
/// needs to be extended, unless there's a reason other than simply
/// because it's already a member function.
///
/// \param rdata_head A pointer to \c RdataSet from which the search
/// starts. It can be NULL.
/// \param type The RRType of \c RdataSet to find.
/// \return A pointer to the found \c RdataSet or NULL if none found.
static const RdataSet*
find(const RdataSet* rdataset_head, const dns::RRType& type) {
return (find<const RdataSet>(rdataset_head, type));
}
/// \brief Find \c RdataSet of given RR type from a list (non const
/// version).
///
/// This is similar to the const version, except it takes and returns non
/// const pointers.
static RdataSet*
find(RdataSet* rdataset_head, const dns::RRType& type) {
return (find<RdataSet>(rdataset_head, type));
}
typedef boost::interprocess::offset_ptr<RdataSet> RdataSetPtr;
typedef boost::interprocess::offset_ptr<const RdataSet> ConstRdataSetPtr;
......@@ -228,6 +265,20 @@ private:
static const size_t MANY_RRSIG_COUNT = (1 << 3) - 1;
public:
/// \brief Return the bare pointer to the next node.
///
/// In such an operation as iterating over a linked list of \c RdataSet
/// object, using this method is generally more efficient than using
/// the \c next member directly because it prevents unintentional
/// creation of offset pointer objects. While the application can
/// get the same result by directly calling get() on \c next, it would
/// help encourage the use of more efficient usage if we provide an
/// explicit accessor.
const RdataSet* getNext() const { return (next.get()); }
/// \brief Return the bare pointer to the next node, mutable version.
RdataSet* getNext() { return (next.get()); }
/// \brief Return the number of RDATAs stored in the \c RdataSet.
size_t getRdataCount() const { return (rdata_count_); }
......@@ -293,6 +344,21 @@ private:
return (reinterpret_cast<uint16_t*>(this + 1));
}
// Shared by both mutable and immutable versions of find()
template <typename RdataSetType>
static RdataSetType*
find(RdataSetType* rdataset_head, const dns::RRType& type) {
for (RdataSetType* rdataset = rdataset_head;
rdataset != NULL;
rdataset = rdataset->getNext()) // use getNext() for efficiency
{
if (rdataset->type == type) {
return (rdataset);
}
}
return (NULL);
}
/// \brief The constructor.
///
/// An object of this class is always expected to be created by the
......
// 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 DATASRC_MEMORY_SEGMENT_OBJECT_HOLDER_H
#define DATASRC_MEMORY_SEGMENT_OBJECT_HOLDER_H 1
#include <util/memory_segment.h>
namespace isc {
namespace datasrc {
namespace memory {
namespace detail {
// A simple holder to create and use some objects in this implementation
// in an exception safe manner. It works like std::auto_ptr but much
// more simplified.
// template parameter T is the type of object allocated by mem_sgmt.
// template parameter ARG_T is the type that will be passed to destroy()
// (deleter functor, etc). It must be copyable.
template <typename T, typename ARG_T>
class SegmentObjectHolder {
public:
SegmentObjectHolder(util::MemorySegment& mem_sgmt, T* obj, ARG_T arg) :
mem_sgmt_(mem_sgmt), obj_(obj), arg_(arg)
{}
~SegmentObjectHolder() {
if (obj_ != NULL) {
T::destroy(mem_sgmt_, obj_, arg_);
}
}
T* get() { return (obj_); }
T* release() {
T* ret = obj_;
obj_ = NULL;
return (ret);
}
private:
util::MemorySegment& mem_sgmt_;
T* obj_;
ARG_T arg_;
};
} // detail
} // namespace memory
} // namespace datasrc
} // namespace isc
#endif // DATASRC_MEMORY_SEGMENT_OBJECT_HOLDER_H
// Local Variables:
// mode: c++
// End:
......@@ -22,6 +22,9 @@ run_unittests_SOURCES += rdata_serialization_unittest.cc
run_unittests_SOURCES += rdataset_unittest.cc
run_unittests_SOURCES += domaintree_unittest.cc
run_unittests_SOURCES += zone_table_unittest.cc
run_unittests_SOURCES += zone_data_unittest.cc
run_unittests_SOURCES += memory_segment_test.h
run_unittests_SOURCES += segment_object_holder_unittest.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
......
......@@ -59,18 +59,13 @@ const size_t Name::MAX_LABELS;
namespace {
class DeleterType {
public:
DeleterType() {}
void operator()(util::MemorySegment&, int* i) const {
delete i;
}
};
void deleteData(int* i) {
delete i;
}
typedef DomainTree<int, DeleterType> TestDomainTree;
typedef DomainTreeNode<int, DeleterType> TestDomainTreeNode;
typedef DomainTreeNodeChain<int, DeleterType> TestDomainTreeNodeChain;
typedef DomainTree<int> TestDomainTree;
typedef DomainTreeNode<int> TestDomainTreeNode;
typedef DomainTreeNodeChain<int> TestDomainTreeNodeChain;
class TreeHolder {
public:
......@@ -78,7 +73,7 @@ public:
mem_sgmt_(mem_sgmt), tree_(tree)
{}
~TreeHolder() {
TestDomainTree::destroy(mem_sgmt_, tree_);
TestDomainTree::destroy(mem_sgmt_, tree_, deleteData);
}
TestDomainTree* get() { return (tree_); }
private:
......@@ -102,12 +97,13 @@ protected:
int name_count = sizeof(domain_names) / sizeof(domain_names[0]);
for (int i = 0; i < name_count; ++i) {
dtree.insert(mem_sgmt_, Name(domain_names[i]), &dtnode);
dtnode->setData(mem_sgmt_, new int(i + 1));
// Check the node doesn't have any data initially.
EXPECT_EQ(static_cast<int*>(NULL),
dtnode->setData(new int(i + 1)));
dtree_expose_empty_node.insert(mem_sgmt_, Name(domain_names[i]),
&dtnode);
dtnode->setData(mem_sgmt_, new int(i + 1));
EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(i + 1)));
}
}
......@@ -125,13 +121,22 @@ TEST_F(DomainTreeTest, nodeCount) {
// Delete all nodes, then the count should be set to 0. This also tests
// the behavior of deleteAllNodes().
dtree.deleteAllNodes(mem_sgmt_);
dtree.deleteAllNodes(mem_sgmt_, deleteData);
EXPECT_EQ(0, dtree.getNodeCount());
}
TEST_F(DomainTreeTest, setGetData) {
dtnode->setData(mem_sgmt_, new int(11));
// set new data to an existing node. It should have some data.
int* newdata = new int(11);
int* olddata = dtnode->setData(newdata);
EXPECT_NE(static_cast<int*>(NULL), olddata);
deleteData(olddata);
EXPECT_EQ(11, *(dtnode->getData()));
// clear the node. we should get the new data back we just passed.
olddata = dtnode->setData(NULL);
EXPECT_EQ(newdata, olddata);
deleteData(olddata);
}
TEST_F(DomainTreeTest, insertNames) {
......@@ -151,7 +156,9 @@ TEST_F(DomainTreeTest, insertNames) {
Name("example.com"),
&dtnode));
EXPECT_EQ(17, dtree.getNodeCount());
dtnode->setData(mem_sgmt_, new int(12));
// ad data to it; also make sure it doesn't have data right now
// (otherwise it would leak)
EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(12)));
// return ALREADYEXISTS, since node "example.com" already has
// been explicitly inserted
......@@ -381,7 +388,7 @@ performCallbackTest(TestDomainTree& dtree,
EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt,
Name("callback.example"),
&dtnode));
dtnode->setData(mem_sgmt, new int(1));
EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(1)));
EXPECT_FALSE(dtnode->getFlag(TestDomainTreeNode::FLAG_CALLBACK));
// enable/re-disable callback
......@@ -397,7 +404,7 @@ performCallbackTest(TestDomainTree& dtree,
EXPECT_EQ(TestDomainTree::SUCCESS, dtree.insert(mem_sgmt,
Name("sub.callback.example"),
&subdtnode));
subdtnode->setData(mem_sgmt, new int(2));
EXPECT_EQ(static_cast<int*>(NULL), subdtnode->setData(new int(2)));
TestDomainTreeNode* parentdtnode;
EXPECT_EQ(TestDomainTree::ALREADYEXISTS, dtree.insert(mem_sgmt,
Name("example"),
......@@ -997,7 +1004,7 @@ TEST_F(DomainTreeTest, root) {
TreeHolder tree_holder(mem_sgmt_, TestDomainTree::create(mem_sgmt_));
TestDomainTree& root(*tree_holder.get());
root.insert(mem_sgmt_, Name::ROOT_NAME(), &dtnode);
dtnode->setData(mem_sgmt_, new int(1));
EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(1)));
EXPECT_EQ(TestDomainTree::EXACTMATCH,
root.find(Name::ROOT_NAME(), &cdtnode));
......@@ -1009,7 +1016,7 @@ TEST_F(DomainTreeTest, root) {
// Insert a new name that better matches the query name. find() should
// find the better one.
root.insert(mem_sgmt_, Name("com"), &dtnode);
dtnode->setData(mem_sgmt_, new int(2));
EXPECT_EQ(static_cast<int*>(NULL), dtnode->setData(new int(2)));
EXPECT_EQ(TestDomainTree::PARTIALMATCH,
root.find(Name("example.com"), &cdtnode));
EXPECT_EQ(dtnode, cdtnode);
......
// 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 DATASRC_MEMORY_SEGMENT_TEST_H
#define DATASRC_MEMORY_SEGMENT_TEST_H 1
#include <util/memory_segment_local.h>
#include <cstddef> // for size_t
#include <new> // for bad_alloc
namespace isc {
namespace datasrc {
namespace memory {
namespace test {
// A special memory segment that can be used for tests. It normally behaves
// like a "local" memory segment. If "throw count" is set to non 0 via
// setThrowCount(), it continues the normal behavior until the specified
// number of calls to allocate(), exclusive, and throws an exception at the
// next call. For example, if count is set to 3, the next two calls to
// allocate() will succeed, and the 3rd call will fail with an exception.
// This segment object can be used after the exception is thrown, and the
// count is internally reset to 0.
class MemorySegmentTest : public isc::util::MemorySegmentLocal {
public:
MemorySegmentTest() : throw_count_(0) {}
virtual void* allocate(std::size_t size) {
if (throw_count_ > 0) {
if (--throw_count_ == 0) {
throw std::bad_alloc();
}
}
return (isc::util::MemorySegmentLocal::allocate(size));
}
void setThrowCount(std::size_t count) { throw_count_ = count; }
private:
std::size_t throw_count_;
};
} // namespace test
} // namespace memory
} // namespace datasrc
} // namespace isc
#endif // DATASRC_MEMORY_SEGMENT_TEST_H
// Local Variables:
// mode: c++
// End:
......@@ -115,6 +115,25 @@ TEST_F(RdataSetTest, create) {
RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
}
TEST_F(RdataSetTest, getNext) {
RdataSet* rdataset = RdataSet::create(mem_sgmt_, encoder_, a_rrset_,
ConstRRsetPtr());
// By default, the next pointer should be NULL (already tested in other
// test cases), which should be the case with getNext(). We test both
// mutable and immutable versions of getNext().
EXPECT_EQ(static_cast<RdataSet*>(NULL), rdataset->getNext());
EXPECT_EQ(static_cast<const RdataSet*>(NULL),
static_cast<const RdataSet*>(rdataset)->getNext());
// making a link (it would form an infinite loop, but it doesn't matter
// in this test), and check the pointer returned by getNext().
rdataset->next = rdataset;
EXPECT_EQ(rdataset, static_cast<const RdataSet*>(rdataset)->getNext());
RdataSet::destroy(mem_sgmt_, RRClass::IN(), rdataset);
}
// A helper function to create an RRset containing the given number of
// unique RDATAs.
ConstRRsetPtr
......
// 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 <util/memory_segment_local.h>
#include <datasrc/memory/segment_object_holder.h>
#include <gtest/gtest.h>
using namespace isc::util;
using namespace isc::datasrc::memory;
using namespace isc::datasrc::memory::detail;
namespace {
const int TEST_ARG_VAL = 42; // arbitrary chosen magic number
class TestObject {
public:
static void destroy(MemorySegment& sgmt, TestObject* obj, int arg) {
sgmt.deallocate(obj, sizeof(*obj));
EXPECT_EQ(TEST_ARG_VAL, arg);
}
};
void
useHolder(MemorySegment& sgmt, TestObject* obj, bool release) {
// Create a holder object, check the return value of get(), and,
// if requested, release the held object. At the end of function
// the holder is destructed, and if the object hasn't been released by
// then, it should be deallocated. Passed argument is checked in its
// deallocate().
typedef SegmentObjectHolder<TestObject, int> HolderType;
HolderType holder(sgmt, obj, TEST_ARG_VAL);
EXPECT_EQ(obj, holder.get());
if (release) {
EXPECT_EQ(obj, holder.release());
}
}
TEST(SegmentObjectHolderTest, foo) {
MemorySegmentLocal sgmt;
void* p = sgmt.allocate(sizeof(TestObject));
TestObject* obj = new(p) TestObject;
// Use holder, and release the content. The memory shouldn't be
// deallocated.
useHolder(sgmt, obj, true);
EXPECT_FALSE(sgmt.allMemoryDeallocated());
// Use holder, and let it deallocate the object. The memory segment
// should now be empty.
useHolder(sgmt, obj, false);
EXPECT_TRUE(sgmt.allMemoryDeallocated());
}
}
// 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 "memory_segment_test.h"
#include <dns/rdataclass.h>
#include <exceptions/exceptions.h>
#include <dns/name.h>
#include <dns/labelsequence.h>
#include <dns/rrclass.h>
#include <datasrc/memory/rdata_serialization.h>
#include <datasrc/memory/rdataset.h>
#include <datasrc/memory/zone_data.h>
#include <testutils/dnsmessage_test.h>
#include <gtest/gtest.h>
#include <new> // for bad_alloc
#include <string>
using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace isc::datasrc::memory;
using namespace isc::datasrc::memory::test;
using namespace isc::testutils;
namespace {
// With this single fixture we'll test both NSEC3Data and ZoneData
class ZoneDataTest : public ::testing::Test {
protected:
ZoneDataTest() :
nsec3_data_(NULL), param_rdata_("1 0 12 aabbccdd"),
param_rdata_nosalt_("1 1 10 -"),
param_rdata_largesalt_("2 0 5 " + std::string(255 * 2, 'a')),
nsec3_rdata_("1 0 12 aabbccdd TDK23RP6 SOA"),
nsec3_rdata_nosalt_("1 1 10 - TDK23RP6 SOA"),
nsec3_rdata_largesalt_("2 0 5 " + std::string(255 * 2, 'a') +
" TDK23RP6 SOA"),
zname_("example.com"),
zone_data_(ZoneData::create(mem_sgmt_, zname_)),
a_rrset_(textToRRset("www.example.com. 3600 IN A 192.0.2.1")),
aaaa_rrset_(textToRRset("www.example.com. 3600 IN AAAA 2001:db8::1")),
nsec3_rrset_(textToRRset("TDK23RP6.example.com. 3600 IN NSEC3 "
"1 0 12 aabbccdd TDK23RP6 SOA"))
{}
void TearDown() {
if (nsec3_data_ != NULL) {
NSEC3Data::destroy(mem_sgmt_, nsec3_data_, RRClass::IN());
}
if (zone_data_ != NULL) {
ZoneData::destroy(mem_sgmt_, zone_data_, RRClass::IN());
}
// detect any memory leak in the test memory segment
EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
}
MemorySegmentTest mem_sgmt_;
NSEC3Data* nsec3_data_;
const generic::NSEC3PARAM param_rdata_, param_rdata_nosalt_,
param_rdata_largesalt_;
const generic::NSEC3 nsec3_rdata_, nsec3_rdata_nosalt_,
nsec3_rdata_largesalt_;
const Name zname_;
ZoneData* zone_data_;
const ConstRRsetPtr a_rrset_, aaaa_rrset_, nsec3_rrset_;
RdataEncoder encoder_;
};
// Shared by both test cases using NSEC3 and NSEC3PARAM Rdata
template <typename RdataType>
void
checkNSEC3Data(MemorySegmentTest& mem_sgmt, const RdataType& expect_rdata) {
NSEC3Data* nsec3_data = NSEC3Data::create(mem_sgmt, expect_rdata);
// Internal tree should be created and empty.
EXPECT_EQ(0, nsec3_data->getNSEC3Tree().getNodeCount());
EXPECT_EQ(expect_rdata.getHashalg(), nsec3_data->hashalg);
EXPECT_EQ(expect_rdata.getFlags(), nsec3_data->flags);
EXPECT_EQ(expect_rdata.getIterations(), nsec3_data->iterations);
EXPECT_EQ(expect_rdata.getSalt().size(), nsec3_data->getSaltLen());
if (expect_rdata.getSalt().size() > 0) {
EXPECT_EQ(0, memcmp(&expect_rdata.getSalt()[0],
nsec3_data->getSaltData(),
expect_rdata.getSalt().size()));
}
NSEC3Data::destroy(mem_sgmt, nsec3_data, RRClass::IN());
}
void
checkFindRdataSet(const ZoneTree& tree, const Name& name, RRType type,
const RdataSet* expected_set)
{
ZoneNode* node = NULL;
tree.find(name, &node);
ASSERT_NE(static_cast<ZoneNode*>(NULL), node);
EXPECT_EQ(expected_set, RdataSet::find(node->getData(), type));
}
TEST_F(ZoneDataTest, createNSEC3Data) {
// Create an NSEC3Data object from various types of RDATA (of NSEC3PARAM
// and of NSEC3), check if the resulting parameters match.
checkNSEC3Data(mem_sgmt_, param_rdata_); // one 'usual' form of params
checkNSEC3Data(mem_sgmt_, param_rdata_nosalt_); // empty salt
checkNSEC3Data(mem_sgmt_, param_rdata_largesalt_); // max-len salt
// Same concepts of the tests, using NSEC3 RDATA.
checkNSEC3Data(mem_sgmt_, nsec3_rdata_);
checkNSEC3Data(mem_sgmt_, nsec3_rdata_nosalt_);
checkNSEC3Data(mem_sgmt_, nsec3_rdata_largesalt_);
}
TEST_F(ZoneDataTest, addNSEC3) {
nsec3_data_ = NSEC3Data::create(mem_sgmt_, param_rdata_);
ZoneNode* node = NULL;
nsec3_data_->insertName(mem_sgmt_, nsec3_rrset_->getName(), &node);
ASSERT_NE(static_cast<ZoneNode*>(NULL), node);
EXPECT_TRUE(node->isEmpty()); // initially it should be empty
RdataSet* rdataset_nsec3 =
RdataSet::create(mem_sgmt_, encoder_, nsec3_rrset_, ConstRRsetPtr());