1f9a13d444ed5cc4524e5b8346cca11186c7f914
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativeengine / tst_qdeclarativeengine.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <qtest.h>
43 #include <QDeclarativeEngine>
44 #include <QDeclarativeContext>
45 #include <QNetworkAccessManager>
46 #include <QPointer>
47 #include <QDir>
48 #include <QStandardPaths>
49 #include <QDebug>
50 #include <QDeclarativeComponent>
51 #include <QDeclarativeNetworkAccessManagerFactory>
52 #include <QDeclarativeExpression>
53
54 class tst_qdeclarativeengine : public QObject
55 {
56     Q_OBJECT
57 public:
58     tst_qdeclarativeengine() {}
59
60 private slots:
61     void rootContext();
62     void networkAccessManager();
63     void baseUrl();
64     void contextForObject();
65     void offlineStoragePath();
66     void clearComponentCache();
67     void outputWarningsToStandardError();
68     void objectOwnership();
69     void multipleEngines();
70 };
71
72 void tst_qdeclarativeengine::rootContext()
73 {
74     QDeclarativeEngine engine;
75
76     QVERIFY(engine.rootContext());
77
78     QCOMPARE(engine.rootContext()->engine(), &engine);
79     QVERIFY(engine.rootContext()->parentContext() == 0);
80 }
81
82 class NetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory
83 {
84 public:
85     NetworkAccessManagerFactory() : manager(0) {}
86
87     QNetworkAccessManager *create(QObject *parent) {
88         manager = new QNetworkAccessManager(parent);
89         return manager;
90     }
91
92     QNetworkAccessManager *manager;
93 };
94
95 void tst_qdeclarativeengine::networkAccessManager()
96 {
97     QDeclarativeEngine *engine = new QDeclarativeEngine;
98
99     // Test QDeclarativeEngine created manager
100     QPointer<QNetworkAccessManager> manager = engine->networkAccessManager();
101     QVERIFY(manager != 0);
102     delete engine;
103
104     // Test factory created manager
105     engine = new QDeclarativeEngine;
106     NetworkAccessManagerFactory factory;
107     engine->setNetworkAccessManagerFactory(&factory);
108     QVERIFY(engine->networkAccessManagerFactory() == &factory);
109     QVERIFY(engine->networkAccessManager() == factory.manager);
110     delete engine;
111 }
112
113 void tst_qdeclarativeengine::baseUrl()
114 {
115     QDeclarativeEngine engine;
116
117     QUrl cwd = QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
118
119     QCOMPARE(engine.baseUrl(), cwd);
120     QCOMPARE(engine.rootContext()->resolvedUrl(QUrl("main.qml")), cwd.resolved(QUrl("main.qml")));
121
122     QDir dir = QDir::current();
123     dir.cdUp();
124     QVERIFY(dir != QDir::current());
125     QDir::setCurrent(dir.path());
126     QVERIFY(QDir::current() == dir);
127
128     QUrl cwd2 = QUrl::fromLocalFile(QDir::currentPath() + QDir::separator());
129     QCOMPARE(engine.baseUrl(), cwd2);
130     QCOMPARE(engine.rootContext()->resolvedUrl(QUrl("main.qml")), cwd2.resolved(QUrl("main.qml")));
131
132     engine.setBaseUrl(cwd);
133     QCOMPARE(engine.baseUrl(), cwd);
134     QCOMPARE(engine.rootContext()->resolvedUrl(QUrl("main.qml")), cwd.resolved(QUrl("main.qml")));
135 }
136
137 void tst_qdeclarativeengine::contextForObject()
138 {
139     QDeclarativeEngine *engine = new QDeclarativeEngine;
140
141     // Test null-object
142     QVERIFY(QDeclarativeEngine::contextForObject(0) == 0);
143
144     // Test an object with no context
145     QObject object;
146     QVERIFY(QDeclarativeEngine::contextForObject(&object) == 0);
147
148     // Test setting null-object
149     QDeclarativeEngine::setContextForObject(0, engine->rootContext());
150
151     // Test setting null-context
152     QDeclarativeEngine::setContextForObject(&object, 0);
153
154     // Test setting context
155     QDeclarativeEngine::setContextForObject(&object, engine->rootContext());
156     QVERIFY(QDeclarativeEngine::contextForObject(&object) == engine->rootContext());
157
158     QDeclarativeContext context(engine->rootContext());
159
160     // Try changing context
161     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeEngine::setContextForObject(): Object already has a QDeclarativeContext");
162     QDeclarativeEngine::setContextForObject(&object, &context);
163     QVERIFY(QDeclarativeEngine::contextForObject(&object) == engine->rootContext());
164
165     // Delete context
166     delete engine; engine = 0;
167     QVERIFY(QDeclarativeEngine::contextForObject(&object) == 0);
168 }
169
170 void tst_qdeclarativeengine::offlineStoragePath()
171 {
172     // Without these set, QDesktopServices::storageLocation returns
173     // strings with extra "//" at the end. We set them to ignore this problem.
174     qApp->setApplicationName("tst_qdeclarativeengine");
175     qApp->setOrganizationName("Nokia");
176     qApp->setOrganizationDomain("nokia.com");
177
178     QDeclarativeEngine engine;
179
180     QDir dir(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
181     dir.mkpath("QML");
182     dir.cd("QML");
183     dir.mkpath("OfflineStorage");
184     dir.cd("OfflineStorage");
185
186     QCOMPARE(QDir::fromNativeSeparators(engine.offlineStoragePath()), dir.path());
187
188     engine.setOfflineStoragePath(QDir::homePath());
189     QCOMPARE(engine.offlineStoragePath(), QDir::homePath());
190 }
191
192 void tst_qdeclarativeengine::clearComponentCache()
193 {
194     QDeclarativeEngine engine;
195
196     // Create original qml file
197     {
198         QFile file("temp.qml");
199         QVERIFY(file.open(QIODevice::WriteOnly));
200         file.write("import QtQuick 1.0\nQtObject {\nproperty int test: 10\n}\n");
201         file.close();
202     }
203
204     // Test "test" property
205     {
206         QDeclarativeComponent component(&engine, "temp.qml");
207         QObject *obj = component.create();
208         QVERIFY(obj != 0);
209         QCOMPARE(obj->property("test").toInt(), 10);
210         delete obj;
211     }
212
213     // Modify qml file
214     {
215         QFile file("temp.qml");
216         QVERIFY(file.open(QIODevice::WriteOnly));
217         file.write("import QtQuick 1.0\nQtObject {\nproperty int test: 11\n}\n");
218         file.close();
219     }
220
221     // Test cache hit
222     {
223         QDeclarativeComponent component(&engine, "temp.qml");
224         QObject *obj = component.create();
225         QVERIFY(obj != 0);
226         QCOMPARE(obj->property("test").toInt(), 10);
227         delete obj;
228     }
229
230     // Clear cache
231     engine.clearComponentCache();
232
233     // Test cache refresh
234     {
235         QDeclarativeComponent component(&engine, "temp.qml");
236         QObject *obj = component.create();
237         QVERIFY(obj != 0);
238         QCOMPARE(obj->property("test").toInt(), 11);
239         delete obj;
240     }
241 }
242
243 static QStringList warnings;
244 static void msgHandler(QtMsgType, const char *warning)
245 {
246     warnings << QString::fromUtf8(warning);
247 }
248
249 void tst_qdeclarativeengine::outputWarningsToStandardError()
250 {
251     QDeclarativeEngine engine;
252
253     QCOMPARE(engine.outputWarningsToStandardError(), true);
254
255     QDeclarativeComponent c(&engine);
256     c.setData("import QtQuick 1.0; QtObject { property int a: undefined }", QUrl());
257
258     QVERIFY(c.isReady() == true);
259
260     warnings.clear();
261     QtMsgHandler old = qInstallMsgHandler(msgHandler);
262
263     QObject *o = c.create();
264
265     qInstallMsgHandler(old);
266
267     QVERIFY(o != 0);
268     delete o;
269
270     QCOMPARE(warnings.count(), 1);
271     QCOMPARE(warnings.at(0), QLatin1String("<Unknown File>:1: Unable to assign [undefined] to int"));
272     warnings.clear();
273
274
275     engine.setOutputWarningsToStandardError(false);
276     QCOMPARE(engine.outputWarningsToStandardError(), false);
277
278
279     old = qInstallMsgHandler(msgHandler);
280
281     o = c.create();
282
283     qInstallMsgHandler(old);
284
285     QVERIFY(o != 0);
286     delete o;
287
288     QCOMPARE(warnings.count(), 0);
289 }
290
291 void tst_qdeclarativeengine::objectOwnership()
292 {
293     {
294     QCOMPARE(QDeclarativeEngine::objectOwnership(0), QDeclarativeEngine::CppOwnership);
295     QDeclarativeEngine::setObjectOwnership(0, QDeclarativeEngine::JavaScriptOwnership);
296     QCOMPARE(QDeclarativeEngine::objectOwnership(0), QDeclarativeEngine::CppOwnership);
297     }
298
299     {
300     QObject o;
301     QCOMPARE(QDeclarativeEngine::objectOwnership(&o), QDeclarativeEngine::CppOwnership);
302     QDeclarativeEngine::setObjectOwnership(&o, QDeclarativeEngine::CppOwnership);
303     QCOMPARE(QDeclarativeEngine::objectOwnership(&o), QDeclarativeEngine::CppOwnership);
304     QDeclarativeEngine::setObjectOwnership(&o, QDeclarativeEngine::JavaScriptOwnership);
305     QCOMPARE(QDeclarativeEngine::objectOwnership(&o), QDeclarativeEngine::JavaScriptOwnership);
306     QDeclarativeEngine::setObjectOwnership(&o, QDeclarativeEngine::CppOwnership);
307     QCOMPARE(QDeclarativeEngine::objectOwnership(&o), QDeclarativeEngine::CppOwnership);
308     }
309
310     {
311     QDeclarativeEngine engine;
312     QDeclarativeComponent c(&engine);
313     c.setData("import QtQuick 1.0; QtObject { property QtObject object: QtObject {} }", QUrl());
314
315     QObject *o = c.create();
316     QVERIFY(o != 0);
317
318     QCOMPARE(QDeclarativeEngine::objectOwnership(o), QDeclarativeEngine::CppOwnership);
319
320     QObject *o2 = qvariant_cast<QObject *>(o->property("object"));
321     QCOMPARE(QDeclarativeEngine::objectOwnership(o2), QDeclarativeEngine::JavaScriptOwnership);
322
323     delete o;
324     }
325
326 }
327
328 // Test an object can be accessed by multiple engines
329 void tst_qdeclarativeengine::multipleEngines()
330 {
331     QObject o;
332     o.setObjectName("TestName");
333
334     // Simultaneous engines
335     {
336         QDeclarativeEngine engine1;
337         QDeclarativeEngine engine2;
338         engine1.rootContext()->setContextProperty("object", &o);
339         engine2.rootContext()->setContextProperty("object", &o);
340
341         QDeclarativeExpression expr1(engine1.rootContext(), 0, QString("object.objectName"));
342         QDeclarativeExpression expr2(engine2.rootContext(), 0, QString("object.objectName"));
343
344         QCOMPARE(expr1.evaluate().toString(), QString("TestName"));
345         QCOMPARE(expr2.evaluate().toString(), QString("TestName"));
346     }
347
348     // Serial engines
349     {
350         QDeclarativeEngine engine1;
351         engine1.rootContext()->setContextProperty("object", &o);
352         QDeclarativeExpression expr1(engine1.rootContext(), 0, QString("object.objectName"));
353         QCOMPARE(expr1.evaluate().toString(), QString("TestName"));
354     }
355     {
356         QDeclarativeEngine engine1;
357         engine1.rootContext()->setContextProperty("object", &o);
358         QDeclarativeExpression expr1(engine1.rootContext(), 0, QString("object.objectName"));
359         QCOMPARE(expr1.evaluate().toString(), QString("TestName"));
360     }
361 }
362
363 QTEST_MAIN(tst_qdeclarativeengine)
364
365 #include "tst_qdeclarativeengine.moc"