Commit d5db8b95 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[master] Merge branch 'trac2107merge'

parents 307a588d e69183d6
......@@ -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));
// add 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());
node->setData(rdataset_nsec3);