#include #include #include #include #include #include #include #include class DockerRunner { enum class Status { Running, Exited, Missing }; public: DockerRunner(std::string name) : _name{std::move(name)} { using namespace boost::process; auto getStatus = [this]() { ipstream is; // reading pipe-stream auto status = system(search_path("docker"), "inspect", _name, std_out > is); if(!status) { std::string statusBuf, line; statusBuf.reserve(10240); while(std::getline(is, line) && !line.empty()) statusBuf.append(line); auto status = nlohmann::json::parse(std::move(statusBuf))[0]["State"]["Status"]; if(status == "running") { return Status::Running; } else if(status == "exited") { return Status::Exited; } } return Status::Missing; }; auto status = getStatus(); if(status == Status::Exited) { system(search_path("docker"), "start", _name); } else if(status == Status::Missing) { system(search_path("docker"), "run --detach", "--name", _name, "-p 5432:5432", "-e POSTGRES_PASSWORD=postgres", "-e POSTGRES_DB=eedb", "postgres:9.5-alpine"); } } ~DockerRunner() { // using namespace boost::process; // auto p = search_path("docker"); // system(p, "stop", _name); // system(p, "rm", "-v", _name); } private: std::string _name; }; class PgTestDatabasePrepare { public: PgTestDatabasePrepare() { _docker = std::make_unique< DockerRunner >("eedb_test_database"); auto dbConfig = std::make_shared< eedb::db::PgConfig >(); dbConfig->host = "localhost"; dbConfig->port = 5432; dbConfig->password = "postgres"; dbConfig->user = "postgres"; dbConfig->dbname = "eedb"; dbConfig->debug = false; bool conOk{false}; int faild_attempts_count{0}; do { try { _db = std::make_unique< eedb::db::PgConnection >(dbConfig); conOk = true; } catch(sqlpp::postgresql::broken_connection &) { std::this_thread::sleep_for(std::chrono::milliseconds(500)); faild_attempts_count++; } } while(!conOk && faild_attempts_count < 30); if(faild_attempts_count >= 30) std::terminate(); } eedb::db::PgConnection & db() { if(!_db) throw std::runtime_error("db not initialized"); return *_db; } private: std::unique_ptr< DockerRunner > _docker; std::unique_ptr< eedb::db::PgConnection > _db; }; template < typename T > class DbTestBase : public testing::Test { public: static void SetUpTestCase() { _test_db = std::make_unique< PgTestDatabasePrepare >(); _test_db->db().native()->start_transaction(); _test_db->db().native()->execute("SET synchronous_commit=off;"); eedb::db::exec_file(_test_db->db(), "/home/bwieczor/src/eedb/sql/schema.sql"); _test_db->db().native()->commit_transaction(); } static void TearDownTestCase() { _test_db.reset(); } eedb::db::PgConnection & db() { return _test_db->db(); } protected: static std::unique_ptr< PgTestDatabasePrepare > _test_db; };