1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
41 #include "testtypes.h"
49 #include <QDeclarativeEngine>
50 #include <QDeclarativeContext>
51 #include <QDeclarativeProperty>
52 #include <QDeclarativeComponent>
53 #include <QDeclarativeIncubator>
54 #include "../../shared/util.h"
56 class tst_qdeclarativeincubator : public QDeclarativeDataTest
60 tst_qdeclarativeincubator() {}
65 void incubationMode();
68 void noIncubationController();
69 void forceCompletion();
70 void setInitialState();
71 void clearDuringCompletion();
72 void objectDeletionAfterInit();
73 void recursiveClear();
75 void asynchronousIfNested();
76 void nestedComponent();
77 void chainedAsynchronousIfNested();
78 void chainedAsynchronousIfNestedOnCompleted();
83 QDeclarativeIncubationController controller;
84 QDeclarativeEngine engine;
87 #define VERIFY_ERRORS(component, errorfile) \
89 if (qgetenv("DEBUG") != "" && !component.errors().isEmpty()) \
90 qWarning() << "Unexpected Errors:" << component.errors(); \
91 QVERIFY(!component.isError()); \
92 QVERIFY(component.errors().isEmpty()); \
94 QFile file(QDeclarativeDataTest::instance()->testFile(errorfile)); \
95 QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \
96 QByteArray data = file.readAll(); \
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; \
109 if (qgetenv("DEBUG") != "" && expected != actual) \
110 qWarning() << "Expected:" << expected << "Actual:" << actual; \
111 QCOMPARE(expected, actual); \
114 void tst_qdeclarativeincubator::initTestCase()
116 QDeclarativeDataTest::initTestCase();
118 engine.setIncubationController(&controller);
121 void tst_qdeclarativeincubator::incubationMode()
124 QDeclarativeIncubator incubator;
125 QCOMPARE(incubator.incubationMode(), QDeclarativeIncubator::Asynchronous);
128 QDeclarativeIncubator incubator(QDeclarativeIncubator::Asynchronous);
129 QCOMPARE(incubator.incubationMode(), QDeclarativeIncubator::Asynchronous);
132 QDeclarativeIncubator incubator(QDeclarativeIncubator::Synchronous);
133 QCOMPARE(incubator.incubationMode(), QDeclarativeIncubator::Synchronous);
136 QDeclarativeIncubator incubator(QDeclarativeIncubator::AsynchronousIfNested);
137 QCOMPARE(incubator.incubationMode(), QDeclarativeIncubator::AsynchronousIfNested);
141 void tst_qdeclarativeincubator::objectDeleted()
143 SelfRegisteringType::clearMe();
145 QDeclarativeComponent component(&engine, testFileUrl("objectDeleted.qml"));
146 QVERIFY(component.isReady());
148 QDeclarativeIncubator incubator;
149 component.create(incubator);
151 QCOMPARE(incubator.status(), QDeclarativeIncubator::Loading);
152 QVERIFY(SelfRegisteringType::me() == 0);
154 while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
156 controller.incubateWhile(&b);
159 QVERIFY(SelfRegisteringType::me() != 0);
160 QVERIFY(incubator.isLoading());
162 delete SelfRegisteringType::me();
166 controller.incubateWhile(&b);
169 QVERIFY(incubator.isError());
170 VERIFY_ERRORS(incubator, "objectDeleted.errors.txt");
171 QVERIFY(incubator.object() == 0);
174 void tst_qdeclarativeincubator::clear()
176 SelfRegisteringType::clearMe();
178 QDeclarativeComponent component(&engine, testFileUrl("clear.qml"));
179 QVERIFY(component.isReady());
181 // Clear in null state
183 QDeclarativeIncubator incubator;
184 QVERIFY(incubator.isNull());
185 incubator.clear(); // no effect
186 QVERIFY(incubator.isNull());
189 // Clear in loading state
191 QDeclarativeIncubator incubator;
192 component.create(incubator);
193 QVERIFY(incubator.isLoading());
195 QVERIFY(incubator.isNull());
200 QDeclarativeIncubator incubator;
201 component.create(incubator);
203 while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
205 controller.incubateWhile(&b);
208 QVERIFY(incubator.isLoading());
209 QVERIFY(SelfRegisteringType::me() != 0);
210 QPointer<SelfRegisteringType> srt = SelfRegisteringType::me();
213 QVERIFY(incubator.isNull());
214 QVERIFY(srt.isNull());
217 // Clear in ready state
219 QDeclarativeIncubator incubator;
220 component.create(incubator);
224 controller.incubateWhile(&b);
227 QVERIFY(incubator.isReady());
228 QVERIFY(incubator.object() != 0);
229 QPointer<QObject> obj = incubator.object();
232 QVERIFY(incubator.isNull());
233 QVERIFY(incubator.object() == 0);
234 QVERIFY(!obj.isNull());
237 QVERIFY(obj.isNull());
241 void tst_qdeclarativeincubator::noIncubationController()
243 // All incubators should behave synchronously when there is no controller
245 QDeclarativeEngine engine;
246 QDeclarativeComponent component(&engine, testFileUrl("noIncubationController.qml"));
248 QVERIFY(component.isReady());
251 QDeclarativeIncubator incubator(QDeclarativeIncubator::Asynchronous);
252 component.create(incubator);
253 QVERIFY(incubator.isReady());
254 QVERIFY(incubator.object());
255 QCOMPARE(incubator.object()->property("testValue").toInt(), 1913);
256 delete incubator.object();
260 QDeclarativeIncubator incubator(QDeclarativeIncubator::AsynchronousIfNested);
261 component.create(incubator);
262 QVERIFY(incubator.isReady());
263 QVERIFY(incubator.object());
264 QCOMPARE(incubator.object()->property("testValue").toInt(), 1913);
265 delete incubator.object();
269 QDeclarativeIncubator incubator(QDeclarativeIncubator::Synchronous);
270 component.create(incubator);
271 QVERIFY(incubator.isReady());
272 QVERIFY(incubator.object());
273 QCOMPARE(incubator.object()->property("testValue").toInt(), 1913);
274 delete incubator.object();
278 void tst_qdeclarativeincubator::forceCompletion()
280 QDeclarativeComponent component(&engine, testFileUrl("forceCompletion.qml"));
281 QVERIFY(component.isReady());
284 // forceCompletion on a null incubator does nothing
285 QDeclarativeIncubator incubator;
286 QVERIFY(incubator.isNull());
287 incubator.forceCompletion();
288 QVERIFY(incubator.isNull());
292 // forceCompletion immediately after creating an asynchronous object completes it
293 QDeclarativeIncubator incubator;
294 QVERIFY(incubator.isNull());
295 component.create(incubator);
296 QVERIFY(incubator.isLoading());
298 incubator.forceCompletion();
300 QVERIFY(incubator.isReady());
301 QVERIFY(incubator.object() != 0);
302 QCOMPARE(incubator.object()->property("testValue").toInt(), 3499);
304 delete incubator.object();
308 // forceCompletion during creation completes it
309 SelfRegisteringType::clearMe();
311 QDeclarativeIncubator incubator;
312 QVERIFY(incubator.isNull());
313 component.create(incubator);
314 QVERIFY(incubator.isLoading());
316 while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
318 controller.incubateWhile(&b);
321 QVERIFY(SelfRegisteringType::me() != 0);
322 QVERIFY(incubator.isLoading());
324 incubator.forceCompletion();
326 QVERIFY(incubator.isReady());
327 QVERIFY(incubator.object() != 0);
328 QCOMPARE(incubator.object()->property("testValue").toInt(), 3499);
330 delete incubator.object();
334 // forceCompletion on a ready incubator has no effect
335 QDeclarativeIncubator incubator;
336 QVERIFY(incubator.isNull());
337 component.create(incubator);
338 QVERIFY(incubator.isLoading());
340 incubator.forceCompletion();
342 QVERIFY(incubator.isReady());
343 QVERIFY(incubator.object() != 0);
344 QCOMPARE(incubator.object()->property("testValue").toInt(), 3499);
346 incubator.forceCompletion();
348 QVERIFY(incubator.isReady());
349 QVERIFY(incubator.object() != 0);
350 QCOMPARE(incubator.object()->property("testValue").toInt(), 3499);
352 delete incubator.object();
356 void tst_qdeclarativeincubator::setInitialState()
358 QDeclarativeComponent component(&engine, testFileUrl("setInitialState.qml"));
359 QVERIFY(component.isReady());
361 struct MyIncubator : public QDeclarativeIncubator
363 MyIncubator(QDeclarativeIncubator::IncubationMode mode)
364 : QDeclarativeIncubator(mode) {}
366 virtual void setInitialState(QObject *o) {
367 QDeclarativeProperty::write(o, "test2", 19);
368 QDeclarativeProperty::write(o, "testData1", 201);
373 MyIncubator incubator(QDeclarativeIncubator::Asynchronous);
374 component.create(incubator);
375 QVERIFY(incubator.isLoading());
377 controller.incubateWhile(&b);
378 QVERIFY(incubator.isReady());
379 QVERIFY(incubator.object());
380 QCOMPARE(incubator.object()->property("myValueFunctionCalled").toBool(), false);
381 QCOMPARE(incubator.object()->property("test1").toInt(), 502);
382 QCOMPARE(incubator.object()->property("test2").toInt(), 19);
383 delete incubator.object();
387 MyIncubator incubator(QDeclarativeIncubator::Synchronous);
388 component.create(incubator);
389 QVERIFY(incubator.isReady());
390 QVERIFY(incubator.object());
391 QCOMPARE(incubator.object()->property("myValueFunctionCalled").toBool(), false);
392 QCOMPARE(incubator.object()->property("test1").toInt(), 502);
393 QCOMPARE(incubator.object()->property("test2").toInt(), 19);
394 delete incubator.object();
398 void tst_qdeclarativeincubator::clearDuringCompletion()
400 CompletionRegisteringType::clearMe();
401 SelfRegisteringType::clearMe();
403 QDeclarativeComponent component(&engine, testFileUrl("clearDuringCompletion.qml"));
404 QVERIFY(component.isReady());
406 QDeclarativeIncubator incubator;
407 component.create(incubator);
409 QCOMPARE(incubator.status(), QDeclarativeIncubator::Loading);
410 QVERIFY(CompletionRegisteringType::me() == 0);
412 while (CompletionRegisteringType::me() == 0 && incubator.isLoading()) {
414 controller.incubateWhile(&b);
417 QVERIFY(CompletionRegisteringType::me() != 0);
418 QVERIFY(SelfRegisteringType::me() != 0);
419 QVERIFY(incubator.isLoading());
421 QPointer<QObject> srt = SelfRegisteringType::me();
424 QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
425 QCoreApplication::processEvents();
426 QVERIFY(incubator.isNull());
427 QVERIFY(srt.isNull());
430 void tst_qdeclarativeincubator::objectDeletionAfterInit()
432 QDeclarativeComponent component(&engine, testFileUrl("clear.qml"));
433 QVERIFY(component.isReady());
435 struct MyIncubator : public QDeclarativeIncubator
437 MyIncubator(QDeclarativeIncubator::IncubationMode mode)
438 : QDeclarativeIncubator(mode), obj(0) {}
440 virtual void setInitialState(QObject *o) {
447 SelfRegisteringType::clearMe();
448 MyIncubator incubator(QDeclarativeIncubator::Asynchronous);
449 component.create(incubator);
451 while (!incubator.obj && incubator.isLoading()) {
453 controller.incubateWhile(&b);
456 QVERIFY(incubator.isLoading());
457 QVERIFY(SelfRegisteringType::me() != 0);
459 delete incubator.obj;
462 QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
463 QCoreApplication::processEvents();
464 QVERIFY(incubator.isNull());
467 class Switcher : public QObject
471 Switcher(QDeclarativeEngine *e) : QObject(), engine(e) { }
473 struct MyIncubator : public QDeclarativeIncubator
475 MyIncubator(QDeclarativeIncubator::IncubationMode mode, QObject *s)
476 : QDeclarativeIncubator(mode), switcher(s) {}
478 virtual void setInitialState(QObject *o) {
479 if (o->objectName() == "switchMe")
480 connect(o, SIGNAL(switchMe()), switcher, SLOT(switchIt()));
488 incubator = new MyIncubator(QDeclarativeIncubator::Synchronous, this);
489 component = new QDeclarativeComponent(engine, QDeclarativeDataTest::instance()->testFileUrl("recursiveClear.1.qml"));
490 component->create(*incubator);
493 QDeclarativeEngine *engine;
494 MyIncubator *incubator;
495 QDeclarativeComponent *component;
499 component->deleteLater();
501 component = new QDeclarativeComponent(engine, QDeclarativeDataTest::instance()->testFileUrl("recursiveClear.2.qml"));
502 component->create(*incubator);
506 void tst_qdeclarativeincubator::recursiveClear()
508 Switcher switcher(&engine);
512 void tst_qdeclarativeincubator::statusChanged()
514 class MyIncubator : public QDeclarativeIncubator
517 MyIncubator(QDeclarativeIncubator::IncubationMode mode = QDeclarativeIncubator::Asynchronous)
518 : QDeclarativeIncubator(mode) {}
522 virtual void statusChanged(Status s) { statuses << s; }
523 virtual void setInitialState(QObject *) { statuses << -1; }
527 QDeclarativeComponent component(&engine, testFileUrl("statusChanged.qml"));
528 QVERIFY(component.isReady());
530 MyIncubator incubator(QDeclarativeIncubator::Synchronous);
531 component.create(incubator);
532 QVERIFY(incubator.isReady());
533 QCOMPARE(incubator.statuses.count(), 3);
534 QCOMPARE(incubator.statuses.at(0), int(QDeclarativeIncubator::Loading));
535 QCOMPARE(incubator.statuses.at(1), -1);
536 QCOMPARE(incubator.statuses.at(2), int(QDeclarativeIncubator::Ready));
537 delete incubator.object();
541 QDeclarativeComponent component(&engine, testFileUrl("statusChanged.qml"));
542 QVERIFY(component.isReady());
544 MyIncubator incubator(QDeclarativeIncubator::Asynchronous);
545 component.create(incubator);
546 QVERIFY(incubator.isLoading());
547 QCOMPARE(incubator.statuses.count(), 1);
548 QCOMPARE(incubator.statuses.at(0), int(QDeclarativeIncubator::Loading));
552 controller.incubateWhile(&b);
555 QCOMPARE(incubator.statuses.count(), 3);
556 QCOMPARE(incubator.statuses.at(0), int(QDeclarativeIncubator::Loading));
557 QCOMPARE(incubator.statuses.at(1), -1);
558 QCOMPARE(incubator.statuses.at(2), int(QDeclarativeIncubator::Ready));
559 delete incubator.object();
563 QDeclarativeComponent component2(&engine, testFileUrl("statusChanged.nested.qml"));
564 QVERIFY(component2.isReady());
566 MyIncubator incubator(QDeclarativeIncubator::Asynchronous);
567 component2.create(incubator);
568 QVERIFY(incubator.isLoading());
569 QCOMPARE(incubator.statuses.count(), 1);
570 QCOMPARE(incubator.statuses.at(0), int(QDeclarativeIncubator::Loading));
574 controller.incubateWhile(&b);
577 QVERIFY(incubator.isReady());
578 QCOMPARE(incubator.statuses.count(), 3);
579 QCOMPARE(incubator.statuses.at(0), int(QDeclarativeIncubator::Loading));
580 QCOMPARE(incubator.statuses.at(1), -1);
581 QCOMPARE(incubator.statuses.at(2), int(QDeclarativeIncubator::Ready));
582 delete incubator.object();
586 void tst_qdeclarativeincubator::asynchronousIfNested()
588 // Asynchronous if nested within a finalized context behaves synchronously
590 QDeclarativeComponent component(&engine, testFileUrl("asynchronousIfNested.1.qml"));
591 QVERIFY(component.isReady());
593 QObject *object = component.create();
594 QVERIFY(object != 0);
595 QCOMPARE(object->property("a").toInt(), 10);
597 QDeclarativeIncubator incubator(QDeclarativeIncubator::AsynchronousIfNested);
598 component.create(incubator, 0, qmlContext(object));
600 QVERIFY(incubator.isReady());
601 QVERIFY(incubator.object());
602 QCOMPARE(incubator.object()->property("a").toInt(), 10);
603 delete incubator.object();
607 // Asynchronous if nested within an executing context behaves asynchronously, but prevents
608 // the parent from finishing
610 SelfRegisteringType::clearMe();
612 QDeclarativeComponent component(&engine, testFileUrl("asynchronousIfNested.2.qml"));
613 QVERIFY(component.isReady());
615 QDeclarativeIncubator incubator;
616 component.create(incubator);
618 QVERIFY(incubator.isLoading());
619 QVERIFY(SelfRegisteringType::me() == 0);
620 while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
622 controller.incubateWhile(&b);
625 QVERIFY(SelfRegisteringType::me() != 0);
626 QVERIFY(incubator.isLoading());
628 QDeclarativeIncubator nested(QDeclarativeIncubator::AsynchronousIfNested);
629 component.create(nested, 0, qmlContext(SelfRegisteringType::me()));
630 QVERIFY(nested.isLoading());
632 while (nested.isLoading()) {
633 QVERIFY(incubator.isLoading());
635 controller.incubateWhile(&b);
638 QVERIFY(nested.isReady());
639 QVERIFY(incubator.isLoading());
643 controller.incubateWhile(&b);
646 QVERIFY(nested.isReady());
647 QVERIFY(incubator.isReady());
649 delete nested.object();
650 delete incubator.object();
653 // AsynchronousIfNested within a synchronous AsynchronousIfNested behaves synchronously
655 SelfRegisteringType::clearMe();
657 QDeclarativeComponent component(&engine, testFileUrl("asynchronousIfNested.3.qml"));
658 QVERIFY(component.isReady());
660 struct CallbackData {
661 CallbackData(QDeclarativeEngine *e) : engine(e), pass(false) {}
662 QDeclarativeEngine *engine;
664 static void callback(CallbackRegisteringType *o, void *data) {
665 CallbackData *d = (CallbackData *)data;
667 QDeclarativeComponent c(d->engine, QDeclarativeDataTest::instance()->testFileUrl("asynchronousIfNested.1.qml"));
668 if (!c.isReady()) return;
670 QDeclarativeIncubator incubator(QDeclarativeIncubator::AsynchronousIfNested);
671 c.create(incubator, 0, qmlContext(o));
673 if (!incubator.isReady()) return;
675 if (incubator.object()->property("a").toInt() != 10) return;
681 CallbackData cd(&engine);
682 CallbackRegisteringType::registerCallback(&CallbackData::callback, &cd);
684 QDeclarativeIncubator incubator(QDeclarativeIncubator::AsynchronousIfNested);
685 component.create(incubator);
687 QVERIFY(incubator.isReady());
688 QCOMPARE(cd.pass, true);
690 delete incubator.object();
694 void tst_qdeclarativeincubator::nestedComponent()
696 QDeclarativeComponent component(&engine, testFileUrl("nestedComponent.qml"));
697 QVERIFY(component.isReady());
699 QObject *object = component.create();
701 QDeclarativeComponent *nested = object->property("c").value<QDeclarativeComponent*>();
703 QVERIFY(nested->isReady());
705 // Test without incubator
707 QObject *nestedObject = nested->create();
708 QCOMPARE(nestedObject->property("value").toInt(), 19988);
712 // Test with incubator
714 QDeclarativeIncubator incubator(QDeclarativeIncubator::Synchronous);
715 nested->create(incubator);
716 QVERIFY(incubator.isReady());
717 QVERIFY(incubator.object());
718 QCOMPARE(incubator.object()->property("value").toInt(), 19988);
719 delete incubator.object();
725 // Checks that a new AsynchronousIfNested incubator can be correctly started in the
726 // statusChanged() callback of another.
727 void tst_qdeclarativeincubator::chainedAsynchronousIfNested()
729 SelfRegisteringType::clearMe();
731 QDeclarativeComponent component(&engine, testFileUrl("chainedAsynchronousIfNested.qml"));
732 QVERIFY(component.isReady());
734 QDeclarativeIncubator incubator(QDeclarativeIncubator::Asynchronous);
735 component.create(incubator);
737 QVERIFY(incubator.isLoading());
738 QVERIFY(SelfRegisteringType::me() == 0);
740 while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
742 controller.incubateWhile(&b);
745 QVERIFY(SelfRegisteringType::me() != 0);
746 QVERIFY(incubator.isLoading());
748 struct MyIncubator : public QDeclarativeIncubator {
749 MyIncubator(MyIncubator *next, QDeclarativeComponent *component, QDeclarativeContext *ctxt)
750 : QDeclarativeIncubator(AsynchronousIfNested), next(next), component(component), ctxt(ctxt) {}
753 virtual void statusChanged(Status s) {
754 if (s == Ready && next)
755 component->create(*next, 0, ctxt);
760 QDeclarativeComponent *component;
761 QDeclarativeContext *ctxt;
764 MyIncubator incubator2(0, &component, 0);
765 MyIncubator incubator1(&incubator2, &component, qmlContext(SelfRegisteringType::me()));
767 component.create(incubator1, 0, qmlContext(SelfRegisteringType::me()));
769 QVERIFY(incubator.isLoading());
770 QVERIFY(incubator1.isLoading());
771 QVERIFY(incubator2.isNull());
773 while (incubator1.isLoading()) {
774 QVERIFY(incubator.isLoading());
775 QVERIFY(incubator1.isLoading());
776 QVERIFY(incubator2.isNull());
779 controller.incubateWhile(&b);
782 QVERIFY(incubator.isLoading());
783 QVERIFY(incubator1.isReady());
784 QVERIFY(incubator2.isLoading());
786 while (incubator2.isLoading()) {
787 QVERIFY(incubator.isLoading());
788 QVERIFY(incubator1.isReady());
789 QVERIFY(incubator2.isLoading());
792 controller.incubateWhile(&b);
795 QVERIFY(incubator.isLoading());
796 QVERIFY(incubator1.isReady());
797 QVERIFY(incubator2.isReady());
801 controller.incubateWhile(&b);
804 QVERIFY(incubator.isReady());
805 QVERIFY(incubator1.isReady());
806 QVERIFY(incubator2.isReady());
809 // Checks that new AsynchronousIfNested incubators can be correctly chained if started in
810 // componentCompleted().
811 void tst_qdeclarativeincubator::chainedAsynchronousIfNestedOnCompleted()
813 SelfRegisteringType::clearMe();
815 QDeclarativeComponent component(&engine, testFileUrl("chainInCompletion.qml"));
816 QVERIFY(component.isReady());
818 QDeclarativeComponent c1(&engine, testFileUrl("chainedAsynchronousIfNested.qml"));
819 QVERIFY(c1.isReady());
821 struct MyIncubator : public QDeclarativeIncubator {
822 MyIncubator(MyIncubator *next, QDeclarativeComponent *component, QDeclarativeContext *ctxt)
823 : QDeclarativeIncubator(AsynchronousIfNested), next(next), component(component), ctxt(ctxt) {}
826 virtual void statusChanged(Status s) {
827 if (s == Ready && next) {
828 component->create(*next, 0, ctxt);
834 QDeclarativeComponent *component;
835 QDeclarativeContext *ctxt;
838 struct CallbackData {
839 CallbackData(QDeclarativeComponent *c, MyIncubator *i, QDeclarativeContext *ct)
840 : component(c), incubator(i), ctxt(ct) {}
841 QDeclarativeComponent *component;
842 MyIncubator *incubator;
843 QDeclarativeContext *ctxt;
844 static void callback(CompletionCallbackType *, void *data) {
845 CallbackData *d = (CallbackData *)data;
846 d->component->create(*d->incubator, 0, d->ctxt);
850 QDeclarativeIncubator incubator(QDeclarativeIncubator::Asynchronous);
851 component.create(incubator);
853 QVERIFY(incubator.isLoading());
854 QVERIFY(SelfRegisteringType::me() == 0);
856 while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
858 controller.incubateWhile(&b);
861 QVERIFY(SelfRegisteringType::me() != 0);
862 QVERIFY(incubator.isLoading());
864 MyIncubator incubator3(0, &c1, qmlContext(SelfRegisteringType::me()));
865 MyIncubator incubator2(&incubator3, &c1, qmlContext(SelfRegisteringType::me()));
866 MyIncubator incubator1(&incubator2, &c1, qmlContext(SelfRegisteringType::me()));
868 // start incubator1 in componentComplete
869 CallbackData cd(&c1, &incubator1, qmlContext(SelfRegisteringType::me()));
870 CompletionCallbackType::registerCallback(&CallbackData::callback, &cd);
872 while (!incubator1.isLoading()) {
873 QVERIFY(incubator.isLoading());
874 QVERIFY(incubator2.isNull());
875 QVERIFY(incubator3.isNull());
878 controller.incubateWhile(&b);
881 QVERIFY(incubator.isLoading());
882 QVERIFY(incubator1.isLoading());
883 QVERIFY(incubator2.isNull());
884 QVERIFY(incubator3.isNull());
886 while (incubator1.isLoading()) {
887 QVERIFY(incubator.isLoading());
888 QVERIFY(incubator1.isLoading());
889 QVERIFY(incubator2.isNull());
890 QVERIFY(incubator3.isNull());
893 controller.incubateWhile(&b);
896 QVERIFY(incubator.isLoading());
897 QVERIFY(incubator1.isReady());
898 QVERIFY(incubator2.isLoading());
899 QVERIFY(incubator3.isNull());
901 while (incubator2.isLoading()) {
902 QVERIFY(incubator.isLoading());
903 QVERIFY(incubator1.isReady());
904 QVERIFY(incubator2.isLoading());
905 QVERIFY(incubator3.isNull());
908 controller.incubateWhile(&b);
911 QVERIFY(incubator.isLoading());
912 QVERIFY(incubator1.isReady());
913 QVERIFY(incubator2.isReady());
914 QVERIFY(incubator3.isLoading());
916 while (incubator3.isLoading()) {
917 QVERIFY(incubator.isLoading());
918 QVERIFY(incubator1.isReady());
919 QVERIFY(incubator2.isReady());
920 QVERIFY(incubator3.isLoading());
923 controller.incubateWhile(&b);
928 controller.incubateWhile(&b);
931 QVERIFY(incubator.isReady());
932 QVERIFY(incubator1.isReady());
933 QVERIFY(incubator2.isReady());
934 QVERIFY(incubator3.isReady());
937 void tst_qdeclarativeincubator::selfDelete()
939 struct MyIncubator : public QDeclarativeIncubator {
940 MyIncubator(bool *done, Status status, IncubationMode mode)
941 : QDeclarativeIncubator(mode), done(done), status(status) {}
944 virtual void statusChanged(Status s) {
947 if (s == Ready) delete object();
958 QDeclarativeComponent component(&engine, testFileUrl("selfDelete.qml"));
960 #define DELETE_TEST(status, mode) { \
962 component.create(*(new MyIncubator(&done, status, mode))); \
964 controller.incubateWhile(&True); \
965 QVERIFY(done == true); \
968 DELETE_TEST(QDeclarativeIncubator::Loading, QDeclarativeIncubator::Synchronous);
969 DELETE_TEST(QDeclarativeIncubator::Ready, QDeclarativeIncubator::Synchronous);
970 DELETE_TEST(QDeclarativeIncubator::Loading, QDeclarativeIncubator::Asynchronous);
971 DELETE_TEST(QDeclarativeIncubator::Ready, QDeclarativeIncubator::Asynchronous);
976 // Delete within error status
978 SelfRegisteringType::clearMe();
980 QDeclarativeComponent component(&engine, testFileUrl("objectDeleted.qml"));
981 QVERIFY(component.isReady());
984 MyIncubator *incubator = new MyIncubator(&done, QDeclarativeIncubator::Error,
985 QDeclarativeIncubator::Asynchronous);
986 component.create(*incubator);
988 QCOMPARE(incubator->QDeclarativeIncubator::status(), QDeclarativeIncubator::Loading);
989 QVERIFY(SelfRegisteringType::me() == 0);
991 while (SelfRegisteringType::me() == 0 && incubator->isLoading()) {
993 controller.incubateWhile(&b);
996 QVERIFY(SelfRegisteringType::me() != 0);
997 QVERIFY(incubator->isLoading());
999 delete SelfRegisteringType::me();
1003 controller.incubateWhile(&b);
1010 // Test that QML doesn't crash if the context is deleted prior to the incubator
1012 void tst_qdeclarativeincubator::contextDelete()
1014 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
1015 QDeclarativeComponent component(&engine, testFileUrl("contextDelete.qml"));
1017 QDeclarativeIncubator incubator;
1018 component.create(incubator, context);
1024 controller.incubateWhile(&b);
1028 QTEST_MAIN(tst_qdeclarativeincubator)
1030 #include "tst_qdeclarativeincubator.moc"