Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativemoduleplugin / tst_qdeclarativemoduleplugin.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 <qdir.h>
43 #include <QtDeclarative/qdeclarativeengine.h>
44 #include <QtDeclarative/qdeclarativecomponent.h>
45 #include <QDebug>
46
47 #include "../../shared/testhttpserver.h"
48 #include "../../shared/util.h"
49
50 #define SERVER_ADDR "http://127.0.0.1:14450"
51 #define SERVER_PORT 14450
52
53
54 class tst_qdeclarativemoduleplugin : public QDeclarativeDataTest
55 {
56     Q_OBJECT
57 public:
58
59 private slots:
60     virtual void initTestCase();
61     void importsPlugin();
62     void importsPlugin2();
63     void importsPlugin21();
64     void importsMixedQmlCppPlugin();
65     void incorrectPluginCase();
66     void importPluginWithQmlFile();
67     void remoteImportWithQuotedUrl();
68     void remoteImportWithUnquotedUri();
69     void versionNotInstalled();
70     void versionNotInstalled_data();
71     void implicitQmldir();
72     void implicitQmldir_data();
73
74 private:
75     QString m_importsDirectory;
76 };
77
78 void tst_qdeclarativemoduleplugin::initTestCase()
79 {
80     QDeclarativeDataTest::initTestCase();
81     m_importsDirectory = directory() + QStringLiteral("/imports");
82     QVERIFY2(QFileInfo(m_importsDirectory).isDir(),
83              qPrintable(QString::fromLatin1("Imports directory '%1' does not exist.").arg(m_importsDirectory)));
84 }
85
86 #define VERIFY_ERRORS(errorfile) \
87     if (!errorfile) { \
88         if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
89             qWarning() << "Unexpected Errors:" << component.errors(); \
90         QVERIFY(!component.isError()); \
91         QVERIFY(component.errors().isEmpty()); \
92     } else { \
93         QString verify_errors_file_name = testFile(errorfile); \
94         QFile file(verify_errors_file_name); \
95         QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \
96         QByteArray data = file.readAll(); \
97         file.close(); \
98         QList<QByteArray> expected = data.split('\n'); \
99         expected.removeAll(QByteArray("")); \
100         QList<QDeclarativeError> errors = component.errors(); \
101         QList<QByteArray> actual; \
102         for (int ii = 0; ii < errors.count(); ++ii) { \
103             const QDeclarativeError &error = errors.at(ii); \
104             QByteArray errorStr = QByteArray::number(error.line()) + ":" +  \
105                                   QByteArray::number(error.column()) + ":" + \
106                                   error.description().toUtf8(); \
107             actual << errorStr; \
108         } \
109         if (qgetenv("DEBUG") != "" && expected != actual) { \
110             qWarning() << "Expected:" << expected << "Actual:" << actual; \
111         } \
112         if (qgetenv("QDECLARATIVELANGUAGE_UPDATEERRORS") != "" && expected != actual) {\
113             QFile file(testFile(errorfile)); \
114             QVERIFY(file.open(QIODevice::WriteOnly)); \
115             for (int ii = 0; ii < actual.count(); ++ii) { \
116                 file.write(actual.at(ii)); file.write("\n"); \
117             } \
118             file.close(); \
119         } else { \
120             QCOMPARE(expected, actual); \
121         } \
122     }
123
124 void tst_qdeclarativemoduleplugin::importsPlugin()
125 {
126     QDeclarativeEngine engine;
127     engine.addImportPath(m_importsDirectory);
128     QTest::ignoreMessage(QtWarningMsg, "plugin created");
129     QTest::ignoreMessage(QtWarningMsg, "import worked");
130     QDeclarativeComponent component(&engine, testFileUrl(QStringLiteral("works.qml")));
131     foreach (QDeclarativeError err, component.errors())
132         qWarning() << err;
133     VERIFY_ERRORS(0);
134     QObject *object = component.create();
135     QVERIFY(object != 0);
136     QCOMPARE(object->property("value").toInt(),123);
137     delete object;
138 }
139
140 void tst_qdeclarativemoduleplugin::importsPlugin2()
141 {
142     QDeclarativeEngine engine;
143     engine.addImportPath(m_importsDirectory);
144     QTest::ignoreMessage(QtWarningMsg, "plugin2 created");
145     QTest::ignoreMessage(QtWarningMsg, "import2 worked");
146     QDeclarativeComponent component(&engine, testFileUrl(QStringLiteral("works2.qml")));
147     foreach (QDeclarativeError err, component.errors())
148         qWarning() << err;
149     VERIFY_ERRORS(0);
150     QObject *object = component.create();
151     QVERIFY(object != 0);
152     QCOMPARE(object->property("value").toInt(),123);
153     delete object;
154 }
155
156 void tst_qdeclarativemoduleplugin::importsPlugin21()
157 {
158     QDeclarativeEngine engine;
159     engine.addImportPath(m_importsDirectory);
160     QTest::ignoreMessage(QtWarningMsg, "plugin2.1 created");
161     QTest::ignoreMessage(QtWarningMsg, "import2.1 worked");
162     QDeclarativeComponent component(&engine, testFileUrl(QStringLiteral("works21.qml")));
163     foreach (QDeclarativeError err, component.errors())
164         qWarning() << err;
165     VERIFY_ERRORS(0);
166     QObject *object = component.create();
167     QVERIFY(object != 0);
168     QCOMPARE(object->property("value").toInt(),123);
169     delete object;
170 }
171
172 void tst_qdeclarativemoduleplugin::incorrectPluginCase()
173 {
174     QDeclarativeEngine engine;
175     engine.addImportPath(m_importsDirectory);
176
177     QDeclarativeComponent component(&engine, testFileUrl(QStringLiteral("incorrectCase.qml")));
178
179     QList<QDeclarativeError> errors = component.errors();
180     QCOMPARE(errors.count(), 1);
181
182 #if defined(Q_OS_MAC) || defined(Q_OS_WIN32)
183 #if defined(Q_OS_MAC)
184     QString libname = "libPluGin.dylib";
185 #elif defined(Q_OS_WIN32)
186     QString libname = "PluGin.dll";
187 #endif
188     QString expectedError = QLatin1String("plugin cannot be loaded for module \"com.nokia.WrongCase\": File name case mismatch for \"") + QDir(m_importsDirectory).filePath("com/nokia/WrongCase/" + libname) + QLatin1String("\"");
189 #else
190     QString expectedError = QLatin1String("module \"com.nokia.WrongCase\" plugin \"PluGin\" not found");
191 #endif
192
193     QCOMPARE(errors.at(0).description(), expectedError);
194 }
195
196 void tst_qdeclarativemoduleplugin::importPluginWithQmlFile()
197 {
198     QString path = m_importsDirectory;
199
200     // QTBUG-16885: adding an import path with a lower-case "c:" causes assert failure
201     // (this only happens if the plugin includes pure QML files)
202     #ifdef Q_OS_WIN
203         QVERIFY(path.at(0).isUpper() && path.at(1) == QLatin1Char(':'));
204         path = path.at(0).toLower() + path.mid(1);
205     #endif
206
207     QDeclarativeEngine engine;
208     engine.addImportPath(path);
209
210     QDeclarativeComponent component(&engine, testFileUrl(QStringLiteral("pluginWithQmlFile.qml")));
211     foreach (QDeclarativeError err, component.errors())
212         qWarning() << err;
213     VERIFY_ERRORS(0);
214     QObject *object = component.create();
215     QVERIFY(object != 0);
216     delete object;
217 }
218
219 void tst_qdeclarativemoduleplugin::remoteImportWithQuotedUrl()
220 {
221     TestHTTPServer server(SERVER_PORT);
222     QVERIFY(server.isValid());
223     server.serveDirectory(m_importsDirectory);
224
225     QDeclarativeEngine engine;
226     QDeclarativeComponent component(&engine);
227     component.setData("import \"http://127.0.0.1:14450/com/nokia/PureQmlModule\" \nComponentA { width: 300; ComponentB{} }", QUrl());
228
229     QTRY_COMPARE(component.status(), QDeclarativeComponent::Ready);
230     QObject *object = component.create();
231     QCOMPARE(object->property("width").toInt(), 300);
232     QVERIFY(object != 0);
233     delete object;
234
235     foreach (QDeclarativeError err, component.errors())
236         qWarning() << err;
237     VERIFY_ERRORS(0);
238 }
239
240 void tst_qdeclarativemoduleplugin::remoteImportWithUnquotedUri()
241 {
242     TestHTTPServer server(SERVER_PORT);
243     QVERIFY(server.isValid());
244     server.serveDirectory(m_importsDirectory);
245
246     QDeclarativeEngine engine;
247     engine.addImportPath(m_importsDirectory);
248     QDeclarativeComponent component(&engine);
249     component.setData("import com.nokia.PureQmlModule 1.0 \nComponentA { width: 300; ComponentB{} }", QUrl());
250
251
252     QTRY_COMPARE(component.status(), QDeclarativeComponent::Ready);
253     QObject *object = component.create();
254     QVERIFY(object != 0);
255     QCOMPARE(object->property("width").toInt(), 300);
256     delete object;
257
258     foreach (QDeclarativeError err, component.errors())
259         qWarning() << err;
260     VERIFY_ERRORS(0);
261 }
262
263 // QTBUG-17324
264
265 void tst_qdeclarativemoduleplugin::importsMixedQmlCppPlugin()
266 {
267     QDeclarativeEngine engine;
268     engine.addImportPath(m_importsDirectory);
269
270     {
271     QDeclarativeComponent component(&engine, testFileUrl(QStringLiteral("importsMixedQmlCppPlugin.qml")));
272
273     QObject *o = component.create();
274     QVERIFY2(o != 0, QDeclarativeDataTest::msgComponentError(component, &engine));
275     QCOMPARE(o->property("test").toBool(), true);
276     delete o;
277     }
278
279     {
280     QDeclarativeComponent component(&engine, testFileUrl(QStringLiteral("importsMixedQmlCppPlugin.2.qml")));
281
282     QObject *o = component.create();
283     QVERIFY2(o != 0, QDeclarativeDataTest::msgComponentError(component, &engine));
284     QCOMPARE(o->property("test").toBool(), true);
285     QCOMPARE(o->property("test2").toBool(), true);
286     delete o;
287     }
288
289
290 }
291
292 void tst_qdeclarativemoduleplugin::versionNotInstalled_data()
293 {
294     QTest::addColumn<QString>("file");
295     QTest::addColumn<QString>("errorFile");
296
297     QTest::newRow("versionNotInstalled") << "versionNotInstalled.qml" << "versionNotInstalled.errors.txt";
298     QTest::newRow("versionNotInstalled") << "versionNotInstalled.2.qml" << "versionNotInstalled.2.errors.txt";
299 }
300
301 void tst_qdeclarativemoduleplugin::versionNotInstalled()
302 {
303     QFETCH(QString, file);
304     QFETCH(QString, errorFile);
305
306     QDeclarativeEngine engine;
307     engine.addImportPath(m_importsDirectory);
308
309     QDeclarativeComponent component(&engine, testFileUrl(file));
310     VERIFY_ERRORS(errorFile.toLatin1().constData());
311 }
312
313
314 // test that errors are reporting correctly for plugin loading and qmldir parsing
315 void tst_qdeclarativemoduleplugin::implicitQmldir_data()
316 {
317     QTest::addColumn<QString>("directory");
318     QTest::addColumn<QString>("file");
319     QTest::addColumn<QString>("errorFile");
320
321     // parsing qmldir succeeds, but plugin specified in the qmldir file doesn't exist
322     QTest::newRow("implicitQmldir") << "implicit1" << "temptest.qml" << "implicitQmldir.errors.txt";
323
324     // parsing qmldir fails due to syntax errors, etc.
325     QTest::newRow("implicitQmldir2") << "implicit2" << "temptest2.qml" << "implicitQmldir.2.errors.txt";
326 }
327 void tst_qdeclarativemoduleplugin::implicitQmldir()
328 {
329     QFETCH(QString, directory);
330     QFETCH(QString, file);
331     QFETCH(QString, errorFile);
332
333     QString importPath = testFile(directory);
334     QString fileName = directory + QDir::separator() + file;
335     QString errorFileName = directory + QDir::separator() + errorFile;
336     QUrl testUrl = testFileUrl(fileName);
337
338     QDeclarativeEngine engine;
339     engine.addImportPath(importPath);
340
341     QDeclarativeComponent component(&engine, testUrl);
342     QList<QDeclarativeError> errors = component.errors();
343     VERIFY_ERRORS(errorFileName.toLatin1().constData());
344     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeComponent: Component is not ready");
345     QObject *obj = component.create();
346     QVERIFY(!obj);
347     delete obj;
348 }
349
350
351 QTEST_MAIN(tst_qdeclarativemoduleplugin)
352
353 #include "tst_qdeclarativemoduleplugin.moc"