2011-08-01 11:47:37 +02:00
|
|
|
// Copyright (C) 2011 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.
|
|
|
|
|
2011-08-16 18:31:09 -07:00
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
|
2011-08-01 11:47:37 +02:00
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
#include <dns/name.h>
|
2011-08-16 18:31:09 -07:00
|
|
|
#include <dns/rdata.h>
|
2011-08-09 11:19:13 +02:00
|
|
|
#include <dns/rrttl.h>
|
2011-08-11 17:31:06 +02:00
|
|
|
#include <dns/rrset.h>
|
2011-08-01 12:03:35 +02:00
|
|
|
#include <exceptions/exceptions.h>
|
2011-08-01 11:47:37 +02:00
|
|
|
|
|
|
|
#include <datasrc/database.h>
|
2011-08-04 14:32:53 +02:00
|
|
|
#include <datasrc/zone.h>
|
|
|
|
#include <datasrc/data_source.h>
|
|
|
|
|
2011-08-11 17:31:06 +02:00
|
|
|
#include <testutils/dnsmessage_test.h>
|
|
|
|
|
2011-08-17 10:31:29 -07:00
|
|
|
#include <algorithm>
|
2011-08-04 14:32:53 +02:00
|
|
|
#include <map>
|
2011-08-17 10:31:29 -07:00
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
2011-08-01 11:47:37 +02:00
|
|
|
|
|
|
|
using namespace isc::datasrc;
|
|
|
|
using namespace std;
|
|
|
|
using namespace boost;
|
2011-08-16 18:31:09 -07:00
|
|
|
using namespace isc::dns;
|
2011-08-01 11:47:37 +02:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2011-08-12 16:05:04 -07:00
|
|
|
const int READONLY_ZONE_ID = 42;
|
|
|
|
const int WRITABLE_ZONE_ID = 4200;
|
|
|
|
|
2011-08-01 11:47:37 +02:00
|
|
|
/*
|
2011-08-12 10:29:44 +02:00
|
|
|
* A virtual database database that pretends it contains single zone --
|
2011-08-01 11:47:37 +02:00
|
|
|
* example.org.
|
|
|
|
*/
|
2011-08-09 09:02:03 +02:00
|
|
|
class MockAccessor : public DatabaseAccessor {
|
2011-08-12 16:05:04 -07:00
|
|
|
typedef std::map<std::string, std::vector< std::vector<std::string> > >
|
|
|
|
RECORDS;
|
2011-08-01 11:47:37 +02:00
|
|
|
public:
|
2011-08-12 18:55:58 -07:00
|
|
|
MockAccessor() : search_running_(false), rollbacked_(false),
|
|
|
|
database_name_("mock_database")
|
2011-08-11 13:09:12 +02:00
|
|
|
{
|
|
|
|
fillData();
|
|
|
|
}
|
2011-08-04 14:32:53 +02:00
|
|
|
|
2011-08-12 16:05:04 -07:00
|
|
|
virtual pair<bool, int> getZone(const Name& name) const {
|
|
|
|
return (getZone(name.toText()));
|
|
|
|
}
|
|
|
|
pair<bool, int> getZone(const string& name) const {
|
|
|
|
if (name == "example.org.") {
|
|
|
|
return (std::pair<bool, int>(true, READONLY_ZONE_ID));
|
2011-08-01 11:47:37 +02:00
|
|
|
} else {
|
|
|
|
return (std::pair<bool, int>(false, 0));
|
|
|
|
}
|
|
|
|
}
|
2011-08-04 14:32:53 +02:00
|
|
|
|
|
|
|
virtual void searchForRecords(int zone_id, const std::string& name) {
|
2011-08-09 11:19:13 +02:00
|
|
|
search_running_ = true;
|
|
|
|
|
|
|
|
// 'hardcoded' name to trigger exceptions (for testing
|
2011-08-11 02:07:39 -07:00
|
|
|
// the error handling of find() (the other on is below in
|
2011-08-09 11:19:13 +02:00
|
|
|
// if the name is "exceptiononsearch" it'll raise an exception here
|
|
|
|
if (name == "dsexception.in.search.") {
|
|
|
|
isc_throw(DataSourceError, "datasource exception on search");
|
|
|
|
} else if (name == "iscexception.in.search.") {
|
|
|
|
isc_throw(isc::Exception, "isc exception on search");
|
|
|
|
} else if (name == "basicexception.in.search.") {
|
|
|
|
throw std::exception();
|
|
|
|
}
|
|
|
|
searched_name_ = name;
|
|
|
|
|
2011-08-04 14:32:53 +02:00
|
|
|
// we're not aiming for efficiency in this test, simply
|
|
|
|
// copy the relevant vector from records
|
|
|
|
cur_record = 0;
|
2011-08-12 16:05:04 -07:00
|
|
|
const RECORDS& cur_records = getRecords(zone_id);
|
|
|
|
if (cur_records.count(name) > 0) {
|
|
|
|
cur_name = cur_records.find(name)->second;
|
2011-08-04 14:32:53 +02:00
|
|
|
} else {
|
|
|
|
cur_name.clear();
|
|
|
|
}
|
2011-08-12 16:05:04 -07:00
|
|
|
}
|
2011-08-04 14:32:53 +02:00
|
|
|
|
2011-08-09 11:19:13 +02:00
|
|
|
virtual bool getNextRecord(std::string columns[], size_t column_count) {
|
|
|
|
if (searched_name_ == "dsexception.in.getnext.") {
|
|
|
|
isc_throw(DataSourceError, "datasource exception on getnextrecord");
|
|
|
|
} else if (searched_name_ == "iscexception.in.getnext.") {
|
|
|
|
isc_throw(isc::Exception, "isc exception on getnextrecord");
|
|
|
|
} else if (searched_name_ == "basicexception.in.getnext.") {
|
|
|
|
throw std::exception();
|
|
|
|
}
|
|
|
|
|
2011-08-12 10:29:44 +02:00
|
|
|
if (column_count != DatabaseAccessor::COLUMN_COUNT) {
|
2011-08-09 11:19:13 +02:00
|
|
|
isc_throw(DataSourceError, "Wrong column count in getNextRecord");
|
|
|
|
}
|
2011-08-04 14:32:53 +02:00
|
|
|
if (cur_record < cur_name.size()) {
|
2011-08-09 11:19:13 +02:00
|
|
|
for (size_t i = 0; i < column_count; ++i) {
|
|
|
|
columns[i] = cur_name[cur_record][i];
|
|
|
|
}
|
|
|
|
cur_record++;
|
2011-08-08 01:41:39 -07:00
|
|
|
return (true);
|
2011-08-04 14:32:53 +02:00
|
|
|
} else {
|
2011-08-09 11:19:13 +02:00
|
|
|
resetSearch();
|
2011-08-08 01:41:39 -07:00
|
|
|
return (false);
|
2011-08-04 14:32:53 +02:00
|
|
|
}
|
2011-08-12 18:55:58 -07:00
|
|
|
}
|
2011-08-04 14:32:53 +02:00
|
|
|
|
2011-08-09 11:19:13 +02:00
|
|
|
virtual void resetSearch() {
|
|
|
|
search_running_ = false;
|
2011-08-12 18:55:58 -07:00
|
|
|
}
|
2011-08-09 11:19:13 +02:00
|
|
|
|
2011-08-16 18:31:09 -07:00
|
|
|
virtual pair<bool, int> startUpdateZone(const std::string& zone_name,
|
|
|
|
bool replace)
|
|
|
|
{
|
|
|
|
const pair<bool, int> zone_info = getZone(zone_name);
|
|
|
|
if (!zone_info.first) {
|
|
|
|
return (pair<bool, int>(false, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prepare the record set for update. If replacing the existing one,
|
|
|
|
// we use an empty set; otherwise we use a writable copy of the
|
|
|
|
// original.
|
|
|
|
if (replace) {
|
|
|
|
update_records.clear();
|
|
|
|
} else {
|
|
|
|
update_records = readonly_records;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (pair<bool, int>(true, WRITABLE_ZONE_ID));
|
|
|
|
}
|
|
|
|
virtual void commitUpdateZone() {
|
|
|
|
readonly_records = update_records;
|
|
|
|
}
|
|
|
|
virtual void rollbackUpdateZone() {
|
|
|
|
rollbacked_ = true;
|
|
|
|
}
|
|
|
|
virtual void addRecordToZone(const vector<string>& columns) {
|
|
|
|
// Copy the current value to cur_name. If it doesn't exist,
|
|
|
|
// operator[] will create a new one.
|
|
|
|
cur_name = update_records[columns[DatabaseAccessor::ADD_NAME]];
|
|
|
|
addRecord(columns[DatabaseAccessor::ADD_TYPE],
|
|
|
|
columns[DatabaseAccessor::ADD_TTL],
|
|
|
|
columns[DatabaseAccessor::ADD_SIGTYPE],
|
|
|
|
columns[DatabaseAccessor::ADD_RDATA]);
|
|
|
|
// copy back the added entry.
|
|
|
|
update_records[columns[DatabaseAccessor::ADD_NAME]] = cur_name;
|
|
|
|
|
|
|
|
// remember this one so that test cases can check it.
|
|
|
|
columns_lastadded = columns;
|
|
|
|
}
|
2011-08-17 10:31:29 -07:00
|
|
|
|
|
|
|
// Helper predicate class used in deleteRecordInZone().
|
|
|
|
struct deleteMatch {
|
|
|
|
deleteMatch(const string& type, const string& rdata) :
|
|
|
|
type_(type), rdata_(rdata)
|
|
|
|
{}
|
|
|
|
bool operator()(const vector<string>& row) const {
|
|
|
|
return (row[0] == type_ && row[3] == rdata_);
|
|
|
|
}
|
|
|
|
const string& type_;
|
|
|
|
const string& rdata_;
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual void deleteRecordInZone(const vector<string>& params) {
|
|
|
|
vector<vector<string> > records =
|
|
|
|
update_records[params[DatabaseAccessor::DEL_NAME]];
|
|
|
|
records.erase(remove_if(records.begin(), records.end(),
|
|
|
|
deleteMatch(
|
|
|
|
params[DatabaseAccessor::DEL_TYPE],
|
|
|
|
params[DatabaseAccessor::DEL_RDATA])),
|
|
|
|
records.end());
|
|
|
|
if (records.empty()) {
|
|
|
|
update_records.erase(params[DatabaseAccessor::DEL_NAME]);
|
|
|
|
} else {
|
|
|
|
update_records[params[DatabaseAccessor::DEL_NAME]] = records;
|
|
|
|
}
|
|
|
|
}
|
2011-08-16 18:31:09 -07:00
|
|
|
|
2011-08-09 11:19:13 +02:00
|
|
|
bool searchRunning() const {
|
|
|
|
return (search_running_);
|
|
|
|
}
|
|
|
|
|
2011-08-12 18:55:58 -07:00
|
|
|
bool isRollbacked() const {
|
|
|
|
return (rollbacked_);
|
|
|
|
}
|
|
|
|
|
2011-08-11 13:09:12 +02:00
|
|
|
virtual const std::string& getDBName() const {
|
2011-08-11 12:14:55 -07:00
|
|
|
return (database_name_);
|
2011-08-11 13:09:12 +02:00
|
|
|
}
|
2011-08-16 18:31:09 -07:00
|
|
|
|
|
|
|
const vector<string>& getLastAdded() const {
|
|
|
|
return (columns_lastadded);
|
|
|
|
}
|
2011-08-04 14:32:53 +02:00
|
|
|
private:
|
2011-08-12 16:05:04 -07:00
|
|
|
RECORDS readonly_records;
|
|
|
|
RECORDS update_records;
|
|
|
|
RECORDS empty_records;
|
|
|
|
|
2011-08-04 14:32:53 +02:00
|
|
|
// used as internal index for getNextRecord()
|
|
|
|
size_t cur_record;
|
|
|
|
// used as temporary storage after searchForRecord() and during
|
|
|
|
// getNextRecord() calls, as well as during the building of the
|
|
|
|
// fake data
|
|
|
|
std::vector< std::vector<std::string> > cur_name;
|
|
|
|
|
2011-08-16 18:31:09 -07:00
|
|
|
// The columns that were most recently added via addRecordToZone()
|
|
|
|
vector<string> columns_lastadded;
|
|
|
|
|
2011-08-09 11:19:13 +02:00
|
|
|
// This boolean is used to make sure find() calls resetSearch
|
|
|
|
// when it encounters an error
|
|
|
|
bool search_running_;
|
|
|
|
|
2011-08-12 18:55:58 -07:00
|
|
|
// Whether rollback operation has been performed for the database.
|
|
|
|
// Not useful except for purely testing purpose.
|
|
|
|
bool rollbacked_;
|
|
|
|
|
2011-08-09 11:19:13 +02:00
|
|
|
// We store the name passed to searchForRecords, so we can
|
|
|
|
// hardcode some exceptions into getNextRecord
|
|
|
|
std::string searched_name_;
|
|
|
|
|
2011-08-11 13:09:12 +02:00
|
|
|
const std::string database_name_;
|
|
|
|
|
2011-08-12 16:05:04 -07:00
|
|
|
const RECORDS& getRecords(int zone_id) const {
|
|
|
|
if (zone_id == READONLY_ZONE_ID) {
|
|
|
|
return (readonly_records);
|
|
|
|
} else if (zone_id == WRITABLE_ZONE_ID) {
|
|
|
|
return (update_records);
|
|
|
|
}
|
|
|
|
return (empty_records);
|
|
|
|
}
|
|
|
|
|
2011-08-04 22:12:04 +02:00
|
|
|
// Adds one record to the current name in the database
|
|
|
|
// The actual data will not be added to 'records' until
|
|
|
|
// addCurName() is called
|
2011-08-16 18:31:09 -07:00
|
|
|
void addRecord(const std::string& type,
|
|
|
|
const std::string& ttl,
|
2011-08-04 14:32:53 +02:00
|
|
|
const std::string& sigtype,
|
|
|
|
const std::string& rdata) {
|
|
|
|
std::vector<std::string> columns;
|
|
|
|
columns.push_back(type);
|
2011-08-16 18:31:09 -07:00
|
|
|
columns.push_back(ttl);
|
2011-08-04 14:32:53 +02:00
|
|
|
columns.push_back(sigtype);
|
|
|
|
columns.push_back(rdata);
|
|
|
|
cur_name.push_back(columns);
|
|
|
|
}
|
|
|
|
|
2011-08-04 22:12:04 +02:00
|
|
|
// Adds all records we just built with calls to addRecords
|
|
|
|
// to the actual fake database. This will clear cur_name,
|
|
|
|
// so we can immediately start adding new records.
|
2011-08-04 14:32:53 +02:00
|
|
|
void addCurName(const std::string& name) {
|
2011-08-12 16:05:04 -07:00
|
|
|
ASSERT_EQ(0, readonly_records.count(name));
|
|
|
|
readonly_records[name] = cur_name;
|
2011-08-04 14:32:53 +02:00
|
|
|
cur_name.clear();
|
|
|
|
}
|
|
|
|
|
2011-08-04 22:12:04 +02:00
|
|
|
// Fills the database with zone data.
|
|
|
|
// This method constructs a number of resource records (with addRecord),
|
|
|
|
// which will all be added for one domain name to the fake database
|
|
|
|
// (with addCurName). So for instance the first set of calls create
|
|
|
|
// data for the name 'www.example.org', which will consist of one A RRset
|
|
|
|
// of one record, and one AAAA RRset of two records.
|
|
|
|
// The order in which they are added is the order in which getNextRecord()
|
|
|
|
// will return them (so we can test whether find() etc. support data that
|
|
|
|
// might not come in 'normal' order)
|
|
|
|
// It shall immediately fail if you try to add the same name twice.
|
2011-08-04 14:32:53 +02:00
|
|
|
void fillData() {
|
2011-08-04 21:27:38 +02:00
|
|
|
// some plain data
|
2011-08-04 14:32:53 +02:00
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addRecord("AAAA", "3600", "", "2001:db8::1");
|
|
|
|
addRecord("AAAA", "3600", "", "2001:db8::2");
|
|
|
|
addCurName("www.example.org.");
|
2011-08-04 22:12:04 +02:00
|
|
|
|
2011-08-09 11:19:13 +02:00
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addRecord("AAAA", "3600", "", "2001:db8::1");
|
|
|
|
addRecord("A", "3600", "", "192.0.2.2");
|
|
|
|
addCurName("www2.example.org.");
|
|
|
|
|
2011-08-04 14:32:53 +02:00
|
|
|
addRecord("CNAME", "3600", "", "www.example.org.");
|
|
|
|
addCurName("cname.example.org.");
|
|
|
|
|
2011-08-04 21:27:38 +02:00
|
|
|
// some DNSSEC-'signed' data
|
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
2011-08-05 18:02:33 +02:00
|
|
|
addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12346 example.org. FAKEFAKEFAKE");
|
2011-08-04 21:27:38 +02:00
|
|
|
addRecord("AAAA", "3600", "", "2001:db8::1");
|
|
|
|
addRecord("AAAA", "3600", "", "2001:db8::2");
|
|
|
|
addRecord("RRSIG", "3600", "", "AAAA 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addCurName("signed1.example.org.");
|
2011-08-04 21:57:16 +02:00
|
|
|
addRecord("CNAME", "3600", "", "www.example.org.");
|
|
|
|
addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addCurName("signedcname1.example.org.");
|
2011-08-05 18:02:33 +02:00
|
|
|
// special case might fail; sig is for cname, which isn't there (should be ignored)
|
|
|
|
// (ignoring of 'normal' other type is done above by www.)
|
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addCurName("acnamesig1.example.org.");
|
2011-08-04 21:27:38 +02:00
|
|
|
|
|
|
|
// let's pretend we have a database that is not careful
|
|
|
|
// about the order in which it returns data
|
|
|
|
addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addRecord("AAAA", "3600", "", "2001:db8::2");
|
2011-08-05 18:02:33 +02:00
|
|
|
addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12346 example.org. FAKEFAKEFAKE");
|
2011-08-04 21:27:38 +02:00
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addRecord("RRSIG", "3600", "", "AAAA 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addRecord("AAAA", "3600", "", "2001:db8::1");
|
|
|
|
addCurName("signed2.example.org.");
|
|
|
|
addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
2011-08-04 21:57:16 +02:00
|
|
|
addRecord("CNAME", "3600", "", "www.example.org.");
|
|
|
|
addCurName("signedcname2.example.org.");
|
2011-08-04 21:27:38 +02:00
|
|
|
|
2011-08-05 18:02:33 +02:00
|
|
|
addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addCurName("acnamesig2.example.org.");
|
|
|
|
|
|
|
|
addRecord("RRSIG", "3600", "", "CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addRecord("RRSIG", "3600", "", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addCurName("acnamesig3.example.org.");
|
|
|
|
|
2011-08-09 11:19:13 +02:00
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addRecord("A", "360", "", "192.0.2.2");
|
|
|
|
addCurName("ttldiff1.example.org.");
|
|
|
|
addRecord("A", "360", "", "192.0.2.1");
|
|
|
|
addRecord("A", "3600", "", "192.0.2.2");
|
|
|
|
addCurName("ttldiff2.example.org.");
|
|
|
|
|
2011-08-04 14:32:53 +02:00
|
|
|
// also add some intentionally bad data
|
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addRecord("CNAME", "3600", "", "www.example.org.");
|
2011-08-09 11:19:13 +02:00
|
|
|
addCurName("badcname1.example.org.");
|
|
|
|
|
|
|
|
addRecord("CNAME", "3600", "", "www.example.org.");
|
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addCurName("badcname2.example.org.");
|
|
|
|
|
|
|
|
addRecord("CNAME", "3600", "", "www.example.org.");
|
|
|
|
addRecord("CNAME", "3600", "", "www.example2.org.");
|
|
|
|
addCurName("badcname3.example.org.");
|
|
|
|
|
2011-08-05 18:02:33 +02:00
|
|
|
addRecord("A", "3600", "", "bad");
|
|
|
|
addCurName("badrdata.example.org.");
|
2011-08-09 11:19:13 +02:00
|
|
|
|
2011-08-05 18:02:33 +02:00
|
|
|
addRecord("BAD_TYPE", "3600", "", "192.0.2.1");
|
|
|
|
addCurName("badtype.example.org.");
|
2011-08-09 11:19:13 +02:00
|
|
|
|
2011-08-05 18:02:33 +02:00
|
|
|
addRecord("A", "badttl", "", "192.0.2.1");
|
|
|
|
addCurName("badttl.example.org.");
|
2011-08-09 11:19:13 +02:00
|
|
|
|
|
|
|
addRecord("A", "badttl", "", "192.0.2.1");
|
|
|
|
addRecord("RRSIG", "3600", "", "A 5 3 3600 somebaddata 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addCurName("badsig.example.org.");
|
|
|
|
|
|
|
|
addRecord("A", "3600", "", "192.0.2.1");
|
|
|
|
addRecord("RRSIG", "3600", "TXT", "A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
addCurName("badsigtype.example.org.");
|
2011-08-04 14:32:53 +02:00
|
|
|
}
|
2011-08-01 11:47:37 +02:00
|
|
|
};
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
template <typename ACCESSOR_TYPE>
|
2011-08-01 11:47:37 +02:00
|
|
|
class DatabaseClientTest : public ::testing::Test {
|
2011-08-12 16:05:04 -07:00
|
|
|
protected:
|
2011-08-17 12:15:42 -07:00
|
|
|
DatabaseClientTest() : zname("example.org"), qname("www.example.org"),
|
|
|
|
qclass(RRClass::IN()), qtype(RRType::A()),
|
|
|
|
rrttl(3600)
|
|
|
|
{
|
2011-08-01 11:47:37 +02:00
|
|
|
createClient();
|
2011-08-16 18:31:09 -07:00
|
|
|
|
|
|
|
// set up the commonly used finder.
|
|
|
|
DataSourceClient::FindResult zone(
|
|
|
|
client_->findZone(Name("example.org")));
|
|
|
|
assert(zone.code == result::SUCCESS);
|
|
|
|
finder = dynamic_pointer_cast<DatabaseClient::Finder>(
|
|
|
|
zone.zone_finder);
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
rrset.reset(new RRset(qname, qclass, qtype, rrttl));
|
2011-08-16 18:31:09 -07:00
|
|
|
// Adding an IN/A RDATA. Intentionally using different data
|
2011-08-17 10:31:29 -07:00
|
|
|
// than the initial data configured in MockAccessor::fillData().
|
2011-08-16 18:31:09 -07:00
|
|
|
rrset->addRdata(rdata::createRdata(rrset->getType(), rrset->getClass(),
|
|
|
|
"192.0.2.2"));
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
rrsigset.reset(new RRset(qname, qclass, RRType::RRSIG(),
|
2011-08-16 18:31:09 -07:00
|
|
|
rrttl));
|
|
|
|
rrsigset->addRdata(rdata::createRdata(rrsigset->getType(),
|
|
|
|
rrsigset->getClass(),
|
|
|
|
"A 5 3 0 20000101000000 "
|
|
|
|
"20000201000000 0 example.org. "
|
|
|
|
"FAKEFAKEFAKE"));
|
2011-08-01 11:47:37 +02:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* We initialize the client from a function, so we can call it multiple
|
|
|
|
* times per test.
|
|
|
|
*/
|
|
|
|
void createClient() {
|
2011-08-17 12:15:42 -07:00
|
|
|
current_accessor_ = new ACCESSOR_TYPE();
|
|
|
|
client_.reset(new DatabaseClient(qclass,
|
2011-08-12 18:55:58 -07:00
|
|
|
shared_ptr<DatabaseAccessor>(
|
|
|
|
current_accessor_)));
|
2011-08-01 11:47:37 +02:00
|
|
|
}
|
2011-08-17 12:15:42 -07:00
|
|
|
|
|
|
|
bool searchRunning(bool expected = false) const {
|
|
|
|
try {
|
|
|
|
const MockAccessor* mock_accessor =
|
|
|
|
dynamic_cast<const MockAccessor*>(current_accessor_);
|
|
|
|
return (mock_accessor->searchRunning());
|
|
|
|
} catch (const bad_cast&) {
|
|
|
|
return (expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isRollbacked(bool expected = false) const {
|
|
|
|
try {
|
|
|
|
const MockAccessor* mock_accessor =
|
|
|
|
dynamic_cast<const MockAccessor*>(current_accessor_);
|
|
|
|
return (mock_accessor->isRollbacked());
|
|
|
|
} catch (const bad_cast&) {
|
|
|
|
return (expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void checkLastAdded(const char* const expected[]) const {
|
|
|
|
try {
|
|
|
|
const MockAccessor* mock_accessor =
|
|
|
|
dynamic_cast<const MockAccessor*>(current_accessor_);
|
|
|
|
int i = 0;
|
|
|
|
BOOST_FOREACH(const string& column,
|
|
|
|
mock_accessor->getLastAdded()) {
|
|
|
|
EXPECT_EQ(expected[i++], column);
|
|
|
|
}
|
|
|
|
} catch (const bad_cast&) {
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-01 11:47:37 +02:00
|
|
|
// Will be deleted by client_, just keep the current value for comparison.
|
2011-08-17 12:15:42 -07:00
|
|
|
//MockAccessor* current_accessor_;
|
|
|
|
DatabaseAccessor* current_accessor_;
|
2011-08-04 17:18:54 +02:00
|
|
|
shared_ptr<DatabaseClient> client_;
|
2011-08-11 13:09:12 +02:00
|
|
|
const std::string database_name_;
|
|
|
|
|
2011-08-16 18:31:09 -07:00
|
|
|
// The zone finder of the test zone commonly used in various tests.
|
|
|
|
shared_ptr<DatabaseClient::Finder> finder;
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
const Name zname; // the zone name stored in the test data source
|
2011-08-12 18:55:58 -07:00
|
|
|
const Name qname; // commonly used name to be found
|
2011-08-17 12:15:42 -07:00
|
|
|
const RRClass qclass; // commonly used RR class with qname
|
2011-08-12 18:55:58 -07:00
|
|
|
const RRType qtype; // commonly used RR type with qname
|
2011-08-16 18:31:09 -07:00
|
|
|
const RRTTL rrttl; // commonly used RR TTL
|
|
|
|
RRsetPtr rrset; // for adding/deleting an RRset
|
|
|
|
RRsetPtr rrsigset; // for adding/deleting an RRset
|
2011-08-12 18:55:58 -07:00
|
|
|
|
|
|
|
ZoneUpdaterPtr updater;
|
2011-08-12 16:05:04 -07:00
|
|
|
const std::vector<std::string> empty_rdatas; // for NXRRSET/NXDOMAIN
|
|
|
|
std::vector<std::string> expected_rdatas;
|
|
|
|
std::vector<std::string> expected_sig_rdatas;
|
|
|
|
|
2011-08-01 11:47:37 +02:00
|
|
|
/**
|
|
|
|
* Check the zone finder is a valid one and references the zone ID and
|
2011-08-07 12:26:36 +02:00
|
|
|
* database available here.
|
2011-08-01 11:47:37 +02:00
|
|
|
*/
|
|
|
|
void checkZoneFinder(const DataSourceClient::FindResult& zone) {
|
|
|
|
ASSERT_NE(ZoneFinderPtr(), zone.zone_finder) << "No zone finder";
|
|
|
|
shared_ptr<DatabaseClient::Finder> finder(
|
|
|
|
dynamic_pointer_cast<DatabaseClient::Finder>(zone.zone_finder));
|
|
|
|
ASSERT_NE(shared_ptr<DatabaseClient::Finder>(), finder) <<
|
|
|
|
"Wrong type of finder";
|
2011-08-12 16:05:04 -07:00
|
|
|
EXPECT_EQ(READONLY_ZONE_ID, finder->zone_id());
|
2011-08-12 16:27:57 -07:00
|
|
|
EXPECT_EQ(current_accessor_, &finder->getAccessor());
|
2011-08-01 11:47:37 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
typedef ::testing::Types<MockAccessor> TestAccessorTypes;
|
|
|
|
TYPED_TEST_CASE(DatabaseClientTest, TestAccessorTypes);
|
|
|
|
|
|
|
|
TYPED_TEST(DatabaseClientTest, zoneNotFound) {
|
|
|
|
DataSourceClient::FindResult zone(
|
|
|
|
this->client_->findZone(Name("example.com")));
|
2011-08-01 11:47:37 +02:00
|
|
|
EXPECT_EQ(result::NOTFOUND, zone.code);
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, exactZone) {
|
|
|
|
DataSourceClient::FindResult zone( this->client_->findZone(this->zname));
|
2011-08-01 11:47:37 +02:00
|
|
|
EXPECT_EQ(result::SUCCESS, zone.code);
|
2011-08-17 12:15:42 -07:00
|
|
|
this->checkZoneFinder(zone);
|
2011-08-01 11:47:37 +02:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, superZone) {
|
|
|
|
DataSourceClient::FindResult zone(this->client_->findZone(Name(
|
2011-08-01 11:47:37 +02:00
|
|
|
"sub.example.org")));
|
|
|
|
EXPECT_EQ(result::PARTIALMATCH, zone.code);
|
2011-08-17 12:15:42 -07:00
|
|
|
this->checkZoneFinder(zone);
|
2011-08-01 11:47:37 +02:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
// This test doesn't depend on derived accessor class, so we use TEST().
|
|
|
|
TEST(GenericDatabaseClientTest, noAccessorException) {
|
2011-08-12 18:55:58 -07:00
|
|
|
EXPECT_THROW(DatabaseClient(RRClass::IN(), shared_ptr<DatabaseAccessor>()),
|
2011-08-01 12:03:35 +02:00
|
|
|
isc::InvalidParameter);
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, startUpdate) {
|
2011-08-12 16:05:04 -07:00
|
|
|
// startUpdate will succeed only when there's an exact match zone.
|
|
|
|
|
|
|
|
EXPECT_EQ(ZoneUpdaterPtr(),
|
2011-08-17 12:15:42 -07:00
|
|
|
this->client_->startUpdateZone(Name("example.com"), false));
|
2011-08-12 16:05:04 -07:00
|
|
|
EXPECT_NE(ZoneUpdaterPtr(),
|
2011-08-17 12:15:42 -07:00
|
|
|
this->client_->startUpdateZone(this->zname, false));
|
|
|
|
|
2011-08-12 16:05:04 -07:00
|
|
|
EXPECT_EQ(ZoneUpdaterPtr(),
|
2011-08-17 12:15:42 -07:00
|
|
|
this->client_->startUpdateZone(Name("sub.example.org"), false));
|
2011-08-12 16:05:04 -07:00
|
|
|
}
|
|
|
|
|
2011-08-11 22:52:21 +02:00
|
|
|
// checks if the given rrset matches the
|
|
|
|
// given name, class, type and rdatas
|
|
|
|
void
|
|
|
|
checkRRset(isc::dns::ConstRRsetPtr rrset,
|
2011-08-17 12:15:42 -07:00
|
|
|
const Name& name,
|
2011-08-11 22:52:21 +02:00
|
|
|
const isc::dns::RRClass& rrclass,
|
|
|
|
const isc::dns::RRType& rrtype,
|
|
|
|
const isc::dns::RRTTL& rrttl,
|
2011-08-12 11:00:12 +02:00
|
|
|
const std::vector<std::string>& rdatas) {
|
2011-08-11 22:52:21 +02:00
|
|
|
isc::dns::RRsetPtr expected_rrset(
|
|
|
|
new isc::dns::RRset(name, rrclass, rrtype, rrttl));
|
|
|
|
for (unsigned int i = 0; i < rdatas.size(); ++i) {
|
|
|
|
expected_rrset->addRdata(
|
|
|
|
isc::dns::rdata::createRdata(rrtype, rrclass,
|
|
|
|
rdatas[i]));
|
|
|
|
}
|
|
|
|
isc::testutils::rrsetCheck(expected_rrset, rrset);
|
|
|
|
}
|
|
|
|
|
2011-08-04 21:57:16 +02:00
|
|
|
void
|
2011-08-12 16:05:04 -07:00
|
|
|
doFindTest(ZoneFinder& finder,
|
2011-08-17 12:15:42 -07:00
|
|
|
const Name& name,
|
2011-08-04 21:57:16 +02:00
|
|
|
const isc::dns::RRType& type,
|
|
|
|
const isc::dns::RRType& expected_type,
|
2011-08-09 11:19:13 +02:00
|
|
|
const isc::dns::RRTTL expected_ttl,
|
2011-08-04 21:57:16 +02:00
|
|
|
ZoneFinder::Result expected_result,
|
2011-08-11 17:31:06 +02:00
|
|
|
const std::vector<std::string>& expected_rdatas,
|
|
|
|
const std::vector<std::string>& expected_sig_rdatas)
|
2011-08-04 21:57:16 +02:00
|
|
|
{
|
2011-08-09 11:19:13 +02:00
|
|
|
ZoneFinder::FindResult result =
|
2011-08-12 16:05:04 -07:00
|
|
|
finder.find(name, type, NULL, ZoneFinder::FIND_DEFAULT);
|
2011-08-09 11:19:13 +02:00
|
|
|
ASSERT_EQ(expected_result, result.code) << name << " " << type;
|
2011-08-11 17:31:06 +02:00
|
|
|
if (expected_rdatas.size() > 0) {
|
2011-08-12 16:05:04 -07:00
|
|
|
checkRRset(result.rrset, name, finder.getClass(),
|
2011-08-11 22:52:21 +02:00
|
|
|
expected_type, expected_ttl, expected_rdatas);
|
2011-08-11 17:31:06 +02:00
|
|
|
|
|
|
|
if (expected_sig_rdatas.size() > 0) {
|
2011-08-11 22:52:21 +02:00
|
|
|
checkRRset(result.rrset->getRRsig(), name,
|
2011-08-12 16:05:04 -07:00
|
|
|
finder.getClass(), isc::dns::RRType::RRSIG(),
|
2011-08-11 22:52:21 +02:00
|
|
|
expected_ttl, expected_sig_rdatas);
|
2011-08-04 21:57:16 +02:00
|
|
|
} else {
|
|
|
|
EXPECT_EQ(isc::dns::RRsetPtr(), result.rrset->getRRsig());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
EXPECT_EQ(isc::dns::RRsetPtr(), result.rrset);
|
|
|
|
}
|
|
|
|
}
|
2011-08-17 12:15:42 -07:00
|
|
|
|
|
|
|
TYPED_TEST(DatabaseClientTest, find) {
|
|
|
|
EXPECT_EQ(READONLY_ZONE_ID, this->finder->zone_id());
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
doFindTest(*this->finder, Name("www.example.org."),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_rdatas.push_back("192.0.2.2");
|
|
|
|
doFindTest(*this->finder, Name("www2.example.org."),
|
|
|
|
this->qtype, this->qtype,
|
|
|
|
this->rrttl,
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::SUCCESS,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("2001:db8::1");
|
|
|
|
this->expected_rdatas.push_back("2001:db8::2");
|
|
|
|
doFindTest(*this->finder, Name("www.example.org."),
|
2011-08-04 21:57:16 +02:00
|
|
|
isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrttl,
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::SUCCESS,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
2011-08-11 17:31:06 +02:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
doFindTest(*this->finder, Name("www.example.org."),
|
2011-08-04 21:57:16 +02:00
|
|
|
isc::dns::RRType::TXT(), isc::dns::RRType::TXT(),
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrttl, ZoneFinder::NXRRSET,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("www.example.org.");
|
|
|
|
doFindTest(*this->finder, Name("cname.example.org."),
|
|
|
|
this->qtype, isc::dns::RRType::CNAME(), this->rrttl,
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::CNAME,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
2011-08-11 17:31:06 +02:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("www.example.org.");
|
|
|
|
doFindTest(*this->finder, Name("cname.example.org."),
|
2011-08-09 11:19:13 +02:00
|
|
|
isc::dns::RRType::CNAME(), isc::dns::RRType::CNAME(),
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
doFindTest(*this->finder, Name("doesnotexist.example.org."),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::NXDOMAIN,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_sig_rdatas.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
this->expected_sig_rdatas.push_back("A 5 3 3600 20000101000000 20000201000000 12346 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("signed1.example.org."),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("2001:db8::1");
|
|
|
|
this->expected_rdatas.push_back("2001:db8::2");
|
|
|
|
this->expected_sig_rdatas.push_back("AAAA 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("signed1.example.org."),
|
2011-08-04 21:57:16 +02:00
|
|
|
isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(),
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
doFindTest(*this->finder, Name("signed1.example.org."),
|
|
|
|
isc::dns::RRType::TXT(), isc::dns::RRType::TXT(), this->rrttl,
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::NXRRSET,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("www.example.org.");
|
|
|
|
this->expected_sig_rdatas.push_back("CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("signedcname1.example.org."),
|
|
|
|
this->qtype, isc::dns::RRType::CNAME(), this->rrttl,
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::CNAME,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_sig_rdatas.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
this->expected_sig_rdatas.push_back("A 5 3 3600 20000101000000 20000201000000 12346 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("signed2.example.org."),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("2001:db8::2");
|
|
|
|
this->expected_rdatas.push_back("2001:db8::1");
|
|
|
|
this->expected_sig_rdatas.push_back("AAAA 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("signed2.example.org."),
|
|
|
|
isc::dns::RRType::AAAA(), isc::dns::RRType::AAAA(), this->rrttl,
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::SUCCESS,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
2011-08-11 17:31:06 +02:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
doFindTest(*this->finder, Name("signed2.example.org."),
|
|
|
|
isc::dns::RRType::TXT(), isc::dns::RRType::TXT(), this->rrttl,
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::NXRRSET,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("www.example.org.");
|
|
|
|
this->expected_sig_rdatas.push_back("CNAME 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("signedcname2.example.org."),
|
|
|
|
this->qtype, isc::dns::RRType::CNAME(), this->rrttl,
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::CNAME,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_sig_rdatas.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("acnamesig1.example.org."),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_sig_rdatas.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("acnamesig2.example.org."),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_sig_rdatas.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("acnamesig3.example.org."),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_rdatas.push_back("192.0.2.2");
|
|
|
|
doFindTest(*this->finder, Name("ttldiff1.example.org."),
|
|
|
|
this->qtype, this->qtype, isc::dns::RRTTL(360),
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::SUCCESS,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_rdatas.push_back("192.0.2.2");
|
|
|
|
doFindTest(*this->finder, Name("ttldiff2.example.org."),
|
|
|
|
this->qtype, this->qtype, isc::dns::RRTTL(360),
|
2011-08-11 17:31:06 +02:00
|
|
|
ZoneFinder::SUCCESS,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
2011-08-09 11:19:13 +02:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_THROW(this->finder->find(Name("badcname1.example.org."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-09 11:19:13 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(Name("badcname2.example.org."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-04 14:32:53 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(Name("badcname3.example.org."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-04 14:32:53 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(Name("badrdata.example.org."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-05 18:02:33 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(Name("badtype.example.org."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-05 18:02:33 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(Name("badttl.example.org."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-05 18:02:33 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(Name("badsig.example.org."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-09 11:19:13 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
2011-08-09 11:19:13 +02:00
|
|
|
|
|
|
|
// Trigger the hardcoded exceptions and see if find() has cleaned up
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_THROW(this->finder->find(Name("dsexception.in.search."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-09 11:19:13 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(Name("iscexception.in.search."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-09 11:19:13 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(
|
|
|
|
Name("basicexception.in.search."),
|
|
|
|
this->qtype, NULL, ZoneFinder::FIND_DEFAULT),
|
2011-08-09 11:19:13 +02:00
|
|
|
std::exception);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
2011-08-11 17:31:06 +02:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_THROW(this->finder->find(Name("dsexception.in.getnext."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-09 11:19:13 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(Name("iscexception.in.getnext."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-09 11:19:13 +02:00
|
|
|
DataSourceError);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
|
|
|
EXPECT_THROW(this->finder->find(Name("basicexception.in.getnext."),
|
|
|
|
this->qtype, NULL,
|
|
|
|
ZoneFinder::FIND_DEFAULT),
|
2011-08-09 11:19:13 +02:00
|
|
|
std::exception);
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->searchRunning());
|
2011-08-09 11:19:13 +02:00
|
|
|
|
|
|
|
// This RRSIG has the wrong sigtype field, which should be
|
|
|
|
// an error if we decide to keep using that field
|
|
|
|
// Right now the field is ignored, so it does not error
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_sig_rdatas.push_back("A 5 3 3600 20000101000000 20000201000000 12345 example.org. FAKEFAKEFAKE");
|
|
|
|
doFindTest(*this->finder, Name("badsigtype.example.org."),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
|
|
|
EXPECT_FALSE(this->searchRunning());
|
2011-08-04 14:32:53 +02:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, updaterFinder) {
|
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
ASSERT_TRUE(this->updater);
|
2011-08-12 16:05:04 -07:00
|
|
|
|
|
|
|
// If this update isn't replacing the zone, the finder should work
|
|
|
|
// just like the normal find() case.
|
|
|
|
EXPECT_EQ(WRITABLE_ZONE_ID, dynamic_cast<DatabaseClient::Finder&>(
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater->getFinder()).zone_id());
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
doFindTest(this->updater->getFinder(), Name("www.example.org."),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-12 16:05:04 -07:00
|
|
|
|
|
|
|
// When replacing the zone, the updater's finder shouldn't see anything
|
|
|
|
// in the zone until something is added.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, true);
|
|
|
|
ASSERT_TRUE(this->updater);
|
2011-08-12 16:05:04 -07:00
|
|
|
EXPECT_EQ(WRITABLE_ZONE_ID, dynamic_cast<DatabaseClient::Finder&>(
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater->getFinder()).zone_id());
|
|
|
|
doFindTest(this->updater->getFinder(), Name("www.example.org."),
|
2011-08-12 16:05:04 -07:00
|
|
|
RRType::A(), RRType::A(), RRTTL(3600), ZoneFinder::NXDOMAIN,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->empty_rdatas, this->empty_rdatas);
|
2011-08-12 16:05:04 -07:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, flushZone) {
|
2011-08-12 18:55:58 -07:00
|
|
|
// A simple update case: flush the entire zone
|
|
|
|
|
|
|
|
// Before update, the name exists.
|
2011-08-17 12:15:42 -07:00
|
|
|
ZoneFinderPtr finder = this->client_->findZone(this->zname).zone_finder;
|
|
|
|
EXPECT_EQ(ZoneFinder::SUCCESS, this->finder->find(this->qname,
|
|
|
|
this->qtype).code);
|
2011-08-12 18:55:58 -07:00
|
|
|
|
|
|
|
// start update in the replace mode. the normal finder should still
|
|
|
|
// be able to see the record, but the updater's finder shouldn't.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, true);
|
|
|
|
EXPECT_EQ(ZoneFinder::SUCCESS, this->finder->find(this->qname,
|
|
|
|
this->qtype).code);
|
2011-08-12 18:55:58 -07:00
|
|
|
EXPECT_EQ(ZoneFinder::NXDOMAIN,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater->getFinder().find(this->qname, this->qtype).code);
|
2011-08-12 18:55:58 -07:00
|
|
|
|
|
|
|
// commit the update. now the normal finder shouldn't see it.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater->commit();
|
|
|
|
EXPECT_EQ(ZoneFinder::NXDOMAIN, this->finder->find(this->qname,
|
|
|
|
this->qtype).code);
|
2011-08-12 18:55:58 -07:00
|
|
|
|
|
|
|
// Check rollback wasn't accidentally performed.
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->isRollbacked());
|
2011-08-12 18:55:58 -07:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
|
|
|
|
TYPED_TEST(DatabaseClientTest, updateCancel) {
|
2011-08-12 18:55:58 -07:00
|
|
|
// similar to the previous test, but destruct the updater before commit.
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
ZoneFinderPtr finder = this->client_->findZone(this->zname).zone_finder;
|
|
|
|
EXPECT_EQ(ZoneFinder::SUCCESS, this->finder->find(this->qname,
|
|
|
|
this->qtype).code);
|
2011-08-12 18:55:58 -07:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, true);
|
2011-08-12 18:55:58 -07:00
|
|
|
EXPECT_EQ(ZoneFinder::NXDOMAIN,
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater->getFinder().find(this->qname, this->qtype).code);
|
2011-08-12 18:55:58 -07:00
|
|
|
// DB should not have been rolled back yet.
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_FALSE(this->isRollbacked());
|
|
|
|
this->updater.reset(); // destruct without commit
|
2011-08-12 18:55:58 -07:00
|
|
|
|
|
|
|
// reset() should have triggered rollback (although it doesn't affect
|
|
|
|
// anything to the mock accessor implementation except for the result of
|
|
|
|
// isRollbacked())
|
2011-08-17 12:15:42 -07:00
|
|
|
EXPECT_TRUE(this->isRollbacked(true));
|
|
|
|
EXPECT_EQ(ZoneFinder::SUCCESS, this->finder->find(this->qname,
|
|
|
|
this->qtype).code);
|
2011-08-12 18:55:58 -07:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, duplicateCommit) {
|
2011-08-12 18:55:58 -07:00
|
|
|
// duplicate commit. should result in exception.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, true);
|
|
|
|
this->updater->commit();
|
|
|
|
EXPECT_THROW(this->updater->commit(), DataSourceError);
|
2011-08-12 18:55:58 -07:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, addRRsetToNewZone) {
|
2011-08-16 18:31:09 -07:00
|
|
|
// Add a single RRset to a fresh empty zone
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, true);
|
|
|
|
this->updater->addRRset(*this->rrset);
|
2011-08-16 18:31:09 -07:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.2");
|
2011-08-16 18:31:09 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("add RRset");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Similar to the previous case, but with RRSIG
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, true);
|
|
|
|
this->updater->addRRset(*this->rrset);
|
|
|
|
this->updater->addRRset(*this->rrsigset);
|
2011-08-16 18:31:09 -07:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
// confirm the expected columns were passed to the accessor (if checkable).
|
2011-08-16 18:31:09 -07:00
|
|
|
const char* const rrsig_added[] = {
|
|
|
|
"www.example.org.", "org.example.www.", "3600", "RRSIG", "A",
|
|
|
|
"A 5 3 0 20000101000000 20000201000000 0 example.org. FAKEFAKEFAKE"
|
|
|
|
};
|
2011-08-17 12:15:42 -07:00
|
|
|
this->checkLastAdded(rrsig_added);
|
2011-08-16 18:31:09 -07:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_sig_rdatas.clear();
|
|
|
|
this->expected_sig_rdatas.push_back(
|
|
|
|
rrsig_added[DatabaseAccessor::ADD_RDATA]);
|
2011-08-16 18:31:09 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("add RRset with RRSIG");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->expected_sig_rdatas);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, addRRsetToCurrentZone) {
|
2011-08-16 18:31:09 -07:00
|
|
|
// Similar to the previous test, but not replacing the existing data.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->updater->addRRset(*this->rrset);
|
2011-08-16 18:31:09 -07:00
|
|
|
|
|
|
|
// We should see both old and new data.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_rdatas.push_back("192.0.2.2");
|
2011-08-16 18:31:09 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("add RRset");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater->commit();
|
2011-08-16 18:31:09 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("add RRset after commit");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(*this->finder, this->qname, this->qtype, this->qtype,
|
|
|
|
this->rrttl, ZoneFinder::SUCCESS, this->expected_rdatas,
|
|
|
|
this->empty_rdatas);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, addMultipleRRs) {
|
2011-08-17 10:31:29 -07:00
|
|
|
// Similar to the previous case, but the added RRset contains multiple
|
|
|
|
// RRs.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"192.0.2.3"));
|
|
|
|
this->updater->addRRset(*this->rrset);
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_rdatas.push_back("192.0.2.2");
|
|
|
|
this->expected_rdatas.push_back("192.0.2.3");
|
2011-08-17 10:31:29 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("add multiple RRs");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, addRRsetOfLargerTTL) {
|
2011-08-16 18:31:09 -07:00
|
|
|
// Similar to the previous one, but the TTL of the added RRset is larger
|
|
|
|
// than that of the existing record. The finder should use the smaller
|
|
|
|
// one.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->rrset->setTTL(RRTTL(7200));
|
|
|
|
this->updater->addRRset(*this->rrset);
|
2011-08-16 18:31:09 -07:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_rdatas.push_back("192.0.2.2");
|
2011-08-16 18:31:09 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("add RRset of larger TTL");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, addRRsetOfSmallerTTL) {
|
2011-08-16 18:31:09 -07:00
|
|
|
// Similar to the previous one, but the added RRset has a smaller TTL.
|
|
|
|
// The added TTL should be used by the finder.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->rrset->setTTL(RRTTL(1800));
|
|
|
|
this->updater->addRRset(*this->rrset);
|
2011-08-16 18:31:09 -07:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_rdatas.push_back("192.0.2.2");
|
2011-08-16 18:31:09 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("add RRset of smaller TTL");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, RRTTL(1800), ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, addSameRR) {
|
2011-08-16 18:31:09 -07:00
|
|
|
// Add the same RR as that is already in the data source.
|
|
|
|
// Currently the add interface doesn't try to suppress the duplicate,
|
|
|
|
// neither does the finder. We may want to revisit it in future versions.
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->rrset.reset(new RRset(this->qname, this->qclass, this->qtype,
|
|
|
|
this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"192.0.2.1"));
|
|
|
|
this->updater->addRRset(*this->rrset);
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
2011-08-16 18:31:09 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("add same RR");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, addDeviantRR) {
|
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
2011-08-16 18:31:09 -07:00
|
|
|
|
|
|
|
// RR class mismatch. This should be detected and rejected.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrset.reset(new RRset(this->qname, RRClass::CH(), RRType::TXT(),
|
|
|
|
this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"test text"));
|
|
|
|
EXPECT_THROW(this->updater->addRRset(*this->rrset), DataSourceError);
|
2011-08-16 18:31:09 -07:00
|
|
|
|
|
|
|
// Out-of-zone owner name. At a higher level this should be rejected,
|
|
|
|
// but it doesn't happen in this interface.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrset.reset(new RRset(Name("example.com"), this->qclass, this->qtype,
|
|
|
|
this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"192.0.2.100"));
|
|
|
|
this->updater->addRRset(*this->rrset);
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("192.0.2.100");
|
2011-08-16 18:31:09 -07:00
|
|
|
{
|
|
|
|
// Note: with the find() implementation being more strict about
|
|
|
|
// zone cuts, this test may fail. Then the test should be updated.
|
|
|
|
SCOPED_TRACE("add out-of-zone RR");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), Name("example.com"),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, addEmptyRRset) {
|
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->rrset.reset(new RRset(this->qname, this->qclass, this->qtype,
|
|
|
|
this->rrttl));
|
|
|
|
EXPECT_THROW(this->updater->addRRset(*this->rrset), DataSourceError);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, addAfterCommit) {
|
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->updater->commit();
|
|
|
|
EXPECT_THROW(this->updater->addRRset(*this->rrset), DataSourceError);
|
2011-08-16 18:31:09 -07:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, deleteRRset) {
|
|
|
|
this->rrset.reset(new RRset(this->qname, this->qclass, this->qtype,
|
|
|
|
this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"192.0.2.1"));
|
2011-08-17 10:31:29 -07:00
|
|
|
|
|
|
|
// Delete one RR from an RRset
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->updater->deleteRRset(*this->rrset);
|
2011-08-17 10:31:29 -07:00
|
|
|
|
|
|
|
// Delete the only RR of a name
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrset.reset(new RRset(Name("cname.example.org"), this->qclass,
|
|
|
|
RRType::CNAME(), this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"www.example.org"));
|
|
|
|
this->updater->deleteRRset(*this->rrset);
|
2011-08-17 10:31:29 -07:00
|
|
|
|
|
|
|
// The updater finder should immediately see the deleted results.
|
|
|
|
{
|
|
|
|
SCOPED_TRACE("delete RRset");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::NXRRSET,
|
|
|
|
this->empty_rdatas, this->empty_rdatas);
|
|
|
|
doFindTest(this->updater->getFinder(), Name("cname.example.org"),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::NXDOMAIN,
|
|
|
|
this->empty_rdatas, this->empty_rdatas);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// before committing the change, the original finder should see the
|
|
|
|
// original record.
|
|
|
|
{
|
|
|
|
SCOPED_TRACE("delete RRset before commit");
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
doFindTest(*this->finder, this->qname, this->qtype, this->qtype,
|
|
|
|
this->rrttl, ZoneFinder::SUCCESS, this->expected_rdatas,
|
|
|
|
this->empty_rdatas);
|
|
|
|
|
|
|
|
this->expected_rdatas.clear();
|
|
|
|
this->expected_rdatas.push_back("www.example.org.");
|
|
|
|
doFindTest(*this->finder, Name("cname.example.org"), this->qtype,
|
|
|
|
RRType::CNAME(), this->rrttl, ZoneFinder::CNAME,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// once committed, the record should be removed from the original finder's
|
|
|
|
// view, too.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater->commit();
|
2011-08-17 10:31:29 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("delete RRset after commit");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(*this->finder, this->qname, this->qtype, this->qtype,
|
|
|
|
this->rrttl, ZoneFinder::NXRRSET, this->empty_rdatas,
|
|
|
|
this->empty_rdatas);
|
|
|
|
doFindTest(*this->finder, Name("cname.example.org"),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::NXDOMAIN,
|
|
|
|
this->empty_rdatas, this->empty_rdatas);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, deleteRRsetToNXDOMAIN) {
|
2011-08-17 10:31:29 -07:00
|
|
|
// similar to the previous case, but it removes the only record of the
|
|
|
|
// given name. a subsequent find() should result in NXDOMAIN.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrset.reset(new RRset(Name("cname.example.org"), this->qclass,
|
|
|
|
RRType::CNAME(), this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"www.example.org"));
|
|
|
|
|
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->updater->deleteRRset(*this->rrset);
|
2011-08-17 10:31:29 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("delete RRset to NXDOMAIN");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), Name("cname.example.org"),
|
|
|
|
this->qtype, this->qtype, this->rrttl, ZoneFinder::NXDOMAIN,
|
|
|
|
this->empty_rdatas, this->empty_rdatas);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, deleteMultipleRRs) {
|
|
|
|
this->rrset.reset(new RRset(this->qname, this->qclass, RRType::AAAA(),
|
|
|
|
this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"2001:db8::1"));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"2001:db8::2"));
|
2011-08-17 10:31:29 -07:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->updater->deleteRRset(*this->rrset);
|
2011-08-17 10:31:29 -07:00
|
|
|
|
|
|
|
{
|
|
|
|
SCOPED_TRACE("delete multiple RRs");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, RRType::AAAA(),
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::NXRRSET,
|
|
|
|
this->empty_rdatas, this->empty_rdatas);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, partialDelete) {
|
|
|
|
this->rrset.reset(new RRset(this->qname, this->qclass, RRType::AAAA(),
|
|
|
|
this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"2001:db8::1"));
|
2011-08-17 10:31:29 -07:00
|
|
|
// This does not exist in the test data source:
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"2001:db8::3"));
|
2011-08-17 10:31:29 -07:00
|
|
|
|
|
|
|
// deleteRRset should succeed "silently", and subsequent find() should
|
|
|
|
// find the remaining RR.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->updater->deleteRRset(*this->rrset);
|
2011-08-17 10:31:29 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("partial delete");
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.push_back("2001:db8::2");
|
|
|
|
doFindTest(this->updater->getFinder(), this->qname, RRType::AAAA(),
|
|
|
|
RRType::AAAA(), this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, deleteNoMatch) {
|
2011-08-17 10:31:29 -07:00
|
|
|
// similar to the previous test, but there's not even a match in the
|
|
|
|
// specified RRset. Essentially there's no difference in the result.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->updater->deleteRRset(*this->rrset);
|
2011-08-17 10:31:29 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("delete no match");
|
2011-08-17 12:15:42 -07:00
|
|
|
this->expected_rdatas.push_back("192.0.2.1");
|
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::SUCCESS,
|
|
|
|
this->expected_rdatas, this->empty_rdatas);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
2011-08-12 18:55:58 -07:00
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, deleteWithDifferentTTL) {
|
2011-08-17 10:31:29 -07:00
|
|
|
// Our delete interface simply ignores TTL (may change in a future version)
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrset.reset(new RRset(this->qname, this->qclass, this->qtype,
|
|
|
|
RRTTL(1800)));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"192.0.2.1"));
|
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->updater->deleteRRset(*this->rrset);
|
2011-08-17 10:31:29 -07:00
|
|
|
{
|
|
|
|
SCOPED_TRACE("delete RRset with a different TTL");
|
2011-08-17 12:15:42 -07:00
|
|
|
doFindTest(this->updater->getFinder(), this->qname, this->qtype,
|
|
|
|
this->qtype, this->rrttl, ZoneFinder::NXRRSET,
|
|
|
|
this->empty_rdatas, this->empty_rdatas);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, deleteDeviantRR) {
|
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
2011-08-17 10:31:29 -07:00
|
|
|
|
|
|
|
// RR class mismatch. This should be detected and rejected.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrset.reset(new RRset(this->qname, RRClass::CH(), RRType::TXT(),
|
|
|
|
this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"test text"));
|
|
|
|
EXPECT_THROW(this->updater->deleteRRset(*this->rrset), DataSourceError);
|
2011-08-17 10:31:29 -07:00
|
|
|
|
|
|
|
// Out-of-zone owner name. At a higher level this should be rejected,
|
|
|
|
// but it doesn't happen in this interface.
|
2011-08-17 12:15:42 -07:00
|
|
|
this->rrset.reset(new RRset(Name("example.com"), this->qclass, this->qtype,
|
|
|
|
this->rrttl));
|
|
|
|
this->rrset->addRdata(rdata::createRdata(this->rrset->getType(),
|
|
|
|
this->rrset->getClass(),
|
|
|
|
"192.0.2.100"));
|
|
|
|
EXPECT_NO_THROW(this->updater->deleteRRset(*this->rrset));
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, deleteAfterCommit) {
|
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->updater->commit();
|
|
|
|
EXPECT_THROW(this->updater->deleteRRset(*this->rrset), DataSourceError);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
|
|
|
|
2011-08-17 12:15:42 -07:00
|
|
|
TYPED_TEST(DatabaseClientTest, deleteEmptyRRset) {
|
|
|
|
this->updater = this->client_->startUpdateZone(this->zname, false);
|
|
|
|
this->rrset.reset(new RRset(this->qname, this->qclass, this->qtype,
|
|
|
|
this->rrttl));
|
|
|
|
EXPECT_THROW(this->updater->deleteRRset(*this->rrset), DataSourceError);
|
2011-08-17 10:31:29 -07:00
|
|
|
}
|
2011-08-01 11:47:37 +02:00
|
|
|
}
|