Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativeworkerscript / tst_qdeclarativeworkerscript.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 <QtCore/qdebug.h>
43 #include <QtCore/qtimer.h>
44 #include <QtCore/qdir.h>
45 #include <QtCore/qfileinfo.h>
46 #include <QtDeclarative/qjsengine.h>
47
48 #include <QtDeclarative/qdeclarativecomponent.h>
49 #include <QtDeclarative/qdeclarativeengine.h>
50
51 #include <private/qdeclarativeworkerscript_p.h>
52 #include <private/qdeclarativeengine_p.h>
53 #include "../../shared/util.h"
54
55 class tst_QDeclarativeWorkerScript : public QDeclarativeDataTest
56 {
57     Q_OBJECT
58 public:
59     tst_QDeclarativeWorkerScript() {}
60 private slots:
61     void source();
62     void messaging();
63     void messaging_data();
64     void messaging_sendQObjectList();
65     void messaging_sendJsObject();
66     void messaging_sendExternalObject();
67     void script_with_pragma();
68     void script_included();
69     void scriptError_onLoad();
70     void scriptError_onCall();
71     void stressDispose();
72
73 private:
74     void waitForEchoMessage(QDeclarativeWorkerScript *worker) {
75         QEventLoop loop;
76         QVERIFY(connect(worker, SIGNAL(done()), &loop, SLOT(quit())));
77         QTimer timer;
78         timer.setSingleShot(true);
79         connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
80         timer.start(10000);
81         loop.exec();
82         QVERIFY(timer.isActive());
83     }
84
85     QDeclarativeEngine m_engine;
86 };
87
88 void tst_QDeclarativeWorkerScript::source()
89 {
90     QDeclarativeComponent component(&m_engine, testFileUrl("worker.qml"));
91     QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create());
92     QVERIFY(worker != 0);
93     const QMetaObject *mo = worker->metaObject();
94
95     QVariant value(100);
96     QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
97     waitForEchoMessage(worker);
98     QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>(), value);
99
100     QUrl source = testFileUrl("script_fixed_return.js");
101     worker->setSource(source);
102     QCOMPARE(worker->source(), source);
103     QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
104     waitForEchoMessage(worker);
105     QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>(), qVariantFromValue(QString("Hello_World")));
106
107     qApp->processEvents();
108     delete worker;
109 }
110
111 void tst_QDeclarativeWorkerScript::messaging()
112 {
113     QFETCH(QVariant, value);
114
115     QDeclarativeComponent component(&m_engine, testFileUrl("worker.qml"));
116     QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create());
117     QVERIFY(worker != 0);
118
119     QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
120     waitForEchoMessage(worker);
121
122     const QMetaObject *mo = worker->metaObject();
123     QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>(), value);
124
125     qApp->processEvents();
126     delete worker;
127 }
128
129 void tst_QDeclarativeWorkerScript::messaging_data()
130 {
131     QTest::addColumn<QVariant>("value");
132
133     QTest::newRow("invalid") << QVariant();
134     QTest::newRow("bool") << qVariantFromValue(true);
135     QTest::newRow("int") << qVariantFromValue(1001);
136     QTest::newRow("real") << qVariantFromValue(10334.375);
137     QTest::newRow("string") << qVariantFromValue(QString("More cheeeese, Gromit!"));
138     QTest::newRow("variant list") << qVariantFromValue((QVariantList() << "a" << "b" << "c"));
139     QTest::newRow("date time") << qVariantFromValue(QDateTime::currentDateTime());
140 #ifndef QT_NO_REGEXP
141     // QtScript's QScriptValue -> QRegExp uses RegExp2 pattern syntax
142     QTest::newRow("regexp") << qVariantFromValue(QRegExp("^\\d\\d?$", Qt::CaseInsensitive, QRegExp::RegExp2));
143 #endif
144 }
145
146 void tst_QDeclarativeWorkerScript::messaging_sendQObjectList()
147 {
148     // Not allowed to send QObjects other than QDeclarativeWorkerListModelAgent
149     // instances. If objects are sent in a list, they will be sent as 'undefined'
150     // js values.
151
152     QDeclarativeComponent component(&m_engine, testFileUrl("worker.qml"));
153     QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create());
154     QVERIFY(worker != 0);
155
156     QVariantList objects;
157     for (int i=0; i<3; i++)
158         objects << qVariantFromValue(new QObject(this));
159
160     QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, qVariantFromValue(objects))));
161     waitForEchoMessage(worker);
162
163     const QMetaObject *mo = worker->metaObject();
164     QVariantList result = mo->property(mo->indexOfProperty("response")).read(worker).value<QVariantList>();
165     QCOMPARE(result, (QVariantList() << QVariant() << QVariant() << QVariant()));
166
167     qApp->processEvents();
168     delete worker;
169 }
170
171 void tst_QDeclarativeWorkerScript::messaging_sendJsObject()
172 {
173     QDeclarativeComponent component(&m_engine, testFileUrl("worker.qml"));
174     QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create());
175     QVERIFY(worker != 0);
176
177     // Properties are in alphabetical order to enable string-based comparison after
178     // QVariant roundtrip, since the properties will be stored in a QVariantMap.
179     QString jsObject = "{'haste': 1125, 'name': 'zyz', 'spell power': 3101}";
180
181     QVariantMap map;
182     map.insert("haste", 1125);
183     map.insert("name", "zyz");
184     map.insert("spell power", 3101);
185
186     QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, qVariantFromValue(map))));
187     waitForEchoMessage(worker);
188
189     QVariant result = qVariantFromValue(false);
190     QVERIFY(QMetaObject::invokeMethod(worker, "compareLiteralResponse", Qt::DirectConnection, 
191             Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, jsObject)));
192     QVERIFY(result.toBool());
193
194     qApp->processEvents();
195     delete worker;
196 }
197
198 void tst_QDeclarativeWorkerScript::messaging_sendExternalObject()
199 {
200     QDeclarativeComponent component(&m_engine, testFileUrl("externalObjectWorker.qml"));
201     QObject *obj = component.create();
202     QVERIFY(obj);
203     QMetaObject::invokeMethod(obj, "testExternalObject");
204     QTest::qWait(100); // shouldn't crash.
205     delete obj;
206 }
207
208 void tst_QDeclarativeWorkerScript::script_with_pragma()
209 {
210     QVariant value(100);
211
212     QDeclarativeComponent component(&m_engine, testFileUrl("worker_pragma.qml"));
213     QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create());
214     QVERIFY(worker != 0);
215
216     QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
217     waitForEchoMessage(worker);
218
219     const QMetaObject *mo = worker->metaObject();
220     QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).value<QVariant>(), value);
221
222     qApp->processEvents();
223     delete worker;
224 }
225
226 void tst_QDeclarativeWorkerScript::script_included()
227 {
228     QDeclarativeComponent component(&m_engine, testFileUrl("worker_include.qml"));
229     QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create());
230     QVERIFY(worker != 0);
231
232     QString value("Hello");
233
234     QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
235     waitForEchoMessage(worker);
236
237     const QMetaObject *mo = worker->metaObject();
238     QCOMPARE(mo->property(mo->indexOfProperty("response")).read(worker).toString(), value + " World");
239
240     qApp->processEvents();
241     delete worker;
242 }
243
244 static QString qdeclarativeworkerscript_lastWarning;
245 static void qdeclarativeworkerscript_warningsHandler(QtMsgType type, const char *msg)
246 {
247     if (type == QtWarningMsg)
248          qdeclarativeworkerscript_lastWarning = QString::fromUtf8(msg);
249 }
250
251 void tst_QDeclarativeWorkerScript::scriptError_onLoad()
252 {
253     QDeclarativeComponent component(&m_engine, testFileUrl("worker_error_onLoad.qml"));
254
255     QtMsgHandler previousMsgHandler = qInstallMsgHandler(qdeclarativeworkerscript_warningsHandler);
256     QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create());
257     QVERIFY(worker != 0);
258
259     QTRY_COMPARE(qdeclarativeworkerscript_lastWarning,
260             testFileUrl("script_error_onLoad.js").toString() + QLatin1String(":3: SyntaxError: Unexpected identifier"));
261
262     qInstallMsgHandler(previousMsgHandler);
263     qApp->processEvents();
264     delete worker;
265 }
266
267 void tst_QDeclarativeWorkerScript::scriptError_onCall()
268 {
269     QDeclarativeComponent component(&m_engine, testFileUrl("worker_error_onCall.qml"));
270     QDeclarativeWorkerScript *worker = qobject_cast<QDeclarativeWorkerScript*>(component.create());
271     QVERIFY(worker != 0);
272
273     QtMsgHandler previousMsgHandler = qInstallMsgHandler(qdeclarativeworkerscript_warningsHandler);
274     QVariant value;
275     QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value)));
276
277     QTRY_COMPARE(qdeclarativeworkerscript_lastWarning,
278             testFileUrl("script_error_onCall.js").toString() + QLatin1String(":4: ReferenceError: Can't find variable: getData"));
279
280     qInstallMsgHandler(previousMsgHandler);
281     qApp->processEvents();
282     delete worker;
283 }
284
285 // Rapidly create and destroy worker scripts to test resources are being disposed
286 // in the correct isolate
287 void tst_QDeclarativeWorkerScript::stressDispose()
288 {
289     for (int ii = 0; ii < 100; ++ii) {
290         QDeclarativeEngine engine;
291         QDeclarativeComponent component(&engine, testFileUrl("stressDispose.qml"));
292         QObject *o = component.create();
293         QVERIFY(o);
294         delete o;
295     }
296 }
297
298 QTEST_MAIN(tst_QDeclarativeWorkerScript)
299
300 #include "tst_qdeclarativeworkerscript.moc"