From 53075e2b911dc62619b3843985b6aab0ac32c436 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sat, 2 May 2015 18:11:51 +0100 Subject: Centralize the mocking code --- project2/sql/mockDatabase.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++ project2/sql/mockDatabase.h | 37 ++++++++++++++++++++ project2/sql/sql-modMySQL.cpp | 56 +++---------------------------- project2/sql/sql-modMySQL.h | 13 ++------ project2/sql/sql-modPQ.cpp | 40 ++++------------------ project2/sql/sql-modPQ.h | 12 +++---- project2/sql/sql-modSQLite.cpp | 30 ++++------------- project2/sql/sql-modSQLite.h | 12 +++---- 8 files changed, 144 insertions(+), 132 deletions(-) create mode 100644 project2/sql/mockDatabase.cpp create mode 100644 project2/sql/mockDatabase.h diff --git a/project2/sql/mockDatabase.cpp b/project2/sql/mockDatabase.cpp new file mode 100644 index 0000000..259dfd6 --- /dev/null +++ b/project2/sql/mockDatabase.cpp @@ -0,0 +1,76 @@ +#include "mockDatabase.h" +#include "mockDatasource.h" +#include +#include +#include +#include + +MockDatabase::MockDatabase(const std::string & name) : + mockName(name) +{ +} + +MockDatabase::~MockDatabase() +{ +} + +void +MockDatabase::PlaySchemaScripts(const std::vector & ss) const +{ + DB::Connection * conn = openConnection(); + try { + for (auto s : ss) { + conn->beginTx(); + Logger()->messagebf(LOG_DEBUG, "%s << %s", mockName, s); + std::ifstream f; + f.open(s.string()); + while (!f.eof()) { + char buf[BUFSIZ]; + f.getline(buf, BUFSIZ, ';'); + if (!f.eof()) + conn->execute(buf); + } + f.close(); + conn->commitTx(); + } + delete conn; + Logger()->messagebf(LOG_DEBUG, "%s initialized", mockName); + MockConnectionLoader::mocks[mockName] = boost::bind(&MockDatabase::openConnection, this); + } + catch (...) { + if (conn->inTx()) { + conn->rollbackTx(); + } + delete conn; + DropDatabase(); + throw; + } + +} + +MockServerDatabase::MockServerDatabase(const std::string & masterdb, const std::string & name, const std::string & type) : + MockDatabase(name), + master(InstanceMap::Get(type)->create(masterdb)), + testDbName(stringbf("test_%d_%d", getpid(), ++MockConnectionLoader::mocked)) +{ +} + +MockServerDatabase::~MockServerDatabase() +{ +} + +void +MockServerDatabase::CreateNewDatabase() const +{ + DropDatabase(); + Logger()->messagebf(LOG_INFO, "Creating new database %s", testDbName); + master->execute("CREATE DATABASE " + testDbName); +} + +void +MockServerDatabase::DropDatabase() const +{ + Logger()->messagebf(LOG_INFO, "Creating new database %s", testDbName); + master->execute("DROP DATABASE IF EXISTS " + testDbName); +} + diff --git a/project2/sql/mockDatabase.h b/project2/sql/mockDatabase.h new file mode 100644 index 0000000..49e49a8 --- /dev/null +++ b/project2/sql/mockDatabase.h @@ -0,0 +1,37 @@ +#ifndef MOCKDATABASE_H +#define MOCKDATABASE_H + +#include +#include +#include +#include + +class MockDatabase { + public: + MockDatabase(const std::string & mockName); + virtual ~MockDatabase(); + + protected: + virtual void CreateNewDatabase() const = 0; + virtual void PlaySchemaScripts(const std::vector & ss) const; + virtual void DropDatabase() const = 0; + virtual DB::Connection * openConnection() const = 0; + + const std::string mockName; +}; + +class MockServerDatabase : public MockDatabase { + public: + MockServerDatabase(const std::string & masterdb, const std::string & name, const std::string & type); + virtual ~MockServerDatabase(); + + protected: + virtual void CreateNewDatabase() const override; + virtual void DropDatabase() const override; + + DB::Connection * master; + const std::string testDbName; +}; + +#endif + diff --git a/project2/sql/sql-modMySQL.cpp b/project2/sql/sql-modMySQL.cpp index 24172ce..0466cbc 100644 --- a/project2/sql/sql-modMySQL.cpp +++ b/project2/sql/sql-modMySQL.cpp @@ -10,67 +10,21 @@ typedef MySQL::Connection MySQLConnection; DECLARE_GENERIC_LOADER("mysql", ConnectionLoader, MySQLConnection) MockMySQLDatabase::MockMySQLDatabase(const std::string & name, const std::vector & ss) : - master(InstanceMap::Get("mysql")->create("options=p2testmysql")), - testDbName(stringbf("test_%d_%d", getpid(), ++MockConnectionLoader::mocked)), - mockName(name) + MockServerDatabase("options=p2testmysql", name, "mysql") { - Logger()->messagebf(LOG_DEBUG, "Setting up new mocked database %s", testDbName); - DropDatabase(); CreateNewDatabase(); - DB::Connection * conn = openConnection(stringbf("options=p2testmysql;database=%s", testDbName)); - try { - for (auto s : ss) { - conn->beginTx(); - Logger()->messagebf(LOG_DEBUG, "%s << %s", testDbName, s); - std::ifstream f; - f.open(s.string()); - while (!f.eof()) { - char buf[BUFSIZ]; - f.getline(buf, BUFSIZ, ';'); - if (!f.eof()) - conn->execute(buf); - } - f.close(); - conn->commitTx(); - } - Logger()->messagebf(LOG_DEBUG, "%s initialized", testDbName); - MockConnectionLoader::mocks[name] = boost::bind(MockMySQLDatabase::openConnection, stringbf("options=p2testmysql;database=%s", testDbName)); - } - catch (...) { - if (conn->inTx()) { - conn->rollbackTx(); - } - delete conn; - DropDatabase(); - throw; - } + PlaySchemaScripts(ss); } DB::Connection * -MockMySQLDatabase::openConnection(const std::string & connStr) +MockMySQLDatabase::openConnection() const { - return InstanceMap::Get("mysql")->create(connStr); + return InstanceMap::Get("mysql")->create( + stringbf("options=p2testmysql;database=%s", testDbName)); } MockMySQLDatabase::~MockMySQLDatabase() { - Logger()->messagebf(LOG_DEBUG, "Tearing down mocked database %s", testDbName); DropDatabase(); - delete master; - MockConnectionLoader::mocks.erase(mockName); - Logger()->messagebf(LOG_DEBUG, "%s torn down", testDbName); -} - -void MockMySQLDatabase::DropDatabase() const -{ - Logger()->messagebf(LOG_INFO, "Dropping (if exists) old database %s", testDbName); - master->execute("DROP DATABASE IF EXISTS " + testDbName); } -void MockMySQLDatabase::CreateNewDatabase() const -{ - Logger()->messagebf(LOG_INFO, "Creating new database %s", testDbName); - master->execute("CREATE DATABASE " + testDbName); -} - - diff --git a/project2/sql/sql-modMySQL.h b/project2/sql/sql-modMySQL.h index 628bfdb..b303e71 100644 --- a/project2/sql/sql-modMySQL.h +++ b/project2/sql/sql-modMySQL.h @@ -1,23 +1,16 @@ #ifndef MOCKMYSQLDATASOURCE_H #define MOCKMYSQLDATASOURCE_H -#include "mockDatasource.h" +#include "mockDatabase.h" #include -class MockMySQLDatabase { +class MockMySQLDatabase : public MockServerDatabase { public: MockMySQLDatabase(const std::string & name, const std::vector & ss); ~MockMySQLDatabase(); - protected: - void DropDatabase() const; - void CreateNewDatabase() const; - private: - static DB::Connection * openConnection(const std::string & connStr); - const DB::Connection * master; - const std::string testDbName; - const std::string mockName; + DB::Connection * openConnection() const override; }; #endif diff --git a/project2/sql/sql-modPQ.cpp b/project2/sql/sql-modPQ.cpp index 5267f28..ec2fcf3 100644 --- a/project2/sql/sql-modPQ.cpp +++ b/project2/sql/sql-modPQ.cpp @@ -9,56 +9,28 @@ typedef PQ::Connection PQConnection; DECLARE_GENERIC_LOADER("postgresql", ConnectionLoader, PQConnection) MockPqDatabase::MockPqDatabase(const std::string & masterdb, const std::string & name, const std::vector & ss) : - master(InstanceMap::Get("postgresql")->create(masterdb)), - testDbName(stringbf("test_%d_%d", getpid(), ++MockConnectionLoader::mocked)), - mockName(name) + MockServerDatabase(masterdb, name, "postgresql") { - Logger()->messagebf(LOG_DEBUG, "Setting up new mocked database %s", testDbName); - DropDatabase(); CreateNewDatabase(); - try { - for (auto s : ss) { - Logger()->messagebf(LOG_DEBUG, "%s << %s", testDbName, s); - if (system(("psql -v ON_ERROR_STOP=1 -q -1 -U postgres " + testDbName + " -f " + s.string()).c_str())) { - throw std::runtime_error("Failed to execute " + s.string()); - } - } - Logger()->messagebf(LOG_DEBUG, "%s initialized", testDbName); - MockConnectionLoader::mocks[name] = boost::bind(MockPqDatabase::openConnection, stringbf("user=postgres dbname=%s", testDbName)); - } - catch (...) { - DropDatabase(); - throw; - } + PlaySchemaScripts(ss); } DB::Connection * -MockPqDatabase::openConnection(const std::string & connStr) +MockPqDatabase::openConnection() const { - return InstanceMap::Get("postgresql")->create(connStr); + return InstanceMap::Get("postgresql")->create( + stringbf("user=postgres dbname=%s", testDbName)); } MockPqDatabase::~MockPqDatabase() { - Logger()->messagebf(LOG_DEBUG, "Tearing down mocked database %s", testDbName); DropDatabase(); - delete master; - MockConnectionLoader::mocks.erase(mockName); - Logger()->messagebf(LOG_DEBUG, "%s torn down", testDbName); } void MockPqDatabase::DropDatabase() const { Logger()->messagebf(LOG_INFO, "Killing any active connections to database %s", testDbName); master->execute("SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '" + testDbName + "'"); - Logger()->messagebf(LOG_INFO, "Dropping (if exists) old database %s", testDbName); - master->execute("DROP DATABASE IF EXISTS " + testDbName); + MockServerDatabase::DropDatabase(); } -void MockPqDatabase::CreateNewDatabase() const -{ - Logger()->messagebf(LOG_INFO, "Creating new database %s", testDbName); - master->execute("CREATE DATABASE " + testDbName); -} - - diff --git a/project2/sql/sql-modPQ.h b/project2/sql/sql-modPQ.h index f71b5ab..43ef1ee 100644 --- a/project2/sql/sql-modPQ.h +++ b/project2/sql/sql-modPQ.h @@ -1,23 +1,19 @@ #ifndef MOCKPQDATASOURCE_H #define MOCKPQDATASOURCE_H -#include "mockDatasource.h" +#include "mockDatabase.h" #include -class MockPqDatabase { +class MockPqDatabase : public MockServerDatabase { public: MockPqDatabase(const std::string & master, const std::string & name, const std::vector & ss); ~MockPqDatabase(); protected: - void DropDatabase() const; - void CreateNewDatabase() const; + void DropDatabase() const override; private: - static DB::Connection * openConnection(const std::string & connStr); - const DB::Connection * master; - const std::string testDbName; - const std::string mockName; + DB::Connection * openConnection() const override; }; #endif diff --git a/project2/sql/sql-modSQLite.cpp b/project2/sql/sql-modSQLite.cpp index 6b4cb85..ef8e133 100644 --- a/project2/sql/sql-modSQLite.cpp +++ b/project2/sql/sql-modSQLite.cpp @@ -5,45 +5,28 @@ #include #include #include +#include "mockDatasource.h" typedef SQLite::Connection SQLiteConnection; DECLARE_GENERIC_LOADER("sqlite", ConnectionLoader, SQLiteConnection) MockSQLiteDatabase::MockSQLiteDatabase(const std::string & name, const std::vector & ss) : - testDbPath(boost::filesystem::path("/tmp") / "sqliteut" / stringbf("%d", getpid()) / stringbf("%d", ++MockConnectionLoader::mocked)), - mockName(name) + MockDatabase(name), + testDbPath(boost::filesystem::path("/tmp") / "sqliteut" / stringbf("%d", getpid()) / stringbf("%d", ++MockConnectionLoader::mocked)) { - Logger()->messagebf(LOG_DEBUG, "Setting up new mocked database at %s", testDbPath); - DropDatabase(); CreateNewDatabase(); - try { - for (auto s : ss) { - Logger()->messagebf(LOG_DEBUG, "%s << %s", testDbPath, s); - if (system(("sqlite3 -bail " + testDbPath.string() + " < " + s.string()).c_str())) { - throw std::runtime_error("Failed to execute " + s.string()); - } - } - Logger()->messagebf(LOG_DEBUG, "%s initialized", testDbPath); - MockConnectionLoader::mocks[name] = boost::bind(MockSQLiteDatabase::openConnection, testDbPath.string()); - } - catch (...) { - DropDatabase(); - throw; - } + PlaySchemaScripts(ss); } DB::Connection * -MockSQLiteDatabase::openConnection(const std::string & connStr) +MockSQLiteDatabase::openConnection() const { - return InstanceMap::Get("sqlite")->create(connStr); + return InstanceMap::Get("sqlite")->create(testDbPath.string()); } MockSQLiteDatabase::~MockSQLiteDatabase() { - Logger()->messagebf(LOG_DEBUG, "Tearing down mocked database %s", testDbPath); DropDatabase(); - MockConnectionLoader::mocks.erase(mockName); - Logger()->messagebf(LOG_DEBUG, "%s torn down", testDbPath); } void MockSQLiteDatabase::DropDatabase() const @@ -56,6 +39,7 @@ void MockSQLiteDatabase::CreateNewDatabase() const { Logger()->messagebf(LOG_INFO, "Creating new database at %s", testDbPath); boost::filesystem::create_directories(testDbPath.parent_path()); + delete openConnection(); } diff --git a/project2/sql/sql-modSQLite.h b/project2/sql/sql-modSQLite.h index 267ba0b..36bca22 100644 --- a/project2/sql/sql-modSQLite.h +++ b/project2/sql/sql-modSQLite.h @@ -1,22 +1,22 @@ #ifndef MOCKSQLITEDATASOURCE_H #define MOCKSQLITEDATASOURCE_H -#include "mockDatasource.h" +#include "mockDatabase.h" #include -class MockSQLiteDatabase { +class MockSQLiteDatabase : public MockDatabase { public: MockSQLiteDatabase(const std::string & name, const std::vector & ss); ~MockSQLiteDatabase(); protected: - void DropDatabase() const; - void CreateNewDatabase() const; + void DropDatabase() const override; + void CreateNewDatabase() const override; + + DB::Connection * openConnection() const override; private: - static DB::Connection * openConnection(const std::string & connStr); const boost::filesystem::path testDbPath; - const std::string mockName; }; #endif -- cgit v1.2.3