Commit 8a5601ac authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[4489] Created a test for read only backend initialization.

parent 71a38f02
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -40,6 +40,13 @@ public:
isc::Exception(file, line, what) {}
};
/// @brief Attempt to modify data in read-only database.
class ReadOnlyDb : public Exception {
public:
ReadOnlyDb(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
};
};
......
......@@ -12,8 +12,10 @@
#include <dhcp/option_string.h>
#include <dhcp/option_int.h>
#include <dhcp/option_vendor.h>
#include <dhcpsrv/host_data_source_factory.h>
#include <dhcpsrv/tests/generic_host_data_source_unittest.h>
#include <dhcpsrv/tests/test_utils.h>
#include <dhcpsrv/testutils/schema.h>
#include <dhcpsrv/database_connection.h>
#include <asiolink/io_address.h>
#include <util/buffer.h>
......@@ -505,6 +507,47 @@ GenericHostDataSourceTest::addTestOptions(const HostPtr& host,
LibDHCP::setRuntimeOptionDefs(defs);
}
void
GenericHostDataSourceTest::testReadOnlyDatabase(const char* valid_db_type) {
ASSERT_TRUE(hdsptr_);
// The database is initially opened in "read-write" mode. We can
// insert some data to the databse.
HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
ASSERT_NO_THROW(hdsptr_->add(host));
// Subnet id will be used in queries to the database.
SubnetID subnet_id = host->getIPv6SubnetID();
// Make sure that the host has been inserted and that the data can be
// retrieved.
ConstHostPtr host_by_id = hdsptr_->get6(subnet_id, host->getIdentifierType(),
&host->getIdentifier()[0],
host->getIdentifier().size());
ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_id));
// Close the database connection and reopen in "read-only" mode as
// specified by the "VALID_READONLY_DB" parameter.
HostDataSourceFactory::destroy();
HostDataSourceFactory::create(connectionString(valid_db_type,
VALID_NAME,
VALID_HOST,
VALID_USER,
VALID_PASSWORD,
VALID_READONLY_DB));
// Check that an attempt to insert new host would result in
// exception.
host = initializeHost6("2001:db8::2", Host::IDENT_DUID, false);
ASSERT_THROW(hdsptr_->add(host), ReadOnlyDb);
// Reading from the database should still be possible, though.
host_by_id = hdsptr_->get6(subnet_id, host->getIdentifierType(),
&host->getIdentifier()[0],
host->getIdentifier().size());
ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_id));
}
void GenericHostDataSourceTest::testBasic4(const Host::IdentifierType& id) {
// Make sure we have the pointer to the host data source.
ASSERT_TRUE(hdsptr_);
......
......@@ -337,6 +337,23 @@ public:
/// @brief Pointer to the host data source
HostDataSourcePtr hdsptr_;
/// @brief Test that backend can be started in read-only mode.
///
/// Some backends can operate when the database is read only, e.g.
/// host reservation tables are read only, or the database user has
/// read only privileges on the entire database. In such cases, the
/// Kea server administrator can specify in the backend configuration
/// that the database should be opened in read only mode, i.e.
/// INSERT, UPDATE, DELETE statements can't be issued. If any of the
/// functions updating the database is called for the backend, the
/// error is reported. The database running in read only mode can
/// be merely used to retrieve existing host reservations from the
/// database. This test verifies that this is the case.
///
/// @param valid_db_type Parameter specifying type of backend to
/// be used, e.g. type=mysql.
void testReadOnlyDatabase(const char* valid_db_type);
/// @brief Test that checks that simple host with IPv4 reservation
/// can be inserted and later retrieved.
///
......
......@@ -167,6 +167,8 @@ TEST(MySqlHostDataSource, OpenDatabase) {
destroyMySQLSchema();
}
/// @brief Check conversion functions
///
/// The server works using cltt and valid_filetime. In the database, the
......@@ -208,6 +210,10 @@ TEST(MySqlConnection, checkTimeConversion) {
EXPECT_EQ(cltt, converted_cltt);
}
TEST_F(MySqlHostDataSourceTest, testReadOnlyDatabase) {
testReadOnlyDatabase(MYSQL_VALID_TYPE);
}
// Test verifies if a host reservation can be added and later retrieved by IPv4
// address. Host uses hw address as identifier.
TEST_F(MySqlHostDataSourceTest, basic4HWAddr) {
......
......@@ -31,9 +31,11 @@ const char* INVALID_PASSWORD = "password=invalid";
const char* VALID_TIMEOUT = "connect-timeout=10";
const char* INVALID_TIMEOUT_1 = "connect-timeout=foo";
const char* INVALID_TIMEOUT_2 = "connect-timeout=-17";
const char* VALID_READONLY_DB = "readonly=true";
string connectionString(const char* type, const char* name, const char* host,
const char* user, const char* password, const char* timeout) {
const char* user, const char* password, const char* timeout,
const char* readonly_db = NULL) {
const string space = " ";
string result = "";
......@@ -75,6 +77,13 @@ string connectionString(const char* type, const char* name, const char* host,
result += string(timeout);
}
if (readonly_db != NULL) {
if (! result.empty()) {
result += space;
}
result += string(readonly_db);
}
return (result);
}
......
......@@ -27,6 +27,8 @@ extern const char* INVALID_PASSWORD;
extern const char* VALID_TIMEOUT;
extern const char* INVALID_TIMEOUT_1;
extern const char* INVALID_TIMEOUT_2;
extern const char* VALID_READONLY_DB;
/// @brief Given a combination of strings above, produce a connection string.
///
/// @param type type of the database
......@@ -35,10 +37,12 @@ extern const char* INVALID_TIMEOUT_2;
/// @param user username used to authenticate during connection attempt
/// @param password password used to authenticate during connection attempt
/// @param timeout timeout used during connection attempt
/// @param readonly_db specifies if database is read only
/// @return string containing all specified parameters
std::string connectionString(const char* type, const char* name = NULL,
const char* host = NULL, const char* user = NULL,
const char* password = NULL, const char* timeout = NULL);
const char* password = NULL, const char* timeout = NULL,
const char* readonly_db = NULL);
};
};
};
......
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