Commit 3be59fcc authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[3569_rebase] MySQL host data source is now indeed created and stored.

parent 4aba6227
......@@ -39,9 +39,9 @@ namespace isc {
namespace dhcp {
boost::scoped_ptr<BaseHostDataSource>&
HostDataSourcePtr&
HostDataSourceFactory::getHostDataSourcePtr() {
static boost::scoped_ptr<BaseHostDataSource> hostDataSourcePtr;
static HostDataSourcePtr hostDataSourcePtr;
return (hostDataSourcePtr);
}
......@@ -99,6 +99,7 @@ HostDataSourceFactory::destroy() {
getHostDataSourcePtr().reset();
}
#if 0
BaseHostDataSource&
HostDataSourceFactory::instance() {
BaseHostDataSource* hdsptr = getHostDataSourcePtr().get();
......@@ -108,6 +109,7 @@ HostDataSourceFactory::instance() {
}
return (*hdsptr);
}
#endif
}; // namespace dhcp
}; // namespace isc
......@@ -88,23 +88,12 @@ public:
/// host data source is available.
static void destroy();
/// @brief Return current host data source
///
/// @returns An instance of the "current" host data source. An exception
/// will be thrown if none is available.
///
/// @throw NoHostDataSourceManager No host data source is available: use
/// create() to create one before calling this method.
static BaseHostDataSource& instance();
private:
/// @brief Hold pointer to host data source instance
///
/// Holds a pointer to the singleton host data source. The singleton
/// is encapsulated in this method to avoid a "static initialization
/// fiasco" if defined in an external static variable.
static boost::scoped_ptr<BaseHostDataSource>& getHostDataSourcePtr();
static HostDataSourcePtr& getHostDataSourcePtr();
};
......
......@@ -51,9 +51,10 @@ HostMgr::create(const std::string& access) {
if (!access.empty()) {
HostDataSourceFactory::create(access);
/// @todo Initialize alternate_source here.
//alternate_source = HostDataSourceFactory::getHostDataSourcePtr();
}
// Now store the host data source pointer.
getHostMgrPtr()->alternate_source = HostDataSourceFactory::getHostDataSourcePtr();
}
HostMgr&
......
......@@ -19,6 +19,7 @@
#include <boost/scoped_ptr.hpp>
#include <mysql.h>
#include <vector>
#include <stdint.h>
namespace isc {
namespace dhcp {
......
......@@ -104,6 +104,7 @@ libdhcpsrv_unittests_SOURCES += generic_host_data_source_unittest.cc generic_hos
libdhcpsrv_unittests_SOURCES += memfile_lease_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += dhcp_parsers_unittest.cc
if HAVE_MYSQL
libdhcpsrv_unittests_SOURCES += mysql_schema.cc mysql_schema.h
libdhcpsrv_unittests_SOURCES += mysql_lease_mgr_unittest.cc
libdhcpsrv_unittests_SOURCES += mysql_host_data_source_unittest.cc
endif
......
......@@ -17,6 +17,7 @@
#include <cc/command_interpreter.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/parsers/dbaccess_parser.h>
#include <dhcpsrv/tests/mysql_schema.h>
#include <dhcpsrv/host_mgr.h>
#include <log/logger_support.h>
......@@ -28,6 +29,7 @@
using namespace std;
using namespace isc;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
using namespace isc::data;
using namespace isc::config;
......@@ -536,6 +538,8 @@ TEST_F(DbAccessParserTest, getDbAccessString) {
// that does not assume that the test has been built with MySQL support.
TEST_F(DbAccessParserTest, commitLeaseDb) {
EXPECT_NO_THROW(createMySQLSchema());
// Verify that no lease database is open
EXPECT_THROW({
LeaseMgr& manager = LeaseMgrFactory::instance();
......@@ -566,8 +570,11 @@ TEST_F(DbAccessParserTest, commitLeaseDb) {
EXPECT_EQ(std::string("memfile"), dbtype);
}
#ifdef HAVE_MYSQL
// Check that the "commit" function actually opens the database, when type
// is set to HOSTS_DB.
// is set to HOSTS_DB. We're using MySQL here. Since the only currently supported
// host data source is the one that uses MySQL, we have no other choice, but to
// depend this test on MYSQL availability.
TEST_F(DbAccessParserTest, commitHostsDb) {
// Verify that no lease database is open
......@@ -577,7 +584,8 @@ TEST_F(DbAccessParserTest, commitHostsDb) {
}, isc::dhcp::NoLeaseManager);
// Set up the parser to open the memfile database.
const char* config[] = {"type", "memfile", "persist", "false", NULL};
const char* config[] = {"type", "mysql", "user", "keatest",
"password", "keatest", "name", "keatest", NULL};
string json_config = toJson(config);
ConstElementPtr json_elements = Element::fromJSON(json_config);
......@@ -588,24 +596,29 @@ TEST_F(DbAccessParserTest, commitHostsDb) {
EXPECT_NO_THROW(parser.build(json_elements));
// Ensure that the access string is as expected.
EXPECT_EQ("persist=false type=memfile universe=4",
EXPECT_EQ("name=keatest password=keatest type=mysql universe=4 user=keatest",
parser.getDbAccessString());
// Destroy lease mgr (if there's any)
LeaseMgrFactory::destroy();
EXPECT_NO_THROW(createMySQLSchema());
// Committal of the parser changes should not create LeaseMgr.
// It should create HostDataSource instead.
EXPECT_NO_THROW(parser.commit());
// Check that LeaseMgr was NOT created (it shouldn't, this is for HOSTS_DB.
// Check that LeaseMgr was NOT created (it shouldn't, this is for HOSTS_DB).
EXPECT_THROW(LeaseMgrFactory::instance(), NoLeaseManager);
// Verify that HostDataSource has been created.
HostDataSourcePtr hds = HostMgr::instance().getHostDataSource();
ASSERT_TRUE(hds);
EXPECT_EQ("mysql", hds->getType());
/// @todo: Uncomment this once 3682 is merged. The whole unit-test
/// should create MySQL database and be ifdefed appropriately.
// ASSERT_TRUE(hds);
EXPECT_NO_THROW(destroyMySQLSchema());
}
#endif
}; // Anonymous namespace
......@@ -27,7 +27,7 @@ namespace dhcp {
namespace test {
GenericHostDataSourceTest::GenericHostDataSourceTest()
:hdsptr_(NULL) {
:hdsptr_() {
}
......
......@@ -125,7 +125,7 @@ public:
const ClientClasses& classes2);
/// @brief Pointer to the host data source
BaseHostDataSource* hdsptr_;
HostDataSourcePtr hdsptr_;
/// @brief Test that checks that simple host with IPv4 reservation
/// can be inserted and later retrieved.
......
......@@ -166,7 +166,7 @@ public:
throw;
}
hdsptr_ = &(HostDataSourceFactory::instance());
hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
}
/// @brief Destructor
......@@ -189,7 +189,7 @@ public:
void reopen(Universe) {
HostDataSourceFactory::destroy();
HostDataSourceFactory::create(validConnectionString());
hdsptr_ = &(HostDataSourceFactory::instance());
hdsptr_ = HostDataSourceFactory::getHostDataSourcePtr();
}
};
......@@ -211,7 +211,7 @@ TEST(MySqlHostDataSource, OpenDatabase) {
// If it fails, print the error message.
try {
HostDataSourceFactory::create(validConnectionString());
EXPECT_NO_THROW((void) HostDataSourceFactory::instance());
EXPECT_NO_THROW((void) HostDataSourceFactory::getHostDataSourcePtr());
HostDataSourceFactory::destroy();
} catch (const isc::Exception& ex) {
FAIL() << "*** ERROR: unable to open database, reason:\n"
......@@ -222,7 +222,7 @@ TEST(MySqlHostDataSource, OpenDatabase) {
// Check that attempting to get an instance of the lease manager when
// none is set throws an exception.
EXPECT_THROW(HostDataSourceFactory::instance(), NoHostDataSourceManager);
EXPECT_FALSE(HostDataSourceFactory::getHostDataSourcePtr());
// Check that wrong specification of backend throws an exception.
// (This is really a check on LeaseMgrFactory, but is convenient to
......
......@@ -20,6 +20,7 @@
#include <dhcpsrv/mysql_lease_mgr.h>
#include <dhcpsrv/tests/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <dhcpsrv/tests/mysql_schema.h>
#include <exceptions/exceptions.h>
#include <gtest/gtest.h>
......@@ -38,108 +39,6 @@ using namespace std;
namespace {
// This holds statements to create and destroy the schema.
#include "schema_mysql_copy.h"
// Connection strings.
// Database: keatest
// Host: localhost
// Username: keatest
// Password: keatest
const char* VALID_TYPE = "type=mysql";
const char* INVALID_TYPE = "type=unknown";
const char* VALID_NAME = "name=keatest";
const char* INVALID_NAME = "name=invalidname";
const char* VALID_HOST = "host=localhost";
const char* INVALID_HOST = "host=invalidhost";
const char* VALID_USER = "user=keatest";
const char* INVALID_USER = "user=invaliduser";
const char* VALID_PASSWORD = "password=keatest";
const char* INVALID_PASSWORD = "password=invalid";
// Given a combination of strings above, produce a connection string.
string connectionString(const char* type, const char* name, const char* host,
const char* user, const char* password) {
const string space = " ";
string result = "";
if (type != NULL) {
result += string(type);
}
if (name != NULL) {
if (! result.empty()) {
result += space;
}
result += string(name);
}
if (host != NULL) {
if (! result.empty()) {
result += space;
}
result += string(host);
}
if (user != NULL) {
if (! result.empty()) {
result += space;
}
result += string(user);
}
if (password != NULL) {
if (! result.empty()) {
result += space;
}
result += string(password);
}
return (result);
}
// Return valid connection string
string
validConnectionString() {
return (connectionString(VALID_TYPE, VALID_NAME, VALID_HOST,
VALID_USER, VALID_PASSWORD));
}
// @brief Clear everything from the database
//
// There is no error checking in this code: if something fails, one of the
// tests will (should) fall over.
void destroySchema() {
MySqlHolder mysql;
// Open database
(void) mysql_real_connect(mysql, "localhost", "keatest",
"keatest", "keatest", 0, NULL, 0);
// Get rid of everything in it.
for (int i = 0; destroy_statement[i] != NULL; ++i) {
(void) mysql_query(mysql, destroy_statement[i]);
}
}
// @brief Create the Schema
//
// Creates all the tables in what is assumed to be an empty database.
//
// There is no error checking in this code: if it fails, one of the tests
// will fall over.
void createSchema() {
MySqlHolder mysql;
// Open database
(void) mysql_real_connect(mysql, "localhost", "keatest",
"keatest", "keatest", 0, NULL, 0);
// Execute creation statements.
for (int i = 0; create_statement[i] != NULL; ++i) {
ASSERT_EQ(0, mysql_query(mysql, create_statement[i]))
<< "Failed on statement " << i << ": " << create_statement[i];
}
}
/// @brief Test fixture class for testing MySQL Lease Manager
///
......@@ -154,12 +53,12 @@ public:
MySqlLeaseMgrTest() {
// Ensure schema is the correct one.
destroySchema();
createSchema();
destroyMySQLSchema();
createMySQLSchema();
// Connect to the database
try {
LeaseMgrFactory::create(validConnectionString());
LeaseMgrFactory::create(validMySQLConnectionString());
} catch (...) {
std::cerr << "*** ERROR: unable to open database. The test\n"
"*** environment is broken and must be fixed before\n"
......@@ -178,7 +77,7 @@ public:
virtual ~MySqlLeaseMgrTest() {
lmptr_->rollback();
LeaseMgrFactory::destroy();
destroySchema();
destroyMySQLSchema();
}
/// @brief Reopen the database
......@@ -190,7 +89,7 @@ public:
/// the same database.
void reopen(Universe) {
LeaseMgrFactory::destroy();
LeaseMgrFactory::create(validConnectionString());
LeaseMgrFactory::create(validMySQLConnectionString());
lmptr_ = &(LeaseMgrFactory::instance());
}
......@@ -206,13 +105,13 @@ public:
TEST(MySqlOpenTest, OpenDatabase) {
// Schema needs to be created for the test to work.
destroySchema();
createSchema();
destroyMySQLSchema();
createMySQLSchema();
// Check that lease manager open the database opens correctly and tidy up.
// If it fails, print the error message.
try {
LeaseMgrFactory::create(validConnectionString());
LeaseMgrFactory::create(validMySQLConnectionString());
EXPECT_NO_THROW((void) LeaseMgrFactory::instance());
LeaseMgrFactory::destroy();
} catch (const isc::Exception& ex) {
......@@ -256,7 +155,7 @@ TEST(MySqlOpenTest, OpenDatabase) {
NoDatabaseName);
// Tidy up after the test
destroySchema();
destroyMySQLSchema();
}
/// @brief Check the getType() method
......
// Copyright (C) 2015 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.
#include <config.h>
#include <string>
#include <mysql.h>
#include <dhcpsrv/mysql_connection.h>
#include <gtest/gtest.h>
// This holds statements to create and destroy the schema.
#include "schema_mysql_copy.h"
using namespace std;
namespace isc {
namespace dhcp {
namespace test {
// Connection strings.
// Database: keatest
// Host: localhost
// Username: keatest
// Password: keatest
const char* VALID_TYPE = "type=mysql";
const char* INVALID_TYPE = "type=unknown";
const char* VALID_NAME = "name=keatest";
const char* INVALID_NAME = "name=invalidname";
const char* VALID_HOST = "host=localhost";
const char* INVALID_HOST = "host=invalidhost";
const char* VALID_USER = "user=keatest";
const char* INVALID_USER = "user=invaliduser";
const char* VALID_PASSWORD = "password=keatest";
const char* INVALID_PASSWORD = "password=invalid";
string connectionString(const char* type, const char* name, const char* host,
const char* user, const char* password) {
const string space = " ";
string result = "";
if (type != NULL) {
result += string(type);
}
if (name != NULL) {
if (! result.empty()) {
result += space;
}
result += string(name);
}
if (host != NULL) {
if (! result.empty()) {
result += space;
}
result += string(host);
}
if (user != NULL) {
if (! result.empty()) {
result += space;
}
result += string(user);
}
if (password != NULL) {
if (! result.empty()) {
result += space;
}
result += string(password);
}
return (result);
}
// Return valid connection string
string
validMySQLConnectionString() {
return (connectionString(VALID_TYPE, VALID_NAME, VALID_HOST,
VALID_USER, VALID_PASSWORD));
}
// @brief Clear everything from the database
//
// There is no error checking in this code: if something fails, one of the
// tests will (should) fall over.
void destroyMySQLSchema() {
MySqlHolder mysql;
// Open database
(void) mysql_real_connect(mysql, "localhost", "keatest",
"keatest", "keatest", 0, NULL, 0);
// Get rid of everything in it.
for (int i = 0; destroy_statement[i] != NULL; ++i) {
(void) mysql_query(mysql, destroy_statement[i]);
}
}
// @brief Create the Schema
//
// Creates all the tables in what is assumed to be an empty database.
//
// There is no error checking in this code: if it fails, one of the tests
// will fall over.
void createMySQLSchema() {
MySqlHolder mysql;
// Open database
(void) mysql_real_connect(mysql, "localhost", "keatest",
"keatest", "keatest", 0, NULL, 0);
// Execute creation statements.
for (int i = 0; create_statement[i] != NULL; ++i) {
ASSERT_EQ(0, mysql_query(mysql, create_statement[i]))
<< "Failed on statement " << i << ": " << create_statement[i];
}
}
};
};
};
// Copyright (C) 2015 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.
#ifndef TEST_MYSQL_SCHEMA_H
#define TEST_MYSQL_SCHEMA_H
#include <config.h>
#include <string>
namespace isc {
namespace dhcp {
namespace test {
extern const char* VALID_TYPE;
extern const char* INVALID_TYPE;
extern const char* VALID_NAME;
extern const char* INVALID_NAME;
extern const char* VALID_HOST;
extern const char* INVALID_HOST;
extern const char* VALID_USER;
extern const char* INVALID_USER;
extern const char* VALID_PASSWORD;
extern const char* INVALID_PASSWORD;
/// @brief Create the Schema
///
/// Creates all the tables in what is assumed to be an empty database.
///
/// There is no error checking in this code: if it fails, one of the tests
/// will fall over.
void createMySQLSchema();
/// @brief Clear everything from the database
///
/// There is no error checking in this code: if something fails, one of the
/// tests will (should) fall over.
void destroyMySQLSchema();
/// Return valid connection string
///
/// @return valid MySQL connection string.
std::string validMySQLConnectionString();
/// @brief Given a combination of strings above, produce a connection string.
///
/// @param type type of the database
/// @param name name of the database to connect to
/// @param host hostname
/// @param user username used to authendicate during connection attempt
/// @param password password used to authendicate during connection attempt
/// @return string containing all specified parameters
std::string connectionString(const char* type, const char* name, const char* host,
const char* user, const char* password);
};
};
};
#endif
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