From: Marcin Siodelski Date: Tue, 12 Jul 2016 07:43:30 +0000 (+0200) Subject: [4489] Created a test for read only backend initialization. X-Git-Tag: trac4631_base~9^2~18 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8a5601acbf74e375b2deffee44652448941868c2;p=thirdparty%2Fkea.git [4489] Created a test for read only backend initialization. --- diff --git a/src/lib/dhcpsrv/db_exceptions.h b/src/lib/dhcpsrv/db_exceptions.h index 664c43e144..d9cc4449dd 100644 --- a/src/lib/dhcpsrv/db_exceptions.h +++ b/src/lib/dhcpsrv/db_exceptions.h @@ -1,4 +1,4 @@ -// 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) {} +}; + }; }; diff --git a/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc index a616f4f081..c12ea64b08 100644 --- a/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.cc @@ -12,8 +12,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -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_); diff --git a/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h b/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h index cf5421b19e..bb1e28cb4a 100644 --- a/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h +++ b/src/lib/dhcpsrv/tests/generic_host_data_source_unittest.h @@ -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. /// diff --git a/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc b/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc index 450d816268..849e31b40b 100644 --- a/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc +++ b/src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc @@ -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) { diff --git a/src/lib/dhcpsrv/testutils/schema.cc b/src/lib/dhcpsrv/testutils/schema.cc index cefcbdae5c..3420cc7c7e 100644 --- a/src/lib/dhcpsrv/testutils/schema.cc +++ b/src/lib/dhcpsrv/testutils/schema.cc @@ -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); } diff --git a/src/lib/dhcpsrv/testutils/schema.h b/src/lib/dhcpsrv/testutils/schema.h index 5a0471512f..fe842ff9e7 100644 --- a/src/lib/dhcpsrv/testutils/schema.h +++ b/src/lib/dhcpsrv/testutils/schema.h @@ -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); }; }; };