Commit 7aac25a5 authored by JINMEI Tatuya's avatar JINMEI Tatuya

[1891] implemented addNSEC3RecordToZone, 1st step.

defined a new statement for updating the nsec3 table, and used it from
addNSEC3RecordToZone.  some validation checks are still missing.
also made simple cleanup of removing unnecessary namespace qualifiers.
parent 358beb2e
......@@ -73,7 +73,8 @@ enum StatementID {
NSEC3 = 16,
NSEC3_PREVIOUS = 17,
NSEC3_LAST = 18,
NUM_STATEMENTS = 19
ADD_NSEC3_RECORD = 19,
NUM_STATEMENTS = 20
};
const char* const text_statements[NUM_STATEMENTS] = {
......@@ -135,19 +136,22 @@ const char* const text_statements[NUM_STATEMENTS] = {
"WHERE zone_id=?1 AND id>=?2 and id<=?3 "
"ORDER BY id ASC",
// Query to get the NSEC3 records
// NSEC3: Query to get the NSEC3 records
//
// The "1" in SELECT is for positioning the rdata column to the
// expected position, so we can reuse the same code as for other
// lookups.
"SELECT rdtype, ttl, 1, rdata FROM nsec3 WHERE zone_id=?1 AND "
"hash=?2",
// For getting the previous NSEC3 hash
// NSEC3_PREVIOUS: For getting the previous NSEC3 hash
"SELECT DISTINCT hash FROM nsec3 WHERE zone_id=?1 AND hash < ?2 "
"ORDER BY hash DESC LIMIT 1",
// And for wrap-around
// NSEC3_LAST: And for wrap-around
"SELECT DISTINCT hash FROM nsec3 WHERE zone_id=?1 "
"ORDER BY hash DESC LIMIT 1",
// ADD_NSEC3_RECORD: Add NSEC3-related (NSEC3 or NSEC3-covering RRSIG) RR
"INSERT INTO nsec3 (zone_id, hash, owner, ttl, rdtype, rdata) "
"VALUES (?1, ?2, '', ?3, ?4, ?5)"
};
struct SQLite3Parameters {
......@@ -1128,15 +1132,17 @@ SQLite3Accessor::addRecordToZone(const string (&columns)[ADD_COLUMN_COUNT]) {
isc_throw(DataSourceError, "adding record to SQLite3 "
"data source without transaction");
}
doUpdate<const string (&)[DatabaseAccessor::ADD_COLUMN_COUNT]>(
doUpdate<const string (&)[ADD_COLUMN_COUNT]>(
*dbparameters_, ADD_RECORD, columns, "add record to zone");
}
void
SQLite3Accessor::addNSEC3RecordToZone(
const string (&/*columns*/)[ADD_NSEC3_COLUMN_COUNT])
const string (&columns)[ADD_NSEC3_COLUMN_COUNT])
{
isc_throw(NotImplemented, "not yet implemented");
// TODO: no transaction case
doUpdate<const string (&)[ADD_NSEC3_COLUMN_COUNT]>(
*dbparameters_, ADD_NSEC3_RECORD, columns, "add NSEC3 record to zone");
}
void
......@@ -1145,7 +1151,7 @@ SQLite3Accessor::deleteRecordInZone(const string (&params)[DEL_PARAM_COUNT]) {
isc_throw(DataSourceError, "deleting record in SQLite3 "
"data source without transaction");
}
doUpdate<const string (&)[DatabaseAccessor::DEL_PARAM_COUNT]>(
doUpdate<const string (&)[DEL_PARAM_COUNT]>(
*dbparameters_, DEL_RECORD, params, "delete record from zone");
}
......
......@@ -12,8 +12,7 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <algorithm>
#include <vector>
#include "faked_nsec3.h"
#include <datasrc/sqlite3_accessor.h>
......@@ -21,14 +20,20 @@
#include <dns/rrclass.h>
#include <sqlite3.h>
#include <gtest/gtest.h>
#include <boost/lexical_cast.hpp>
#include <boost/scoped_ptr.hpp>
#include <algorithm>
#include <vector>
#include <fstream>
#include <sqlite3.h>
using namespace std;
using namespace isc::datasrc;
using namespace isc::datasrc::test;
using boost::lexical_cast;
using isc::data::ConstElementPtr;
using isc::data::Element;
......@@ -463,11 +468,11 @@ TEST(SQLite3Open, getDBNameExampleROOT) {
// Simple function to match records
void
checkRecordRow(const std::string columns[],
const std::string& field0,
const std::string& field1,
const std::string& field2,
const std::string& field3,
const std::string& field4)
const std::string& field0, // for type
const std::string& field1, // for TTL
const std::string& field2, // for "sigtype"
const std::string& field3, // for rdata
const std::string& field4) // for name
{
EXPECT_EQ(field0, columns[DatabaseAccessor::TYPE_COLUMN]);
EXPECT_EQ(field1, columns[DatabaseAccessor::TTL_COLUMN]);
......@@ -736,6 +741,18 @@ const char* const deleted_data[] = {
// Existing data to be removed commonly used by some of the tests below
"foo.bar.example.com.", "A", "192.0.2.1"
};
const char* const nsec3_data[DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT] = {
// example NSEC parameters. Using "apex_hash" just as a convenient
// shortcut; otherwise it has nothing to do with the zone apex for the
// purpose of this test.
apex_hash, "3600", "NSEC3",
"1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR NS SOA"
};
const char* const nsec3_sig_data[DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT] = {
ns1_hash, "3600", "RRSIG",
"NSEC3 5 3 3600 20000101000000 20000201000000 12345 "
"example.com. FAKEFAKEFAKE"
};
class SQLite3Update : public SQLite3AccessorTest {
protected:
......@@ -762,6 +779,7 @@ protected:
int zone_id;
std::string get_columns[DatabaseAccessor::COLUMN_COUNT];
std::string add_columns[DatabaseAccessor::ADD_COLUMN_COUNT];
std::string add_nsec3_columns[DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT];
std::string del_params[DatabaseAccessor::DEL_PARAM_COUNT];
std::string diff_params[DatabaseAccessor::DIFF_PARAM_COUNT];
......@@ -789,6 +807,28 @@ checkRecords(SQLite3Accessor& accessor, int zone_id, const std::string& name,
EXPECT_TRUE(it == expected_rows.end());
}
// Similar to the previous one, but checking transactions on the nsec3 table.
void
checkNSEC3Records(SQLite3Accessor& accessor, int zone_id,
const std::string& hash,
vector<const char* const*> expected_rows)
{
DatabaseAccessor::IteratorContextPtr iterator =
accessor.getNSEC3Records(hash, zone_id);
std::string columns[DatabaseAccessor::COLUMN_COUNT];
vector<const char* const*>::const_iterator it = expected_rows.begin();
while (iterator->getNext(columns)) {
ASSERT_TRUE(it != expected_rows.end());
checkRecordRow(columns, (*it)[DatabaseAccessor::ADD_NSEC3_TYPE],
(*it)[DatabaseAccessor::ADD_NSEC3_TTL],
"", // sigtype, should always be empty
(*it)[DatabaseAccessor::ADD_NSEC3_RDATA],
""); // name, always empty
++it;
}
EXPECT_TRUE(it == expected_rows.end());
}
TEST_F(SQLite3Update, emptyUpdate) {
// If we do nothing between start and commit, the zone content
// should be intact.
......@@ -924,6 +964,38 @@ TEST_F(SQLite3Update, addRecord) {
checkRecords(*accessor, zone_id, "newdata.example.com.", expected_stored);
}
TEST_F(SQLite3Update, addNSEC3Record) {
// Similar to the previous test, but for NSEC3-related records
checkRecords(*accessor, zone_id, apex_hash, empty_stored);
checkRecords(*accessor, zone_id, ns1_hash, empty_stored);
zone_id = accessor->startUpdateZone("example.com.", false).second;
// Add an NSEC3
copy(nsec3_data, nsec3_data + DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT,
add_nsec3_columns);
accessor->addNSEC3RecordToZone(add_nsec3_columns);
// Add an RRSIG for NSEC3
copy(nsec3_sig_data,
nsec3_sig_data + DatabaseAccessor::ADD_NSEC3_COLUMN_COUNT,
add_nsec3_columns);
accessor->addNSEC3RecordToZone(add_nsec3_columns);
// Check the stored data, before and after commit().
for (size_t i = 0; i < 2; ++i) {
expected_stored.clear();
expected_stored.push_back(nsec3_data);
checkNSEC3Records(*accessor, zone_id, apex_hash, expected_stored);
expected_stored.clear();
expected_stored.push_back(nsec3_sig_data);
checkNSEC3Records(*accessor, zone_id, ns1_hash, expected_stored);
if (i == 0) { // make sure commit() happens only once
accessor->commit();
}
}
}
TEST_F(SQLite3Update, addThenRollback) {
zone_id = accessor->startUpdateZone("example.com.", false).second;
copy(new_data, new_data + DatabaseAccessor::ADD_COLUMN_COUNT,
......
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