diff options
Diffstat (limited to 'project2/sql')
-rw-r--r-- | project2/sql/Jamfile.jam | 14 | ||||
-rw-r--r-- | project2/sql/sql-modSQLite.cpp | 61 | ||||
-rw-r--r-- | project2/sql/sql-modSQLite.h | 24 | ||||
-rw-r--r-- | project2/sql/unittests/Jamfile.jam | 28 | ||||
-rw-r--r-- | project2/sql/unittests/datasources/sqlitemock.xml | 5 | ||||
-rw-r--r-- | project2/sql/unittests/sqliteschema.sql | 6 | ||||
-rw-r--r-- | project2/sql/unittests/testsqlite.cpp | 89 |
7 files changed, 217 insertions, 10 deletions
diff --git a/project2/sql/Jamfile.jam b/project2/sql/Jamfile.jam index 306c94a..01ba44b 100644 --- a/project2/sql/Jamfile.jam +++ b/project2/sql/Jamfile.jam @@ -2,6 +2,7 @@ alias glibmm : : : : <cflags>"`pkg-config --cflags glibmm-2.4`" <linkflags>"`pkg-config --libs glibmm-2.4`" ; +lib boost_filesystem ; build-project unittests ; @@ -16,6 +17,19 @@ lib p2sqlmodMySQL : : : <library>../../libmysqlpp//mysqlpp ; + +explicit library p2sqlmodSQLite ; +lib p2sqlmodSQLite : + sql-modSQLite.cpp : + <library>../../libsqlitepp//sqlitepp + <library>glibmm + <include>../../libmisc + <library>../common//p2common + <library>p2sql + <library>boost_filesystem + : : + <library>../../libsqlitepp//sqlitepp + ; explicit library p2sqlmodODBC ; lib p2sqlmodODBC : diff --git a/project2/sql/sql-modSQLite.cpp b/project2/sql/sql-modSQLite.cpp new file mode 100644 index 0000000..6b4cb85 --- /dev/null +++ b/project2/sql/sql-modSQLite.cpp @@ -0,0 +1,61 @@ +#include "connectionLoader.h" +#include "../libsqlitepp/connection.h" +#include "sql-modSQLite.h" +#include <misc.h> +#include <scripts.h> +#include <logger.h> +#include <boost/filesystem/operations.hpp> + +typedef SQLite::Connection SQLiteConnection; +DECLARE_GENERIC_LOADER("sqlite", ConnectionLoader, SQLiteConnection) + +MockSQLiteDatabase::MockSQLiteDatabase(const std::string & name, const std::vector<boost::filesystem::path> & ss) : + testDbPath(boost::filesystem::path("/tmp") / "sqliteut" / stringbf("%d", getpid()) / stringbf("%d", ++MockConnectionLoader::mocked)), + mockName(name) +{ + 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; + } +} + +DB::Connection * +MockSQLiteDatabase::openConnection(const std::string & connStr) +{ + return InstanceMap<ConnectionLoader, std::string>::Get<std::invalid_argument>("sqlite")->create(connStr); +} + +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 +{ + Logger()->messagebf(LOG_INFO, "Deleting database %s", testDbPath); + boost::filesystem::remove(testDbPath); +} + +void MockSQLiteDatabase::CreateNewDatabase() const +{ + Logger()->messagebf(LOG_INFO, "Creating new database at %s", testDbPath); + boost::filesystem::create_directories(testDbPath.parent_path()); +} + + diff --git a/project2/sql/sql-modSQLite.h b/project2/sql/sql-modSQLite.h new file mode 100644 index 0000000..267ba0b --- /dev/null +++ b/project2/sql/sql-modSQLite.h @@ -0,0 +1,24 @@ +#ifndef MOCKSQLITEDATASOURCE_H +#define MOCKSQLITEDATASOURCE_H + +#include "mockDatasource.h" +#include <boost/filesystem/path.hpp> + +class MockSQLiteDatabase { + public: + MockSQLiteDatabase(const std::string & name, const std::vector<boost::filesystem::path> & ss); + ~MockSQLiteDatabase(); + + protected: + void DropDatabase() const; + void CreateNewDatabase() const; + + private: + static DB::Connection * openConnection(const std::string & connStr); + const boost::filesystem::path testDbPath; + const std::string mockName; +}; + +#endif + + diff --git a/project2/sql/unittests/Jamfile.jam b/project2/sql/unittests/Jamfile.jam index 24db2e5..d9874ce 100644 --- a/project2/sql/unittests/Jamfile.jam +++ b/project2/sql/unittests/Jamfile.jam @@ -1,4 +1,3 @@ - import testing ; lib boost_system ; @@ -10,29 +9,38 @@ path-constant me : . ; lib sqlTestCore : testCore.cpp - : : + : <library>../../ut//p2ut <library>../../common//p2common <library>boost_filesystem <define>ROOT=\"$(me)\" - ; - -run - testpq.cpp - : : : - <define>BOOST_TEST_DYN_LINK - <library>sqlTestCore + : : <library>../../common//p2common <library>../../basics//p2basics <library>../../ut//p2ut <library>../../lib//p2lib <library>../../xml//p2xml <library>..//p2sql - <library>..//p2sqlmodPQ <library>boost_system <library>boost_filesystem <library>../../ut//boost_utf <define>ROOT=\"$(me)\" + <define>BOOST_TEST_DYN_LINK + ; + +run + testpq.cpp + : : : + <library>sqlTestCore + <library>..//p2sqlmodPQ <dependency>pqschema.sql : testpq ; +run + testsqlite.cpp + : : : + <library>sqlTestCore + <library>..//p2sqlmodSQLite + <dependency>sqliteschema.sql + : testsqlite ; + diff --git a/project2/sql/unittests/datasources/sqlitemock.xml b/project2/sql/unittests/datasources/sqlitemock.xml new file mode 100644 index 0000000..762de90 --- /dev/null +++ b/project2/sql/unittests/datasources/sqlitemock.xml @@ -0,0 +1,5 @@ +<?xml version="1.0"?> +<project2:rdbmsdatasource xmlns:project2="http://project2.randomdan.homeip.net" name="sqlitemock"> + <masterdsn provider="mock" dsn="sqlitemock" /> +</project2:rdbmsdatasource> + diff --git a/project2/sql/unittests/sqliteschema.sql b/project2/sql/unittests/sqliteschema.sql new file mode 100644 index 0000000..393d21a --- /dev/null +++ b/project2/sql/unittests/sqliteschema.sql @@ -0,0 +1,6 @@ +CREATE TABLE test( + id int, + fl numeric(5,2), + string text); +INSERT INTO test VALUES(4, 123.45, 'some text'); + diff --git a/project2/sql/unittests/testsqlite.cpp b/project2/sql/unittests/testsqlite.cpp new file mode 100644 index 0000000..89a1f77 --- /dev/null +++ b/project2/sql/unittests/testsqlite.cpp @@ -0,0 +1,89 @@ +#define BOOST_TEST_MODULE TestSQLite +#include <boost/test/unit_test.hpp> + +#include <mockDatasource.h> +#include <definedDirs.h> +#include <modifycommand.h> +#include <selectcommand.h> +#include <column.h> +#include <sql-modSQLite.h> +#include "testCore.h" +#include <sqlHandleAsVariableType.h> + +class StandardMockDatabase : public MockSQLiteDatabase { + public: + StandardMockDatabase() : MockSQLiteDatabase("sqlitemock", { + RootDir / "sqliteschema.sql" }) + { + } +}; + +BOOST_GLOBAL_FIXTURE( StandardMockDatabase ); + +BOOST_FIXTURE_TEST_SUITE( Core, TestCore ); + +BOOST_AUTO_TEST_CASE( transactions ) +{ + RdbmsDataSource * ds = CommonObjects::dataSource<RdbmsDataSource>("sqlitemock"); + auto ro = ds->getReadonly(); + + 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()); + + ds->close(); +} + +BOOST_AUTO_TEST_CASE( bindAndSend ) +{ + RdbmsDataSource * ds = CommonObjects::dataSource<RdbmsDataSource>("sqlitemock"); + auto rw = ds->getWritable(); + + auto mod = rw->newModifyCommand("INSERT INTO test VALUES(?, ?, ?)"); + mod->bindParamI(0, testInt); + mod->bindParamF(1, testDouble); + mod->bindParamS(2, testString); + mod->execute(); + delete mod; + ds->commit(); + ds->close(); +} + +template<typename T> +void +assertColumnValueHelper(DB::SelectCommand & sel, unsigned int col, const T & t) +{ + HandleAsVariableType h; + sel[col].apply(h); + BOOST_REQUIRE_EQUAL(t, h.variable.as<T>()); +} + +BOOST_AUTO_TEST_CASE( bindAndSelect ) +{ + RdbmsDataSource * ds = CommonObjects::dataSource<RdbmsDataSource>("sqlitemock"); + auto ro = ds->getReadonly(); + + 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); + rows += 1; + } + delete select; + BOOST_REQUIRE_EQUAL(1, rows); + ds->close(); +} + +BOOST_AUTO_TEST_SUITE_END(); + |