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

[2107] test the case of adding some RdataSets as node data

also now make sure all linked RdataSets are released.
parent 6679f424
......@@ -228,6 +228,17 @@ 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.
RdataSet* getNext() const { return (next.get()); }
/// \brief Return the number of RDATAs stored in the \c RdataSet.
size_t getRdataCount() const { return (rdata_count_); }
......
......@@ -18,15 +18,19 @@
#include <dns/name.h>
#include <dns/labelsequence.h>
#include <dns/rrclass.h>
#include <datasrc/memory/rdata_encoder.h>
#include <datasrc/memory/rdataset.h>
#include <datasrc/memory/zone_data.h>
#include <testutils/dnsmessage_test.h>
#include <gtest/gtest.h>
using namespace isc::dns;
using namespace isc::datasrc::memory;
using namespace isc::testutils;
namespace {
......@@ -37,7 +41,7 @@ protected:
{}
void TearDown() {
if (zone_data_ != NULL) {
ZoneData::destroy(mem_sgmt_, zone_data_);
ZoneData::destroy(RRClass::IN(), mem_sgmt_, zone_data_);
}
// detect any memory leak in the test memory segment
EXPECT_TRUE(mem_sgmt_.allMemoryDeallocated());
......@@ -52,4 +56,31 @@ protected:
TEST_F(ZoneDataTest, getOriginNode) {
EXPECT_EQ(LabelSequence(zname_), zone_data_->getOriginNode()->getLabels());
}
TEST_F(ZoneDataTest, addRdataSets) {
// Insert a name to the zone, and add a couple the data (RdataSet) objects
// to the corresponding node.
ConstRRsetPtr a_rrset_ =
textToRRset("www.example.com. 3600 IN A 192.0.2.1");
ZoneData::ZoneNode* node = NULL;
zone_data_->insertName(mem_sgmt_, a_rrset_->getName(), &node);
ASSERT_NE(static_cast<ZoneData::ZoneNode*>(NULL), node);
EXPECT_TRUE(node->isEmpty()); // initially it should be empty
RdataSet* rdataset_a =
RdataSet::create(mem_sgmt_, encoder_, a_rrset_, ConstRRsetPtr());
node->setData(rdataset_a);
ConstRRsetPtr aaaa_rrset_ =
textToRRset("www.example.com. 3600 IN AAAA 2001:db8::1");
RdataSet* rdataset_aaaa =
RdataSet::create(mem_sgmt_, encoder_, aaaa_rrset_, ConstRRsetPtr());
// make a linked list and replace the list head
rdataset_aaaa->next = rdataset_a;
node->setData(rdataset_aaaa);
// TearDown() will confirm there's no leak on destroy
}
}
......@@ -15,11 +15,14 @@
#include <util/memory_segment.h>
#include <dns/name.h>
#include <dns/rrclass.h>
#include "rdataset.h"
#include "rdata_encoder.h"
#include "zone_data.h"
#include <boost/bind.hpp>
#include <cassert>
#include <new> // for the placement new
......@@ -42,12 +45,40 @@ ZoneData::create(util::MemorySegment& mem_sgmt, const Name& zone_origin) {
return (zone_data);
}
namespace {
void
rdataSetDeleter(RRClass rrclass, util::MemorySegment* mem_sgmt,
RdataSet* rdataset_head)
{
for (RdataSet* rdataset = rdataset_head;
rdataset != NULL;
rdataset = rdataset->getNext()) {
RdataSet::destroy(*mem_sgmt, rrclass, rdataset);
}
}
}
void
ZoneData::destroy(util::MemorySegment& mem_sgmt, ZoneData* zone_data) {
ZoneTree::destroy(mem_sgmt, zone_data->zone_tree_.get());
ZoneData::destroy(RRClass zone_class, util::MemorySegment& mem_sgmt,
ZoneData* zone_data)
{
ZoneTree::destroy(mem_sgmt, zone_data->zone_tree_.get(),
boost::bind(rdataSetDeleter, zone_class, &mem_sgmt,
_1));
mem_sgmt.deallocate(zone_data, sizeof(ZoneData));
}
void
ZoneData::insertName(util::MemorySegment& mem_sgmt, const Name& name,
ZoneNode** node)
{
const ZoneTree::Result result = zone_tree_->insert(mem_sgmt, name, node);
// This should be ensured by the API:
assert((result == ZoneTree::SUCCESS ||
result == ZoneTree::ALREADYEXISTS) && node!= NULL);
}
} // namespace memory
} // namespace datasrc
} // datasrc isc
......@@ -18,6 +18,7 @@
#include <util/memory_segment.h>
#include <dns/name.h>
#include <dns/rrclass.h>
#include <datasrc/memory/domaintree.h>
#include <datasrc/memory/rdataset.h>
......@@ -33,13 +34,14 @@ class ZoneData : boost::noncopyable {
struct RdataSetDeleter {
public:
RdataSetDeleter() {}
void operator()(util::MemorySegment& /*mem_sgmt*/,
RdataSet* /*rdataset_head*/) const
{}
void operator()(util::MemorySegment& mem_sgmt,
RdataSet* rdataset_head) const;
};
typedef DomainTree<RdataSet, RdataSetDeleter> ZoneTree;
typedef DomainTreeNode<RdataSet, RdataSetDeleter> ZoneNode;
public:
typedef DomainTree<RdataSet> ZoneTree;
typedef DomainTreeNode<RdataSet> ZoneNode;
private:
ZoneData(ZoneTree* zone_tree, ZoneNode* origin_node) :
zone_tree_(zone_tree), origin_node_(origin_node)
{}
......@@ -47,7 +49,13 @@ class ZoneData : boost::noncopyable {
public:
static ZoneData* create(util::MemorySegment& mem_sgmt,
const dns::Name& zone_name);
static void destroy(util::MemorySegment& mem_sgmt, ZoneData* zone_data);
static void destroy(dns::RRClass zone_class, util::MemorySegment& mem_sgmt,
ZoneData* zone_data);
void insertName(util::MemorySegment& mem_sgmt, const dns::Name& name,
ZoneNode** node);
// This is a shortcut.
const ZoneNode* getOriginNode() const {
return (origin_node_.get());
}
......
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