#include "PgTestEnvironment.h" #include #include #include #include #include #include "Pgsql_Connection.h" #include "Pgsql_Result.h" namespace pgtest { namespace { bool g_available = false; int g_versionNum = 0; } // namespace std::optional baseUrl() { QByteArray v = qgetenv("TEST_DATABASE_URL"); if (v.isEmpty()) return std::nullopt; return QString::fromUtf8(v); } QString urlForDb(const QString &db) { auto base = baseUrl(); if (!base) throw std::runtime_error("TEST_DATABASE_URL is not set"); QUrl url(*base); url.setPath("/" + db); return url.toString(); } bool available() { return g_available; } int serverVersionNum() { return g_versionNum; } qint64 processId() { return QCoreApplication::applicationPid(); } QString templateDbName() { return QString("tmpl_%1").arg(processId()); } QString quoteIdent(const QString &name) { QString r = name; r.replace('"', "\"\""); return "\"" + r + "\""; } void PgEnv::SetUp() { auto base = baseUrl(); if (!base) { std::cerr << "TEST_DATABASE_URL not set, integration tests will be skipped\n"; return; } const QString tmpl = templateDbName(); try { { Pgsql::Connection admin; admin.connect(*base); Pgsql::Result r = admin.query("SHOW server_version_num"); if (!r || r.rows() != 1) throw std::runtime_error("could not query server_version_num"); g_versionNum = QString::fromUtf8(r.val(0, 0)).toInt(); admin.query(QString("DROP DATABASE IF EXISTS %1 WITH (FORCE)").arg(quoteIdent(tmpl))); admin.query(QString("CREATE DATABASE %1").arg(quoteIdent(tmpl))); } { QFile f(fixtureDir_ + "/schema.sql"); if (!f.open(QIODevice::ReadOnly)) throw std::runtime_error("cannot open " + f.fileName().toStdString()); QByteArray sql = f.readAll(); Pgsql::Connection c; c.connect(urlForDb(tmpl)); c.query(sql.constData()); } g_available = true; } catch (const std::exception &e) { ADD_FAILURE() << "Setting up template database failed: " << e.what(); try { Pgsql::Connection admin; admin.connect(*base); admin.query(QString("DROP DATABASE IF EXISTS %1 WITH (FORCE)").arg(quoteIdent(tmpl))); } catch (const std::exception &) { } } } void PgEnv::TearDown() { if (!g_available) return; try { Pgsql::Connection admin; admin.connect(*baseUrl()); admin.query(QString("DROP DATABASE IF EXISTS %1 WITH (FORCE)").arg(quoteIdent(templateDbName()))); } catch (const std::exception &e) { ADD_FAILURE() << "Dropping template database failed: " << e.what(); } g_available = false; } } // namespace pgtest