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

added test cases for RRParamRegistry, and fixed bugs in error handling code

found by the tests


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jinmei-dnsrrparams@451 e5f2f494-b856-4b98-b285-d166d9295462
parent a414d7fc
......@@ -14,6 +14,7 @@ run_unittests_SOURCES += buffer_unittest.cc name_unittest.cc
run_unittests_SOURCES += messagerenderer_unittest.cc exceptions_unittest.cc
run_unittests_SOURCES += rrclass_unittest.cc rrtype_unittest.cc
run_unittests_SOURCES += rrttl_unittest.cc
run_unittests_SOURCES += rrparamregistry_unittest.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(GTEST_LDFLAGS)
......
......@@ -153,7 +153,7 @@ RRParamRegistry::~RRParamRegistry()
delete impl_;
}
const RRParamRegistry&
RRParamRegistry&
RRParamRegistry::getRegistry()
{
static RRParamRegistry registry;
......@@ -166,25 +166,34 @@ RRParamRegistry::add(const string& classcode_string, uint16_t classcode,
const string& typecode_string, uint16_t typecode
/* rdata_factory (notyet) */)
{
// XXX: rollback logic on failure is complicated.
bool add_type = false;
bool add_class = false;
// Rollback logic on failure is complicated. If adding the new type or
// class fails, we should revert to the original state, cleaning up
// intermediate state. But we need to make sure that we don't remove
// existing data. addType()/AddClass() will simply ignore an attempt to
// add the same data, so the cleanup should be performed only when we add
// something new but we fail in other part of the process.
bool will_add_type = false;
bool type_added = false;
bool will_add_class = false;
bool class_added = false;
if (impl_->code2typemap.find(typecode) == impl_->code2typemap.end()) {
add_type = true;
will_add_type = true;
}
if (impl_->code2classmap.find(classcode) == impl_->code2classmap.end()) {
add_class = true;
will_add_class = true;
}
try {
addType(typecode_string, typecode);
type_added = true;
addClass(classcode_string, classcode);
class_added = true;
} catch (...) {
if (add_type) {
if (will_add_type && type_added) {
removeType(typecode);
}
if (add_class) {
if (will_add_class && class_added) {
removeClass(classcode);
}
throw;
......@@ -202,15 +211,15 @@ namespace {
/// MS: type of mapping class from string: either StrRRTypeMap or StrRRClassMap
/// ET: exception type for error handling: either InvalidRRType or
/// InvalidRRClass
template <typename PT, typename MC, typename MS>
template <typename PT, typename MC, typename MS, typename ET>
inline void
addParam(const string& code_string, uint16_t code, MC& codemap, MS& stringmap)
{
// Duplicate type check
typename MC::const_iterator found = codemap.find(code);
if (codemap.find(code) != codemap.end()) {
if (codemap.find(code)->second->code_string_ != code_string) {
dns_throw(RRClassExist, "Duplicate RR parameter registration");
if (found != codemap.end()) {
if (found->second->code_string_ != code_string) {
dns_throw(ET, "Duplicate RR parameter registration");
}
return;
}
......@@ -296,9 +305,8 @@ getText(uint16_t code, MC& codemap)
void
RRParamRegistry::addType(const string& type_string, uint16_t code)
{
addParam<RRTypeParam, CodeRRTypeMap, StrRRTypeMap>(type_string, code,
impl_->code2typemap,
impl_->str2typemap);
addParam<RRTypeParam, CodeRRTypeMap, StrRRTypeMap, RRTypeExist>
(type_string, code, impl_->code2typemap, impl_->str2typemap);
}
bool
......@@ -324,9 +332,8 @@ RRParamRegistry::getTypeText(uint16_t code) const
void
RRParamRegistry::addClass(const string& class_string, uint16_t code)
{
addParam<RRClassParam, CodeRRClassMap, StrRRClassMap>(class_string, code,
impl_->code2classmap,
impl_->str2classmap);
addParam<RRClassParam, CodeRRClassMap, StrRRClassMap, RRClassExist>
(class_string, code, impl_->code2classmap, impl_->str2classmap);
}
bool
......
......@@ -75,7 +75,7 @@ public:
/// Convert type code into its textual representation.
std::string getTypeText(uint16_t type_code) const;
static const RRParamRegistry& getRegistry();
static RRParamRegistry& getRegistry();
private:
RRParamRegistryImpl* impl_;
};
......
// Copyright (C) 2010 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.
// $Id$
#include <string>
#include <sstream>
#include <stdint.h>
#include <gtest/gtest.h>
#include "rrclass.h"
#include "rrparamregistry.h"
#include "rrtype.h"
using namespace std;
using namespace isc::dns;
namespace {
class RRParamRegistryTest : public ::testing::Test {
protected:
virtual void SetUp() {
ostringstream oss1;
oss1 << test_class_code;
test_class_unknown_str = "CLASS" + oss1.str();
ostringstream oss2;
oss2 << test_type_code;
test_type_unknown_str = "TYPE" + oss2.str();
}
string test_class_unknown_str;
string test_type_unknown_str;
// we assume class/type numbers are officially unassigned. If not we'll
// need to update the test cases.
static const uint16_t test_class_code = 65533;
static const uint16_t test_type_code = 65534;
static const string test_class_str;
static const string test_type_str;
};
const string RRParamRegistryTest::test_class_str("TESTCLASS");
const string RRParamRegistryTest::test_type_str("TESTTYPE");
TEST_F(RRParamRegistryTest, addRemove)
{
RRParamRegistry::getRegistry().add(test_class_str, test_class_code,
test_type_str, test_type_code);
EXPECT_EQ(65533, RRClass("TESTCLASS").getCode());
EXPECT_EQ(65534, RRType("TESTTYPE").getCode());
EXPECT_TRUE(RRParamRegistry::getRegistry().removeClass(65533));
EXPECT_EQ(test_class_unknown_str, RRClass(test_class_code).toText());
EXPECT_TRUE(RRParamRegistry::getRegistry().removeType(65534));
EXPECT_EQ(test_type_unknown_str, RRType(test_type_code).toText());
}
TEST_F(RRParamRegistryTest, addError)
{
// An attempt to override a pre-registered class should fail with an
// exception, and the pre-registered one should remain in the registry.
EXPECT_THROW(RRParamRegistry::getRegistry().add(test_class_str, 1,
test_type_str,
test_type_code),
RRClassExist);
EXPECT_EQ("IN", RRClass(1).toText());
// Same for RRType
EXPECT_THROW(RRParamRegistry::getRegistry().add(test_class_str,
test_class_code,
test_type_str, 1),
RRTypeExist);
EXPECT_EQ("A", RRType(1).toText());
}
}
Supports Markdown
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