diff options
Diffstat (limited to 'tests/auto/qml')
21 files changed, 530 insertions, 10 deletions
diff --git a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp index ab8fa8a9ef..476ad2e955 100644 --- a/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp +++ b/tests/auto/qml/animation/qparallelanimationgroupjob/tst_qparallelanimationgroupjob.cpp @@ -63,8 +63,8 @@ private slots: void tst_QParallelAnimationGroupJob::initTestCase() { qRegisterMetaType<QAbstractAnimationJob::State>("QAbstractAnimationJob::State"); -#if defined(Q_OS_MAC) || defined(Q_OS_WINCE) - // give the mac/wince app start event queue time to clear +#if defined(Q_OS_DARWIN) + // give the Apple application's start event queue time to clear QTest::qWait(1000); #endif } diff --git a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp index b800cc3715..d1150be831 100644 --- a/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp +++ b/tests/auto/qml/debugger/qqmldebugjs/qqmldebugjs/tst_qqmldebugjs.cpp @@ -42,11 +42,6 @@ #include <QtCore/qlibraryinfo.h> #include <QtQml/qjsengine.h> -#if defined (Q_OS_WINCE) -#undef IN -#undef OUT -#endif - const char *V8REQUEST = "v8request"; const char *V8MESSAGE = "v8message"; const char *SEQ = "seq"; diff --git a/tests/auto/qml/qqmlbinding/data/delayed.qml b/tests/auto/qml/qqmlbinding/data/delayed.qml new file mode 100644 index 0000000000..6f8281cc33 --- /dev/null +++ b/tests/auto/qml/qqmlbinding/data/delayed.qml @@ -0,0 +1,26 @@ +import QtQuick 2.8 + +Item { + width: 400 + height: 400 + + property int changeCount: 0 + + property string text1 + property string text2 + + function updateText() { + text1 = "Hello" + text2 = "World" + } + + Text { + anchors.centerIn: parent + Binding on text { + value: text1 + " " + text2 + delayed: true + } + onTextChanged: ++changeCount + } +} + diff --git a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp index 3e8dfbdb12..6f1d82eca5 100644 --- a/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp +++ b/tests/auto/qml/qqmlbinding/tst_qqmlbinding.cpp @@ -49,6 +49,7 @@ private slots: void warningOnReadOnlyProperty(); void disabledOnUnknownProperty(); void disabledOnReadonlyProperty(); + void delayed(); private: QQmlEngine engine; @@ -281,6 +282,27 @@ void tst_qqmlbinding::disabledOnReadonlyProperty() QCOMPARE(messageHandler.messages().count(), 0); } +void tst_qqmlbinding::delayed() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("delayed.qml")); + QQuickItem *item = qobject_cast<QQuickItem*>(c.create()); + + QVERIFY(item != 0); + // update on creation + QCOMPARE(item->property("changeCount").toInt(), 1); + + QMetaObject::invokeMethod(item, "updateText"); + // doesn't update immediately + QCOMPARE(item->property("changeCount").toInt(), 1); + + QCoreApplication::processEvents(); + // only updates once (non-delayed would update twice) + QCOMPARE(item->property("changeCount").toInt(), 2); + + delete item; +} + QTEST_MAIN(tst_qqmlbinding) #include "tst_qqmlbinding.moc" diff --git a/tests/auto/qml/qqmlengine/data/qtqmlModule.4.qml b/tests/auto/qml/qqmlengine/data/qtqmlModule.4.qml index 9b9b7922da..94ee46ddf0 100644 --- a/tests/auto/qml/qqmlengine/data/qtqmlModule.4.qml +++ b/tests/auto/qml/qqmlengine/data/qtqmlModule.4.qml @@ -1,4 +1,4 @@ -import QtQml 2.5 +import QtQml 2.50 QtObject { } diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 3208745c5c..3af1cf46b3 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -615,9 +615,9 @@ void tst_qqmlengine::qtqmlModule_data() << QString(testFileUrl("qtqmlModule.3.qml").toString() + QLatin1String(":1 module \"QtQml\" version 1.0 is not installed\n")) << QStringList(); - QTest::newRow("import QtQml of incorrect version (2.5)") + QTest::newRow("import QtQml of incorrect version (2.50)") << testFileUrl("qtqmlModule.4.qml") - << QString(testFileUrl("qtqmlModule.4.qml").toString() + QLatin1String(":1 module \"QtQml\" version 2.5 is not installed\n")) + << QString(testFileUrl("qtqmlModule.4.qml").toString() + QLatin1String(":1 module \"QtQml\" version 2.50 is not installed\n")) << QStringList(); QTest::newRow("QtQml 2.0 module provides Component, QtObject, Connections, Binding and Timer") diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml new file mode 100644 index 0000000000..b64a2e23c0 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_arg.qml @@ -0,0 +1,11 @@ +import QtQuick 2.7 +import Test 1.0 + +MyArrayBufferTestClass { + property bool ok: false + Component.onCompleted: { + var data = new Uint8Array([1, 2, 3]); + var sum = byteArrayMethod_Sum(data.buffer); + ok = sum == 6; + } +} diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml new file mode 100644 index 0000000000..9e1c91810a --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_overload.qml @@ -0,0 +1,7 @@ +import QtQuick 2.7 +import Test 1.0 + +MyArrayBufferTestClass { + property bool ok: false + Component.onCompleted: ok = byteArrayMethod_Overloaded(new ArrayBuffer()); +} diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml new file mode 100644 index 0000000000..5a4f9fec0b --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_method_return.qml @@ -0,0 +1,15 @@ +import QtQuick 2.7 +import Test 1.0 + +MyArrayBufferTestClass { + property bool ok: false + Component.onCompleted: { + var buf = byteArrayMethod_CountUp(1, 3); + var view = new DataView(buf); + ok = buf instanceof ArrayBuffer + && buf.byteLength == 3 + && view.getUint8(0) == 1 + && view.getUint8(1) == 2 + && view.getUint8(2) == 3; + } +} diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml new file mode 100644 index 0000000000..78ebb1abe1 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_get.qml @@ -0,0 +1,5 @@ +import Test 1.0 + +MyArrayBufferTestClass { + property bool ok: byteArrayProperty instanceof ArrayBuffer +} diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml new file mode 100644 index 0000000000..e8a51273ca --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_property_set.qml @@ -0,0 +1,11 @@ +import QtQuick 2.7 +import Test 1.0 + +MyArrayBufferTestClass { + property bool ok: false + onByteArraySignal: ok = byteArrayProperty instanceof ArrayBuffer + Component.onCompleted: { + byteArrayProperty = new ArrayBuffer(42); + ok = byteArrayProperty instanceof ArrayBuffer && byteArrayProperty.byteLength == 42; + } +} diff --git a/tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml b/tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml new file mode 100644 index 0000000000..d9f436e788 --- /dev/null +++ b/tests/auto/qml/qqmllanguage/data/arraybuffer_signal_arg.qml @@ -0,0 +1,14 @@ +import QtQuick 2.7 +import Test 1.0 + +MyArrayBufferTestClass { + property bool ok: false + onByteArraySignal: { + var view = new DataView(arg); + ok = arg instanceof ArrayBuffer + && arg.byteLength == 2 + && view.getUint8(0) == 42 + && view.getUint8(1) == 43; + } + Component.onCompleted: emitByteArraySignal(42, 2) +} diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp index 9593bfc940..cc39422dce 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.cpp +++ b/tests/auto/qml/qqmllanguage/testtypes.cpp @@ -98,6 +98,8 @@ void registerTypes() qmlRegisterType<MyCompositeBaseType>("Test", 1, 0, "MyCompositeBaseType"); qmlRegisterSingletonType<MyTypeObjectSingleton>("Test", 1, 0, "MyTypeObjectSingleton", myTypeObjectSingleton); + + qmlRegisterType<MyArrayBufferTestClass>("Test", 1, 0, "MyArrayBufferTestClass"); } QVariant myCustomVariantTypeConverter(const QString &data) diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h index 082182e8e6..2344b6a03b 100644 --- a/tests/auto/qml/qqmllanguage/testtypes.h +++ b/tests/auto/qml/qqmllanguage/testtypes.h @@ -1090,6 +1090,58 @@ public: static QObject *qmlAttachedProperties(QObject *parent) { return new QObject(parent); } }; +class MyArrayBufferTestClass : public QObject +{ + Q_OBJECT + Q_PROPERTY(QByteArray byteArrayProperty READ byteArrayProperty WRITE setByteArrayProperty NOTIFY byteArrayPropertyChanged) + +signals: + void byteArrayPropertyChanged(); + void byteArraySignal(QByteArray arg); + +public: + QByteArray byteArrayPropertyValue; + QByteArray byteArrayProperty() const { + return byteArrayPropertyValue; + } + void setByteArrayProperty(const QByteArray &v) { + byteArrayPropertyValue = v; + emit byteArrayPropertyChanged(); + } + Q_INVOKABLE void emitByteArraySignal(char begin, char num) { + byteArraySignal(byteArrayMethod_CountUp(begin, num)); + } + Q_INVOKABLE int byteArrayMethod_Sum(QByteArray arg) { + int sum = 0; + for (int i = 0; i < arg.size(); ++i) { + sum += arg[i]; + } + return sum; + } + Q_INVOKABLE QByteArray byteArrayMethod_CountUp(char begin, int num) { + QByteArray ret; + for (int i = 0; i < num; ++i) { + ret.push_back(begin++); + } + return ret; + } + Q_INVOKABLE bool byteArrayMethod_Overloaded(QByteArray) { + return true; + } + Q_INVOKABLE bool byteArrayMethod_Overloaded(int) { + return false; + } + Q_INVOKABLE bool byteArrayMethod_Overloaded(QString) { + return false; + } + Q_INVOKABLE bool byteArrayMethod_Overloaded(QJSValue) { + return false; + } + Q_INVOKABLE bool byteArrayMethod_Overloaded(QVariant) { + return false; + } +}; + Q_DECLARE_METATYPE(MyEnum2Class::EnumB) Q_DECLARE_METATYPE(MyEnum1Class::EnumA) Q_DECLARE_METATYPE(Qt::TextFormat) diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index c74b4dd1f1..dd7410dfd3 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -250,6 +250,9 @@ private slots: void deleteSingletons(); + void arrayBuffer_data(); + void arrayBuffer(); + private: QQmlEngine engine; QStringList defaultImportPathList; @@ -4145,6 +4148,27 @@ void tst_qqmllanguage::deleteSingletons() QVERIFY(singleton.data() == 0); } +void tst_qqmllanguage::arrayBuffer_data() +{ + QTest::addColumn<QString>("file"); + QTest::newRow("arraybuffer_property_get") << "arraybuffer_property_get.qml"; + QTest::newRow("arraybuffer_property_set") << "arraybuffer_property_set.qml"; + QTest::newRow("arraybuffer_signal_arg") << "arraybuffer_signal_arg.qml"; + QTest::newRow("arraybuffer_method_arg") << "arraybuffer_method_arg.qml"; + QTest::newRow("arraybuffer_method_return") << "arraybuffer_method_return.qml"; + QTest::newRow("arraybuffer_method_overload") << "arraybuffer_method_overload.qml"; +} + +void tst_qqmllanguage::arrayBuffer() +{ + QFETCH(QString, file); + QQmlComponent component(&engine, testFile(file)); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + QCOMPARE(object->property("ok").toBool(), true); +} + QTEST_MAIN(tst_qqmllanguage) #include "tst_qqmllanguage.moc" diff --git a/tests/auto/qml/qqmlqt/data/LaterComponent.qml b/tests/auto/qml/qqmlqt/data/LaterComponent.qml new file mode 100644 index 0000000000..7dbd81d93d --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/LaterComponent.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import LaterImports 1.0 + +TestElement { + id: deleteme + function testFn() { + gc(); // at this point, obj is deleted. + dangerousFunction(); // calling this function will throw an exeption + // because this object has been deleted and its context is not available + + // which means that we shouldn't get to this line. + row.test10_1 = 1; + } +} diff --git a/tests/auto/qml/qqmlqt/data/LaterComponent2.qml b/tests/auto/qml/qqmlqt/data/LaterComponent2.qml new file mode 100644 index 0000000000..56bcc0235b --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/LaterComponent2.qml @@ -0,0 +1,13 @@ +import QtQuick 2.0 + +Item { + id: deleteme2 + function testFn() { + // this function shouldn't be called, + // since the object will have been deleted. + var crashy = Qt.createQmlObject("import QtQuick 2.0; Item { }", deleteme2) // invalid calling context if invoked after gc + row.test11_1 = 2; + } + + Component.onDestruction: row.test11_1 = 1; // success == the object was deleted, but testFn wasn't called. +} diff --git a/tests/auto/qml/qqmlqt/data/LaterComponent3.qml b/tests/auto/qml/qqmlqt/data/LaterComponent3.qml new file mode 100644 index 0000000000..c6f445253a --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/LaterComponent3.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 +import LaterImports 1.0 + +TestElement { + id: deleteme3 + function testFn() { + gc(); // at this point, obj is deleted. + dangerousFunction(); // calling this function will throw an exeption + // because this object has been deleted and its context is not available + + // which means that we shouldn't get to this line. + row.test12_1 = 1; + } +} diff --git a/tests/auto/qml/qqmlqt/data/LaterComponent4.qml b/tests/auto/qml/qqmlqt/data/LaterComponent4.qml new file mode 100644 index 0000000000..0c53bd368b --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/LaterComponent4.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0 + +Item { + id: deleteme4 + function testFn() { + // this function shouldn't be called, + // since the object will have been deleted. + row.test13_1 = 2; + } + + Component.onDestruction: row.test13_1 = 1; // success == the object was deleted, but testFn wasn't called. +} diff --git a/tests/auto/qml/qqmlqt/data/later.qml b/tests/auto/qml/qqmlqt/data/later.qml new file mode 100644 index 0000000000..a90f3aba9f --- /dev/null +++ b/tests/auto/qml/qqmlqt/data/later.qml @@ -0,0 +1,124 @@ +import QtQuick 2.0 +import LaterImports 1.0 + +Row { + id: row + Repeater { + id: repeater + model: 5 + delegate: Item { } + } + + property bool test1_1: false + property bool test1_2: row.focus + property bool test2_1: false + property bool test2_2: (firstFunctionCallCounter == 1 && secondFunctionCallCounter == 1 && signalCallCounter == 1) + + property int firstFunctionCallCounter: 0 + property int secondFunctionCallCounter: 0 + property int signalCallCounter: 0 + + signal testSignal + onTestSignal: { + signalCallCounter++; + } + + onChildrenChanged: { + Qt.callLater(row.forceActiveFocus); // built-in function + Qt.callLater(row.firstFunction); // JS function + Qt.callLater(row.testSignal); // signal + } + + function firstFunction() { + firstFunctionCallCounter++; + } + + function secondFunction() { + secondFunctionCallCounter++; + } + + Component.onCompleted: { + test1_1 = !row.focus; + test2_1 = (firstFunctionCallCounter == 0); + + Qt.callLater(secondFunction); + Qt.callLater(firstFunction); + Qt.callLater(secondFunction); + } + + function test2() { + repeater.model = 2; + } + + function test3() { + Qt.callLater(test3_recursive); + } + + property int recursion: 0 + property bool test3_1: (recursion == 1) + property bool test3_2: (recursion == 2) + property bool test3_3: (recursion == 3) + function test3_recursive() { + if (recursion < 3) { + Qt.callLater(test3_recursive); + Qt.callLater(test3_recursive); + } + recursion++; + } + + function test4() { + Qt.callLater(functionThatDoesNotExist); + } + + property bool test5_1: false + function test5() { + Qt.callLater(functionWithArguments, "THESE", "ARGS", "WILL", "BE", "OVERWRITTEN") + Qt.callLater(functionWithArguments, "firstArg", 2, "thirdArg") + } + + function functionWithArguments(firstStr, secondInt, thirdString) { + test5_1 = (firstStr == "firstArg" && secondInt == 2 && thirdString == "thirdArg"); + } + + + property bool test6_1: (callOrder_Later == "TWO THREE ") // not "THREE TWO " + function test6() { + Qt.callLater(test6Function1, "ONE"); + Qt.callLater(test6Function2, "TWO"); + Qt.callLater(test6Function1, "THREE"); + } + + property string callOrder_Later + function test6Function1(arg) { callOrder_Later += arg + " "; } + function test6Function2(arg) { callOrder_Later += arg + " "; } + + property int test9_1: SingletonType.intProp; + function test9() { + SingletonType.resetIntProp(); + Qt.callLater(SingletonType.testFunc) + Qt.callLater(SingletonType.testFunc) + Qt.callLater(SingletonType.testFunc) + Qt.callLater(SingletonType.testFunc) + // should only get called once. + } + + property int test10_1: 0 + function test10() { + var c = Qt.createComponent("LaterComponent.qml"); + var obj = c.createObject(); // QML ownership. + Qt.callLater(obj.testFn); + // note: obj will be cleaned up during next gc(). + } + + property int test11_1: 0 + function test11() { + var c = Qt.createComponent("LaterComponent2.qml"); + var obj = c.createObject(); // QML ownership. + Qt.callLater(obj.testFn); + gc(); // this won't actually collect the obj, we need to trigger gc manually in the test. + } + + function test14() { + Qt.callLater(console.log, "success") + } +} diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp index 01283dd587..413feb0eb4 100644 --- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp +++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp @@ -53,6 +53,7 @@ public: tst_qqmlqt() {} private slots: + void initTestCase(); void enums(); void rgba(); void hsla(); @@ -87,11 +88,68 @@ private slots: void fontFamilies(); void quit(); void resolvedUrl(); + void later_data(); + void later(); private: QQmlEngine engine; }; +// for callLater() +class TestElement : public QQuickItem +{ + Q_OBJECT +public: + TestElement() : m_intptr(new int) {} + ~TestElement() { delete m_intptr; } + + Q_INVOKABLE void dangerousFunction() { + delete m_intptr; + m_intptr = new int; + *m_intptr = 5; + } +private: + int *m_intptr; +}; + +// for callLater() +class TestModuleApi : public QObject +{ + Q_OBJECT + Q_PROPERTY(int intProp READ intProp WRITE setIntProp NOTIFY intPropChanged) + +public: + TestModuleApi() : m_int(0) {} + ~TestModuleApi() {} + + int intProp() const { return m_int; } + void setIntProp(int v) { m_int = v; emit intPropChanged(); } + + Q_INVOKABLE void testFunc() { ++m_int; emit intPropChanged(); } + Q_INVOKABLE void resetIntProp() { m_int = 0; emit intPropChanged(); } + +signals: + void intPropChanged(); + +private: + int m_int; +}; + +static QObject *test_module_api_factory(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine) + Q_UNUSED(scriptEngine) + TestModuleApi *api = new TestModuleApi; + return api; +} + +void tst_qqmlqt::initTestCase() +{ + QQmlDataTest::initTestCase(); + qmlRegisterSingletonType<TestModuleApi>("LaterImports", 1, 0, "SingletonType", test_module_api_factory); + qmlRegisterType<TestElement>("LaterImports", 1, 0, "TestElement"); +} + void tst_qqmlqt::enums() { QQmlComponent component(&engine, testFileUrl("enums.qml")); @@ -934,6 +992,107 @@ void tst_qqmlqt::resolvedUrl() delete object; } +void tst_qqmlqt::later_data() +{ + QTest::addColumn<QString>("function"); + QTest::addColumn<QStringList>("expectedWarnings"); + QTest::addColumn<QStringList>("propNames"); + QTest::addColumn<QVariantList>("values"); + + QVariant vtrue = QVariant(true); + + QTest::newRow("callLater from onCompleted") + << QString() + << QStringList() + << (QStringList() << "test1_1" << "test2_1" << "processEvents" << "test1_2" << "test2_2") + << (QVariantList() << vtrue << vtrue << QVariant() << vtrue << vtrue); + + QTest::newRow("trigger Qt.callLater() via repeater") + << QString(QLatin1String("test2")) + << QStringList() + << (QStringList() << "processEvents" << "test2_2") + << (QVariantList() << QVariant() << vtrue); + + QTest::newRow("recursive Qt.callLater()") + << QString(QLatin1String("test3")) + << QStringList() + << (QStringList() << "processEvents" << "test3_1" << "processEvents" << "test3_2" << "processEvents" << "test3_3") + << (QVariantList() << QVariant() << vtrue << QVariant() << vtrue << QVariant() << vtrue); + + QTest::newRow("nonexistent function") + << QString(QLatin1String("test4")) + << (QStringList() << QString(testFileUrl("later.qml").toString() + QLatin1String(":70: ReferenceError: functionThatDoesNotExist is not defined"))) + << QStringList() + << QVariantList(); + + QTest::newRow("callLater with different args") + << QString(QLatin1String("test5")) + << QStringList() + << (QStringList() << "processEvents" << "test5_1") + << (QVariantList() << QVariant() << vtrue); + + QTest::newRow("delayed call ordering") + << QString(QLatin1String("test6")) + << QStringList() + << (QStringList() << "processEvents" << "test6_1") + << (QVariantList() << QVariant() << vtrue); + + QTest::newRow("invoke module api invokable") + << QString(QLatin1String("test9")) + << QStringList() + << (QStringList() << "processEvents" << "test9_1" << "processEvents") + << (QVariantList() << QVariant() << QVariant(1) << QVariant()); + + QTest::newRow("invoke function of deleted QObject via callLater() causing deletion") + << QString(QLatin1String("test10")) + << (QStringList() << QString(testFileUrl("LaterComponent.qml").toString() + QLatin1String(":8: ReferenceError: dangerousFunction is not defined (exception occurred during delayed function evaluation)"))) + << (QStringList() << "processEvents" << "test10_1" << "processEvents") + << (QVariantList() << QVariant() << QVariant(0) << QVariant()); + + QTest::newRow("invoke function of deleted QObject via callLater() after deletion") + << QString(QLatin1String("test11")) + << QStringList() + << (QStringList() << "collectGarbage" << "processEvents" << "test11_1" << "processEvents") + << (QVariantList() << QVariant() << QVariant() << QVariant(1) << QVariant()); + + QTest::newRow("invoke function which has no script origin") + << QString(QLatin1String("test14")) + << QStringList() + << (QStringList() << "collectGarbage") + << (QVariantList() << QVariant()); +} + +void tst_qqmlqt::later() +{ + QFETCH(QString, function); + QFETCH(QStringList, expectedWarnings); + QFETCH(QStringList, propNames); + QFETCH(QVariantList, values); + + foreach (const QString &w, expectedWarnings) + QTest::ignoreMessage(QtWarningMsg, qPrintable(w)); + + QQmlComponent component(&engine, testFileUrl("later.qml")); + QObject *root = component.create(); + QVERIFY(root != 0); + + if (!function.isEmpty()) + QMetaObject::invokeMethod(root, qPrintable(function)); + + for (int i = 0; i < propNames.size(); ++i) { + if (propNames.at(i) == QLatin1String("processEvents")) { + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::processEvents(); + } else if (propNames.at(i) == QLatin1String("collectGarbage")) { + engine.collectGarbage(); + } else { + QCOMPARE(root->property(qPrintable(propNames.at(i))), values.at(i)); + } + } + + delete root; +} + QTEST_MAIN(tst_qqmlqt) #include "tst_qqmlqt.moc" |