From b5d7878e1a9ec23d0619146c82b4cae222f73ebf Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Tue, 10 Aug 2021 22:11:57 +0300 Subject: [PATCH] add QMetaObject test Signed-off-by: Ivailo Monev --- tests/auto/qmetaobject/CMakeLists.txt | 3 + tests/auto/qmetaobject/tst_qmetaobject.cpp | 1100 ++++++++++++++++++++ 2 files changed, 1103 insertions(+) create mode 100644 tests/auto/qmetaobject/CMakeLists.txt create mode 100644 tests/auto/qmetaobject/tst_qmetaobject.cpp diff --git a/tests/auto/qmetaobject/CMakeLists.txt b/tests/auto/qmetaobject/CMakeLists.txt new file mode 100644 index 000000000..57f9915a2 --- /dev/null +++ b/tests/auto/qmetaobject/CMakeLists.txt @@ -0,0 +1,3 @@ +katie_gui_test(tst_qmetaobject + ${CMAKE_CURRENT_SOURCE_DIR}/tst_qmetaobject.cpp +) diff --git a/tests/auto/qmetaobject/tst_qmetaobject.cpp b/tests/auto/qmetaobject/tst_qmetaobject.cpp new file mode 100644 index 000000000..5bf14d1fb --- /dev/null +++ b/tests/auto/qmetaobject/tst_qmetaobject.cpp @@ -0,0 +1,1100 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 Ivailo Monev +** +** This file is part of the test suite of the Katie 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. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include + +#include +#include +#include +#include +#include + +//TESTED_CLASS= +//TESTED_FILES= + +struct MyStruct +{ + int i; +}; + +namespace MyNamespace { + class MyClass : public QObject + { + Q_OBJECT + Q_PROPERTY(MyEnum myEnum READ myEnum WRITE setMyEnum) + Q_PROPERTY(MyFlags myFlags READ myFlags WRITE setMyFlags) + + Q_ENUMS(MyEnum) + Q_FLAGS(MyFlags) + public: + enum MyEnum { + MyEnum1, + MyEnum2, + MyEnum3 + }; + + enum MyFlag { + MyFlag1 = 0x01, + MyFlag2 = 0x02, + MyFlag3 = 0x04 + }; + Q_DECLARE_FLAGS(MyFlags, MyFlag) + + MyEnum myEnum() const { return m_enum; } + void setMyEnum(MyEnum val) { m_enum = val; } + + MyFlags myFlags() const { return m_flags; } + void setMyFlags(MyFlags val) { m_flags = val; } + + MyClass(QObject *parent = 0) + : QObject(parent), + m_enum(MyEnum1), + m_flags(MyFlag1|MyFlag2) + { } + private: + MyEnum m_enum; + MyFlags m_flags; + }; + Q_DECLARE_OPERATORS_FOR_FLAGS(MyClass::MyFlags) +} + + +class tst_QMetaObject : public QObject +{ + Q_OBJECT + Q_ENUMS(EnumType) + Q_PROPERTY(EnumType value WRITE setValue READ getValue) + Q_PROPERTY(EnumType value2 WRITE set_value READ get_value) + Q_PROPERTY(MyStruct value3 WRITE setVal3 READ val3) + Q_PROPERTY(QList value4 WRITE setVal4 READ val4) + Q_PROPERTY(QVariantList value5 WRITE setVal5 READ val5) + Q_PROPERTY(int value6 READ value6 NOTIFY value6Changed) + Q_PROPERTY(MyStruct value7 READ value7 WRITE setVal7 NOTIFY value7Changed) + Q_PROPERTY(int value8 READ value8) + Q_PROPERTY(int value9 READ value9 CONSTANT) + Q_PROPERTY(int value10 READ value10 FINAL) + +public: + enum EnumType { EnumType1 }; + + tst_QMetaObject(); + ~tst_QMetaObject(); + + void setValue(EnumType) {} + EnumType getValue() const { return EnumType1; } + + void set_value(EnumType) {} + EnumType get_value() const { return EnumType1; } + + void setVal3(MyStruct) {} + MyStruct val3() const { MyStruct s = {42}; return s; } + + void setVal4(const QList &list) { value4 = list; } + QList val4() const { return value4; } + + void setVal5(const QVariantList &list) { value5 = list; } + QVariantList val5() const { return value5; } + + int value6() const { return 1; } + + void setVal7(MyStruct) {} + MyStruct value7() const { MyStruct s = {42}; return s; } + + int value8() const { return 1; } + + int value9() const { return 1; } + + int value10() const { return 1; } + + QList value4; + QVariantList value5; + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); +private slots: + void connectSlotsByName(); + void invokeMetaMember(); + void invokeQueuedMetaMember(); + void invokeBlockingQueuedMetaMember(); + void invokeCustomTypes(); + void invokeMetaConstructor(); + void invokeTypedefTypes(); + void qtMetaObjectInheritance(); + void normalizedSignature_data(); + void normalizedSignature(); + void normalizedType_data(); + void normalizedType(); + void customPropertyType(); + void checkScope(); + void propertyNotify(); + void propertyConstant(); + void propertyFinal(); + + void stdSet(); + void classInfo(); + + void metaMethod(); + + void indexOfMethod_data(); + void indexOfMethod(); + +signals: + void value6Changed(); + void value7Changed(const QString &); +}; + +tst_QMetaObject::tst_QMetaObject() +{ + +} + +tst_QMetaObject::~tst_QMetaObject() +{ + +} + +void tst_QMetaObject::initTestCase() +{ +} + +void tst_QMetaObject::cleanupTestCase() +{ +} + +void tst_QMetaObject::init() +{ +} + +void tst_QMetaObject::cleanup() +{ +} + +void tst_QMetaObject::stdSet() +{ + const QMetaObject *mo = metaObject(); + + QMetaProperty prop = mo->property(mo->indexOfProperty("value")); + QVERIFY(prop.isValid()); + QVERIFY(prop.hasStdCppSet()); + + prop = mo->property(mo->indexOfProperty("value2")); + QVERIFY(prop.isValid()); + QVERIFY(!prop.hasStdCppSet()); +} + +class CTestObject: public QObject +{ + Q_OBJECT + +public: + CTestObject(): QObject(), invokeCount1(0), invokeCount2(0) + { + } + + void fire(const QString &name) + { + child = new QObject(this); + child->setObjectName(name); + QMetaObject::connectSlotsByName(this); + delete child; child = 0; + } + + int invokeCount1; + int invokeCount2; + QObject *child; + +public slots: + void on_child1_destroyed(QObject *obj = 0) + { + ++invokeCount1; + if (!obj || obj != child) + qWarning() << "on_child1_destroyed invoked with wrong child object"; + } + void on_child2_destroyed() { ++invokeCount2; } +}; + +class CTestObjectOverloads: public QObject +{ + Q_OBJECT + +public: + CTestObjectOverloads(): invokeCount1(0), invokeCount2(0) {} + + int invokeCount1; + int invokeCount2; + QObject *child; + + void fire(const QString &name) + { + child = new QObject(this); + child->setObjectName(name); + QMetaObject::connectSlotsByName(this); + delete child; child = 0; + } + +private slots: + void on_child1_destroyed(QObject *obj) + { + ++invokeCount1; + if (!obj || obj != child) + qWarning() << "on_child1_destroyed invoked with wrong child object"; + } + void on_child1_destroyed() { ++invokeCount2; } +}; + +#define FUNCTION(x) "QMetaObject::" x ": " + +void tst_QMetaObject::connectSlotsByName() +{ + CTestObject obj; + QCOMPARE(obj.invokeCount1, 0); + QCOMPARE(obj.invokeCount2, 0); + + QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child1_destroyed(QObject*)"); + QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child2_destroyed()"); + obj.fire("bubu"); + QCOMPARE(obj.invokeCount1, 0); + QCOMPARE(obj.invokeCount2, 0); + + QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child2_destroyed()"); + obj.fire("child1"); + QCOMPARE(obj.invokeCount1, 1); + QCOMPARE(obj.invokeCount2, 0); + + QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child1_destroyed(QObject*)"); + obj.fire("child2"); + QCOMPARE(obj.invokeCount1, 1); + QCOMPARE(obj.invokeCount2, 1); + + QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child2_destroyed()"); + obj.fire("child1"); + QCOMPARE(obj.invokeCount1, 2); + QCOMPARE(obj.invokeCount2, 1); + + // now test with real overloads + CTestObjectOverloads obj2; + obj2.fire("child1"); + QCOMPARE(obj2.invokeCount1, 1); + QCOMPARE(obj2.invokeCount2, 1); +} + +class QtTestObject: public QObject +{ + Q_OBJECT + +public: + QtTestObject(); + Q_INVOKABLE QtTestObject(QObject *parent); + +public slots: + void sl0(); + QString sl1(QString s1); + void sl2(QString s1, QString s2); + void sl3(QString s1, QString s2, QString s3); + void sl4(QString s1, QString s2, QString s3, const QString s4); + void sl5(QString s1, QString s2, QString s3, QString s4, const QString &s5); + void sl6(QString s1, QString s2, QString s3, QString s4, const QString s5, QString s6); + void sl7(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7); + void sl8(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, + QString s8); + void sl9(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, + QString s8, QString s9); + void sl10(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, + QString s8, QString s9, QString s10); + QObject *sl11(); + const char *sl12(); + QList sl13(QList l1); + void testSender(); + + void testReference(QString &str); + + void testLongLong(qint64 ll1, quint64 ll2); + + void moveToThread(QThread *t) + { QObject::moveToThread(t); } + +signals: + void sig0(); + QString sig1(QString s1); + +protected: + QtTestObject(QVariant) {} +private: + QtTestObject(QVariant, QVariant) {} + +public: + QString slotResult; +}; + +QtTestObject::QtTestObject() +{ + connect(this, SIGNAL(sig0()), this, SLOT(sl0())); + connect(this, SIGNAL(sig1(QString)), this, SLOT(sl1(QString))); +} + +QtTestObject::QtTestObject(QObject *parent) + : QObject(parent) +{ +} + +void QtTestObject::sl0() { slotResult = "sl0"; }; +QString QtTestObject::sl1(QString s1) { slotResult = "sl1:" + s1; return "yessir"; } +void QtTestObject::sl2(QString s1, QString s2) { slotResult = "sl2:" + s1 + s2; } +void QtTestObject::sl3(QString s1, QString s2, QString s3) +{ slotResult = "sl3:" + s1 + s2 + s3; } +void QtTestObject::sl4(QString s1, QString s2, QString s3, const QString s4) +{ slotResult = "sl4:" + s1 + s2 + s3 + s4; } +void QtTestObject::sl5(QString s1, QString s2, QString s3, QString s4, const QString &s5) +{ slotResult = "sl5:" + s1 + s2 + s3 + s4 + s5; } +void QtTestObject::sl6(QString s1, QString s2, QString s3, QString s4, + const QString s5, QString s6) +{ slotResult = "sl6:" + s1 + s2 + s3 + s4 + s5 + s6; } +void QtTestObject::sl7(QString s1, QString s2, QString s3, QString s4, QString s5, + QString s6, QString s7) +{ slotResult = "sl7:" + s1 + s2 + s3 + s4 + s5 + s6 + s7; } +void QtTestObject::sl8(QString s1, QString s2, QString s3, QString s4, QString s5, + QString s6, QString s7, QString s8) +{ slotResult = "sl8:" + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8; } +void QtTestObject::sl9(QString s1, QString s2, QString s3, QString s4, QString s5, + QString s6, QString s7, QString s8, QString s9) +{ slotResult = "sl9:" + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9; } +void QtTestObject::sl10(QString s1, QString s2, QString s3, QString s4, QString s5, + QString s6, QString s7, QString s8, QString s9, QString s10) +{ slotResult = "sl10:" + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10; } +QObject *QtTestObject::sl11() +{ slotResult = "sl11"; return this; } +const char *QtTestObject::sl12() +{ slotResult = "sl12"; return "foo"; } +QList QtTestObject::sl13(QList l1) +{ slotResult = "sl13"; return l1; } +void QtTestObject::testReference(QString &str) +{ slotResult = "testReference:" + str; str = "gotcha"; } + +void QtTestObject::testLongLong(qint64 ll1, quint64 ll2) +{ slotResult = "testLongLong:" + QString::number(ll1) + "," + QString::number(ll2); } + +void QtTestObject::testSender() +{ + slotResult.sprintf("%p", sender()); +} + + +void tst_QMetaObject::invokeMetaMember() +{ + QtTestObject obj; + + QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5"); + QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X"); + + QVERIFY(!QMetaObject::invokeMethod(0, 0)); + QVERIFY(!QMetaObject::invokeMethod(0, "sl0")); + QVERIFY(!QMetaObject::invokeMethod(&obj, 0)); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl0")); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, t1))); + QCOMPARE(obj.slotResult, QString("sl1:1")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", Q_ARG(const QString, t1), Q_ARG(QString, t2))); + QCOMPARE(obj.slotResult, QString("sl2:12")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3))); + QCOMPARE(obj.slotResult, QString("sl3:123")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), + Q_ARG(QString, t4))); + QCOMPARE(obj.slotResult, QString("sl4:1234")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), + Q_ARG(QString, t4), Q_ARG(QString, "5"))); + QCOMPARE(obj.slotResult, QString("sl5:12345")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), + Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6))); + QCOMPARE(obj.slotResult, QString("sl6:123456")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), + Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), + Q_ARG(QString, t7))); + QCOMPARE(obj.slotResult, QString("sl7:1234567")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), + Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), + Q_ARG(QString, t7), Q_ARG(QString, t8))); + QCOMPARE(obj.slotResult, QString("sl8:12345678")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), + Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), + Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9))); + QCOMPARE(obj.slotResult, QString("sl9:123456789")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11")); + QCOMPARE(obj.slotResult, QString("sl11")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "testSender")); + QCOMPARE(obj.slotResult, QString("0x0")); + + QString refStr("whatever"); + QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", QGenericArgument("QString&", &refStr))); + QCOMPARE(obj.slotResult, QString("testReference:whatever")); + QCOMPARE(refStr, QString("gotcha")); + + qint64 ll1 = -1; + quint64 ll2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, + "testLongLong", + Q_ARG(qint64, ll1), + Q_ARG(quint64, ll2))); + QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); + + QString exp; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_RETURN_ARG(QString, exp), Q_ARG(QString, "bubu"))); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:bubu")); + + QObject *ptr = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Q_RETURN_ARG(QObject*,ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + // try again with a space: + ptr = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Q_RETURN_ARG(QObject * , ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + + const char *ptr2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Q_RETURN_ARG(const char*, ptr2))); + QVERIFY(ptr2 != 0); + QCOMPARE(obj.slotResult, QString("sl12")); + // try again with a space: + ptr2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Q_RETURN_ARG(char const * , ptr2))); + QVERIFY(ptr2 != 0); + QCOMPARE(obj.slotResult, QString("sl12")); + + // test w/ template args + QList returnValue, argument; + argument << QString("one") << QString("two") << QString("three"); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl13", + Q_RETURN_ARG(QList, returnValue), + Q_ARG(QList, argument))); + QCOMPARE(returnValue, argument); + QCOMPARE(obj.slotResult, QString("sl13")); + + //test signals + QVERIFY(QMetaObject::invokeMethod(&obj, "sig0")); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Q_ARG(QString, "baba"))); + QCOMPARE(obj.slotResult, QString("sl1:baba")); + + exp.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Q_RETURN_ARG(QString, exp), Q_ARG(QString, "hehe"))); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:hehe")); + + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist")); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Q_ARG(QString, "arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Q_ARG(QString, "arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, "arg"), Q_ARG(QString, "arg"), Q_ARG(QString, "arg"))); + + //should not have changed since last test. + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:hehe")); +} + +void tst_QMetaObject::invokeQueuedMetaMember() +{ + QtTestObject obj; + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl0", Qt::QueuedConnection)); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl0")); + obj.slotResult = QString(); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::QueuedConnection, Q_ARG(QString, QString("hallo")))); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl1:hallo")); + obj.slotResult = QString(); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::QueuedConnection, Q_ARG(QString, "1"), Q_ARG(QString, "2"), + Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"), + Q_ARG(QString, "6"), Q_ARG(QString, "7"), Q_ARG(QString, "8"), + Q_ARG(QString, "9"))); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl9:123456789")); + + // signals + + obj.slotResult.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::QueuedConnection)); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::QueuedConnection, Q_ARG(QString, "gogo"))); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl1:gogo")); + + QString exp; + QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to invoke methods with return values in queued connections"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sig1", Qt::QueuedConnection, Q_RETURN_ARG(QString, exp), + Q_ARG(QString, "nono"))); + + qint64 ll1 = -1; + quint64 ll2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, + "testLongLong", + Qt::QueuedConnection, + Q_ARG(qint64, ll1), + Q_ARG(quint64, ll2))); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); +} + +void tst_QMetaObject::invokeBlockingQueuedMetaMember() +{ + QThread t; + t.start(); + QtTestObject obj; + obj.moveToThread(&t); + + QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5"); + QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X"); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_ARG(QString, t1))); + QCOMPARE(obj.slotResult, QString("sl1:1")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", Qt::BlockingQueuedConnection, Q_ARG(const QString, t1), Q_ARG(QString, t2))); + QCOMPARE(obj.slotResult, QString("sl2:12")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3))); + QCOMPARE(obj.slotResult, QString("sl3:123")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4))); + QCOMPARE(obj.slotResult, QString("sl4:1234")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, "5"))); + QCOMPARE(obj.slotResult, QString("sl5:12345")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6))); + QCOMPARE(obj.slotResult, QString("sl6:123456")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), + Q_ARG(QString, t7))); + QCOMPARE(obj.slotResult, QString("sl7:1234567")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), + Q_ARG(QString, t7), Q_ARG(QString, t8))); + QCOMPARE(obj.slotResult, QString("sl8:12345678")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), + Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), + Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9))); + QCOMPARE(obj.slotResult, QString("sl9:123456789")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("sl11")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "testSender", Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("0x0")); + + QString refStr("whatever"); + QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, QGenericArgument("QString&", &refStr))); + QCOMPARE(obj.slotResult, QString("testReference:whatever")); + QCOMPARE(refStr, QString("gotcha")); + + qint64 ll1 = -1; + quint64 ll2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, + "testLongLong", + Qt::BlockingQueuedConnection, + Q_ARG(qint64, ll1), + Q_ARG(quint64, ll2))); + QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); + + QString exp; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, exp), Q_ARG(QString, "bubu"))); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:bubu")); + + QObject *ptr = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QObject*,ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + // try again with a space: + ptr = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QObject * , ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + + const char *ptr2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, Q_RETURN_ARG(const char*, ptr2))); + QVERIFY(ptr2 != 0); + QCOMPARE(obj.slotResult, QString("sl12")); + // try again with a space: + ptr2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, Q_RETURN_ARG(char const * , ptr2))); + QVERIFY(ptr2 != 0); + QCOMPARE(obj.slotResult, QString("sl12")); + + // test w/ template args + QList returnValue, argument; + argument << QString("one") << QString("two") << QString("three"); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl13", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QList, returnValue), + Q_ARG(QList, argument))); + QCOMPARE(returnValue, argument); + QCOMPARE(obj.slotResult, QString("sl13")); + + //test signals + QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_ARG(QString, "baba"))); + QCOMPARE(obj.slotResult, QString("sl1:baba")); + + exp.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, exp), Q_ARG(QString, "hehe"))); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:hehe")); + + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection)); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"), Q_ARG(QString, "arg"), Q_ARG(QString, "arg"))); + + //should not have changed since last test. + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:hehe")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "moveToThread", Qt::BlockingQueuedConnection, Q_ARG(QThread*, QThread::currentThread()))); + t.quit(); + QVERIFY(t.wait()); +} + +void tst_QMetaObject::qtMetaObjectInheritance() +{ + QVERIFY(QObject::staticMetaObject.superClass() == 0); + QCOMPARE(QLabel::staticMetaObject.indexOfEnumerator("Qt::Alignment"), -1); + QCOMPARE(QLabel::staticMetaObject.indexOfEnumerator("Alignment"), -1); + int indexOfAlignment = QLabel::staticMetaObject.indexOfProperty("alignment"); + QVERIFY(indexOfAlignment != -1); + QMetaProperty alignment = QLabel::staticMetaObject.property(indexOfAlignment); + QVERIFY(alignment.isValid()); + QCOMPARE(alignment.enumerator().name(), "Alignment"); +} + +struct MyType +{ + int i1, i2, i3; +}; + +typedef QString CustomString; + +class QtTestCustomObject: public QObject +{ + Q_OBJECT +public: + QtTestCustomObject(): QObject(), sum(0) {} + +public slots: + void sl1(MyType myType); + +signals: + void sig_custom(const CustomString &string); + +public: + int sum; +}; + +void QtTestCustomObject::sl1(MyType myType) +{ + sum = myType.i1 + myType.i2 + myType.i3; +} + +void tst_QMetaObject::invokeCustomTypes() +{ + QtTestCustomObject obj; + MyType tp = {1, 1, 1}; + + QCOMPARE(obj.sum, 0); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(MyType, tp))); + QCOMPARE(obj.sum, 3); +} + +namespace NamespaceWithConstructibleClass +{ + +class ConstructibleClass : public QObject +{ + Q_OBJECT +public: + Q_INVOKABLE ConstructibleClass(QObject *parent = 0) + : QObject(parent) {} +}; + +} + +void tst_QMetaObject::invokeMetaConstructor() +{ + const QMetaObject *mo = &QtTestObject::staticMetaObject; + { + QObject *obj = mo->newInstance(); + QVERIFY(obj == 0); + } + { + QtTestObject obj; + QObject *obj2 = mo->newInstance(Q_ARG(QObject*, &obj)); + QVERIFY(obj2 != 0); + QCOMPARE(obj2->parent(), (QObject*)&obj); + QVERIFY(qobject_cast(obj2) != 0); + } + // class in namespace + const QMetaObject *nsmo = &NamespaceWithConstructibleClass::ConstructibleClass::staticMetaObject; + { + QtTestObject obj; + QObject *obj2 = nsmo->newInstance(Q_ARG(QObject*, &obj)); + QVERIFY(obj2 != 0); + QCOMPARE(obj2->parent(), (QObject*)&obj); + QVERIFY(qobject_cast(obj2) != 0); + } +} + +void tst_QMetaObject::invokeTypedefTypes() +{ + qRegisterMetaType("CustomString"); + QtTestCustomObject obj; + QSignalSpy spy(&obj, SIGNAL(sig_custom(CustomString))); + + QCOMPARE(spy.count(), 0); + CustomString arg("hello"); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig_custom", Q_ARG(CustomString, arg))); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.at(0).count(), 1); + QCOMPARE(spy.at(0).at(0), QVariant(arg)); +} + +void tst_QMetaObject::normalizedSignature_data() +{ + QTest::addColumn("signature"); + QTest::addColumn("result"); + + QTest::newRow("function") << "void foo()" << "void foo()"; + QTest::newRow("spaces") << " void foo( ) " << "void foo()"; + QTest::newRow("template args") << " void foo( QMap, QList) " + << "void foo(QMap,QList)"; + QTest::newRow("rettype") << "QList foo()" << "QListfoo()"; + QTest::newRow("const rettype") << "const QString *foo()" << "const QString*foo()"; + QTest::newRow("const ref") << "const QString &foo()" << "const QString&foo()"; + QTest::newRow("reference") << "QString &foo()" << "QString&foo()"; + QTest::newRow("const1") << "void foo(QString const *)" << "void foo(const QString*)"; + QTest::newRow("const2") << "void foo(QString * const)" << "void foo(QString*const)"; + QTest::newRow("const3") << "void foo(QString const &)" << "void foo(QString)"; + QTest::newRow("const4") << "void foo(const int)" << "void foo(int)"; + QTest::newRow("const5") << "void foo(const int, int const, const int &, int const &)" + << "void foo(int,int,int,int)"; + QTest::newRow("const6") << "void foo(QList)" << "void foo(QList)"; + QTest::newRow("const7") << "void foo(QList)" << "void foo(QList)"; + QTest::newRow("const8") << "void foo(QList)" << "void foo(QList)"; + QTest::newRow("const9") << "void foo(const Foo)" << "void foo(Foo)"; + QTest::newRow("const10") << "void foo(Fooconst)" << "void foo(Foo)"; + QTest::newRow("const11") << "void foo(Foo *const)" << "void foo(Foo*const)"; + QTest::newRow("const12") << "void foo(Fooconst*const *const)" << "void foo(Foo*const*const)"; + QTest::newRow("const13") << "void foo(const Foo&)" << "void foo(Foo)"; + QTest::newRow("const14") << "void foo(Fooconst&)" << "void foo(Foo)"; + + QTest::newRow("invalid1") << "a( b" << "a(b"; +} + +void tst_QMetaObject::normalizedSignature() +{ + QFETCH(QString, signature); + QFETCH(QString, result); + + QCOMPARE(QMetaObject::normalizedSignature(signature.toLatin1()), result.toLatin1()); +} + +void tst_QMetaObject::normalizedType_data() +{ + QTest::addColumn("type"); + QTest::addColumn("result"); + + QTest::newRow("simple") << "int" << "int"; + QTest::newRow("white") << " int " << "int"; + QTest::newRow("const1") << "int const *" << "const int*"; + QTest::newRow("const2") << "const int *" << "const int*"; + QTest::newRow("template1") << "QList" << "QList"; + QTest::newRow("template2") << "QList" << "QList"; + QTest::newRow("template3") << "QMap" << "QMap"; + QTest::newRow("template4") << "const QMap &" << "QMap"; + QTest::newRow("template5") << "QList< ::Foo::Bar>" << "QList< ::Foo::Bar>"; + QTest::newRow("template6") << "QList<::Foo::Bar>" << "QList<::Foo::Bar>"; + QTest::newRow("template7") << "QList >" << "QList >"; + QTest::newRow("template8") << "QMap" << "QMap"; + QTest::newRow("template9") << "QPair , QPair > >" << "QPair,QPair > >"; + QTest::newRow("value1") << "const QString &" << "QString"; + QTest::newRow("value2") << "QString const &" << "QString"; + QTest::newRow("constInName1") << "constconst" << "constconst"; + QTest::newRow("constInName2") << "constconst*" << "constconst*"; + QTest::newRow("constInName3") << "const constconst&" << "constconst"; + QTest::newRow("constInName4") << "constconst const*const" << "constconst*const"; + QTest::newRow("class") << "const class foo&" << "foo"; + QTest::newRow("struct") << "const struct foo*" << "const foo*"; + QTest::newRow("struct2") << "struct foo const*" << "const foo*"; + QTest::newRow("enum") << "enum foo" << "foo"; +} + +void tst_QMetaObject::normalizedType() +{ + QFETCH(QString, type); + QFETCH(QString, result); + + QCOMPARE(QMetaObject::normalizedType(type.toLatin1()), result.toLatin1()); +} + +void tst_QMetaObject::customPropertyType() +{ + QMetaProperty prop = metaObject()->property(metaObject()->indexOfProperty("value3")); + + QCOMPARE(prop.type(), QVariant::UserType); + QCOMPARE(prop.userType(), 0); + + qRegisterMetaType("MyStruct"); + QCOMPARE(prop.userType(), QMetaType::type("MyStruct")); + + prop = metaObject()->property(metaObject()->indexOfProperty("value4")); + QCOMPARE(prop.type(), QVariant::List); + + prop = metaObject()->property(metaObject()->indexOfProperty("value5")); + QCOMPARE(prop.type(), QVariant::List); +} + +void tst_QMetaObject::checkScope() +{ + MyNamespace::MyClass obj; + + const QMetaObject *mo = obj.metaObject(); + QMetaEnum me = mo->enumerator(mo->indexOfEnumerator("MyEnum")); + QVERIFY(me.isValid()); + QVERIFY(!me.isFlag()); + QCOMPARE(QLatin1String(me.scope()), QLatin1String("MyNamespace::MyClass")); + QCOMPARE(me.keyToValue("MyNamespace::MyClass::MyEnum2"), 1); + QCOMPARE(me.keyToValue("MyClass::MyEnum2"), -1); + QCOMPARE(me.keyToValue("MyNamespace::MyEnum2"), -1); + QCOMPARE(me.keyToValue("MyEnum2"), 1); + QCOMPARE(me.keyToValue("MyEnum"), -1); + QCOMPARE(QLatin1String(me.valueToKey(1)), QLatin1String("MyEnum2")); + + QMetaEnum mf = mo->enumerator(mo->indexOfEnumerator("MyFlags")); + QVERIFY(mf.isValid()); + QVERIFY(mf.isFlag()); + QCOMPARE(QLatin1String(mf.scope()), QLatin1String("MyNamespace::MyClass")); + QCOMPARE(mf.keysToValue("MyNamespace::MyClass::MyFlag2"), 2); + QCOMPARE(mf.keysToValue("MyClass::MyFlag2"), -1); + QCOMPARE(mf.keysToValue("MyNamespace::MyFlag2"), -1); + QCOMPARE(mf.keysToValue("MyFlag2"), 2); + QCOMPARE(mf.keysToValue("MyFlag"), -1); + QCOMPARE(QLatin1String(mf.valueToKey(2)), QLatin1String("MyFlag2")); + QCOMPARE(mf.keysToValue("MyNamespace::MyClass::MyFlag1|MyNamespace::MyClass::MyFlag2"), 3); + QCOMPARE(mf.keysToValue("MyClass::MyFlag1|MyClass::MyFlag2"), -1); + QCOMPARE(mf.keysToValue("MyNamespace::MyFlag1|MyNamespace::MyFlag2"), -1); + QCOMPARE(mf.keysToValue("MyFlag1|MyFlag2"), 3); + QCOMPARE(mf.keysToValue("MyFlag2|MyFlag2"), 2); + QCOMPARE(mf.keysToValue("MyFlag1|MyNamespace::MyClass::MyFlag2"), 3); + QCOMPARE(mf.keysToValue("MyNamespace::MyClass::MyFlag2|MyNamespace::MyClass::MyFlag2"), 2); + QCOMPARE(QLatin1String(mf.valueToKeys(3)), QLatin1String("MyFlag1|MyFlag2")); +} + +void tst_QMetaObject::propertyNotify() +{ + const QMetaObject *mo = metaObject(); + + QMetaProperty prop = mo->property(mo->indexOfProperty("value6")); + QVERIFY(prop.isValid()); + QVERIFY(prop.hasNotifySignal()); + QMetaMethod signal = prop.notifySignal(); + QCOMPARE(signal.signature(), "value6Changed()"); + + prop = mo->property(mo->indexOfProperty("value7")); + QVERIFY(prop.isValid()); + QVERIFY(prop.hasNotifySignal()); + signal = prop.notifySignal(); + QCOMPARE(signal.signature(), "value7Changed(QString)"); + + prop = mo->property(mo->indexOfProperty("value8")); + QVERIFY(prop.isValid()); + QVERIFY(!prop.hasNotifySignal()); + signal = prop.notifySignal(); + QCOMPARE(signal.signature(), (const char *)0); + + prop = mo->property(mo->indexOfProperty("value")); + QVERIFY(prop.isValid()); + QVERIFY(!prop.hasNotifySignal()); + signal = prop.notifySignal(); + QCOMPARE(signal.signature(), (const char *)0); +} + +void tst_QMetaObject::propertyConstant() +{ + const QMetaObject *mo = metaObject(); + + QMetaProperty prop = mo->property(mo->indexOfProperty("value8")); + QVERIFY(prop.isValid()); + QVERIFY(!prop.isConstant()); + + prop = mo->property(mo->indexOfProperty("value9")); + QVERIFY(prop.isValid()); + QVERIFY(prop.isConstant()); +} + +void tst_QMetaObject::propertyFinal() +{ + const QMetaObject *mo = metaObject(); + + QMetaProperty prop = mo->property(mo->indexOfProperty("value10")); + QVERIFY(prop.isValid()); + QVERIFY(prop.isFinal()); + + prop = mo->property(mo->indexOfProperty("value9")); + QVERIFY(prop.isValid()); + QVERIFY(!prop.isFinal()); +} + +class ClassInfoTestObjectA : public QObject +{ + Q_OBJECT + Q_CLASSINFO("Author", "Christopher Pike") +}; + +class ClassInfoTestObjectB : public ClassInfoTestObjectA +{ + Q_OBJECT +}; + +void tst_QMetaObject::classInfo() +{ + ClassInfoTestObjectB b; + int index = b.metaObject()->indexOfClassInfo("Author"); + QCOMPARE(index, 0); + QVERIFY(index <= b.metaObject()->classInfoOffset()); + QCOMPARE(QLatin1String(b.metaObject()->classInfo(index).value()), QLatin1String("Christopher Pike")); +} + +void tst_QMetaObject::metaMethod() +{ + QString str("foo"); + QString ret("bar"); + QMetaMethod method; + QVERIFY(!method.invoke(this)); + QVERIFY(!method.invoke(this, Q_ARG(QString, str))); + QVERIFY(!method.invoke(this, Q_RETURN_ARG(QString, ret), Q_ARG(QString, str))); + QCOMPARE(str, QString("foo")); + QCOMPARE(ret, QString("bar")); + + + QtTestObject obj; + QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5"); + QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X"); + + int index = QtTestObject::staticMetaObject.indexOfMethod("sl5(QString,QString,QString,QString,QString)"); + QVERIFY(index > 0); + method = QtTestObject::staticMetaObject.method(index); + //wrong args + QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"))); + //QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"), Q_ARG(QString, "6"))); + //QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(int, 5))); + QVERIFY(!method.invoke(&obj, Q_RETURN_ARG(QString, ret), Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); + + //wrong object + //QVERIFY(!method.invoke(this, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); + QVERIFY(!method.invoke(0, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); + QCOMPARE(ret, QString("bar")); + QCOMPARE(obj.slotResult, QString()); + + QVERIFY(method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); + QCOMPARE(obj.slotResult, QString("sl5:12345")); + + index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QList)"); + QVERIFY(index > 0); + QMetaMethod sl13 = QtTestObject::staticMetaObject.method(index); + QList returnValue, argument; + argument << QString("one") << QString("two") << QString("three"); + //wrong object + //QVERIFY(!sl13.invoke(this, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); + QVERIFY(!sl13.invoke(0, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); + QCOMPARE(returnValue, QList()); + + QVERIFY(sl13.invoke(&obj, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); + QCOMPARE(returnValue, argument); + QCOMPARE(obj.slotResult, QString("sl13")); +} + +void tst_QMetaObject::indexOfMethod_data() +{ + QTest::addColumn("object"); + QTest::addColumn("name"); + QTest::addColumn("isSignal"); + QTest::newRow("indexOfMethod_data") << (QObject*)this << QByteArray("indexOfMethod_data()") << false; + QTest::newRow("deleteLater") << (QObject*)this << QByteArray("deleteLater()") << false; + QTest::newRow("value6changed") << (QObject*)this << QByteArray("value6Changed()") << true; + QTest::newRow("value7changed") << (QObject*)this << QByteArray("value7Changed(QString)") << true; + QTest::newRow("destroyed") << (QObject*)this << QByteArray("destroyed()") << true; + QTest::newRow("destroyed2") << (QObject*)this << QByteArray("destroyed(QObject*)") << true; +} + +void tst_QMetaObject::indexOfMethod() +{ + QFETCH(QObject *, object); + QFETCH(QByteArray, name); + QFETCH(bool, isSignal); + int idx = object->metaObject()->indexOfMethod(name); + QVERIFY(idx >= 0); + QCOMPARE(object->metaObject()->method(idx).signature(), name.constData()); + QCOMPARE(object->metaObject()->indexOfSlot(name), isSignal ? -1 : idx); + QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx); +} + + +QTEST_MAIN(tst_QMetaObject) + +#include "moc_tst_qmetaobject.cpp"