// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include #include #include #include #include #include #include #include #include #include #include "../qsqldatabase/tst_databases.h" class tst_QSql : public QObject { Q_OBJECT public: tst_QSql(); virtual ~tst_QSql(); public slots: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); private slots: void open(); void openInvalid(); void registerSqlDriver(); // problem specific tests void openErrorRecovery(); void concurrentAccess(); void basicDriverTest(); }; /****************** General Qt SQL Module tests *****************/ tst_QSql::tst_QSql() { } tst_QSql::~tst_QSql() { } void tst_QSql::initTestCase() { } void tst_QSql::cleanupTestCase() { } void tst_QSql::init() { } void tst_QSql::cleanup() { } // this is a very basic test for drivers that cannot create/delete tables // it can be used while developing new drivers, // it's original purpose is to test ODBC Text datasources that are basically // to stupid to do anything more advanced than SELECT/INSERT/UPDATE/DELETE // the datasource has to have a table called "qtest_basictest" consisting // of a field "id"(integer) and "name"(char/varchar). void tst_QSql::basicDriverTest() { int argc = 1; char *argv[] = { const_cast(QTest::currentAppName()) }; QCoreApplication app(argc, argv, false); tst_Databases dbs; QVERIFY(dbs.open()); foreach (const QString& dbName, dbs.dbNames) { QSqlDatabase db = QSqlDatabase::database(dbName); QVERIFY_SQL(db, isValid()); QStringList tables = db.tables(); QString tableName; if (tables.contains("qtest_basictest.txt")) tableName = "qtest_basictest.txt"; else if (tables.contains("qtest_basictest")) tableName = "qtest_basictest"; else if (tables.contains("QTEST_BASICTEST")) tableName = "QTEST_BASICTEST"; else { QVERIFY(1); continue; } qDebug("Testing: %s", qPrintable(tst_Databases::dbToString(db))); QSqlRecord rInf = db.record(tableName); QCOMPARE(rInf.count(), 2); QCOMPARE(rInf.fieldName(0).toLower(), QString("id")); QCOMPARE(rInf.fieldName(1).toLower(), QString("name")); } dbs.close(); QVERIFY(1); // make sure the test doesn't fail if no database drivers are there } // make sure that the static stuff will be deleted // when using multiple QCoreApplication objects void tst_QSql::open() { int i; int argc = 1; char *argv[] = { const_cast(QTest::currentAppName()) }; int count = -1; for (i = 0; i < 10; ++i) { QCoreApplication app(argc, argv, false); tst_Databases dbs; QVERIFY(dbs.open()); if (count == -1) // first iteration: see how many dbs are open count = (int) dbs.dbNames.size(); else // next iterations: make sure all are opened again QCOMPARE(count, (int)dbs.dbNames.size()); dbs.close(); } } void tst_QSql::openInvalid() { QSqlDatabase db; QVERIFY(!db.open()); QSqlDatabase db2 = QSqlDatabase::addDatabase("doesnt_exist_will_never_exist", "blah"); QFAIL_SQL(db2, open()); } void tst_QSql::concurrentAccess() { int argc = 1; char *argv[] = { const_cast(QTest::currentAppName()) }; QCoreApplication app(argc, argv, false); tst_Databases dbs; QVERIFY(dbs.open()); foreach (const QString& dbName, dbs.dbNames) { QSqlDatabase db = QSqlDatabase::database(dbName); QVERIFY(db.isValid()); if (tst_Databases::isMSAccess(db)) continue; QSqlDatabase ndb = QSqlDatabase::addDatabase(db.driverName(), "tst_QSql::concurrentAccess"); ndb.setDatabaseName(db.databaseName()); ndb.setHostName(db.hostName()); ndb.setPort(db.port()); ndb.setUserName(db.userName()); ndb.setPassword(db.password()); QVERIFY_SQL(ndb, open()); QCOMPARE(db.tables(), ndb.tables()); ndb.close(); } // no database servers installed - don't fail QVERIFY(1); dbs.close(); } void tst_QSql::openErrorRecovery() { int argc = 1; char *argv[] = { const_cast(QTest::currentAppName()) }; QCoreApplication app(argc, argv, false); tst_Databases dbs; QVERIFY(dbs.addDbs()); if (dbs.dbNames.isEmpty()) QSKIP("No database drivers installed"); foreach (const QString& dbName, dbs.dbNames) { QSqlDatabase db = QSqlDatabase::database(dbName, false); CHECK_DATABASE(db); QString userName = db.userName(); QString password = db.password(); // force an open error if (db.open("dummy130977", "doesnt_exist")) { qDebug("Promiscuous database server without access control - test skipped for %s", qPrintable(tst_Databases::dbToString(db))); QVERIFY(1); continue; } QFAIL_SQL(db, isOpen()); QVERIFY_SQL(db, isOpenError()); // now open it if (!db.open(userName, password)) { qDebug() << "Could not open Database " << tst_Databases::dbToString(db) << ". Assuming DB is down, skipping... (Error: " << tst_Databases::printError(db.lastError()) << ")"; continue; } QVERIFY_SQL(db, open(userName, password)); QVERIFY_SQL(db, isOpen()); QFAIL_SQL(db, isOpenError()); db.close(); QFAIL_SQL(db, isOpen()); // force another open error QFAIL_SQL(db, open("dummy130977", "doesnt_exist")); QFAIL_SQL(db, isOpen()); QVERIFY_SQL(db, isOpenError()); } } void tst_QSql::registerSqlDriver() { int argc = 1; char *argv[] = { const_cast(QTest::currentAppName()) }; QCoreApplication app(argc, argv, false); QSqlDatabase::registerSqlDriver("QSQLTESTDRIVER", new QSqlDriverCreator); QVERIFY(QSqlDatabase::drivers().contains("QSQLTESTDRIVER")); QSqlDatabase db = QSqlDatabase::addDatabase("QSQLTESTDRIVER"); QVERIFY(db.isValid()); QCOMPARE(db.tables(), QStringList()); } QTEST_APPLESS_MAIN(tst_QSql) #include "tst_qsql.moc"