Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativecontext / tst_qdeclarativecontext.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
42 #include <qtest.h>
43 #include <QDebug>
44 #include <QDeclarativeEngine>
45 #include <QDeclarativeContext>
46 #include <QDeclarativeComponent>
47 #include <QDeclarativeExpression>
48 #include <private/qdeclarativecontext_p.h>
49 #include "../../shared/util.h"
50
51 class tst_qdeclarativecontext : public QDeclarativeDataTest
52 {
53     Q_OBJECT
54 public:
55     tst_qdeclarativecontext() {}
56
57 private slots:
58     void baseUrl();
59     void resolvedUrl();
60     void engineMethod();
61     void parentContext();
62     void setContextProperty();
63     void setContextObject();
64     void destruction();
65     void idAsContextProperty();
66     void readOnlyContexts();
67     void nameForObject();
68
69     void refreshExpressions();
70     void refreshExpressionsCrash();
71     void refreshExpressionsRootContext();
72
73     void qtbug_22535();
74 private:
75     QDeclarativeEngine engine;
76 };
77
78 void tst_qdeclarativecontext::baseUrl()
79 {
80     QDeclarativeContext ctxt(&engine);
81
82     QCOMPARE(ctxt.baseUrl(), QUrl());
83
84     ctxt.setBaseUrl(QUrl("http://www.nokia.com/"));
85
86     QCOMPARE(ctxt.baseUrl(), QUrl("http://www.nokia.com/"));
87 }
88
89 void tst_qdeclarativecontext::resolvedUrl()
90 {
91     // Relative to the component
92     {
93         QDeclarativeContext ctxt(&engine);
94         ctxt.setBaseUrl(QUrl("http://www.nokia.com/"));
95
96         QCOMPARE(ctxt.resolvedUrl(QUrl("main.qml")), QUrl("http://www.nokia.com/main.qml"));
97     }
98
99     // Relative to a parent
100     {
101         QDeclarativeContext ctxt(&engine);
102         ctxt.setBaseUrl(QUrl("http://www.nokia.com/"));
103
104         QDeclarativeContext ctxt2(&ctxt);
105         QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
106     }
107
108     // Relative to the engine
109     {
110         QDeclarativeContext ctxt(&engine);
111         QCOMPARE(ctxt.resolvedUrl(QUrl("main.qml")), engine.baseUrl().resolved(QUrl("main.qml")));
112     }
113
114     // Relative to a deleted parent
115     {
116         QDeclarativeContext *ctxt = new QDeclarativeContext(&engine);
117         ctxt->setBaseUrl(QUrl("http://www.nokia.com/"));
118
119         QDeclarativeContext ctxt2(ctxt);
120         QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
121
122         delete ctxt; ctxt = 0;
123
124         QCOMPARE(ctxt2.resolvedUrl(QUrl("main2.qml")), QUrl());
125     }
126
127     // Absolute
128     {
129         QDeclarativeContext ctxt(&engine);
130
131         QCOMPARE(ctxt.resolvedUrl(QUrl("http://www.nokia.com/main2.qml")), QUrl("http://www.nokia.com/main2.qml"));
132         QCOMPARE(ctxt.resolvedUrl(QUrl("file:///main2.qml")), QUrl("file:///main2.qml"));
133     }
134 }
135
136 void tst_qdeclarativecontext::engineMethod()
137 {
138     QDeclarativeEngine *engine = new QDeclarativeEngine;
139
140     QDeclarativeContext ctxt(engine);
141     QDeclarativeContext ctxt2(&ctxt);
142     QDeclarativeContext ctxt3(&ctxt2);
143     QDeclarativeContext ctxt4(&ctxt2);
144
145     QCOMPARE(ctxt.engine(), engine);
146     QCOMPARE(ctxt2.engine(), engine);
147     QCOMPARE(ctxt3.engine(), engine);
148     QCOMPARE(ctxt4.engine(), engine);
149
150     delete engine; engine = 0;
151
152     QCOMPARE(ctxt.engine(), engine);
153     QCOMPARE(ctxt2.engine(), engine);
154     QCOMPARE(ctxt3.engine(), engine);
155     QCOMPARE(ctxt4.engine(), engine);
156 }
157
158 void tst_qdeclarativecontext::parentContext()
159 {
160     QDeclarativeEngine *engine = new QDeclarativeEngine;
161
162     QCOMPARE(engine->rootContext()->parentContext(), (QDeclarativeContext *)0);
163
164     QDeclarativeContext *ctxt = new QDeclarativeContext(engine);
165     QDeclarativeContext *ctxt2 = new QDeclarativeContext(ctxt);
166     QDeclarativeContext *ctxt3 = new QDeclarativeContext(ctxt2);
167     QDeclarativeContext *ctxt4 = new QDeclarativeContext(ctxt2);
168     QDeclarativeContext *ctxt5 = new QDeclarativeContext(ctxt);
169     QDeclarativeContext *ctxt6 = new QDeclarativeContext(engine);
170     QDeclarativeContext *ctxt7 = new QDeclarativeContext(engine->rootContext());
171
172     QCOMPARE(ctxt->parentContext(), engine->rootContext());
173     QCOMPARE(ctxt2->parentContext(), ctxt);
174     QCOMPARE(ctxt3->parentContext(), ctxt2);
175     QCOMPARE(ctxt4->parentContext(), ctxt2);
176     QCOMPARE(ctxt5->parentContext(), ctxt);
177     QCOMPARE(ctxt6->parentContext(), engine->rootContext());
178     QCOMPARE(ctxt7->parentContext(), engine->rootContext());
179
180     delete ctxt2; ctxt2 = 0;
181
182     QCOMPARE(ctxt->parentContext(), engine->rootContext());
183     QCOMPARE(ctxt3->parentContext(), (QDeclarativeContext *)0);
184     QCOMPARE(ctxt4->parentContext(), (QDeclarativeContext *)0);
185     QCOMPARE(ctxt5->parentContext(), ctxt);
186     QCOMPARE(ctxt6->parentContext(), engine->rootContext());
187     QCOMPARE(ctxt7->parentContext(), engine->rootContext());
188
189     delete engine; engine = 0;
190
191     QCOMPARE(ctxt->parentContext(), (QDeclarativeContext *)0);
192     QCOMPARE(ctxt3->parentContext(), (QDeclarativeContext *)0);
193     QCOMPARE(ctxt4->parentContext(), (QDeclarativeContext *)0);
194     QCOMPARE(ctxt5->parentContext(), (QDeclarativeContext *)0);
195     QCOMPARE(ctxt6->parentContext(), (QDeclarativeContext *)0);
196     QCOMPARE(ctxt7->parentContext(), (QDeclarativeContext *)0);
197
198     delete ctxt7;
199     delete ctxt6;
200     delete ctxt5;
201     delete ctxt4;
202     delete ctxt3;
203     delete ctxt;
204 }
205
206 class TestObject : public QObject
207 {
208     Q_OBJECT
209     Q_PROPERTY(int a READ a NOTIFY aChanged)
210     Q_PROPERTY(int b READ b NOTIFY bChanged)
211     Q_PROPERTY(int c READ c NOTIFY cChanged)
212
213 public:
214     TestObject() : _a(10), _b(10), _c(10) {}
215
216     int a() const { return _a; }
217     void setA(int a) { _a = a; emit aChanged(); }
218
219     int b() const { return _b; }
220     void setB(int b) { _b = b; emit bChanged(); }
221
222     int c() const { return _c; }
223     void setC(int c) { _c = c; emit cChanged(); }
224
225 signals:
226     void aChanged();
227     void bChanged();
228     void cChanged();
229
230 private:
231     int _a;
232     int _b;
233     int _c;
234 };
235
236 #define TEST_CONTEXT_PROPERTY(ctxt, name, value) \
237 { \
238     QDeclarativeComponent component(&engine); \
239     component.setData("import QtQuick 1.0; QtObject { property variant test: " #name " }", QUrl()); \
240 \
241     QObject *obj = component.create(ctxt); \
242 \
243     QCOMPARE(obj->property("test"), value); \
244 \
245     delete obj; \
246
247
248 void tst_qdeclarativecontext::setContextProperty()
249 {
250     QDeclarativeContext ctxt(&engine);
251     QDeclarativeContext ctxt2(&ctxt);
252
253     TestObject obj1;
254     obj1.setA(3345);
255     TestObject obj2;
256     obj2.setA(-19);
257
258     // Static context properties
259     ctxt.setContextProperty("a", QVariant(10));
260     ctxt.setContextProperty("b", QVariant(9));
261     ctxt2.setContextProperty("d", &obj2);
262     ctxt2.setContextProperty("b", QVariant(19));
263     ctxt2.setContextProperty("c", QVariant(QString("Hello World!")));
264     ctxt.setContextProperty("d", &obj1);
265     ctxt.setContextProperty("e", &obj1);
266
267     TEST_CONTEXT_PROPERTY(&ctxt2, a, QVariant(10));
268     TEST_CONTEXT_PROPERTY(&ctxt2, b, QVariant(19));
269     TEST_CONTEXT_PROPERTY(&ctxt2, c, QVariant(QString("Hello World!")));
270     TEST_CONTEXT_PROPERTY(&ctxt2, d.a, QVariant(-19));
271     TEST_CONTEXT_PROPERTY(&ctxt2, e.a, QVariant(3345));
272
273     ctxt.setContextProperty("a", QVariant(13));
274     ctxt.setContextProperty("b", QVariant(4));
275     ctxt2.setContextProperty("b", QVariant(8));
276     ctxt2.setContextProperty("c", QVariant(QString("Hi World!")));
277     ctxt2.setContextProperty("d", &obj1);
278     obj1.setA(12);
279
280     TEST_CONTEXT_PROPERTY(&ctxt2, a, QVariant(13));
281     TEST_CONTEXT_PROPERTY(&ctxt2, b, QVariant(8));
282     TEST_CONTEXT_PROPERTY(&ctxt2, c, QVariant(QString("Hi World!")));
283     TEST_CONTEXT_PROPERTY(&ctxt2, d.a, QVariant(12));
284     TEST_CONTEXT_PROPERTY(&ctxt2, e.a, QVariant(12));
285
286     // Changes in context properties
287     {
288         QDeclarativeComponent component(&engine); 
289         component.setData("import QtQuick 1.0; QtObject { property variant test: a }", QUrl());
290
291         QObject *obj = component.create(&ctxt2); 
292
293         QCOMPARE(obj->property("test"), QVariant(13)); 
294         ctxt.setContextProperty("a", QVariant(19));
295         QCOMPARE(obj->property("test"), QVariant(19)); 
296
297         delete obj; 
298     }
299     {
300         QDeclarativeComponent component(&engine); 
301         component.setData("import QtQuick 1.0; QtObject { property variant test: b }", QUrl());
302
303         QObject *obj = component.create(&ctxt2); 
304
305         QCOMPARE(obj->property("test"), QVariant(8)); 
306         ctxt.setContextProperty("b", QVariant(5));
307         QCOMPARE(obj->property("test"), QVariant(8)); 
308         ctxt2.setContextProperty("b", QVariant(1912));
309         QCOMPARE(obj->property("test"), QVariant(1912)); 
310
311         delete obj; 
312     }
313     {
314         QDeclarativeComponent component(&engine); 
315         component.setData("import QtQuick 1.0; QtObject { property variant test: e.a }", QUrl());
316
317         QObject *obj = component.create(&ctxt2); 
318
319         QCOMPARE(obj->property("test"), QVariant(12)); 
320         obj1.setA(13);
321         QCOMPARE(obj->property("test"), QVariant(13)); 
322
323         delete obj; 
324     }
325
326     // New context properties
327     {
328         QDeclarativeComponent component(&engine); 
329         component.setData("import QtQuick 1.0; QtObject { property variant test: a }", QUrl());
330
331         QObject *obj = component.create(&ctxt2); 
332
333         QCOMPARE(obj->property("test"), QVariant(19)); 
334         ctxt2.setContextProperty("a", QVariant(1945));
335         QCOMPARE(obj->property("test"), QVariant(1945)); 
336
337         delete obj; 
338     }
339
340     // Setting an object-variant context property
341     {
342         QDeclarativeComponent component(&engine);
343         component.setData("import QtQuick 1.0; QtObject { id: root; property int a: 10; property int test: ctxtProp.a; property variant obj: root; }", QUrl());
344
345         QDeclarativeContext ctxt(engine.rootContext());
346         ctxt.setContextProperty("ctxtProp", QVariant());
347
348         QTest::ignoreMessage(QtWarningMsg, "<Unknown File>:1: TypeError: Cannot read property 'a' of undefined");
349         QObject *obj = component.create(&ctxt);
350
351         QVariant v = obj->property("obj");
352
353         ctxt.setContextProperty("ctxtProp", v);
354
355         QCOMPARE(obj->property("test"), QVariant(10));
356
357         delete obj;
358     }
359 }
360
361 void tst_qdeclarativecontext::setContextObject()
362 {
363     QDeclarativeContext ctxt(&engine);
364
365     TestObject to;
366
367     to.setA(2);
368     to.setB(192);
369     to.setC(18);
370
371     ctxt.setContextObject(&to);
372     ctxt.setContextProperty("c", QVariant(9));
373
374     // Static context properties
375     TEST_CONTEXT_PROPERTY(&ctxt, a, QVariant(2));
376     TEST_CONTEXT_PROPERTY(&ctxt, b, QVariant(192));
377     TEST_CONTEXT_PROPERTY(&ctxt, c, QVariant(9));
378
379     to.setA(12);
380     to.setB(100);
381     to.setC(7);
382     ctxt.setContextProperty("c", QVariant(3));
383
384     TEST_CONTEXT_PROPERTY(&ctxt, a, QVariant(12));
385     TEST_CONTEXT_PROPERTY(&ctxt, b, QVariant(100));
386     TEST_CONTEXT_PROPERTY(&ctxt, c, QVariant(3));
387
388     // Changes in context properties
389     {
390         QDeclarativeComponent component(&engine); 
391         component.setData("import QtQuick 1.0; QtObject { property variant test: a }", QUrl());
392
393         QObject *obj = component.create(&ctxt); 
394
395         QCOMPARE(obj->property("test"), QVariant(12)); 
396         to.setA(14);
397         QCOMPARE(obj->property("test"), QVariant(14)); 
398
399         delete obj; 
400     }
401 }
402
403 void tst_qdeclarativecontext::destruction()
404 {
405     QDeclarativeContext *ctxt = new QDeclarativeContext(&engine);
406
407     QObject obj;
408     QDeclarativeEngine::setContextForObject(&obj, ctxt);
409     QDeclarativeExpression expr(ctxt, 0, "a");
410
411     QCOMPARE(ctxt, QDeclarativeEngine::contextForObject(&obj));
412     QCOMPARE(ctxt, expr.context());
413
414     delete ctxt; ctxt = 0;
415
416     QCOMPARE(ctxt, QDeclarativeEngine::contextForObject(&obj));
417     QCOMPARE(ctxt, expr.context());
418 }
419
420 void tst_qdeclarativecontext::idAsContextProperty()
421 {
422     QDeclarativeComponent component(&engine);
423     component.setData("import QtQuick 1.0; QtObject { property variant a; a: QtObject { id: myObject } }", QUrl());
424
425     QObject *obj = component.create();
426     QVERIFY(obj);
427
428     QVariant a = obj->property("a");
429     QVERIFY(a.userType() == QMetaType::QObjectStar);
430
431     QVariant ctxt = qmlContext(obj)->contextProperty("myObject");
432     QVERIFY(ctxt.userType() == QMetaType::QObjectStar);
433
434     QVERIFY(a == ctxt);
435
436     delete obj;
437 }
438
439 // Internal contexts should be read-only
440 void tst_qdeclarativecontext::readOnlyContexts()
441 {
442     QDeclarativeComponent component(&engine);
443     component.setData("import QtQuick 1.0; QtObject { id: me }", QUrl());
444
445     QObject *obj = component.create();
446     QVERIFY(obj);
447
448     QDeclarativeContext *context = qmlContext(obj);
449     QVERIFY(context);
450
451     QVERIFY(qvariant_cast<QObject*>(context->contextProperty("me")) == obj);
452     QVERIFY(context->contextObject() == obj);
453
454     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeContext: Cannot set property on internal context.");
455     context->setContextProperty("hello", 12);
456     QVERIFY(context->contextProperty("hello") == QVariant());
457
458     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeContext: Cannot set property on internal context.");
459     context->setContextProperty("hello", obj);
460     QVERIFY(context->contextProperty("hello") == QVariant());
461
462     QTest::ignoreMessage(QtWarningMsg, "QDeclarativeContext: Cannot set context object for internal context.");
463     context->setContextObject(0);
464     QVERIFY(context->contextObject() == obj);
465
466     delete obj;
467 }
468
469 void tst_qdeclarativecontext::nameForObject()
470 {
471     QObject o1;
472     QObject o2;
473     QObject o3;
474
475     QDeclarativeEngine engine;
476
477     // As a context property
478     engine.rootContext()->setContextProperty("o1", &o1);
479     engine.rootContext()->setContextProperty("o2", &o2);
480     engine.rootContext()->setContextProperty("o1_2", &o1);
481
482     QCOMPARE(engine.rootContext()->nameForObject(&o1), QString("o1"));
483     QCOMPARE(engine.rootContext()->nameForObject(&o2), QString("o2"));
484     QCOMPARE(engine.rootContext()->nameForObject(&o3), QString());
485
486     // As an id
487     QDeclarativeComponent component(&engine);
488     component.setData("import QtQuick 1.0; QtObject { id: root; property QtObject o: QtObject { id: nested } }", QUrl());
489
490     QObject *o = component.create();
491     QVERIFY(o != 0);
492
493     QCOMPARE(qmlContext(o)->nameForObject(o), QString("root"));
494     QCOMPARE(qmlContext(o)->nameForObject(qvariant_cast<QObject*>(o->property("o"))), QString("nested"));
495     QCOMPARE(qmlContext(o)->nameForObject(&o1), QString());
496
497     delete o;
498 }
499
500 class DeleteCommand : public QObject
501 {
502 Q_OBJECT
503 public:
504     DeleteCommand() : object(0) {}
505
506     QObject *object;
507
508 public slots:
509     void doCommand() { if (object) delete object; object = 0; }
510 };
511
512 // Calling refresh expressions would crash if an expression or context was deleted during
513 // the refreshing
514 void tst_qdeclarativecontext::refreshExpressionsCrash()
515 {
516     {
517     QDeclarativeEngine engine;
518
519     DeleteCommand command;
520     engine.rootContext()->setContextProperty("deleteCommand", &command);
521     // We use a fresh context here to bypass any root-context optimizations in
522     // the engine
523     QDeclarativeContext ctxt(engine.rootContext());
524
525     QDeclarativeComponent component(&engine);
526     component.setData("import QtQuick 2.0; QtObject { property var binding: deleteCommand.doCommand() }", QUrl());
527     QVERIFY(component.isReady());
528
529     QObject *o1 = component.create(&ctxt);
530     QObject *o2 = component.create(&ctxt);
531
532     command.object = o2;
533
534     QDeclarativeContextData::get(&ctxt)->refreshExpressions();
535
536     delete o1;
537     }
538     {
539     QDeclarativeEngine engine;
540
541     DeleteCommand command;
542     engine.rootContext()->setContextProperty("deleteCommand", &command);
543     // We use a fresh context here to bypass any root-context optimizations in
544     // the engine
545     QDeclarativeContext ctxt(engine.rootContext());
546
547     QDeclarativeComponent component(&engine);
548     component.setData("import QtQuick 2.0; QtObject { property var binding: deleteCommand.doCommand() }", QUrl());
549     QVERIFY(component.isReady());
550
551     QObject *o1 = component.create(&ctxt);
552     QObject *o2 = component.create(&ctxt);
553
554     command.object = o1;
555
556     QDeclarativeContextData::get(&ctxt)->refreshExpressions();
557
558     delete o2;
559     }
560 }
561
562 class CountCommand : public QObject
563 {
564 Q_OBJECT
565 public:
566     CountCommand() : count(0) {}
567
568     int count;
569
570 public slots:
571     void doCommand() { ++count; }
572 };
573
574
575 // Test that calling refresh expressions causes all the expressions to refresh
576 void tst_qdeclarativecontext::refreshExpressions()
577 {
578     QDeclarativeEngine engine;
579     QDeclarativeComponent component(&engine, testFileUrl("refreshExpressions.qml"));
580     QDeclarativeComponent component2(&engine, testFileUrl("RefreshExpressionsType.qml"));
581
582     CountCommand command;
583     engine.rootContext()->setContextProperty("countCommand", &command);
584
585     // We use a fresh context here to bypass any root-context optimizations in
586     // the engine
587     QDeclarativeContext context(engine.rootContext());
588     QDeclarativeContext context2(&context);
589
590     QObject *o1 = component.create(&context);
591     QObject *o2 = component.create(&context2);
592     QObject *o3 = component2.create(&context);
593
594     QCOMPARE(command.count, 5);
595
596     QDeclarativeContextData::get(&context)->refreshExpressions();
597
598     QCOMPARE(command.count, 10);
599
600     delete o3;
601     delete o2;
602     delete o1;
603 }
604
605 // Test that updating the root context, only causes expressions in contexts with an
606 // unresolved name to reevaluate
607 void tst_qdeclarativecontext::refreshExpressionsRootContext()
608 {
609     QDeclarativeEngine engine;
610
611     CountCommand command;
612     engine.rootContext()->setContextProperty("countCommand", &command);
613
614     QDeclarativeComponent component(&engine, testFileUrl("refreshExpressions.qml"));
615     QDeclarativeComponent component2(&engine, testFileUrl("refreshExpressionsRootContext.qml"));
616
617     QDeclarativeContext context(engine.rootContext());
618     QDeclarativeContext context2(engine.rootContext());
619
620     QString warning = component2.url().toString() + QLatin1String(":4: ReferenceError: Can't find variable: unresolvedName");
621
622     QObject *o1 = component.create(&context);
623
624     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
625     QObject *o2 = component2.create(&context2);
626
627     QCOMPARE(command.count, 3);
628
629     QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
630     QDeclarativeContextData::get(engine.rootContext())->refreshExpressions();
631
632     QCOMPARE(command.count, 4);
633
634     delete o2;
635     delete o1;
636 }
637
638 void tst_qdeclarativecontext::qtbug_22535()
639 {
640     QDeclarativeEngine engine;
641     QDeclarativeComponent component(&engine, testFileUrl("qtbug_22535.qml"));
642     QDeclarativeContext context(engine.rootContext());
643
644     QObject *o = component.create(&context);
645
646     // Don't crash!
647     delete o;
648 }
649
650 QTEST_MAIN(tst_qdeclarativecontext)
651
652 #include "tst_qdeclarativecontext.moc"