04fc5e1c7c8030421254b304f6682a0636f565f1
[profile/ivi/qtdeclarative.git] / tests / auto / qml / qqmlsqldatabase / tst_qqmlsqldatabase.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
42 #include <QtQml/qqmlengine.h>
43 #include <QtQml/qqmlcomponent.h>
44 #include <QtQuick/private/qquicktext_p.h>
45 #include <private/qqmlengine_p.h>
46 #include <QtCore/qcryptographichash.h>
47 /*
48 #include <QtWebKit/qwebpage.h>
49 #include <QtWebKit/qwebframe.h>
50 #include <QtWebKit/qwebdatabase.h>
51 #include <QtWebKit/qwebsecurityorigin.h>
52 */
53 #include <QtSql/qsqldatabase.h>
54 #include <QtCore/qdir.h>
55 #include <QtCore/qfile.h>
56 #include "../../shared/util.h"
57
58 class tst_qqmlsqldatabase : public QQmlDataTest
59 {
60     Q_OBJECT
61 public:
62     tst_qqmlsqldatabase()
63     {
64         qApp->setApplicationName("tst_qqmlsqldatabase");
65         qApp->setOrganizationName("Nokia");
66         qApp->setOrganizationDomain("nokia.com");
67         engine = new QQmlEngine;
68     }
69
70     ~tst_qqmlsqldatabase()
71     {
72         delete engine;
73     }
74
75 private slots:
76     void initTestCase();
77
78     void checkDatabasePath();
79
80     void testQml_data();
81     void testQml();
82     void testQml_cleanopen_data();
83     void testQml_cleanopen();
84     void totalDatabases();
85
86     void cleanupTestCase();
87
88 private:
89     QString dbDir() const;
90     QQmlEngine *engine;
91 };
92
93 void removeRecursive(const QString& dirname)
94 {
95     QDir dir(dirname);
96     QFileInfoList entries(dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot));
97     for (int i = 0; i < entries.count(); ++i)
98         if (entries[i].isDir())
99             removeRecursive(entries[i].filePath());
100         else
101             dir.remove(entries[i].fileName());
102     QDir().rmdir(dirname);
103 }
104
105 void tst_qqmlsqldatabase::initTestCase()
106 {
107     if (engine->offlineStoragePath().isEmpty())
108         QSKIP("offlineStoragePath is empty, skip this test.");
109     QQmlDataTest::initTestCase();
110     removeRecursive(dbDir());
111     QDir().mkpath(dbDir());
112 }
113
114 void tst_qqmlsqldatabase::cleanupTestCase()
115 {
116     if (engine->offlineStoragePath().isEmpty())
117         QSKIP("offlineStoragePath is empty, skip this test.");
118     removeRecursive(dbDir());
119 }
120
121 QString tst_qqmlsqldatabase::dbDir() const
122 {
123     static QString tmpd = QDir::tempPath()+"/tst_qqmlsqldatabase_output-"
124         + QDateTime::currentDateTime().toString(QLatin1String("yyyyMMddhhmmss"));
125     return tmpd;
126 }
127
128 void tst_qqmlsqldatabase::checkDatabasePath()
129 {
130     if (engine->offlineStoragePath().isEmpty())
131         QSKIP("offlineStoragePath is empty, skip this test.");
132
133     // Check default storage path (we can't use it since we don't want to mess with user's data)
134     QVERIFY(engine->offlineStoragePath().contains("tst_qqmlsqldatabase"));
135     QVERIFY(engine->offlineStoragePath().contains("OfflineStorage"));
136 }
137
138 static const int total_databases_created_by_tests = 12;
139 void tst_qqmlsqldatabase::testQml_data()
140 {
141     QTest::addColumn<QString>("jsfile"); // The input file
142
143     // Each test should use a newly named DB to avoid inter-test dependencies
144     QTest::newRow("creation") << "creation.js";
145     QTest::newRow("creation-a") << "creation-a.js";
146     QTest::newRow("creation") << "creation.js";
147     QTest::newRow("error-creation") << "error-creation.js"; // re-uses above DB
148     QTest::newRow("changeversion") << "changeversion.js";
149     QTest::newRow("readonly") << "readonly.js";
150     QTest::newRow("readonly-error") << "readonly-error.js";
151     QTest::newRow("selection") << "selection.js";
152     QTest::newRow("selection-bindnames") << "selection-bindnames.js";
153     QTest::newRow("iteration") << "iteration.js";
154     QTest::newRow("iteration-forwardonly") << "iteration-forwardonly.js";
155     QTest::newRow("error-a") << "error-a.js";
156     QTest::newRow("error-notransaction") << "error-notransaction.js";
157     QTest::newRow("error-outsidetransaction") << "error-outsidetransaction.js"; // reuse above
158     QTest::newRow("reopen1") << "reopen1.js";
159     QTest::newRow("reopen2") << "reopen2.js"; // re-uses above DB
160
161     // If you add a test, you should usually use a new database in the
162     // test - in which case increment total_databases_created_by_tests above.
163 }
164
165 /*
166 class QWebPageWithJavaScriptConsoleMessages : public QWebPage {
167 public:
168     void javaScriptConsoleMessage(const QString& message, int lineNumber, const QString& sourceID)
169     {
170         qWarning() << sourceID << ":" << lineNumber << ":" << message;
171     }
172 };
173
174 void tst_qqmlsqldatabase::validateAgainstWebkit()
175 {
176     // Validates tests against WebKit (HTML5) support.
177     //
178     QFETCH(QString, jsfile);
179     QFETCH(QString, result);
180     QFETCH(int, databases);
181
182     QFile f(jsfile);
183     QVERIFY(f.open(QIODevice::ReadOnly));
184     QString js=f.readAll();
185
186     QWebPageWithJavaScriptConsoleMessages webpage;
187     webpage.settings()->setOfflineStoragePath(dbDir());
188     webpage.settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true);
189
190     QEXPECT_FAIL("","WebKit doesn't support openDatabaseSync yet", Continue);
191     QCOMPARE(webpage.mainFrame()->evaluateJavaScript(js).toString(),result);
192
193     QTest::qWait(100); // WebKit crashes if you quit it too fast
194
195     QWebSecurityOrigin origin = webpage.mainFrame()->securityOrigin();
196     QList<QWebDatabase> dbs = origin.databases();
197     QCOMPARE(dbs.count(), databases);
198 }
199 */
200
201 void tst_qqmlsqldatabase::testQml()
202 {
203     if (engine->offlineStoragePath().isEmpty())
204         QSKIP("offlineStoragePath is empty, skip this test.");
205
206     // Tests QML SQL Database support with tests
207     // that have been validated against Webkit.
208     //
209     QFETCH(QString, jsfile);
210
211     QString qml=
212         "import QtQuick 2.0\n"
213         "import \""+jsfile+"\" as JS\n"
214         "Text { text: JS.test() }";
215
216     engine->setOfflineStoragePath(dbDir());
217     QQmlComponent component(engine);
218     component.setData(qml.toUtf8(), testFileUrl("empty.qml")); // just a file for relative local imports
219     QVERIFY(!component.isError());
220     QQuickText *text = qobject_cast<QQuickText*>(component.create());
221     QVERIFY(text != 0);
222     QCOMPARE(text->text(),QString("passed"));
223 }
224
225 void tst_qqmlsqldatabase::testQml_cleanopen_data()
226 {
227     QTest::addColumn<QString>("jsfile"); // The input file
228     QTest::newRow("reopen1") << "reopen1.js";
229     QTest::newRow("reopen2") << "reopen2.js";
230     QTest::newRow("error-creation") << "error-creation.js"; // re-uses creation DB
231 }
232
233 void tst_qqmlsqldatabase::testQml_cleanopen()
234 {
235     if (engine->offlineStoragePath().isEmpty())
236         QSKIP("offlineStoragePath is empty, skip this test.");
237
238     // Same as testQml, but clean connections between tests,
239     // making it more like the tests are running in new processes.
240     testQml();
241
242     engine->collectGarbage();
243
244     foreach (QString dbname, QSqlDatabase::connectionNames()) {
245         QSqlDatabase::removeDatabase(dbname);
246     }
247 }
248
249 void tst_qqmlsqldatabase::totalDatabases()
250 {
251     if (engine->offlineStoragePath().isEmpty())
252         QSKIP("offlineStoragePath is empty, skip this test.");
253
254     QCOMPARE(QDir(dbDir()+"/Databases").entryInfoList(QDir::Files|QDir::NoDotAndDotDot).count(), total_databases_created_by_tests*2);
255 }
256
257 QTEST_MAIN(tst_qqmlsqldatabase)
258
259 #include "tst_qqmlsqldatabase.moc"