diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2022-08-01 11:12:20 -0700 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2022-08-30 22:29:07 -0300 |
commit | fe92b080658f0d8609e2a2a69e5ec2b51dd7bf9d (patch) | |
tree | c2e3db61402091538966b89547dbf680e3948be9 /tests | |
parent | 191419e98040d7aa7c306d3ec2776d5c143d8c2d (diff) |
QMetaObject: add a new, variadic invoke/invokeMethod/newInstance
[ChangeLog][QtCore][Meta Objects] The QMetaObject::invokeMethod() taking
a method name by string, QMetaObject::newInstance(), and
QMetaMethod::invoke() now support more than 10 arguments.
[ChangeLog][QtCore][Meta Objects] The use of the Q_ARG and Q_RETURN_ARG
macros is now optional with QMetaObject::invokeMethod(),
QMetaObject::newInstance(), and QMetaMethod::invoke(): the type name
will be obtained from the C++ type (the same as QMetaType). The function
qReturnArg() can be used in place of the Q_RETURN_ARG macro. The macros
are still useful in rare conditions where the type was typedef'ed from
its original name.
Change-Id: I36b24183fbd041179f2ffffd17022a2b48c7639b
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/corelib/global/qlogging/tst_qlogging.cpp | 4 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qmetaobject/CMakeLists.txt | 8 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp | 643 |
3 files changed, 631 insertions, 24 deletions
diff --git a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp index df0cb5ae77..be27ab65b9 100644 --- a/tests/auto/corelib/global/qlogging/tst_qlogging.cpp +++ b/tests/auto/corelib/global/qlogging/tst_qlogging.cpp @@ -732,12 +732,12 @@ void tst_qmessagehandler::qMessagePattern_data() // Q_OBJECT macro hence the ?helper? frame "[MyClass::myFunction|MyClass::mySlot1|?" BACKTRACE_HELPER_NAME "?|", - // QMetaObject::invokeMethod calls internal function + // QMetaObject::invokeMethodImpl calls internal function // (QMetaMethodPrivate::invokeImpl, at the tims of this writing), which // will usually show only as ?libQt6Core.so? or equivalent, so we skip // end of backtrace, actual message - "|" QT_NAMESPACE_STR "QMetaObject::invokeMethod] from_a_function 34" + "|" QT_NAMESPACE_STR "QMetaObject::invokeMethodImpl] from_a_function 34" }; QTest::newRow("backtrace") << "[%{backtrace}] %{message}" << true << expectedBacktrace; #endif diff --git a/tests/auto/corelib/kernel/qmetaobject/CMakeLists.txt b/tests/auto/corelib/kernel/qmetaobject/CMakeLists.txt index 30368e5c52..a4361d4779 100644 --- a/tests/auto/corelib/kernel/qmetaobject/CMakeLists.txt +++ b/tests/auto/corelib/kernel/qmetaobject/CMakeLists.txt @@ -20,3 +20,11 @@ qt_internal_add_test(tst_qmetaobject Qt::CorePrivate ) +qt_internal_add_test(tst_qmetaobject_compat + SOURCES + ${tst_qmetaobject_SOURCES} + DEFINES + USE_COMPAT_Q_ARG=1 + PUBLIC_LIBRARIES + Qt::CorePrivate +) diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index 005b58fcb8..26945b727e 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -14,6 +14,23 @@ Q_DECLARE_METATYPE(const QMetaObject *) #include "forwarddeclared.h" +#ifdef USE_COMPAT_Q_ARG +# define tst_QMetaObject tst_QMetaObject_CompatQArg +# if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) +# error "This is a Qt 6 compatibility check test" +# endif + +# undef Q_ARG +# undef Q_RETURN_ARG +# define Q_ARG(type, data) QArgument<type >(#type, data) +# define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data) +# define Q_NO_ARG , QGenericArgument() +#else +// This macro is used to force the overload selection to the compat +// (non-variadic) code above +# define Q_NO_ARG +#endif + #ifdef QEASINGCURVE_H # error "Please make sure qeasingcurve.h is not #include'd here! " \ "We need QEasingCurve to be only forward-declared." @@ -279,13 +296,17 @@ public: private slots: void connectSlotsByName(); void invokeMetaMember(); + void invokeMetaMemberNoMacros(); void invokePointer(); void invokeQueuedMetaMember(); + void invokeQueuedMetaMemberNoMacro(); void invokeQueuedPointer(); void invokeBlockingQueuedMetaMember(); + void invokeBlockingQueuedMetaMemberNoMacros(); void invokeBlockingQueuedPointer(); void invokeCustomTypes(); void invokeMetaConstructor(); + void invokeMetaConstructorNoMacro(); void invokeTypedefTypes(); void invokeException(); void invokeQueuedAutoRegister(); @@ -307,6 +328,7 @@ private slots: void classInfo(); void metaMethod(); + void metaMethodNoMacro(); void indexOfMethod_data(); void indexOfMethod(); @@ -651,6 +673,7 @@ void QtTestObject::staticFunction0() qint64 QtTestObject::staticFunction1() { staticResult = "staticFunction1"; return Q_INT64_C(123456789)*123456789; } +// this test is duplicated below void tst_QMetaObject::invokeMetaMember() { QtTestObject obj; @@ -661,17 +684,17 @@ void tst_QMetaObject::invokeMetaMember() // Test nullptr char *nullCharArray = nullptr; const char *nullConstCharArray = nullptr; - QVERIFY(!QMetaObject::invokeMethod(nullptr, nullCharArray)); - QVERIFY(!QMetaObject::invokeMethod(nullptr, nullConstCharArray)); - QVERIFY(!QMetaObject::invokeMethod(nullptr, "sl0")); - QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray)); - QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray)); - QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection)); - QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection)); + QVERIFY(!QMetaObject::invokeMethod(nullptr, nullCharArray Q_NO_ARG)); + QVERIFY(!QMetaObject::invokeMethod(nullptr, nullConstCharArray Q_NO_ARG)); + QVERIFY(!QMetaObject::invokeMethod(nullptr, "sl0" Q_NO_ARG)); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray Q_NO_ARG)); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray Q_NO_ARG)); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection Q_NO_ARG)); + QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection Q_NO_ARG)); QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection, QGenericReturnArgument())); QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection, QGenericReturnArgument())); - QVERIFY(QMetaObject::invokeMethod(&obj, "sl0")); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl0" Q_NO_ARG)); QCOMPARE(obj.slotResult, QString("sl0")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, t1))); @@ -710,17 +733,19 @@ void tst_QMetaObject::invokeMetaMember() Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9))); QCOMPARE(obj.slotResult, QString("sl9:123456789")); - QVERIFY(QMetaObject::invokeMethod(&obj, "sl11")); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11" Q_NO_ARG)); QCOMPARE(obj.slotResult, QString("sl11")); - QVERIFY(QMetaObject::invokeMethod(&obj, "testSender")); + QVERIFY(QMetaObject::invokeMethod(&obj, "testSender" Q_NO_ARG)); QCOMPARE(obj.slotResult, QString("0x0")); QString refStr("whatever"); +#ifdef USE_COMPAT_Q_ARG QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", QGenericArgument("QString&", &refStr))); QCOMPARE(obj.slotResult, QString("testReference:whatever")); QCOMPARE(refStr, QString("gotcha")); obj.slotResult.clear(); +#endif refStr = "whatever"; QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Q_ARG(QString&, refStr))); QCOMPARE(obj.slotResult, QString("testReference:whatever")); @@ -800,7 +825,7 @@ void tst_QMetaObject::invokeMetaMember() QCOMPARE(obj.slotResult, "sl17"); // test overloads - QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot" Q_NO_ARG)); QCOMPARE(obj.slotResult, QString("overloadedSlot")); QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Q_ARG(int, 1))); QCOMPARE(obj.slotResult, QString("overloadedSlot:1")); @@ -808,7 +833,7 @@ void tst_QMetaObject::invokeMetaMember() QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42")); //test signals - QVERIFY(QMetaObject::invokeMethod(&obj, "sig0")); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig0" Q_NO_ARG)); QCOMPARE(obj.slotResult, QString("sl0")); QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Q_ARG(QString, "baba"))); @@ -838,6 +863,177 @@ void tst_QMetaObject::invokeMetaMember() QCOMPARE(obj.slotResult, QString("sl1:hehe")); } +// this is a copy-paste-adapt of the above +void tst_QMetaObject::invokeMetaMemberNoMacros() +{ + 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(&obj, "sl0")); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", t1)); + QCOMPARE(obj.slotResult, QString("sl1:1")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", qAsConst(t1), t2)); + QCOMPARE(obj.slotResult, QString("sl2:12")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", t1, t2, t3)); + QCOMPARE(obj.slotResult, QString("sl3:123")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", t1, t2, t3, + t4)); + QCOMPARE(obj.slotResult, QString("sl4:1234")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", t1, t2, t3, + t4, QStringLiteral("5"))); + QCOMPARE(obj.slotResult, QString("sl5:12345")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", t1, t2, t3, + t4, t5, t6)); + QCOMPARE(obj.slotResult, QString("sl6:123456")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", t1, t2, t3, + t4, t5, t6, + t7)); + QCOMPARE(obj.slotResult, QString("sl7:1234567")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", t1, t2, t3, + t4, t5, t6, + t7, t8)); + QCOMPARE(obj.slotResult, QString("sl8:12345678")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", t1, t2, t3, + t4, t5, t6, + t7, t8, 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")); + + // this is not working for now +// QString refStr("whatever"); +// QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", refStr)); +// QCOMPARE(obj.slotResult, QString("testReference:whatever")); +// QCOMPARE(refStr, QString("gotcha")); + + qint64 ll1 = -1; + quint64 ll2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, + "testLongLong", + ll1, + ll2)); + QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); + + QString exp; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", qReturnArg(exp), QStringLiteral("bubu"))); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:bubu")); + + QObject *ptr = nullptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", qReturnArg(ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + // try again with a space: + ptr = nullptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", qReturnArg(ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + + const char *ptr2 = nullptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", qReturnArg(ptr2))); + QVERIFY(ptr2 != nullptr); + QCOMPARE(obj.slotResult, QString("sl12")); + // try again with a space: + ptr2 = nullptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", qReturnArg(ptr2))); + QVERIFY(ptr2 != nullptr); + QCOMPARE(obj.slotResult, QString("sl12")); + + // test w/ template args + QList<QString> returnValue, argument; + argument << QString("one") << QString("two") << QString("three"); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl13", + qReturnArg(returnValue), + argument)); + QCOMPARE(returnValue, argument); + QCOMPARE(obj.slotResult, QString("sl13")); + + // return qint64 + qint64 return64; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl14", + qReturnArg(return64))); + QCOMPARE(return64, Q_INT64_C(123456789)*123456789); + QCOMPARE(obj.slotResult, QString("sl14")); + + // pointers + QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", &return64)); + QCOMPARE(obj.slotResult, QString("sl15")); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl16", getForwardDeclaredPointer())); + QCOMPARE(obj.slotResult, QString("sl16:notnull")); + + obj.slotResult.clear(); + qint64 *return64Ptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", qReturnArg(return64Ptr), &return64)); + QCOMPARE(return64Ptr, &return64); + QCOMPARE(obj.slotResult, QString("sl15")); + + obj.slotResult.clear(); + MyForwardDeclaredType *forwardPtr = nullptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl16", qReturnArg(forwardPtr), + forwardPtr)); + QCOMPARE(forwardPtr, getForwardDeclaredPointer()); + QCOMPARE(obj.slotResult, QString("sl16:null")); + + // forward-declared builtin + obj.slotResult.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl17", getEasingCurve())); + QCOMPARE(obj.slotResult, "sl17"); + + // test overloads + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot")); + QCOMPARE(obj.slotResult, QString("overloadedSlot")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", 1)); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", 1, 42)); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42")); + + //test signals + QVERIFY(QMetaObject::invokeMethod(&obj, "sig0")); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", QStringLiteral("baba"))); + QCOMPARE(obj.slotResult, QString("sl1:baba")); + + exp.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", qReturnArg(exp), QStringLiteral("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)", QStringLiteral("arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n" + "Candidates are:\n sl3(QString,QString,QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", QStringLiteral("arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n" + "Candidates are:\n sl1(QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", QStringLiteral("arg"), QStringLiteral("arg"), QStringLiteral("arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::testReference(QString)\n" + "Candidates are:\n testReference(QString&)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "testReference", exp)); + + //should not have changed since last test. + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:hehe")); +} + void testFunction(){} @@ -908,7 +1104,7 @@ void tst_QMetaObject::invokeQueuedMetaMember() { QtTestObject obj; - QVERIFY(QMetaObject::invokeMethod(&obj, "sl0", Qt::QueuedConnection)); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl0", Qt::QueuedConnection Q_NO_ARG)); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl0")); @@ -942,7 +1138,7 @@ void tst_QMetaObject::invokeQueuedMetaMember() QCOMPARE(obj.slotResult, "sl17"); // test overloads - QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection)); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection Q_NO_ARG)); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("overloadedSlot")); QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection, Q_ARG(int, 1))); @@ -955,7 +1151,7 @@ void tst_QMetaObject::invokeQueuedMetaMember() // signals obj.slotResult.clear(); - QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::QueuedConnection)); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::QueuedConnection Q_NO_ARG)); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl0")); @@ -1013,6 +1209,119 @@ void tst_QMetaObject::invokeQueuedMetaMember() QVERIFY(obj.slotResult.isEmpty()); } +// this is a copy-paste-adapt of the above +void tst_QMetaObject::invokeQueuedMetaMemberNoMacro() +{ + 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, 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, QStringLiteral("1"), QStringLiteral("2"), + QStringLiteral("3"), QStringLiteral("4"), QStringLiteral("5"), + QStringLiteral("6"), QStringLiteral("7"), QStringLiteral("8"), + QStringLiteral("9"))); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl9:123456789")); + + // pointers + qint64 return64; + obj.slotResult.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", Qt::QueuedConnection, &return64)); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("sl15")); + + // forward-declared builtin + obj.slotResult.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl17", Qt::QueuedConnection, getEasingCurve())); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, "sl17"); + + // test overloads + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection)); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("overloadedSlot")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection, 1)); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::QueuedConnection, 1, 42)); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42")); + + // 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, QStringLiteral("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, qReturnArg(exp), + QStringLiteral("nono"))); + + qint64 ll1 = -1; + quint64 ll2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, + "testLongLong", + Qt::QueuedConnection, + ll1, + ll2)); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); + + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::testReference(QString)\n" + "Candidates are:\n testReference(QString&)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "testReference", exp)); + QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); + QVERIFY(exp.isEmpty()); + + // this doesn't work yet +// QString refStr = "whatever"; +// QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'QString&'"); +// QVERIFY(!QMetaObject::invokeMethod(&obj, "testReference", Qt::QueuedConnection, Q_ARG(QString&, refStr))); +// QCOMPARE(refStr, "whatever"); + + obj.slotResult.clear(); + { + const MyForwardDeclaredType &t = getForwardDeclaredType(); + QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyForwardDeclaredType'"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "slotWithUnregisteredParameterType", Qt::QueuedConnection, t)); + QVERIFY(obj.slotResult.isEmpty()); + } + + obj.slotResult.clear(); + { + QString a1("Cannot happen"); + const MyForwardDeclaredType &t = getForwardDeclaredType(); + QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyForwardDeclaredType'"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "slotWithOneUnregisteredParameterType", Qt::QueuedConnection, + a1, t)); + QVERIFY(obj.slotResult.isEmpty()); + } + + obj.slotResult.clear(); + QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyForwardDeclaredType*'"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl16", Qt::QueuedConnection, getForwardDeclaredPointer())); + qApp->processEvents(QEventLoop::AllEvents); + QVERIFY(obj.slotResult.isEmpty()); +} + void tst_QMetaObject::invokeQueuedPointer() { QtTestObject obj; @@ -1062,7 +1371,7 @@ void tst_QMetaObject::invokeQueuedPointer() QCOMPARE(countedStructObjectsCount, 0); } - +// this test is duplicated below void tst_QMetaObject::invokeBlockingQueuedMetaMember() { QThread t; @@ -1109,17 +1418,19 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember() 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)); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection Q_NO_ARG)); QCOMPARE(obj.slotResult, QString("sl11")); - QVERIFY(QMetaObject::invokeMethod(&obj, "testSender", Qt::BlockingQueuedConnection)); + QVERIFY(QMetaObject::invokeMethod(&obj, "testSender", Qt::BlockingQueuedConnection Q_NO_ARG)); QCOMPARE(obj.slotResult, QString("0x0")); QString refStr("whatever"); +#ifdef USE_COMPAT_Q_ARG QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, QGenericArgument("QString&", &refStr))); QCOMPARE(obj.slotResult, QString("testReference:whatever")); QCOMPARE(refStr, QString("gotcha")); obj.slotResult.clear(); +#endif refStr = "whatever"; QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, Q_ARG(QString&, refStr))); QCOMPARE(obj.slotResult, QString("testReference:whatever")); @@ -1200,7 +1511,7 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember() QCOMPARE(obj.slotResult, "sl17"); // test overloads - QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection)); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection Q_NO_ARG)); QCOMPARE(obj.slotResult, QString("overloadedSlot")); QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection, Q_ARG(int, 1))); QCOMPARE(obj.slotResult, QString("overloadedSlot:1")); @@ -1208,7 +1519,7 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember() QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42")); //test signals - QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection)); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection Q_NO_ARG)); QCOMPARE(obj.slotResult, QString("sl0")); QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_ARG(QString, "baba"))); @@ -1220,7 +1531,7 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember() QCOMPARE(obj.slotResult, QString("sl1:hehe")); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()"); - QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection)); + QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection Q_NO_ARG)); 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)\n" @@ -1240,7 +1551,182 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember() QVERIFY(QMetaObject::invokeMethod(&obj, "moveToThread", Qt::BlockingQueuedConnection, Q_ARG(QThread*, QThread::currentThread()))); t.quit(); QVERIFY(t.wait()); +} + +// this is a copy-paste-adapt of the above +void tst_QMetaObject::invokeBlockingQueuedMetaMemberNoMacros() +{ + 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, t1)); + QCOMPARE(obj.slotResult, QString("sl1:1")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", Qt::BlockingQueuedConnection, t1, t2)); + QCOMPARE(obj.slotResult, QString("sl2:12")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, t1, t2, t3)); + QCOMPARE(obj.slotResult, QString("sl3:123")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", Qt::BlockingQueuedConnection, t1, t2, + t3, t4)); + QCOMPARE(obj.slotResult, QString("sl4:1234")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", Qt::BlockingQueuedConnection, t1, t2, + t3, t4, QStringLiteral("5"))); + QCOMPARE(obj.slotResult, QString("sl5:12345")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", Qt::BlockingQueuedConnection, t1, t2, + t3, t4, t5, t6)); + QCOMPARE(obj.slotResult, QString("sl6:123456")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", Qt::BlockingQueuedConnection, t1, t2, + t3, t4, t5, t6, + t7)); + QCOMPARE(obj.slotResult, QString("sl7:1234567")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", Qt::BlockingQueuedConnection, t1, t2, + t3, t4, t5, t6, + t7, t8)); + QCOMPARE(obj.slotResult, QString("sl8:12345678")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::BlockingQueuedConnection, t1, t2, + t3, t4, t5, t6, + t7, t8, 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")); + + // this is not working +// QString refStr("whatever"); +// QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, refStr)); +// QCOMPARE(obj.slotResult, QString("testReference:whatever")); +// QCOMPARE(refStr, QString("gotcha")); + + qint64 ll1 = -1; + quint64 ll2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, + "testLongLong", + Qt::BlockingQueuedConnection, + ll1, + ll2)); + QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); + + QString exp; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, qReturnArg(exp), QStringLiteral("bubu"))); + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:bubu")); + + QObject *ptr = nullptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, qReturnArg(ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + // try again with a space: + ptr = nullptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, qReturnArg(ptr))); + QCOMPARE(ptr, (QObject *)&obj); + QCOMPARE(obj.slotResult, QString("sl11")); + + const char *ptr2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, qReturnArg(ptr2))); + QVERIFY(ptr2 != 0); + QCOMPARE(obj.slotResult, QString("sl12")); + // try again with a space: + ptr2 = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, qReturnArg(ptr2))); + QVERIFY(ptr2 != 0); + QCOMPARE(obj.slotResult, QString("sl12")); + + // test w/ template args + QList<QString> returnValue, argument; + argument << QString("one") << QString("two") << QString("three"); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl13", Qt::BlockingQueuedConnection, + qReturnArg(returnValue), + argument)); + QCOMPARE(returnValue, argument); + QCOMPARE(obj.slotResult, QString("sl13")); + + // return qint64 + qint64 return64; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl14", Qt::BlockingQueuedConnection, + qReturnArg(return64))); + QCOMPARE(return64, Q_INT64_C(123456789)*123456789); + QCOMPARE(obj.slotResult, QString("sl14")); + + // pointers + QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", Qt::BlockingQueuedConnection, &return64)); + QCOMPARE(obj.slotResult, QString("sl15")); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl16", Qt::BlockingQueuedConnection, getForwardDeclaredPointer())); + QCOMPARE(obj.slotResult, QString("sl16:notnull")); + + obj.slotResult.clear(); + qint64 *return64Ptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl15", Qt::BlockingQueuedConnection, qReturnArg(return64Ptr), &return64)); + QCOMPARE(return64Ptr, &return64); + QCOMPARE(obj.slotResult, QString("sl15")); + + obj.slotResult.clear(); + MyForwardDeclaredType *forwardPtr = nullptr; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl16", Qt::BlockingQueuedConnection, qReturnArg(forwardPtr), + forwardPtr)); + QCOMPARE(forwardPtr, getForwardDeclaredPointer()); + QCOMPARE(obj.slotResult, QString("sl16:null")); + + // forward-declared builtin + obj.slotResult.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sl17", Qt::BlockingQueuedConnection, getEasingCurve())); + QCOMPARE(obj.slotResult, "sl17"); + + // test overloads + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("overloadedSlot")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection, 1)); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1")); + QVERIFY(QMetaObject::invokeMethod(&obj, "overloadedSlot", Qt::BlockingQueuedConnection, 1, 42)); + QCOMPARE(obj.slotResult, QString("overloadedSlot:1,42")); + + //test signals + QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection)); + QCOMPARE(obj.slotResult, QString("sl0")); + + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, QStringLiteral("baba"))); + QCOMPARE(obj.slotResult, QString("sl1:baba")); + + exp.clear(); + QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, qReturnArg(exp), QStringLiteral("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, QStringLiteral("arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n" + "Candidates are:\n sl3(QString,QString,QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, QStringLiteral("arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n" + "Candidates are:\n sl1(QString)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, QStringLiteral("arg"), QStringLiteral("arg"), QStringLiteral("arg"))); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::testReference(QString)\n" + "Candidates are:\n testReference(QString&)"); + QVERIFY(!QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, exp)); + + //should not have changed since last test. + QCOMPARE(exp, QString("yessir")); + QCOMPARE(obj.slotResult, QString("sl1:hehe")); + QVERIFY(QMetaObject::invokeMethod(&obj, "moveToThread", Qt::BlockingQueuedConnection, QThread::currentThread())); + t.quit(); + QVERIFY(t.wait()); } void tst_QMetaObject::invokeBlockingQueuedPointer() @@ -1366,6 +1852,10 @@ void tst_QMetaObject::invokeCustomTypes() QCOMPARE(obj.sum, 0); QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(MyType, tp))); QCOMPARE(obj.sum, 3); + + obj.sum = 0; + QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", tp)); + QCOMPARE(obj.sum, 3); } namespace NamespaceWithConstructibleClass @@ -1381,13 +1871,16 @@ public: } +// this test is duplicated below void tst_QMetaObject::invokeMetaConstructor() { const QMetaObject *mo = &QtTestObject::staticMetaObject; +#ifdef USE_COMPAT_Q_ARG { - QObject *obj = mo->newInstance(); + QObject *obj = mo->newInstance(QGenericArgument()); QVERIFY(!obj); } +#endif { QtTestObject obj; QObject *obj2 = mo->newInstance(Q_ARG(QObject*, &obj)); @@ -1430,6 +1923,38 @@ void tst_QMetaObject::invokeMetaConstructor() } } +// this is a copy-paste-adapt of the above +void tst_QMetaObject::invokeMetaConstructorNoMacro() +{ + const QMetaObject *mo = &QtTestObject::staticMetaObject; + { + QObject *obj = mo->newInstance(); + QVERIFY(!obj); + } + { + QtTestObject obj; + QObject *obj2 = mo->newInstance(static_cast<QObject *>(&obj)); + QVERIFY(obj2 != 0); + QCOMPARE(obj2->parent(), (QObject*)&obj); + QVERIFY(qobject_cast<QtTestObject*>(obj2) != 0); + } + // class in namespace + const QMetaObject *nsmo = &NamespaceWithConstructibleClass::ConstructibleClass::staticMetaObject; + { + QtTestObject obj; + QObject *obj2 = nsmo->newInstance(static_cast<QObject *>(&obj)); + QVERIFY(obj2 != 0); + QCOMPARE(obj2->parent(), (QObject*)&obj); + QVERIFY(qobject_cast<NamespaceWithConstructibleClass::ConstructibleClass*>(obj2) != 0); + } + // gadget shouldn't return a valid pointer + { + QCOMPARE(MyGadget::staticMetaObject.constructorCount(), 1); + QTest::ignoreMessage(QtWarningMsg, "QMetaObject::newInstance: type MyGadget does not inherit QObject"); + QVERIFY(!MyGadget::staticMetaObject.newInstance()); + } +} + void tst_QMetaObject::invokeTypedefTypes() { qRegisterMetaType<CustomString>("CustomString"); @@ -1457,6 +1982,14 @@ void tst_QMetaObject::invokeException() QFAIL("Did not throw"); } catch(ObjectException &) {} QCOMPARE(countedStructObjectsCount, 0); + + try { + CountedStruct s; + QVERIFY(QMetaObject::invokeMethod(&obj, "throwingSlot", qReturnArg(s), + s, s)); + QFAIL("Did not throw"); + } catch(ObjectException &) {} + QCOMPARE(countedStructObjectsCount, 0); #else QSKIP("Needs exceptions"); #endif @@ -1478,6 +2011,18 @@ void tst_QMetaObject::invokeQueuedAutoRegister() qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("slotWithRegistrableArgument:myShared-myShared-myShared-myShared-00")); + + obj.slotResult.clear(); + QVERIFY(QMetaObject::invokeMethod( + &obj, "slotWithRegistrableArgument", Qt::QueuedConnection, + shared.data(), QPointer<QtTestObject>(shared.data()), + QSharedPointer<QtTestObject>(shared), QWeakPointer<QtTestObject>(shared), + QList<QtTestObject *>(), + QList<QtTestObject *>())); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, + QString("slotWithRegistrableArgument:myShared-myShared-myShared-myShared-00")); } void tst_QMetaObject::normalizedSignature_data() @@ -1811,6 +2356,7 @@ void tst_QMetaObject::classInfo() QCOMPARE(QLatin1String(b.metaObject()->classInfo(index).value()), QLatin1String("Christopher Pike")); } +// this test is duplicated below void tst_QMetaObject::metaMethod() { QString str("foo"); @@ -1863,6 +2409,59 @@ void tst_QMetaObject::metaMethod() QCOMPARE(obj.slotResult, QString("sl13")); } +// this is a copy-paste-adapt of the above +void tst_QMetaObject::metaMethodNoMacro() +{ + QString str("foo"); + QString ret("bar"); + QMetaMethod method; + QVERIFY(!method.invoke(this)); + QVERIFY(!method.invoke(this, str)); + QVERIFY(!method.invoke(this, qReturnArg(ret), 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 + QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: too few arguments (5) in call to QtTestObject::sl5(QString,QString,QString,QString,QString)"); + QVERIFY(!method.invoke(&obj, QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3"), QStringLiteral("4"))); + //QVERIFY(!method.invoke(&obj, "1", "2", "3", "4", "5", "6")); + //QVERIFY(!method.invoke(&obj, "1", "2", "3", "4", 5)); + QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invokeMethod: return type mismatch for method " + "QtTestObject::sl5(QString,QString,QString,QString,QString): " + "cannot convert from void to QString during invocation"); + QVERIFY(!method.invoke(&obj, qReturnArg(ret), QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3"), QStringLiteral("4"), QStringLiteral("5"))); + + //wrong object + //QVERIFY(!method.invoke(this, "1", "2", "3", "4", "5")); + QVERIFY(!method.invoke(0, QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3"), QStringLiteral("4"), QStringLiteral("5"))); + QCOMPARE(ret, QString("bar")); + QCOMPARE(obj.slotResult, QString()); + + QVERIFY(method.invoke(&obj, QStringLiteral("1"), QStringLiteral("2"), QStringLiteral("3"), QStringLiteral("4"), QStringLiteral("5"))); + QCOMPARE(obj.slotResult, QString("sl5:12345")); + + index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QList<QString>)"); + QVERIFY(index > 0); + QMetaMethod sl13 = QtTestObject::staticMetaObject.method(index); + QList<QString> returnValue, argument; + argument << QString("one") << QString("two") << QString("three"); + //wrong object + //QVERIFY(!sl13.invoke(this, qReturnArg(returnValue), argument)); + QVERIFY(!sl13.invoke(0, qReturnArg(returnValue), argument)); + QVERIFY(returnValue.isEmpty()); + + QVERIFY(sl13.invoke(&obj, qReturnArg(returnValue), argument)); + QCOMPARE(returnValue, argument); + QCOMPARE(obj.slotResult, QString("sl13")); +} + void tst_QMetaObject::indexOfMethod_data() { QTest::addColumn<QObject *>("object"); |