aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qml/qqmlqt/tst_qqmlqt.cpp')
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 2f44c34bc2..8150241e4a 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,12 +88,69 @@ private slots:
void fontFamilies();
void quit();
void resolvedUrl();
+ void later_data();
+ void later();
void qtObjectContents();
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"));
@@ -935,6 +993,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;
+}
+
void tst_qqmlqt::qtObjectContents()
{
struct StaticQtMetaObject : public QObject