Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativeincubator / tst_qdeclarativeincubator.cpp
index 684cd35..7f68b9a 100644 (file)
@@ -1,8 +1,7 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
 **
 ** This file is part of the test suite of the Qt Toolkit.
 **
@@ -35,6 +34,7 @@
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
 #include <QPointer>
 #include <QFileInfo>
 #include <QDeclarativeEngine>
+#include <QDeclarativeContext>
 #include <QDeclarativeProperty>
 #include <QDeclarativeComponent>
 #include <QDeclarativeIncubator>
-#include "../shared/util.h"
-
-inline QUrl TEST_FILE(const QString &filename)
-{
-    return QUrl::fromLocalFile(TESTDATA(filename));
-}
-
-inline QUrl TEST_FILE(const char *filename)
-{
-    return TEST_FILE(QLatin1String(filename));
-}
+#include "../../shared/util.h"
 
-class tst_qdeclarativeincubator : public QObject
+class tst_qdeclarativeincubator : public QDeclarativeDataTest
 {
     Q_OBJECT
 public:
@@ -78,12 +69,15 @@ private slots:
     void forceCompletion();
     void setInitialState();
     void clearDuringCompletion();
+    void objectDeletionAfterInit();
     void recursiveClear();
     void statusChanged();
     void asynchronousIfNested();
     void nestedComponent();
     void chainedAsynchronousIfNested();
+    void chainedAsynchronousIfNestedOnCompleted();
     void selfDelete();
+    void contextDelete();
 
 private:
     QDeclarativeIncubationController controller;
@@ -97,7 +91,7 @@ private:
         QVERIFY(!component.isError()); \
         QVERIFY(component.errors().isEmpty()); \
     } else { \
-        QFile file(TESTDATA(errorfile)); \
+        QFile file(QDeclarativeDataTest::instance()->testFile(errorfile)); \
         QVERIFY(file.open(QIODevice::ReadOnly | QIODevice::Text)); \
         QByteArray data = file.readAll(); \
         file.close(); \
@@ -119,6 +113,7 @@ private:
 
 void tst_qdeclarativeincubator::initTestCase()
 {
+    QDeclarativeDataTest::initTestCase();
     registerTypes();
     engine.setIncubationController(&controller);
 }
@@ -147,7 +142,7 @@ void tst_qdeclarativeincubator::objectDeleted()
 {
     SelfRegisteringType::clearMe();
 
-    QDeclarativeComponent component(&engine, TEST_FILE("objectDeleted.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("objectDeleted.qml"));
     QVERIFY(component.isReady());
 
     QDeclarativeIncubator incubator;
@@ -180,7 +175,7 @@ void tst_qdeclarativeincubator::clear()
 {
     SelfRegisteringType::clearMe();
 
-    QDeclarativeComponent component(&engine, TEST_FILE("clear.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("clear.qml"));
     QVERIFY(component.isReady());
 
     // Clear in null state
@@ -248,7 +243,7 @@ void tst_qdeclarativeincubator::noIncubationController()
     // All incubators should behave synchronously when there is no controller
 
     QDeclarativeEngine engine;
-    QDeclarativeComponent component(&engine, TEST_FILE("noIncubationController.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("noIncubationController.qml"));
 
     QVERIFY(component.isReady());
 
@@ -282,7 +277,7 @@ void tst_qdeclarativeincubator::noIncubationController()
 
 void tst_qdeclarativeincubator::forceCompletion()
 {
-    QDeclarativeComponent component(&engine, TEST_FILE("forceCompletion.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("forceCompletion.qml"));
     QVERIFY(component.isReady());
 
     {
@@ -360,7 +355,7 @@ void tst_qdeclarativeincubator::forceCompletion()
 
 void tst_qdeclarativeincubator::setInitialState()
 {
-    QDeclarativeComponent component(&engine, TEST_FILE("setInitialState.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("setInitialState.qml"));
     QVERIFY(component.isReady());
 
     struct MyIncubator : public QDeclarativeIncubator
@@ -405,7 +400,7 @@ void tst_qdeclarativeincubator::clearDuringCompletion()
     CompletionRegisteringType::clearMe();
     SelfRegisteringType::clearMe();
 
-    QDeclarativeComponent component(&engine, TEST_FILE("clearDuringCompletion.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("clearDuringCompletion.qml"));
     QVERIFY(component.isReady());
 
     QDeclarativeIncubator incubator;
@@ -426,11 +421,49 @@ void tst_qdeclarativeincubator::clearDuringCompletion()
     QPointer<QObject> srt = SelfRegisteringType::me();
 
     incubator.clear();
-    QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
+    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+    QCoreApplication::processEvents();
     QVERIFY(incubator.isNull());
     QVERIFY(srt.isNull());
 }
 
+void tst_qdeclarativeincubator::objectDeletionAfterInit()
+{
+    QDeclarativeComponent component(&engine, testFileUrl("clear.qml"));
+    QVERIFY(component.isReady());
+
+    struct MyIncubator : public QDeclarativeIncubator
+    {
+        MyIncubator(QDeclarativeIncubator::IncubationMode mode)
+        : QDeclarativeIncubator(mode), obj(0) {}
+
+        virtual void setInitialState(QObject *o) {
+            obj = o;
+        }
+
+        QObject *obj;
+    };
+
+    SelfRegisteringType::clearMe();
+    MyIncubator incubator(QDeclarativeIncubator::Asynchronous);
+    component.create(incubator);
+
+    while (!incubator.obj && incubator.isLoading()) {
+        bool b = false;
+        controller.incubateWhile(&b);
+    }
+
+    QVERIFY(incubator.isLoading());
+    QVERIFY(SelfRegisteringType::me() != 0);
+
+    delete incubator.obj;
+
+    incubator.clear();
+    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+    QCoreApplication::processEvents();
+    QVERIFY(incubator.isNull());
+}
+
 class Switcher : public QObject
 {
     Q_OBJECT
@@ -453,7 +486,7 @@ public:
     void start()
     {
         incubator = new MyIncubator(QDeclarativeIncubator::Synchronous, this);
-        component = new QDeclarativeComponent(engine,  TEST_FILE("recursiveClear.1.qml"));
+        component = new QDeclarativeComponent(engine, QDeclarativeDataTest::instance()->testFileUrl("recursiveClear.1.qml"));
         component->create(*incubator);
     }
 
@@ -465,7 +498,7 @@ public slots:
     void switchIt() {
         component->deleteLater();
         incubator->clear();
-        component = new QDeclarativeComponent(engine,  TEST_FILE("recursiveClear.2.qml"));
+        component = new QDeclarativeComponent(engine, QDeclarativeDataTest::instance()->testFileUrl("recursiveClear.2.qml"));
         component->create(*incubator);
     }
 };
@@ -491,7 +524,7 @@ void tst_qdeclarativeincubator::statusChanged()
     };
 
     {
-    QDeclarativeComponent component(&engine, TEST_FILE("statusChanged.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("statusChanged.qml"));
     QVERIFY(component.isReady());
 
     MyIncubator incubator(QDeclarativeIncubator::Synchronous);
@@ -505,7 +538,7 @@ void tst_qdeclarativeincubator::statusChanged()
     }
 
     {
-    QDeclarativeComponent component(&engine, TEST_FILE("statusChanged.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("statusChanged.qml"));
     QVERIFY(component.isReady());
 
     MyIncubator incubator(QDeclarativeIncubator::Asynchronous);
@@ -527,7 +560,7 @@ void tst_qdeclarativeincubator::statusChanged()
     }
 
     {
-    QDeclarativeComponent component2(&engine, TEST_FILE("statusChanged.nested.qml"));
+    QDeclarativeComponent component2(&engine, testFileUrl("statusChanged.nested.qml"));
     QVERIFY(component2.isReady());
 
     MyIncubator incubator(QDeclarativeIncubator::Asynchronous);
@@ -554,7 +587,7 @@ void tst_qdeclarativeincubator::asynchronousIfNested()
 {
     // Asynchronous if nested within a finalized context behaves synchronously
     {
-    QDeclarativeComponent component(&engine, TEST_FILE("asynchronousIfNested.1.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("asynchronousIfNested.1.qml"));
     QVERIFY(component.isReady());
 
     QObject *object = component.create();
@@ -576,7 +609,7 @@ void tst_qdeclarativeincubator::asynchronousIfNested()
     {
     SelfRegisteringType::clearMe();
 
-    QDeclarativeComponent component(&engine, TEST_FILE("asynchronousIfNested.2.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("asynchronousIfNested.2.qml"));
     QVERIFY(component.isReady());
 
     QDeclarativeIncubator incubator;
@@ -621,7 +654,7 @@ void tst_qdeclarativeincubator::asynchronousIfNested()
     {
     SelfRegisteringType::clearMe();
 
-    QDeclarativeComponent component(&engine, TEST_FILE("asynchronousIfNested.3.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("asynchronousIfNested.3.qml"));
     QVERIFY(component.isReady());
 
     struct CallbackData {
@@ -631,7 +664,7 @@ void tst_qdeclarativeincubator::asynchronousIfNested()
         static void callback(CallbackRegisteringType *o, void *data) {
             CallbackData *d = (CallbackData *)data;
 
-            QDeclarativeComponent c(d->engine, TEST_FILE("asynchronousIfNested.1.qml"));
+            QDeclarativeComponent c(d->engine, QDeclarativeDataTest::instance()->testFileUrl("asynchronousIfNested.1.qml"));
             if (!c.isReady()) return;
 
             QDeclarativeIncubator incubator(QDeclarativeIncubator::AsynchronousIfNested);
@@ -660,7 +693,7 @@ void tst_qdeclarativeincubator::asynchronousIfNested()
 
 void tst_qdeclarativeincubator::nestedComponent()
 {
-    QDeclarativeComponent component(&engine, TEST_FILE("nestedComponent.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("nestedComponent.qml"));
     QVERIFY(component.isReady());
 
     QObject *object = component.create();
@@ -695,7 +728,7 @@ void tst_qdeclarativeincubator::chainedAsynchronousIfNested()
 {
     SelfRegisteringType::clearMe();
 
-    QDeclarativeComponent component(&engine, TEST_FILE("chainedAsynchronousIfNested.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("chainedAsynchronousIfNested.qml"));
     QVERIFY(component.isReady());
 
     QDeclarativeIncubator incubator(QDeclarativeIncubator::Asynchronous);
@@ -773,6 +806,134 @@ void tst_qdeclarativeincubator::chainedAsynchronousIfNested()
     QVERIFY(incubator2.isReady());
 }
 
+// Checks that new AsynchronousIfNested incubators can be correctly chained if started in
+// componentCompleted().
+void tst_qdeclarativeincubator::chainedAsynchronousIfNestedOnCompleted()
+{
+    SelfRegisteringType::clearMe();
+
+    QDeclarativeComponent component(&engine, testFileUrl("chainInCompletion.qml"));
+    QVERIFY(component.isReady());
+
+    QDeclarativeComponent c1(&engine, testFileUrl("chainedAsynchronousIfNested.qml"));
+    QVERIFY(c1.isReady());
+
+    struct MyIncubator : public QDeclarativeIncubator {
+        MyIncubator(MyIncubator *next, QDeclarativeComponent *component, QDeclarativeContext *ctxt)
+        : QDeclarativeIncubator(AsynchronousIfNested), next(next), component(component), ctxt(ctxt) {}
+
+    protected:
+        virtual void statusChanged(Status s) {
+            if (s == Ready && next) {
+                component->create(*next, 0, ctxt);
+            }
+        }
+
+    private:
+        MyIncubator *next;
+        QDeclarativeComponent *component;
+        QDeclarativeContext *ctxt;
+    };
+
+    struct CallbackData {
+        CallbackData(QDeclarativeComponent *c, MyIncubator *i, QDeclarativeContext *ct)
+            : component(c), incubator(i), ctxt(ct) {}
+        QDeclarativeComponent *component;
+        MyIncubator *incubator;
+        QDeclarativeContext *ctxt;
+        static void callback(CompletionCallbackType *, void *data) {
+            CallbackData *d = (CallbackData *)data;
+            d->component->create(*d->incubator, 0, d->ctxt);
+        }
+    };
+
+    QDeclarativeIncubator incubator(QDeclarativeIncubator::Asynchronous);
+    component.create(incubator);
+
+    QVERIFY(incubator.isLoading());
+    QVERIFY(SelfRegisteringType::me() == 0);
+
+    while (SelfRegisteringType::me() == 0 && incubator.isLoading()) {
+        bool b = false;
+        controller.incubateWhile(&b);
+    }
+
+    QVERIFY(SelfRegisteringType::me() != 0);
+    QVERIFY(incubator.isLoading());
+
+    MyIncubator incubator3(0, &c1, qmlContext(SelfRegisteringType::me()));
+    MyIncubator incubator2(&incubator3, &c1, qmlContext(SelfRegisteringType::me()));
+    MyIncubator incubator1(&incubator2, &c1, qmlContext(SelfRegisteringType::me()));
+
+    // start incubator1 in componentComplete
+    CallbackData cd(&c1, &incubator1, qmlContext(SelfRegisteringType::me()));
+    CompletionCallbackType::registerCallback(&CallbackData::callback, &cd);
+
+    while (!incubator1.isLoading()) {
+        QVERIFY(incubator.isLoading());
+        QVERIFY(incubator2.isNull());
+        QVERIFY(incubator3.isNull());
+
+        bool b = false;
+        controller.incubateWhile(&b);
+    }
+
+    QVERIFY(incubator.isLoading());
+    QVERIFY(incubator1.isLoading());
+    QVERIFY(incubator2.isNull());
+    QVERIFY(incubator3.isNull());
+
+    while (incubator1.isLoading()) {
+        QVERIFY(incubator.isLoading());
+        QVERIFY(incubator1.isLoading());
+        QVERIFY(incubator2.isNull());
+        QVERIFY(incubator3.isNull());
+
+        bool b = false;
+        controller.incubateWhile(&b);
+    }
+
+    QVERIFY(incubator.isLoading());
+    QVERIFY(incubator1.isReady());
+    QVERIFY(incubator2.isLoading());
+    QVERIFY(incubator3.isNull());
+
+    while (incubator2.isLoading()) {
+        QVERIFY(incubator.isLoading());
+        QVERIFY(incubator1.isReady());
+        QVERIFY(incubator2.isLoading());
+        QVERIFY(incubator3.isNull());
+
+        bool b = false;
+        controller.incubateWhile(&b);
+    }
+
+    QVERIFY(incubator.isLoading());
+    QVERIFY(incubator1.isReady());
+    QVERIFY(incubator2.isReady());
+    QVERIFY(incubator3.isLoading());
+
+    while (incubator3.isLoading()) {
+        QVERIFY(incubator.isLoading());
+        QVERIFY(incubator1.isReady());
+        QVERIFY(incubator2.isReady());
+        QVERIFY(incubator3.isLoading());
+
+        bool b = false;
+        controller.incubateWhile(&b);
+    }
+
+    {
+    bool b = true;
+    controller.incubateWhile(&b);
+    }
+
+    QVERIFY(incubator.isReady());
+    QVERIFY(incubator1.isReady());
+    QVERIFY(incubator2.isReady());
+    QVERIFY(incubator3.isReady());
+}
+
 void tst_qdeclarativeincubator::selfDelete()
 {
     struct MyIncubator : public QDeclarativeIncubator {
@@ -794,7 +955,7 @@ void tst_qdeclarativeincubator::selfDelete()
     };
 
     {
-    QDeclarativeComponent component(&engine, TEST_FILE("selfDelete.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("selfDelete.qml"));
 
 #define DELETE_TEST(status, mode) { \
     bool done = false; \
@@ -816,7 +977,7 @@ void tst_qdeclarativeincubator::selfDelete()
     {
     SelfRegisteringType::clearMe();
 
-    QDeclarativeComponent component(&engine, TEST_FILE("objectDeleted.qml"));
+    QDeclarativeComponent component(&engine, testFileUrl("objectDeleted.qml"));
     QVERIFY(component.isReady());
 
     bool done = false;
@@ -846,6 +1007,24 @@ void tst_qdeclarativeincubator::selfDelete()
     }
 }
 
+// Test that QML doesn't crash if the context is deleted prior to the incubator
+// first executing.
+void tst_qdeclarativeincubator::contextDelete()
+{
+    QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
+    QDeclarativeComponent component(&engine, testFileUrl("contextDelete.qml"));
+
+    QDeclarativeIncubator incubator;
+    component.create(incubator, context);
+
+    delete context;
+
+    {
+        bool b = false;
+        controller.incubateWhile(&b);
+    }
+}
+
 QTEST_MAIN(tst_qdeclarativeincubator)
 
 #include "tst_qdeclarativeincubator.moc"