Add autotest for QML meta-objects
authorKent Hansen <kent.hansen@nokia.com>
Tue, 7 Feb 2012 18:37:38 +0000 (19:37 +0100)
committerQt by Nokia <qt-info@nokia.com>
Wed, 29 Feb 2012 17:26:30 +0000 (18:26 +0100)
This autotest checks that the QMetaObject generated from a QML type
can be introspected from C++ (properties, class info, signals and
slots).

Change-Id: I9a50f138f911690f5c55cd28e5b49f0682450d07
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
27 files changed:
tests/auto/declarative/declarative.pro
tests/auto/declarative/qdeclarativemetaobject/data/method.1.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/method.2.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/method.3.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.MyQmlObject.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.QtObject.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.alias.2.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.alias.3.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.alias.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.bool.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.color.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.date.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.int.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.list.MyQmlObject.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.list.QtObject.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.real.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.string.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.url.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.var.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/property.variant.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/signal.1.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/signal.2.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/signal.3.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/signal.4.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/data/signal.5.qml [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/qdeclarativemetaobject.pro [new file with mode: 0644]
tests/auto/declarative/qdeclarativemetaobject/tst_qdeclarativemetaobject.cpp [new file with mode: 0644]

index 7288da2..85de861 100644 (file)
@@ -15,6 +15,7 @@ PUBLICTESTS += \
     qdeclarativeinfo \
     qdeclarativelistreference \
     qdeclarativelocale \
+    qdeclarativemetaobject \
     qdeclarativemoduleplugin \
     qdeclarativeqt \
     qdeclarativetranslation \
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/method.1.qml b/tests/auto/declarative/qdeclarativemetaobject/data/method.1.qml
new file mode 100644 (file)
index 0000000..a021881
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    function testFunction() { return 19; }
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/method.2.qml b/tests/auto/declarative/qdeclarativemetaobject/data/method.2.qml
new file mode 100644 (file)
index 0000000..d514955
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    function testFunction(foo) { return 19; }
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/method.3.qml b/tests/auto/declarative/qdeclarativemetaobject/data/method.3.qml
new file mode 100644 (file)
index 0000000..d6d1975
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    function testFunction(foo, bar, baz) { return 19; }
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.MyQmlObject.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.MyQmlObject.qml
new file mode 100644 (file)
index 0000000..8903bbb
--- /dev/null
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+QtObject {
+    property MyQmlObject test: MyQmlObject {}
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.QtObject.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.QtObject.qml
new file mode 100644 (file)
index 0000000..20c42b5
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    property QtObject test: QtObject {}
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.alias.2.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.alias.2.qml
new file mode 100644 (file)
index 0000000..cae1ae6
--- /dev/null
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+
+QtObject {
+    id: me
+    property alias test: me
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.alias.3.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.alias.3.qml
new file mode 100644 (file)
index 0000000..86422ae
--- /dev/null
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+Text {
+    id: me
+    font.family: "Arial"
+    property alias test: me.font.family
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.alias.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.alias.qml
new file mode 100644 (file)
index 0000000..33a4a1c
--- /dev/null
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+QtObject {
+    objectName: "Joe"
+    id: me
+    property alias test: me.objectName
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.bool.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.bool.qml
new file mode 100644 (file)
index 0000000..9459cb6
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    default property bool test: true
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.color.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.color.qml
new file mode 100644 (file)
index 0000000..7451a27
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    default property color test: "#ff0000"
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.date.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.date.qml
new file mode 100644 (file)
index 0000000..05fcb25
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    property date test: "2012-02-07"
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.int.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.int.qml
new file mode 100644 (file)
index 0000000..ae419d0
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    property int test: 19
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.list.MyQmlObject.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.list.MyQmlObject.qml
new file mode 100644 (file)
index 0000000..602762c
--- /dev/null
@@ -0,0 +1,6 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+QtObject {
+    property list<MyQmlObject> test: [ MyQmlObject {} ]
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.list.QtObject.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.list.QtObject.qml
new file mode 100644 (file)
index 0000000..e774d70
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    property list<QtObject> test: [ QtObject {} ]
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.real.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.real.qml
new file mode 100644 (file)
index 0000000..de2baf5
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    property real test: 21
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.string.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.string.qml
new file mode 100644 (file)
index 0000000..2a625c4
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    default property string test: "dog"
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.url.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.url.qml
new file mode 100644 (file)
index 0000000..c820c82
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    property url test: "http://foo.bar"
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.var.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.var.qml
new file mode 100644 (file)
index 0000000..9ea9245
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    property var test: [5, true, "ciao"]
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/property.variant.qml b/tests/auto/declarative/qdeclarativemetaobject/data/property.variant.qml
new file mode 100644 (file)
index 0000000..edffa17
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    default property variant test: "12,34"
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/signal.1.qml b/tests/auto/declarative/qdeclarativemetaobject/data/signal.1.qml
new file mode 100644 (file)
index 0000000..113130f
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    signal testSignal
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/signal.2.qml b/tests/auto/declarative/qdeclarativemetaobject/data/signal.2.qml
new file mode 100644 (file)
index 0000000..db860cc
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    signal testSignal(string foo)
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/signal.3.qml b/tests/auto/declarative/qdeclarativemetaobject/data/signal.3.qml
new file mode 100644 (file)
index 0000000..4d04041
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    signal testSignal(int foo, bool bar, real baz)
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/signal.4.qml b/tests/auto/declarative/qdeclarativemetaobject/data/signal.4.qml
new file mode 100644 (file)
index 0000000..ad9b002
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    signal testSignal(variant foo, var bar)
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/data/signal.5.qml b/tests/auto/declarative/qdeclarativemetaobject/data/signal.5.qml
new file mode 100644 (file)
index 0000000..b848bb5
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+    signal testSignal(color foo, date bar, url baz)
+}
diff --git a/tests/auto/declarative/qdeclarativemetaobject/qdeclarativemetaobject.pro b/tests/auto/declarative/qdeclarativemetaobject/qdeclarativemetaobject.pro
new file mode 100644 (file)
index 0000000..206f510
--- /dev/null
@@ -0,0 +1,14 @@
+CONFIG += testcase
+TARGET = tst_qdeclarativemetaobject
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativemetaobject.cpp
+
+include (../../shared/util.pri)
+
+testDataFiles.files = data
+testDataFiles.path = .
+DEPLOYMENT += testDataFiles
+
+CONFIG += parallel_test
+QT += declarative testlib
diff --git a/tests/auto/declarative/qdeclarativemetaobject/tst_qdeclarativemetaobject.cpp b/tests/auto/declarative/qdeclarativemetaobject/tst_qdeclarativemetaobject.cpp
new file mode 100644 (file)
index 0000000..424de87
--- /dev/null
@@ -0,0 +1,364 @@
+/****************************************************************************
+**
+** 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.
+**
+** $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 <QtTest/QtTest>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include "../../shared/util.h"
+
+Q_DECLARE_METATYPE(QMetaMethod::MethodType)
+
+class MyQmlObject : public QObject
+{
+    Q_OBJECT
+};
+QML_DECLARE_TYPE(MyQmlObject)
+
+class tst_QDeclarativeMetaObject : public QDeclarativeDataTest
+{
+    Q_OBJECT
+private slots:
+    void initTestCase();
+
+    void property_data();
+    void property();
+    void method_data();
+    void method();
+
+private:
+    MyQmlObject myQmlObject;
+};
+
+void tst_QDeclarativeMetaObject::initTestCase()
+{
+    QDeclarativeDataTest::initTestCase();
+
+    qmlRegisterType<MyQmlObject>("Qt.test", 1,0, "MyQmlObject");
+}
+
+void tst_QDeclarativeMetaObject::property_data()
+{
+    QTest::addColumn<QString>("testFile");
+    QTest::addColumn<QByteArray>("cppTypeName");
+    QTest::addColumn<int>("cppType");
+    QTest::addColumn<bool>("isDefault");
+    QTest::addColumn<QVariant>("expectedValue");
+    QTest::addColumn<bool>("isWritable");
+    QTest::addColumn<QVariant>("newValue");
+
+    QTest::newRow("int") << "property.int.qml"
+            << QByteArray("int") << int(QMetaType::Int)
+            << false // default
+            << QVariant(19) << true << QVariant(42);
+    QTest::newRow("bool") << "property.bool.qml"
+            << QByteArray("bool") << int(QMetaType::Bool)
+            << true // default
+            << QVariant(true) << true << QVariant(false);
+    QTest::newRow("real") << "property.real.qml"
+            << QByteArray("double") << int(QMetaType::Double)
+            << false // default
+            << QVariant(double(21))
+            << true // writable
+            << QVariant(double(37));
+    QTest::newRow("string") << "property.string.qml"
+            << QByteArray("QString") << int(QMetaType::QString)
+            << true // default
+            << QVariant(QString::fromLatin1("dog"))
+            << true // writable
+            << QVariant(QString::fromLatin1("food"));
+    QTest::newRow("url") << "property.url.qml"
+            << QByteArray("QUrl") << int(QMetaType::QUrl)
+            << false // default
+            << QVariant(QUrl("http://foo.bar"))
+            << true //writable
+            << QVariant(QUrl("http://bar.baz"));
+    QTest::newRow("color") << "property.color.qml"
+            << QByteArray("QColor") << int(QMetaType::QColor)
+            << true // default
+            << QVariant(QColor("#ff0000"))
+            << true // writable
+            << QVariant(QColor("#00ff00"));
+    QTest::newRow("date") << "property.date.qml"
+            << QByteArray("QDateTime") << int(QMetaType::QDateTime)
+            << false // default
+            << QVariant(QDateTime(QDate(2012, 2, 7)))
+            << true // writable
+            << QVariant(QDateTime(QDate(2010, 7, 2)));
+    QTest::newRow("variant") << "property.variant.qml"
+            << QByteArray("QVariant") << int(QMetaType::QVariant)
+            << true // default
+            << QVariant(QPointF(12, 34))
+            << true // writable
+            << QVariant(QSizeF(45, 67));
+    QTest::newRow("var") << "property.var.qml"
+            << QByteArray("QVariant") << int(QMetaType::QVariant)
+            << false // default
+            << QVariant(QVariantList() << 5 << true << "ciao")
+            << true // writable
+            << QVariant(QVariantList() << 17.0);
+    QTest::newRow("QtObject") << "property.QtObject.qml"
+            << QByteArray("QObject*") << int(QMetaType::QObjectStar)
+            << false // default
+            << QVariant()
+            << true // writable
+            << QVariant::fromValue(static_cast<QObject*>(this));
+    QTest::newRow("list<QtObject>") << "property.list.QtObject.qml"
+            << QByteArray("QDeclarativeListProperty<QObject>")
+            << qMetaTypeId<QDeclarativeListProperty<QObject> >()
+            << false // default
+            << QVariant()
+            << false // writable
+            << QVariant();
+    QTest::newRow("MyQmlObject") << "property.MyQmlObject.qml"
+            << QByteArray("MyQmlObject*") << qMetaTypeId<MyQmlObject*>()
+            << false // default
+            << QVariant()
+            << true // writable
+            << QVariant::fromValue(&myQmlObject);
+    QTest::newRow("list<MyQmlObject>") << "property.list.MyQmlObject.qml"
+            << QByteArray("QDeclarativeListProperty<MyQmlObject>")
+            << qMetaTypeId<QDeclarativeListProperty<MyQmlObject> >()
+            << false // default
+            << QVariant()
+            << false // writable
+            << QVariant();
+    QTest::newRow("alias") << "property.alias.qml"
+            << QByteArray("QString") << int(QMetaType::QString)
+            << false // default
+            << QVariant(QString::fromLatin1("Joe"))
+            << true // writable
+            << QVariant(QString::fromLatin1("Bob"));
+    QTest::newRow("alias-2") << "property.alias.2.qml"
+            << QByteArray("QObject*") << int(QMetaType::QObjectStar)
+            << false // default
+            << QVariant()
+            << false // writable
+            << QVariant();
+    QTest::newRow("alias-3") << "property.alias.3.qml"
+            << QByteArray("QString") << int(QMetaType::QString)
+            << false // default
+            << QVariant(QString::fromLatin1("Arial"))
+            << true // writable
+            << QVariant(QString::fromLatin1("Helvetica"));
+}
+
+void tst_QDeclarativeMetaObject::property()
+{
+    QFETCH(QString, testFile);
+    QFETCH(QByteArray, cppTypeName);
+    QFETCH(int, cppType);
+    QFETCH(bool, isDefault);
+    QFETCH(QVariant, expectedValue);
+    QFETCH(bool, isWritable);
+    QFETCH(QVariant, newValue);
+
+    QDeclarativeEngine engine;
+    QDeclarativeComponent component(&engine, testFileUrl(testFile));
+    QObject *object = component.create();
+    QVERIFY(object != 0);
+
+    const QMetaObject *mo = object->metaObject();
+    QVERIFY(mo->superClass() != 0);
+    QVERIFY(QByteArray(mo->className()).contains("_QML_"));
+    QCOMPARE(mo->propertyOffset(), mo->superClass()->propertyCount());
+    QCOMPARE(mo->propertyCount(), mo->superClass()->propertyCount() + 1);
+
+    QMetaProperty prop = mo->property(mo->propertyOffset());
+    QCOMPARE(prop.name(), "test");
+
+    QCOMPARE(QByteArray(prop.typeName()), cppTypeName);
+    QEXPECT_FAIL("QtObject", "prop.type() returns UserType for QtObject properties", Continue);
+    QEXPECT_FAIL("alias-2", "prop.type() returns UserType for QtObject properties", Continue);
+    if (prop.userType() < QMetaType::User)
+        QCOMPARE(prop.type(), QVariant::Type(cppType));
+    QCOMPARE(prop.userType(), cppType);
+
+    QVERIFY(!prop.isConstant());
+    QVERIFY(!prop.isDesignable());
+    QVERIFY(!prop.isEnumType());
+    QVERIFY(!prop.isFinal());
+    QVERIFY(!prop.isFlagType());
+    QVERIFY(prop.isReadable());
+    QVERIFY(!prop.isResettable());
+    QVERIFY(prop.isScriptable());
+    QVERIFY(!prop.isStored());
+    QVERIFY(!prop.isUser());
+    QVERIFY(prop.isValid());
+    QCOMPARE(prop.isWritable(), isWritable);
+
+    QCOMPARE(mo->classInfoOffset(), mo->superClass()->classInfoCount());
+    QCOMPARE(mo->classInfoCount(), mo->superClass()->classInfoCount() + (isDefault ? 1 : 0));
+    if (isDefault) {
+        QMetaClassInfo info = mo->classInfo(mo->classInfoOffset());
+        QCOMPARE(info.name(), "DefaultProperty");
+        QCOMPARE(info.value(), "test");
+    }
+
+    QCOMPARE(mo->methodOffset(), mo->superClass()->methodCount());
+    QCOMPARE(mo->methodCount(), mo->superClass()->methodCount() + 1); // the signal
+
+    QVERIFY(prop.notifySignalIndex() != -1);
+    QMetaMethod signal = prop.notifySignal();
+    QCOMPARE(signal.methodType(), QMetaMethod::Signal);
+    QCOMPARE(signal.signature(), "testChanged()");
+    QCOMPARE(signal.access(), QMetaMethod::Protected);
+    QCOMPARE(signal.parameterTypes(), QList<QByteArray>());
+    QCOMPARE(signal.parameterNames(), QList<QByteArray>());
+    QCOMPARE(signal.tag(), "");
+    QCOMPARE(signal.typeName(), "");
+
+    QSignalSpy changedSpy(object, SIGNAL(testChanged()));
+    QObject::connect(object, SIGNAL(testChanged()), object, SLOT(deleteLater()));
+
+    if (expectedValue.isValid())
+        QCOMPARE(prop.read(object), expectedValue);
+    else
+        QVERIFY(prop.read(object).isValid());
+    QCOMPARE(changedSpy.count(), 0);
+
+    if (isWritable) {
+        QVERIFY(prop.write(object, newValue));
+        QCOMPARE(changedSpy.count(), 1);
+        QCOMPARE(prop.read(object), newValue);
+    } else {
+        QVERIFY(!prop.write(object, prop.read(object)));
+        QCOMPARE(changedSpy.count(), 0);
+    }
+
+    delete object;
+}
+
+void tst_QDeclarativeMetaObject::method_data()
+{
+    QTest::addColumn<QString>("testFile");
+    QTest::addColumn<QString>("signature");
+    QTest::addColumn<QMetaMethod::MethodType>("methodType");
+    QTest::addColumn<QString>("returnTypeName");
+    QTest::addColumn<QList<QByteArray> >("parameterTypeNames");
+    QTest::addColumn<QList<QByteArray> >("parameterNames");
+
+    QTest::newRow("testFunction()") << "method.1.qml"
+            << "testFunction()"
+            << QMetaMethod::Slot
+            << "QVariant"
+            << QList<QByteArray>()
+            << QList<QByteArray>();
+    QTest::newRow("testFunction(foo)") << "method.2.qml"
+            << "testFunction(QVariant)"
+            << QMetaMethod::Slot
+            << "QVariant"
+            << (QList<QByteArray>() << "QVariant")
+            << (QList<QByteArray>() << "foo");
+    QTest::newRow("testFunction(foo, bar, baz)") << "method.3.qml"
+            << "testFunction(QVariant,QVariant,QVariant)"
+            << QMetaMethod::Slot
+            << "QVariant"
+            << (QList<QByteArray>() << "QVariant" << "QVariant" << "QVariant")
+            << (QList<QByteArray>() << "foo" << "bar" << "baz");
+    QTest::newRow("testSignal") << "signal.1.qml"
+            << "testSignal()"
+            << QMetaMethod::Signal
+            << ""
+            << QList<QByteArray>()
+            << QList<QByteArray>();
+    QTest::newRow("testSignal(string foo)") << "signal.2.qml"
+            << "testSignal(QString)"
+            << QMetaMethod::Signal
+            << ""
+            << (QList<QByteArray>() << "QString")
+            << (QList<QByteArray>() << "foo");
+    QTest::newRow("testSignal(int foo, bool bar, real baz)") << "signal.3.qml"
+            << "testSignal(int,bool,qreal)"
+            << QMetaMethod::Signal
+            << ""
+            << (QList<QByteArray>() << "int" << "bool" << "qreal")
+            << (QList<QByteArray>() << "foo" << "bar" << "baz");
+    QTest::newRow("testSignal(variant foo, var bar)") << "signal.4.qml"
+            << "testSignal(QVariant,QVariant)"
+            << QMetaMethod::Signal
+            << ""
+            << (QList<QByteArray>() << "QVariant" << "QVariant")
+            << (QList<QByteArray>() << "foo" << "bar");
+    QTest::newRow("testSignal(color foo, date bar, url baz)") << "signal.5.qml"
+            << "testSignal(QColor,QDateTime,QUrl)"
+            << QMetaMethod::Signal
+            << ""
+            << (QList<QByteArray>() << "QColor" << "QDateTime" << "QUrl")
+            << (QList<QByteArray>() << "foo" << "bar" << "baz");
+}
+
+void tst_QDeclarativeMetaObject::method()
+{
+    QFETCH(QString, testFile);
+    QFETCH(QString, signature);
+    QFETCH(QMetaMethod::MethodType, methodType);
+    QFETCH(QString, returnTypeName);
+    QFETCH(QList<QByteArray>, parameterTypeNames);
+    QFETCH(QList<QByteArray>, parameterNames);
+
+    QCOMPARE(parameterTypeNames.size(), parameterNames.size());
+
+    QDeclarativeEngine engine;
+    QDeclarativeComponent component(&engine, testFileUrl(testFile));
+    QObject *object = component.create();
+    QVERIFY(object != 0);
+
+    const QMetaObject *mo = object->metaObject();
+    QVERIFY(mo->superClass() != 0);
+    QVERIFY(QByteArray(mo->className()).contains("_QML_"));
+    QCOMPARE(mo->methodOffset(), mo->superClass()->methodCount());
+    QCOMPARE(mo->methodCount(), mo->superClass()->methodCount() + 1);
+
+    QMetaMethod method = mo->method(mo->methodOffset());
+    QCOMPARE(method.methodType(), methodType);
+    QCOMPARE(QString::fromUtf8(method.signature()), signature);
+    QCOMPARE(method.access(), QMetaMethod::Protected);
+    QCOMPARE(method.parameterTypes(), parameterTypeNames);
+    QCOMPARE(method.parameterNames(), parameterNames);
+    QCOMPARE(method.tag(), "");
+    QCOMPARE(QString::fromUtf8(method.typeName()), returnTypeName);
+
+    delete object;
+}
+
+QTEST_MAIN(tst_QDeclarativeMetaObject)
+
+#include "tst_qdeclarativemetaobject.moc"