File indexing completed on 2024-04-21 15:30:21

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003-2010 Jarosław Staniek <staniek@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include <QApplication>
0021 #include <QFileInfo>
0022 #include <QPointer>
0023 #include <QTextStream>
0024 
0025 #include <KDbDriverManager>
0026 #include <KDbDriver>
0027 #include <KDbDriverMetaData>
0028 #include <KDbConnection>
0029 #include <KDbConnectionData>
0030 #include <KDbCursor>
0031 #include <KDbTableSchema>
0032 #include <KDbQuerySchema>
0033 #include <KDbIndexSchema>
0034 
0035 #include <iostream>
0036 
0037 using namespace std;
0038 
0039 QByteArray prgname;
0040 QString db_name;
0041 QString drv_id;
0042 QString test_name;
0043 KDbCursor::Options cursor_options;
0044 bool db_name_required = true;
0045 
0046 KDbConnectionData conn_data;
0047 
0048 //! @todo IMPORTANT: replace QPointer<KDbConnection> conn;
0049 KDbConnection* conn = nullptr;
0050 
0051 //! @todo IMPORTANT: replace QPointer<KDbDriver> driver;
0052 KDbDriver* driver;
0053 QApplication *app = nullptr;
0054 
0055 #include "dbcreation_test.h"
0056 #include "cursors_test.h"
0057 #include "schema_test.h"
0058 #include "tables_test.h"
0059 #ifndef NO_GUI
0060 # include "tableview_test.h"
0061 #endif
0062 #include "parser_test.h"
0063 #include "dr_prop_test.h"
0064 
0065 static int finish(int code)
0066 {
0067     qDebug() << "main:" << test_name << "test:" << (code==0?"PASSED":"ERROR");
0068     if (code != 0 && conn) {
0069         qDebug() << "main:" << conn->result();
0070         conn->disconnect();
0071         delete conn;
0072     }
0073     return code;
0074 }
0075 
0076 //! @return true if option @a option or @a shortOption is found
0077 //! Removes the option.
0078 static bool takeOption(QStringList &args, const QString &option,
0079                        const QString &shortOption = QString())
0080 {
0081     return args.removeOne(QLatin1String("-") + (shortOption.isEmpty() ? option : shortOption))
0082         || args.removeOne(QLatin1String("--") + option);
0083 }
0084 
0085 //! @return next element after option @a option or @a shortOption, what should mean parameter
0086 //! Removes option and its argument.
0087 static QString takeOptionWithArg(QStringList &args, const QString &option,
0088                                  const QString &shortOption = QString())
0089 {
0090     int index = args.indexOf(QLatin1String("-") + (shortOption.isEmpty() ? option : shortOption));
0091     if (index == -1)
0092         index = args.indexOf(QLatin1String("--") + option);
0093     if (index == -1)
0094         return QString();
0095     args.removeAt(index);
0096     return args.takeAt(index); // option's argument
0097 }
0098 
0099 #define APPNAME "kdbfeaturestest"
0100 
0101 static void showHelp()
0102 {
0103     QTextStream s(stdout);
0104     s <<
0105 APPNAME ", version " KDB_VERSION_STRING
0106 "\n"
0107 "\nA set of tests for the KDb library API."
0108 "\nEvery test is mostly driver-independent."
0109 "\n (c) 2003-2016, Kexi Team"
0110 "\n (c) 2003-2006, OpenOffice Software LLC."
0111 "\n"
0112 "\nUsage: " APPNAME " --test <test_name> [options]"
0113 "\n         driver_id [db_name] [sql_statement]"
0114 "\n"
0115 "\nOptions:"
0116 "\n  --help                    Displays this help and exits"
0117 "\n  --buffered-cursors        Optional switch: turns cursors used in any"
0118 "\n                            tests to be buffered"
0119 "\n  -h, --host <name>         Host name to use when connecting"
0120 "\n                            to server backends"
0121 "\n  -p, --password <name>     Password to use when connecting to server"
0122 "\n                            backends"
0123 "\n  -P, --port <number>       Port number to use when connecting to server"
0124 "\n                            backends"
0125 "\n  --query-params <params>   Query parameters separated by '|' character"
0126 "\n                            that will be passed to query statement"
0127 "\n                            to replace [...] placeholders"
0128 "\n  -t, --test <test_name>    Specifies test to execute; required"
0129 "\n                            Available tests:"
0130 "\n                            - cursors: test for cursors behavior"
0131 "\n                            - schema: test for db schema retrieving"
0132 "\n                            - dbcreation: test for new db creation"
0133 "\n                            - tables: test for tables creation and data"
0134 "\n                                      inserting"
0135 //"\n                            - tableview: test for KexiDataTableView data-aware
0136 //"\n                               widget
0137 "\n                            - parser: test for parsing sql statements,"
0138 "\n                                      returns debug string for a given"
0139 "\n                                      sql statement or error message"
0140 "\n                            - dr_prop: shows properties of selected"
0141 "\n                                       driver"
0142 "\n  -u, --user <name>         User name to use when connecting to servers"
0143 "\n                            backends"
0144 "\n"
0145 "\nNotes:"
0146 "\n1. 'dr_prop' requires <driver_id> argument"
0147 "\n2. 'parser' test requires <db_name>, <driverid> and <sql_statement>"
0148 "\n     arguments"
0149 "\n3. All other tests require <db_name> and <driver_id> arguments"
0150 "\n4. 'tables' test automatically runs 'dbcreation' test"
0151 "\n     <new_db_name> is removed if already exists"
0152 "\n5. <db_name> must be a valid database created using KDb,"
0153 "\n     e.g. using the \"tables\" test"
0154 "\n"
0155 "\nArguments:"
0156 "\n  driver_id                 Driver ID, e.g. org.kde.kdb.sqlite;"
0157 "\n                            if a word without \".\" is used,"
0158 "\n                            \"org.kde.kdb.\" will be prepended"
0159 "\n  db_name                   Database name"
0160 "\n  sql_statement             Optional SQL statement (for parser test)"
0161 "\n"
0162 "\nExamples:"
0163 "\n  " APPNAME " -t dr_prop sqlite"
0164 "\n                            Shows properties of the SQLite driver"
0165 "\n  " APPNAME " -p PASSWORD -u USER -t tables mysql mysqltest"
0166 "\n                            Creates database \"mysqltest\" with test"
0167 "\n                            tables and datas"
0168 "\n  " APPNAME " -p PASSWORD -u USER -t tables -h myhost.org \\"
0169 "\n    postgresql pgsqltest"
0170 "\n                            Creates database \"pgsqltest\" with test"
0171 "\n                            tables and data on host \"myhost.org\""
0172 "\n";
0173 }
0174 
0175 int main(int argc, char** argv)
0176 {
0177 //    int minargs = 2;
0178 #ifndef NO_GUI
0179     bool gui = false;
0180 #endif
0181     QFileInfo info = QFileInfo(argv[0]);
0182     prgname = info.baseName().toLatin1();
0183     QStringList args;
0184     for (int i=1; i<argc; i++)
0185         args.append(QFile::decodeName(argv[i]));
0186     if (takeOption(args, "help")) {
0187         showHelp();
0188         return 0;
0189     }
0190     QStringList tests;
0191     tests << "cursors" << "schema" << "dbcreation" << "tables"
0192 #ifndef NO_GUI
0193         << "tableview"
0194 #endif
0195         << "parser" << "dr_prop";
0196     test_name = takeOptionWithArg(args, "test", "t");
0197     if (test_name.isEmpty()) {
0198         qDebug() << "No test specified. Use --help.";
0199         return 1;
0200     }
0201     if (!tests.contains(test_name)) {
0202         qDebug() << QString("No such test \"%1\". Use --help.").arg(test_name);
0203         return finish(1);
0204     }
0205 
0206 #ifndef NO_GUI
0207     if (test_name == "tableview") {
0208         gui = true;
0209     } else
0210 #endif
0211     if (test_name == "parser") {
0212 //        minargs = 3;
0213     } else if (test_name == "dr_prop") {
0214 //        minargs = 1;
0215         db_name_required = false;
0216     }
0217 
0218 #ifndef NO_GUI
0219     if (gui) {
0220         app = new QApplication(argc, argv, true);
0221     } else
0222 #endif
0223     {
0224         app = new QApplication(argc, argv, false);
0225     }
0226 
0227     QString hostName = takeOptionWithArg(args, "host" "h");
0228     if (!hostName.isEmpty()) {
0229         conn_data.setHostName(hostName);
0230     }
0231     QString userName = takeOptionWithArg(args, "user", "u");
0232     if (!userName.isEmpty()) {
0233         conn_data.setUserName(userName);
0234     }
0235     QString password = takeOptionWithArg(args, "password", "p");
0236     if (!password.isEmpty()) {
0237         conn_data.setPassword(password);
0238     }
0239     QString port = takeOptionWithArg(args, "port", "P");
0240     if (!port.isEmpty()) {
0241         bool ok;
0242         conn_data.setPort(port.toInt(&ok));
0243         if (!ok) {
0244             return finish(1);
0245         }
0246     }
0247 
0248     const bool bufCursors = takeOption(args, "buffered-cursors");
0249     QString queryParams = takeOptionWithArg(args, "query-params");
0250 
0251     drv_id = args.first();
0252     if (!drv_id.contains('.')) {
0253         drv_id.prepend(QLatin1String("org.kde.kdb."));
0254     }
0255 
0256     KDbDriverManager manager;
0257     const QStringList driverIds = manager.driverIds();
0258     qDebug() << "DRIVERS: " << driverIds;
0259     if (driverIds.isEmpty()) {
0260         qWarning() << "No drivers found";
0261         return finish(1);
0262     }
0263     if (manager.result().isError()) {
0264         qDebug() << manager.result();
0265         return finish(1);
0266     }
0267 
0268     //get driver
0269     driver = manager.driver(drv_id);
0270     if (!driver || manager.result().isError()) {
0271         qDebug() << manager.result();
0272         return finish(1);
0273     }
0274     if (manager.driverMetaData(drv_id)->isFileBased()) {
0275         qDebug() << "main: MIME types for" << driver->metaData()->id() << ":"
0276                  << driver->metaData()->mimeTypes();
0277     }
0278 
0279     //open connection
0280     if (args.count() >= 2)
0281         db_name = args[1];
0282 
0283     if (db_name_required && db_name.isEmpty()) {
0284         qDebug() << prgname << ": database name?";
0285         return finish(1);
0286     }
0287     conn_data.setDatabaseName(db_name);
0288     if (!db_name.isEmpty() ) {
0289         //additional switches:
0290         if (bufCursors) {
0291             cursor_options |= KDbCursor::Option::Buffered;
0292         }
0293         conn = driver->createConnection(conn_data);
0294 
0295         if (!conn || driver->result().isError()) {
0296             qDebug() << driver->result();
0297             return finish(1);
0298         }
0299         qDebug() << "main: KDbConnection object created.";
0300         if (!conn->connect()) {
0301             qDebug() << conn->result();
0302             return finish(1);
0303         }
0304         qDebug() << "main: KDbConnection::connect() OK.";
0305     }
0306 
0307     //start test:
0308     int r = 0;
0309     if (test_name == "cursors")
0310         r = cursorsTest();
0311     else if (test_name == "schema")
0312         r = schemaTest();
0313     else if (test_name == "dbcreation")
0314         r = dbCreationTest();
0315     else if (test_name == "tables")
0316         r = tablesTest(conn);
0317 #ifndef NO_GUI
0318     else if (test_name == "tableview")
0319         r = tableViewTest();
0320 #endif
0321     else if (test_name == "parser") {
0322         QStringList params;
0323         if (!queryParams.isEmpty())
0324             params = queryParams.split("|");
0325         r = parserTest(KDbEscapedString(args[2]), params);
0326     } else if (test_name == "dr_prop")
0327         r = drPropTest();
0328     else {
0329         qWarning() << "No such test:" << test_name;
0330         qWarning() << "Available tests are:" << tests;
0331 //  usage();
0332         return finish(1);
0333     }
0334 
0335 #ifndef NO_GUI
0336     if (app && r == 0 && gui)
0337         app->exec();
0338 #endif
0339 
0340     if (r)
0341         qDebug() << "RECENT SQL STATEMENT: " << conn->recentSqlString();
0342 
0343     if (conn && !conn->disconnect())
0344         r = 1;
0345 
0346 // qDebug() << "!!! KDbTransaction::globalcount == " << KDbTransaction::globalCount();
0347 // qDebug() << "!!! KDbTransactionData::globalcount == " << KDbTransactionData::globalCount();
0348 
0349     delete app;
0350 
0351     return finish(r);
0352 }