diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2015-12-31 04:04:31 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-05-04 20:44:40 +0100 |
commit | db1e2f066393af3e58814417de5bbe7ea08a145d (patch) | |
tree | 9d01e48d8ef7d63fbcca6aced2461b3f1e234dfd | |
parent | Beginnings of embbeded MySQL (diff) | |
download | libdbpp-mysql-db1e2f066393af3e58814417de5bbe7ea08a145d.tar.bz2 libdbpp-mysql-db1e2f066393af3e58814417de5bbe7ea08a145d.tar.xz libdbpp-mysql-db1e2f066393af3e58814417de5bbe7ea08a145d.zip |
Basics working, could do with a tidy up around mocking
-rw-r--r-- | libmysqlpp/embeddedmy-connection.cpp | 64 | ||||
-rw-r--r-- | libmysqlpp/embeddedmy-connection.h | 7 | ||||
-rw-r--r-- | libmysqlpp/embeddedmy-mock.cpp | 30 | ||||
-rw-r--r-- | libmysqlpp/embeddedmy-mock.h | 30 | ||||
-rw-r--r-- | libmysqlpp/embeddedmy-server.cpp | 83 | ||||
-rw-r--r-- | libmysqlpp/embeddedmy-server.h | 45 | ||||
-rw-r--r-- | libmysqlpp/my-connection.cpp | 41 | ||||
-rw-r--r-- | libmysqlpp/my-connection.h | 3 | ||||
-rw-r--r-- | libmysqlpp/my-opts.cpp | 34 | ||||
-rw-r--r-- | libmysqlpp/my-opts.h | 22 | ||||
-rw-r--r-- | libmysqlpp/unittests/Jamfile.jam | 2 | ||||
-rw-r--r-- | libmysqlpp/unittests/test.impl.h (renamed from libmysqlpp/unittests/testMain.cpp) | 77 | ||||
-rw-r--r-- | libmysqlpp/unittests/testmysql.cpp | 45 | ||||
-rw-r--r-- | libmysqlpp/unittests/testmysqle.cpp | 18 |
14 files changed, 371 insertions, 130 deletions
diff --git a/libmysqlpp/embeddedmy-connection.cpp b/libmysqlpp/embeddedmy-connection.cpp index f0bb24d..2a21450 100644 --- a/libmysqlpp/embeddedmy-connection.cpp +++ b/libmysqlpp/embeddedmy-connection.cpp @@ -1,16 +1,74 @@ #include "embeddedmy-connection.h" +#include "my-opts.h" +#include <nvpParse.h> NAMEDFACTORY("embeddedmysql", MySQL::Embedded::Connection, DB::ConnectionFactory); namespace MySQL { namespace Embedded { - Connection::Connection(const std::string &) + class Opts { + public: + boost::filesystem::path path; + MySQL::OptString database; + MySQL::OptString options; + std::vector<std::string> serverOptions; + }; + + using namespace AdHoc; + NvpTarget(Opts) OptsTargetMap { + NvpValue(Opts, path), + NvpValue(Opts, database), + NvpValue(Opts, options), + NvpValue(Opts, serverOptions), + }; + + Connection::Connection(const std::string & str) { + std::stringstream i(str); + Opts o; + NvpParse::parse(i, OptsTargetMap, o); mysql_init(&conn); + if (o.options) { + mysql_options(&conn, MYSQL_READ_DEFAULT_GROUP, ~o.options); + } mysql_options(&conn, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL); - if (mysql_real_connect(&conn, NULL, NULL, NULL, "database1", 0, NULL, 0)) { - throw MySQL::Error(&conn); + server = Server::get(o.path, o.serverOptions); + if (mysql_real_connect(&conn, NULL, NULL, NULL, ~o.database, + 0, NULL, CLIENT_LOCAL_FILES | CLIENT_MULTI_STATEMENTS) == NULL) { + throw MySQL::ConnectionError(&conn); + } + if (mysql_set_character_set(&conn, "utf8")) { + throw MySQL::ConnectionError(&conn); + } + } + + Connection::Connection(Server *, const std::string & db) + { + mysql_init(&conn); + mysql_options(&conn, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL); + if (mysql_real_connect(&conn, NULL, NULL, NULL, db.c_str(), + 0, NULL, CLIENT_LOCAL_FILES | CLIENT_MULTI_STATEMENTS) == NULL) { + throw MySQL::ConnectionError(&conn); + } + if (mysql_set_character_set(&conn, "utf8")) { + throw MySQL::ConnectionError(&conn); } } + + void Connection::beginBulkUpload(const char * t, const char * e) + { + DB::Connection::beginBulkUpload(t, e); + } + + void Connection::endBulkUpload(const char * msg) + { + DB::Connection::endBulkUpload(msg); + } + + size_t Connection::bulkUploadData(const char * b, size_t s) const + { + return DB::Connection::bulkUploadData(b, s); + } + } } diff --git a/libmysqlpp/embeddedmy-connection.h b/libmysqlpp/embeddedmy-connection.h index 3ceba2f..c94d86a 100644 --- a/libmysqlpp/embeddedmy-connection.h +++ b/libmysqlpp/embeddedmy-connection.h @@ -2,6 +2,7 @@ #define EMBEDDEDMY_CONNECTION_H #include "my-connection.h" +#include "embeddedmy-server.h" #include "my-error.h" #include <mysql.h> @@ -10,8 +11,14 @@ namespace MySQL { class Connection : public ::MySQL::Connection { public: Connection(const std::string &); + Connection(Server *, const std::string &); + + void beginBulkUpload(const char *, const char *) override; + void endBulkUpload(const char *) override; + size_t bulkUploadData(const char *, size_t) const override; private: + ServerPtr server; }; } } diff --git a/libmysqlpp/embeddedmy-mock.cpp b/libmysqlpp/embeddedmy-mock.cpp index 0ad0cc5..9e66bb3 100644 --- a/libmysqlpp/embeddedmy-mock.cpp +++ b/libmysqlpp/embeddedmy-mock.cpp @@ -1,5 +1,6 @@ #include "embeddedmy-connection.h" #include "embeddedmy-mock.h" +#include "embeddedmy-server.h" #include <boost/filesystem/convenience.hpp> #include <buffer.h> @@ -8,7 +9,7 @@ namespace MySQL { Mock::Mock(const std::string & name, const std::vector<boost::filesystem::path> & ss) : MockDatabase(name), - testDbPath(boost::filesystem::path("/tmp") / stringbf("embeddedmysql-%d-%d", getpid(), ++DB::MockDatabase::mocked)) + dbname(stringbf("test_%d_%d", getpid(), ++DB::MockDatabase::mocked)) { CreateNewDatabase(); PlaySchemaScripts(ss); @@ -22,30 +23,29 @@ namespace MySQL { DB::Connection * Mock::openConnection() const { - return new Connection(testDbPath.string()); + return new Connection(stringbf("path=%s;database=%s", mockDbPath(), dbname)); } void Mock::CreateNewDatabase() const { - boost::filesystem::create_directories(testDbPath); - const auto datadir = stringbf("--datadir=%s", testDbPath.string()); - static const char * opts[] = { - typeid(this).name(), - datadir.c_str(), - "--bootstrap", - NULL - }; - static const char * groups[] = { NULL }; - mysql_library_init(3, (char**)opts, (char**)groups); - sleep(20); + auto path = mockDbPath(); + embeddedServer = Server::getMock(path); + Connection initialize(embeddedServer.get(), "mysql"); + initialize.execute("CREATE DATABASE " + dbname); } void Mock::DropDatabase() const { - mysql_library_end(); - boost::filesystem::remove_all(testDbPath); + Connection initialize(embeddedServer.get(), "mysql"); + initialize.execute("DROP DATABASE " + dbname); + } + + boost::filesystem::path + Mock::mockDbPath() + { + return boost::filesystem::temp_directory_path() / stringbf("mysql-mock-%d", getpid()); } } } diff --git a/libmysqlpp/embeddedmy-mock.h b/libmysqlpp/embeddedmy-mock.h index 0b90b4b..cad10eb 100644 --- a/libmysqlpp/embeddedmy-mock.h +++ b/libmysqlpp/embeddedmy-mock.h @@ -4,26 +4,30 @@ #include <mockDatabase.h> #include <boost/filesystem/path.hpp> #include <visibility.h> +#include <boost/shared_ptr.hpp> +#include "embeddedmy-server.h" namespace MySQL { -namespace Embedded { + namespace Embedded { + class DLL_PUBLIC Mock : public DB::MockDatabase { + public: + Mock(const std::string & name, const std::vector<boost::filesystem::path> & ss); + ~Mock(); -class DLL_PUBLIC Mock : public DB::MockDatabase { - public: - Mock(const std::string & name, const std::vector<boost::filesystem::path> & ss); - ~Mock(); + protected: + void DropDatabase() const override; + void CreateNewDatabase() const override; - protected: - void DropDatabase() const override; - void CreateNewDatabase() const override; + DB::Connection * openConnection() const override; - DB::Connection * openConnection() const override; + private: + static boost::filesystem::path mockDbPath(); - private: - const boost::filesystem::path testDbPath; -}; + std::string dbname; + mutable ServerPtr embeddedServer; + }; -} + } } #endif diff --git a/libmysqlpp/embeddedmy-server.cpp b/libmysqlpp/embeddedmy-server.cpp new file mode 100644 index 0000000..a0fc3e3 --- /dev/null +++ b/libmysqlpp/embeddedmy-server.cpp @@ -0,0 +1,83 @@ +#include "embeddedmy-server.h" +#include "embeddedmy-connection.h" +#include <stdexcept> +#include <buffer.h> +#include <mysql.h> +#include <boost/filesystem/convenience.hpp> +#include <fstream> + +namespace MySQL { + namespace Embedded { + ServerPtr + Server::get(const boost::filesystem::path & path, const std::vector<std::string> & extraOpts) + { + if (instance) { + if (path == instance->path) { + return instance; + } + throw std::runtime_error(stringbf("Only one embedded server per process. [old=%s, new=%s]", instance->path, path)); + } + instance = new Server(path, extraOpts); + return instance; + } + + ServerPtr + Server::getMock(const boost::filesystem::path & path) + { + boost::filesystem::create_directories(path / "mysql"); + if (instance) { + if (path == instance->path && dynamic_cast<MockServer *>(instance)) { + return instance; + } + throw std::runtime_error(stringbf("Only one embedded server per process. [old=%s, new=%s]", instance->path, path)); + } + auto i = new MockServer(path); + i->initialize(); + return (instance = i); + } + + Server::Server(const boost::filesystem::path & p, const std::vector<std::string> & extraOpts) : + path(p) + { + const auto datadir = stringbf("--datadir=%s", path.string()); + std::vector<const char *> opts; + opts.push_back(typeid(this).name()); + opts.push_back(datadir.c_str()); + for (auto & opt : extraOpts) { + opts.push_back(opt.c_str()); + } + opts.push_back(nullptr); + static const char * groups[] = { NULL }; + mysql_library_init(opts.size() - 1, (char**)&opts.front(), (char**)groups); + } + + Server::~Server() + { + mysql_library_end(); + instance = nullptr; + } + + MockServer::MockServer(const boost::filesystem::path & p) : + Server(p, { "--bootstrap" }) + { + } + + void + MockServer::initialize() + { + Connection initialize(this, "mysql"); + std::ifstream sql1("/usr/share/mysql/mysql_system_tables.sql"); + initialize.executeScript(sql1, path); + std::ifstream sql2("/usr/share/mysql/mysql_system_tables_data.sql"); + initialize.executeScript(sql2, path); + } + + MockServer::~MockServer() + { + boost::filesystem::remove_all(path); + } + + Server * Server::instance = nullptr; + } +} + diff --git a/libmysqlpp/embeddedmy-server.h b/libmysqlpp/embeddedmy-server.h new file mode 100644 index 0000000..a1fa7fb --- /dev/null +++ b/libmysqlpp/embeddedmy-server.h @@ -0,0 +1,45 @@ +#ifndef MYSQL_EMBEDDED_SERVER_H +#define MYSQL_EMBEDDED_SERVER_H + +#include <string> +#include <vector> +#include <boost/filesystem/path.hpp> +#include <intrusivePtrBase.h> +#include <boost/intrusive_ptr.hpp> + +namespace MySQL { + namespace Embedded { + class Server; + + typedef boost::intrusive_ptr<Server> ServerPtr; + + class Server : public IntrusivePtrBase { + public: + virtual ~Server(); + + static ServerPtr get(const boost::filesystem::path &, const std::vector<std::string> &); + static ServerPtr getMock(const boost::filesystem::path &); + + protected: + Server(const boost::filesystem::path &, const std::vector<std::string> &); + + const boost::filesystem::path path; + + private: + static Server * instance; + }; + + class MockServer : public Server { + public: + MockServer(const boost::filesystem::path &); + + void initialize(); + + public: + ~MockServer(); + }; + } +} + +#endif + diff --git a/libmysqlpp/my-connection.cpp b/libmysqlpp/my-connection.cpp index 04c1f8c..2be253b 100644 --- a/libmysqlpp/my-connection.cpp +++ b/libmysqlpp/my-connection.cpp @@ -2,6 +2,7 @@ #include "my-error.h" #include "my-selectcommand.h" #include "my-modifycommand.h" +#include "my-opts.h" #include <nvpParse.h> #include <runtimeContext.h> #include <ucontext.h> @@ -18,35 +19,15 @@ MySQL::ConnectionError::ConnectionError(MYSQL * m) : class Opts { public: Opts() { port = 3306; } - typedef boost::optional<std::string> OptString; - OptString server; - OptString user; - OptString password; - OptString database; + MySQL::OptString server; + MySQL::OptString user; + MySQL::OptString password; + MySQL::OptString database; unsigned int port; - OptString unix_socket; - OptString options; + MySQL::OptString unix_socket; + MySQL::OptString options; }; -const char * -operator~(const Opts::OptString & os) -{ - if (os) { - return os->c_str(); - } - return NULL; -} - -namespace std { - template <typename T> - std::istream & - operator>>(std::istream & s, boost::optional<T> & o) - { - o = T(); - return (s >> *o); - } -} - using namespace AdHoc; NvpTarget(Opts) OptsTargetMap { NvpValue(Opts, server), @@ -143,6 +124,14 @@ MySQL::Connection::newModifyCommand(const std::string & sql, const DB::CommandOp return new ModifyCommand(this, sql); } +void +MySQL::Connection::execute(const std::string & sql) +{ + if (mysql_query(&conn, sql.c_str())) { + throw Error(&conn); + } +} + namespace MySQL { class LoadContext : public AdHoc::System::RuntimeContext { public: diff --git a/libmysqlpp/my-connection.h b/libmysqlpp/my-connection.h index fdc3e5a..36e9388 100644 --- a/libmysqlpp/my-connection.h +++ b/libmysqlpp/my-connection.h @@ -8,7 +8,7 @@ #include <boost/shared_ptr.hpp> namespace MySQL { - class ConnectionError : public virtual Error, public virtual DB::ConnectionError { + class DLL_PUBLIC ConnectionError : public virtual Error, public virtual DB::ConnectionError { public: ConnectionError(MYSQL *); }; @@ -35,6 +35,7 @@ namespace MySQL { size_t bulkUploadData(const char *, size_t) const override; int64_t insertId() override; + void execute(const std::string &) override; mutable MYSQL conn; diff --git a/libmysqlpp/my-opts.cpp b/libmysqlpp/my-opts.cpp new file mode 100644 index 0000000..b0a777d --- /dev/null +++ b/libmysqlpp/my-opts.cpp @@ -0,0 +1,34 @@ +#include "my-opts.h" + +namespace MySQL { + const char * + operator~(const OptString & os) + { + if (os) { + return os->c_str(); + } + return NULL; + } +} + +namespace std { + template <typename T> + std::istream & + operator>>(std::istream & s, std::vector<T> & o) + { + o.push_back(T()); + return (s >> o.back()); + } + + template <typename T> + std::istream & + operator>>(std::istream & s, boost::optional<T> & o) + { + o = T(); + return (s >> *o); + } + + template std::istream & operator>>(std::istream & s, boost::optional<std::string> & o); + template std::istream & operator>>(std::istream & s, std::vector<std::string> & o); +} + diff --git a/libmysqlpp/my-opts.h b/libmysqlpp/my-opts.h new file mode 100644 index 0000000..e444fa8 --- /dev/null +++ b/libmysqlpp/my-opts.h @@ -0,0 +1,22 @@ +#ifndef MYSQL_OPTS_H +#define MYSQL_OPTS_H + +#include <boost/optional.hpp> +#include <string> +#include <visibility.h> + +namespace MySQL { + typedef boost::optional<std::string> OptString; + + DLL_PUBLIC const char * operator~(const OptString & os); +} + +namespace std { + template <typename T> + DLL_PUBLIC std::istream & operator>>(std::istream & s, boost::optional<T> & o); + template <typename T> + DLL_PUBLIC std::istream & operator>>(std::istream & s, std::vector<T> & o); +} + +#endif + diff --git a/libmysqlpp/unittests/Jamfile.jam b/libmysqlpp/unittests/Jamfile.jam index c7bf637..d4014ea 100644 --- a/libmysqlpp/unittests/Jamfile.jam +++ b/libmysqlpp/unittests/Jamfile.jam @@ -24,7 +24,7 @@ run run testmysqle.cpp - : : : + : --log_level=all : : <define>ROOT=\"$(me)\" <define>BOOST_TEST_DYN_LINK <library>..//dbpp-mysql-embedded diff --git a/libmysqlpp/unittests/testMain.cpp b/libmysqlpp/unittests/test.impl.h index 0811d5c..13ae738 100644 --- a/libmysqlpp/unittests/testMain.cpp +++ b/libmysqlpp/unittests/test.impl.h @@ -1,17 +1,19 @@ +#include <boost/test/unit_test.hpp> #include <modifycommand.h> #include <selectcommand.h> +#include <connection.h> +#include <mockDatabase.h> #include <column.h> #include <testCore.h> #include <fstream> #include <boost/date_time/posix_time/posix_time.hpp> - -BOOST_GLOBAL_FIXTURE( StandardMockDatabase ); +#include <definedDirs.h> BOOST_FIXTURE_TEST_SUITE( Core, DB::TestCore ); BOOST_AUTO_TEST_CASE( transactions ) { - auto ro = DB::MockDatabase::openConnectionTo("mysqlmock"); + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); BOOST_REQUIRE_EQUAL(false, ro->inTx()); ro->beginTx(); @@ -23,15 +25,13 @@ BOOST_AUTO_TEST_CASE( transactions ) BOOST_REQUIRE_EQUAL(true, ro->inTx()); ro->commitTx(); BOOST_REQUIRE_EQUAL(false, ro->inTx()); - - delete ro; } BOOST_AUTO_TEST_CASE( bindAndSend ) { - auto rw = DB::MockDatabase::openConnectionTo("mysqlmock"); + auto rw = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); - auto mod = rw->newModifyCommand("INSERT INTO test VALUES(?, ?, ?, ?, ?, ?)"); + auto mod = rw->modify("INSERT INTO test VALUES(?, ?, ?, ?, ?, ?)"); mod->bindParamI(0, testInt); mod->bindParamF(1, testDouble); mod->bindParamS(2, testString); @@ -39,15 +39,13 @@ BOOST_AUTO_TEST_CASE( bindAndSend ) mod->bindParamT(4, testDateTime); mod->bindParamT(5, testInterval); mod->execute(); - delete mod; - delete rw; } BOOST_AUTO_TEST_CASE( bindAndSelect ) { - auto ro = DB::MockDatabase::openConnectionTo("mysqlmock"); + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); - auto select = ro->newSelectCommand("SELECT * FROM test WHERE id = ?"); + auto select = ro->select("SELECT * FROM test WHERE id = ?"); select->bindParamI(0, testInt); select->execute(); int rows = 0; @@ -60,16 +58,14 @@ BOOST_AUTO_TEST_CASE( bindAndSelect ) assertColumnValueHelper(*select, 5, testInterval); rows += 1; } - delete select; BOOST_REQUIRE_EQUAL(1, rows); - delete ro; } BOOST_AUTO_TEST_CASE( bindAndSelectOther ) { - auto ro = DB::MockDatabase::openConnectionTo("mysqlmock"); + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); - auto select = ro->newSelectCommand("SELECT * FROM test WHERE id != ?"); + auto select = ro->select("SELECT * FROM test WHERE id != ?"); select->bindParamI(0, testInt); select->execute(); int rows = 0; @@ -82,54 +78,13 @@ BOOST_AUTO_TEST_CASE( bindAndSelectOther ) assertColumnValueHelper(*select, 5, boost::posix_time::time_duration(38, 13, 12)); rows += 1; } - delete select; BOOST_REQUIRE_EQUAL(1, rows); - delete ro; -} - -BOOST_AUTO_TEST_CASE( bulkload ) -{ - auto ro = DB::MockDatabase::openConnectionTo("mysqlmock"); - - auto count = ro->newSelectCommand("SELECT COUNT(*) FROM bulktest"); - // Test empty - ro->beginBulkUpload("bulktest", ""); - ro->endBulkUpload(NULL); - assertScalarValueHelper(*count, 0); - // Test sample file - ro->beginBulkUpload("bulktest", ""); - std::ifstream in((rootDir / "bulk.sample").string()); - if (!in.good()) throw std::runtime_error("Couldn't open bulk.sample"); - char buf[BUFSIZ]; - for (std::streamsize r; (r = in.readsome(buf, sizeof(buf))) > 0; ) { - ro->bulkUploadData(buf, r); - } - ro->endBulkUpload(NULL); - assertScalarValueHelper(*count, 800); - - delete count; - delete ro; -} - -BOOST_AUTO_TEST_CASE( bigIterate ) -{ - auto ro = DB::MockDatabase::openConnectionTo("mysqlmock"); - - auto count = ro->newSelectCommand("SELECT * FROM bulktest"); - unsigned int rows = 0; - while (count->fetch()) { - rows += 1; - } - BOOST_REQUIRE_EQUAL(800, rows); - - delete count; - delete ro; } BOOST_AUTO_TEST_CASE( insertId ) { - auto ro = DB::MockDatabase::openConnectionTo("mysqlmock"); - auto ins = ro->newModifyCommand("INSERT INTO inserts(num) VALUES(?)"); + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); + auto ins = ro->modify("INSERT INTO inserts(num) VALUES(?)"); ins->bindParamI(0, 4); ins->execute(); BOOST_REQUIRE_EQUAL(1, ro->insertId()); @@ -139,18 +94,14 @@ BOOST_AUTO_TEST_CASE( insertId ) ins->bindParamI(0, -4); ins->execute(); BOOST_REQUIRE_EQUAL(3, ro->insertId()); - delete ins; - delete ro; } BOOST_AUTO_TEST_CASE( errors ) { - auto ro = DB::MockDatabase::openConnectionTo("mysqlmock"); + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); BOOST_REQUIRE_THROW(ro->execute("nonsense"), DB::Error); - delete ro; BOOST_REQUIRE_THROW(DB::ConnectionFactory::createNew("mysql", "server=nohost"), DB::ConnectionError); } BOOST_AUTO_TEST_SUITE_END(); - diff --git a/libmysqlpp/unittests/testmysql.cpp b/libmysqlpp/unittests/testmysql.cpp index d363716..fd29485 100644 --- a/libmysqlpp/unittests/testmysql.cpp +++ b/libmysqlpp/unittests/testmysql.cpp @@ -1,6 +1,3 @@ -#define BOOST_TEST_MODULE TestMySQL -#include <boost/test/unit_test.hpp> - #include <my-mock.h> #include <definedDirs.h> @@ -12,5 +9,45 @@ class StandardMockDatabase : public MySQL::Mock { } }; -#include "testMain.cpp" +#define BOOST_TEST_MODULE TestMySQL + +#include "test.impl.h" +BOOST_GLOBAL_FIXTURE( StandardMockDatabase ); + +BOOST_FIXTURE_TEST_SUITE( Core, DB::TestCore ); + +BOOST_AUTO_TEST_CASE( bulkload ) +{ + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); + + auto count = ro->select("SELECT COUNT(*) FROM bulktest"); + // Test empty + ro->beginBulkUpload("bulktest", ""); + ro->endBulkUpload(NULL); + assertScalarValueHelper(*count, 0); + // Test sample file + ro->beginBulkUpload("bulktest", ""); + std::ifstream in((rootDir / "bulk.sample").string()); + if (!in.good()) throw std::runtime_error("Couldn't open bulk.sample"); + char buf[BUFSIZ]; + for (std::streamsize r; (r = in.readsome(buf, sizeof(buf))) > 0; ) { + ro->bulkUploadData(buf, r); + } + ro->endBulkUpload(NULL); + assertScalarValueHelper(*count, 800); +} + +BOOST_AUTO_TEST_CASE( bigIterate ) +{ + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); + + auto count = ro->select("SELECT * FROM bulktest"); + unsigned int rows = 0; + while (count->fetch()) { + rows += 1; + } + BOOST_REQUIRE_EQUAL(800, rows); +} + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/libmysqlpp/unittests/testmysqle.cpp b/libmysqlpp/unittests/testmysqle.cpp index 0d1defb..659433b 100644 --- a/libmysqlpp/unittests/testmysqle.cpp +++ b/libmysqlpp/unittests/testmysqle.cpp @@ -1,6 +1,3 @@ -#define BOOST_TEST_MODULE TestEmbeddedMySQL -#include <boost/test/unit_test.hpp> - #include <embeddedmy-mock.h> #include <definedDirs.h> @@ -12,5 +9,18 @@ class StandardMockDatabase : public MySQL::Embedded::Mock { } }; -#include "testMain.cpp" +#define BOOST_TEST_MODULE TestEmbeddedMySQL + +#include "test.impl.h" +BOOST_GLOBAL_FIXTURE( StandardMockDatabase ); + +BOOST_FIXTURE_TEST_SUITE( Core, DB::TestCore ); + +BOOST_AUTO_TEST_CASE( bulkload ) +{ + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); + BOOST_REQUIRE_THROW(ro->beginBulkUpload("any", nullptr), DB::BulkUploadNotSupported); +} + +BOOST_AUTO_TEST_SUITE_END(); |