From db1e2f066393af3e58814417de5bbe7ea08a145d Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 31 Dec 2015 04:04:31 +0000 Subject: Basics working, could do with a tidy up around mocking --- libmysqlpp/embeddedmy-connection.cpp | 64 +++++++++++++- libmysqlpp/embeddedmy-connection.h | 7 ++ libmysqlpp/embeddedmy-mock.cpp | 30 +++---- libmysqlpp/embeddedmy-mock.h | 30 ++++--- libmysqlpp/embeddedmy-server.cpp | 83 +++++++++++++++++++ libmysqlpp/embeddedmy-server.h | 45 ++++++++++ libmysqlpp/my-connection.cpp | 41 ++++----- libmysqlpp/my-connection.h | 3 +- libmysqlpp/my-opts.cpp | 34 ++++++++ libmysqlpp/my-opts.h | 22 +++++ libmysqlpp/unittests/Jamfile.jam | 2 +- libmysqlpp/unittests/test.impl.h | 107 ++++++++++++++++++++++++ libmysqlpp/unittests/testMain.cpp | 156 ----------------------------------- libmysqlpp/unittests/testmysql.cpp | 45 +++++++++- libmysqlpp/unittests/testmysqle.cpp | 18 +++- 15 files changed, 464 insertions(+), 223 deletions(-) create mode 100644 libmysqlpp/embeddedmy-server.cpp create mode 100644 libmysqlpp/embeddedmy-server.h create mode 100644 libmysqlpp/my-opts.cpp create mode 100644 libmysqlpp/my-opts.h create mode 100644 libmysqlpp/unittests/test.impl.h delete mode 100644 libmysqlpp/unittests/testMain.cpp 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 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 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 @@ -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 #include @@ -8,7 +9,7 @@ namespace MySQL { Mock::Mock(const std::string & name, const std::vector & 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 #include #include +#include +#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 & ss); + ~Mock(); -class DLL_PUBLIC Mock : public DB::MockDatabase { - public: - Mock(const std::string & name, const std::vector & 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 +#include +#include +#include +#include + +namespace MySQL { + namespace Embedded { + ServerPtr + Server::get(const boost::filesystem::path & path, const std::vector & 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(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 & extraOpts) : + path(p) + { + const auto datadir = stringbf("--datadir=%s", path.string()); + std::vector 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 +#include +#include +#include +#include + +namespace MySQL { + namespace Embedded { + class Server; + + typedef boost::intrusive_ptr ServerPtr; + + class Server : public IntrusivePtrBase { + public: + virtual ~Server(); + + static ServerPtr get(const boost::filesystem::path &, const std::vector &); + static ServerPtr getMock(const boost::filesystem::path &); + + protected: + Server(const boost::filesystem::path &, const std::vector &); + + 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 #include #include @@ -18,35 +19,15 @@ MySQL::ConnectionError::ConnectionError(MYSQL * m) : class Opts { public: Opts() { port = 3306; } - typedef boost::optional 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 - std::istream & - operator>>(std::istream & s, boost::optional & 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 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 + std::istream & + operator>>(std::istream & s, std::vector & o) + { + o.push_back(T()); + return (s >> o.back()); + } + + template + std::istream & + operator>>(std::istream & s, boost::optional & o) + { + o = T(); + return (s >> *o); + } + + template std::istream & operator>>(std::istream & s, boost::optional & o); + template std::istream & operator>>(std::istream & s, std::vector & 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 +#include +#include + +namespace MySQL { + typedef boost::optional OptString; + + DLL_PUBLIC const char * operator~(const OptString & os); +} + +namespace std { + template + DLL_PUBLIC std::istream & operator>>(std::istream & s, boost::optional & o); + template + DLL_PUBLIC std::istream & operator>>(std::istream & s, std::vector & 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 : : ROOT=\"$(me)\" BOOST_TEST_DYN_LINK ..//dbpp-mysql-embedded diff --git a/libmysqlpp/unittests/test.impl.h b/libmysqlpp/unittests/test.impl.h new file mode 100644 index 0000000..13ae738 --- /dev/null +++ b/libmysqlpp/unittests/test.impl.h @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BOOST_FIXTURE_TEST_SUITE( Core, DB::TestCore ); + +BOOST_AUTO_TEST_CASE( transactions ) +{ + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); + + BOOST_REQUIRE_EQUAL(false, ro->inTx()); + ro->beginTx(); + BOOST_REQUIRE_EQUAL(true, ro->inTx()); + ro->rollbackTx(); + BOOST_REQUIRE_EQUAL(false, ro->inTx()); + + ro->beginTx(); + BOOST_REQUIRE_EQUAL(true, ro->inTx()); + ro->commitTx(); + BOOST_REQUIRE_EQUAL(false, ro->inTx()); +} + +BOOST_AUTO_TEST_CASE( bindAndSend ) +{ + auto rw = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); + + auto mod = rw->modify("INSERT INTO test VALUES(?, ?, ?, ?, ?, ?)"); + mod->bindParamI(0, testInt); + mod->bindParamF(1, testDouble); + mod->bindParamS(2, testString); + mod->bindParamB(3, testBool); + mod->bindParamT(4, testDateTime); + mod->bindParamT(5, testInterval); + mod->execute(); +} + +BOOST_AUTO_TEST_CASE( bindAndSelect ) +{ + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); + + auto select = ro->select("SELECT * FROM test WHERE id = ?"); + select->bindParamI(0, testInt); + select->execute(); + int rows = 0; + while (select->fetch()) { + assertColumnValueHelper(*select, 0, testInt); + assertColumnValueHelper(*select, 1, testDouble); + assertColumnValueHelper(*select, 2, testString); + assertColumnValueHelper(*select, 3, testBool); + assertColumnValueHelper(*select, 4, testDateTime); + assertColumnValueHelper(*select, 5, testInterval); + rows += 1; + } + BOOST_REQUIRE_EQUAL(1, rows); +} + +BOOST_AUTO_TEST_CASE( bindAndSelectOther ) +{ + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); + + auto select = ro->select("SELECT * FROM test WHERE id != ?"); + select->bindParamI(0, testInt); + select->execute(); + int rows = 0; + while (select->fetch()) { + assertColumnValueHelper(*select, 0, 4); + assertColumnValueHelper(*select, 1, 123.45); + assertColumnValueHelper(*select, 2, std::string("some text")); + assertColumnValueHelper(*select, 3, true); + assertColumnValueHelper(*select, 4, boost::posix_time::ptime_from_tm({ 3, 6, 23, 27, 3, 115, 0, 0, 0, 0, 0})); + assertColumnValueHelper(*select, 5, boost::posix_time::time_duration(38, 13, 12)); + rows += 1; + } + BOOST_REQUIRE_EQUAL(1, rows); +} + +BOOST_AUTO_TEST_CASE( insertId ) +{ + 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()); + ins->bindParamI(0, 40); + ins->execute(); + BOOST_REQUIRE_EQUAL(2, ro->insertId()); + ins->bindParamI(0, -4); + ins->execute(); + BOOST_REQUIRE_EQUAL(3, ro->insertId()); +} + +BOOST_AUTO_TEST_CASE( errors ) +{ + auto ro = DB::ConnectionPtr(DB::MockDatabase::openConnectionTo("mysqlmock")); + BOOST_REQUIRE_THROW(ro->execute("nonsense"), DB::Error); + BOOST_REQUIRE_THROW(DB::ConnectionFactory::createNew("mysql", "server=nohost"), DB::ConnectionError); +} + +BOOST_AUTO_TEST_SUITE_END(); + diff --git a/libmysqlpp/unittests/testMain.cpp b/libmysqlpp/unittests/testMain.cpp deleted file mode 100644 index 0811d5c..0000000 --- a/libmysqlpp/unittests/testMain.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include -#include -#include -#include - -BOOST_GLOBAL_FIXTURE( StandardMockDatabase ); - -BOOST_FIXTURE_TEST_SUITE( Core, DB::TestCore ); - -BOOST_AUTO_TEST_CASE( transactions ) -{ - auto ro = DB::MockDatabase::openConnectionTo("mysqlmock"); - - BOOST_REQUIRE_EQUAL(false, ro->inTx()); - ro->beginTx(); - BOOST_REQUIRE_EQUAL(true, ro->inTx()); - ro->rollbackTx(); - BOOST_REQUIRE_EQUAL(false, ro->inTx()); - - ro->beginTx(); - 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 mod = rw->newModifyCommand("INSERT INTO test VALUES(?, ?, ?, ?, ?, ?)"); - mod->bindParamI(0, testInt); - mod->bindParamF(1, testDouble); - mod->bindParamS(2, testString); - mod->bindParamB(3, testBool); - 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 select = ro->newSelectCommand("SELECT * FROM test WHERE id = ?"); - select->bindParamI(0, testInt); - select->execute(); - int rows = 0; - while (select->fetch()) { - assertColumnValueHelper(*select, 0, testInt); - assertColumnValueHelper(*select, 1, testDouble); - assertColumnValueHelper(*select, 2, testString); - assertColumnValueHelper(*select, 3, testBool); - assertColumnValueHelper(*select, 4, testDateTime); - 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 select = ro->newSelectCommand("SELECT * FROM test WHERE id != ?"); - select->bindParamI(0, testInt); - select->execute(); - int rows = 0; - while (select->fetch()) { - assertColumnValueHelper(*select, 0, 4); - assertColumnValueHelper(*select, 1, 123.45); - assertColumnValueHelper(*select, 2, std::string("some text")); - assertColumnValueHelper(*select, 3, true); - assertColumnValueHelper(*select, 4, boost::posix_time::ptime_from_tm({ 3, 6, 23, 27, 3, 115, 0, 0, 0, 0, 0})); - 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(?)"); - ins->bindParamI(0, 4); - ins->execute(); - BOOST_REQUIRE_EQUAL(1, ro->insertId()); - ins->bindParamI(0, 40); - ins->execute(); - BOOST_REQUIRE_EQUAL(2, ro->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"); - 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 - #include #include @@ -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 - #include #include @@ -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(); -- cgit v1.2.3