aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorThomas McGuire <thomas.mcguire@kdab.com>2012-07-17 17:35:53 +0200
committerQt by Nokia <qt-info@nokia.com>2012-08-22 12:25:33 +0200
commit26ea8e01e9ee2a8c8c09266147b94c9ac92d09f9 (patch)
treec058873b0082b18a09dde27f7ee124285e696807 /tests
parent2cc57f1e33cc4d739b1b76c605e6241fa0f134a8 (diff)
Make connectNotify() work with QML
Call connectNotify() and disconnectNotify() in QQmlNotifierEndPoint, which works for QML signal handlers and for QML bindings. Task-number: QTBUG-11284 Change-Id: Ic9a08ee6687e5c7e606f315c8fb30eec1493cd83 Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/qml/qml.pro1
-rw-r--r--tests/auto/qml/qqmlnotifier/data/connectnotify.qml73
-rw-r--r--tests/auto/qml/qqmlnotifier/qqmlnotifier.pro11
-rw-r--r--tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp298
4 files changed, 383 insertions, 0 deletions
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index e24e30d2f9..a9fa7648dd 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -19,6 +19,7 @@ PUBLICTESTS += \
qqmllocale \
qqmlmetaobject \
qqmlmoduleplugin \
+ qqmlnotifier \
qqmlqt \
qqmltranslation \
qqmlxmlhttprequest \
diff --git a/tests/auto/qml/qqmlnotifier/data/connectnotify.qml b/tests/auto/qml/qqmlnotifier/data/connectnotify.qml
new file mode 100644
index 0000000000..35226ee5ab
--- /dev/null
+++ b/tests/auto/qml/qqmlnotifier/data/connectnotify.qml
@@ -0,0 +1,73 @@
+import QtQuick 2.0
+import Test 1.0
+
+Item {
+ id: root
+ ExportedClass {
+ id: exportedClass
+ objectName: "exportedClass"
+ onBoundSignal: {}
+ }
+
+ property int v4Binding: exportedClass.v4BindingProp
+
+ property int v8Binding: {
+ Math.abs(12); // Prevent optimization to v4
+ return exportedClass.v8BindingProp
+ }
+
+ property int scriptBinding: {
+ function innerFunction() {} // Prevent usage of v4 or v8 bindings
+ return exportedClass.scriptBindingProp
+ }
+
+ property int foo: exportedClass.qmlObjectProp
+ property int baz: _exportedObject.cppObjectProp
+
+ // v4 bindings that could share a subscription. They don't, though, and the code
+ // relies on that
+ property int v4Binding2: exportedClass.v4BindingProp2
+ property int bla: exportedClass.v4BindingProp2
+
+ function removeV4Binding() {
+ //console.log("Going to remove v4 binding...")
+ root.v4Binding = 1;
+ //console.log("Binding removed!")
+ }
+
+ function removeV8Binding() {
+ //console.log("Going to remove v8 binding...")
+ root.v8Binding = 1;
+ //console.log("Binding removed!")
+ }
+
+ function removeScriptBinding() {
+ //console.log("Going to remove script binding...")
+ root.scriptBinding = 1;
+ //console.log("Binding removed!")
+ }
+
+ function removeV4Binding2() {
+ //console.log("Going to remove v4 binding 2...")
+ root.v4Binding2 = 1;
+ //console.log("Binding removed!")
+ }
+
+ function readProperty() {
+ var test = exportedClass.unboundProp
+ }
+
+ function changeState() {
+ //console.log("Changing state...")
+ if (root.state == "") root.state = "state1"
+ else root.state = ""
+ //console.log("State changed.")
+ }
+
+ property int someValue: 42
+
+ states: State {
+ name: "state1"
+ PropertyChanges { target: root; someValue: exportedClass.unboundProp }
+ }
+}
diff --git a/tests/auto/qml/qqmlnotifier/qqmlnotifier.pro b/tests/auto/qml/qqmlnotifier/qqmlnotifier.pro
new file mode 100644
index 0000000000..5fc40a3c2c
--- /dev/null
+++ b/tests/auto/qml/qqmlnotifier/qqmlnotifier.pro
@@ -0,0 +1,11 @@
+CONFIG += testcase
+TARGET = tst_qqmlnotifier
+SOURCES += tst_qqmlnotifier.cpp
+
+include (../../shared/util.pri)
+
+macx:CONFIG -= app_bundle
+
+TESTDATA = data/*
+
+QT += qml testlib
diff --git a/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
new file mode 100644
index 0000000000..1fb56dbf97
--- /dev/null
+++ b/tests/auto/qml/qqmlnotifier/tst_qqmlnotifier.cpp
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QDebug>
+#include <QQmlEngine>
+#include <QQmlComponent>
+#include <QQmlContext>
+#include <qqml.h>
+#include <QMetaMethod>
+
+#include "../../shared/util.h"
+
+class ExportedClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int qmlObjectProp READ qmlObjectProp NOTIFY qmlObjectPropChanged)
+ Q_PROPERTY(int cppObjectProp READ cppObjectProp NOTIFY cppObjectPropChanged)
+ Q_PROPERTY(int unboundProp READ unboundProp NOTIFY unboundPropChanged)
+ Q_PROPERTY(int v8BindingProp READ v8BindingProp NOTIFY v8BindingPropChanged)
+ Q_PROPERTY(int v4BindingProp READ v4BindingProp NOTIFY v4BindingPropChanged)
+ Q_PROPERTY(int v4BindingProp2 READ v4BindingProp2 NOTIFY v4BindingProp2Changed)
+ Q_PROPERTY(int scriptBindingProp READ scriptBindingProp NOTIFY scriptBindingPropChanged)
+public:
+ int qmlObjectPropConnections;
+ int cppObjectPropConnections;
+ int unboundPropConnections;
+ int v8BindingPropConnections;
+ int v4BindingPropConnections;
+ int v4BindingProp2Connections;
+ int scriptBindingPropConnections;
+ int boundSignalConnections;
+ int unusedSignalConnections;
+
+ ExportedClass()
+ : qmlObjectPropConnections(0), cppObjectPropConnections(0), unboundPropConnections(0),
+ v8BindingPropConnections(0), v4BindingPropConnections(0), v4BindingProp2Connections(0),
+ scriptBindingPropConnections(0), boundSignalConnections(0), unusedSignalConnections(0)
+ {}
+
+ ~ExportedClass()
+ {
+ QCOMPARE(qmlObjectPropConnections, 0);
+ QCOMPARE(cppObjectPropConnections, 0);
+ QCOMPARE(unboundPropConnections, 0);
+ QCOMPARE(v8BindingPropConnections, 0);
+ QCOMPARE(v4BindingPropConnections, 0);
+ QCOMPARE(v4BindingProp2Connections, 0);
+ QCOMPARE(scriptBindingPropConnections, 0);
+ QCOMPARE(boundSignalConnections, 0);
+ QCOMPARE(unusedSignalConnections, 0);
+ }
+
+ int qmlObjectProp() const { return 42; }
+ int unboundProp() const { return 42; }
+ int v8BindingProp() const { return 42; }
+ int v4BindingProp() const { return 42; }
+ int v4BindingProp2() const { return 42; }
+ int cppObjectProp() const { return 42; }
+ int scriptBindingProp() const { return 42; }
+protected:
+ void connectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE {
+ if (signal.name() == "qmlObjectPropChanged") qmlObjectPropConnections++;
+ if (signal.name() == "cppObjectPropChanged") cppObjectPropConnections++;
+ if (signal.name() == "unboundPropChanged") unboundPropConnections++;
+ if (signal.name() == "v8BindingPropChanged") v8BindingPropConnections++;
+ if (signal.name() == "v4BindingPropChanged") v4BindingPropConnections++;
+ if (signal.name() == "v4BindingProp2Changed") v4BindingProp2Connections++;
+ if (signal.name() == "scriptBindingPropChanged") scriptBindingPropConnections++;
+ if (signal.name() == "boundSignal") boundSignalConnections++;
+ if (signal.name() == "unusedSignal") unusedSignalConnections++;
+ //qDebug() << Q_FUNC_INFO << this << signal.name();
+ }
+
+ void disconnectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE {
+ if (signal.name() == "qmlObjectPropChanged") qmlObjectPropConnections--;
+ if (signal.name() == "cppObjectPropChanged") cppObjectPropConnections--;
+ if (signal.name() == "unboundPropChanged") unboundPropConnections--;
+ if (signal.name() == "v8BindingPropChanged") v8BindingPropConnections--;
+ if (signal.name() == "v4BindingPropChanged") v4BindingPropConnections--;
+ if (signal.name() == "v4BindingProp2Changed") v4BindingProp2Connections--;
+ if (signal.name() == "scriptBindingPropChanged") scriptBindingPropConnections--;
+ if (signal.name() == "boundSignal") boundSignalConnections--;
+ if (signal.name() == "unusedSignal") unusedSignalConnections--;
+ //qDebug() << Q_FUNC_INFO << this << signal.methodSignature();
+ }
+
+signals:
+ void qmlObjectPropChanged();
+ void cppObjectPropChanged();
+ void unboundPropChanged();
+ void v8BindingPropChanged();
+ void v4BindingPropChanged();
+ void v4BindingProp2Changed();
+ void scriptBindingPropChanged();
+ void boundSignal();
+ void unusedSignal();
+};
+
+class tst_qqmlnotifier : public QQmlDataTest
+{
+ Q_OBJECT
+public:
+ tst_qqmlnotifier()
+ : root(0), exportedClass(0), exportedObject(0)
+ {}
+
+private slots:
+ void initTestCase() Q_DECL_OVERRIDE;
+ void cleanupTestCase();
+ void connectNotify();
+
+ void removeV4Binding();
+ void removeV4Binding2();
+ void removeV8Binding();
+ void removeScriptBinding();
+ // No need to test value type proxy bindings - the user can't override disconnectNotify() anyway,
+ // as the classes are private to the QML engine
+
+ void readProperty();
+ void propertyChange();
+ void disconnectOnDestroy();
+
+private:
+ void createObjects();
+
+ QQmlEngine engine;
+ QObject *root;
+ ExportedClass *exportedClass;
+ ExportedClass *exportedObject;
+};
+
+void tst_qqmlnotifier::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ qmlRegisterType<ExportedClass>("Test", 1, 0, "ExportedClass");
+}
+
+void tst_qqmlnotifier::createObjects()
+{
+ delete root;
+ root = 0;
+ exportedClass = exportedObject = 0;
+
+ QQmlComponent component(&engine, testFileUrl("connectnotify.qml"));
+ exportedObject = new ExportedClass();
+ exportedObject->setObjectName("exportedObject");
+ engine.rootContext()->setContextProperty("_exportedObject", exportedObject);
+ root = component.create();
+ QVERIFY(root != 0);
+
+ exportedClass = qobject_cast<ExportedClass *>(
+ root->findChild<ExportedClass*>("exportedClass"));
+ QVERIFY(exportedClass != 0);
+}
+
+void tst_qqmlnotifier::cleanupTestCase()
+{
+ delete root;
+ root = 0;
+ delete exportedObject;
+ exportedObject = 0;
+}
+
+void tst_qqmlnotifier::connectNotify()
+{
+ createObjects();
+
+ QCOMPARE(exportedClass->qmlObjectPropConnections, 1);
+ QCOMPARE(exportedClass->cppObjectPropConnections, 0);
+ QCOMPARE(exportedClass->unboundPropConnections, 0);
+ QCOMPARE(exportedClass->v8BindingPropConnections, 1);
+ QCOMPARE(exportedClass->v4BindingPropConnections, 1);
+ QCOMPARE(exportedClass->v4BindingProp2Connections, 2);
+ QCOMPARE(exportedClass->scriptBindingPropConnections, 1);
+ QCOMPARE(exportedClass->boundSignalConnections, 1);
+ QCOMPARE(exportedClass->unusedSignalConnections, 0);
+
+ QCOMPARE(exportedObject->qmlObjectPropConnections, 0);
+ QCOMPARE(exportedObject->cppObjectPropConnections, 1);
+ QCOMPARE(exportedObject->unboundPropConnections, 0);
+ QCOMPARE(exportedObject->v8BindingPropConnections, 0);
+ QCOMPARE(exportedObject->v4BindingPropConnections, 0);
+ QCOMPARE(exportedObject->v4BindingProp2Connections, 0);
+ QCOMPARE(exportedObject->scriptBindingPropConnections, 0);
+ QCOMPARE(exportedObject->boundSignalConnections, 0);
+ QCOMPARE(exportedObject->unusedSignalConnections, 0);
+}
+
+void tst_qqmlnotifier::removeV4Binding()
+{
+ createObjects();
+
+ // Removing a binding should disconnect all of its guarded properties
+ QVERIFY(QMetaObject::invokeMethod(root, "removeV4Binding"));
+ QCOMPARE(exportedClass->v4BindingPropConnections, 0);
+}
+
+void tst_qqmlnotifier::removeV4Binding2()
+{
+ createObjects();
+
+ // In this case, the v4BindingProp2 property is used by two v4 bindings.
+ // Make sure that removing one binding doesn't by accident disconnect all.
+ QVERIFY(QMetaObject::invokeMethod(root, "removeV4Binding2"));
+ QCOMPARE(exportedClass->v4BindingProp2Connections, 1);
+}
+
+void tst_qqmlnotifier::removeV8Binding()
+{
+ createObjects();
+
+ // Removing a binding should disconnect all of its guarded properties
+ QVERIFY(QMetaObject::invokeMethod(root, "removeV8Binding"));
+ QCOMPARE(exportedClass->v8BindingPropConnections, 0);
+}
+
+void tst_qqmlnotifier::removeScriptBinding()
+{
+ createObjects();
+
+ // Removing a binding should disconnect all of its guarded properties
+ QVERIFY(QMetaObject::invokeMethod(root, "removeScriptBinding"));
+ QCOMPARE(exportedClass->scriptBindingPropConnections, 0);
+}
+
+void tst_qqmlnotifier::readProperty()
+{
+ createObjects();
+
+ // Reading a property should not connect to it
+ QVERIFY(QMetaObject::invokeMethod(root, "readProperty"));
+ QCOMPARE(exportedClass->unboundPropConnections, 0);
+}
+
+void tst_qqmlnotifier::propertyChange()
+{
+ createObjects();
+
+ // Changing the state will trigger the PropertyChange to overwrite a value with a binding.
+ // For this, the new binding needs to be connected, and afterwards disconnected.
+ QVERIFY(QMetaObject::invokeMethod(root, "changeState"));
+ QCOMPARE(exportedClass->unboundPropConnections, 1);
+ QVERIFY(QMetaObject::invokeMethod(root, "changeState"));
+ QCOMPARE(exportedClass->unboundPropConnections, 0);
+}
+
+void tst_qqmlnotifier::disconnectOnDestroy()
+{
+ createObjects();
+
+ // Deleting a QML object should remove all connections. For exportedClass, this is tested in
+ // the destructor, and for exportedObject, it is tested below.
+ delete root;
+ root = 0;
+ QCOMPARE(exportedObject->cppObjectPropConnections, 0);
+}
+
+QTEST_MAIN(tst_qqmlnotifier)
+
+#include "tst_qqmlnotifier.moc"