diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:34:13 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:34:13 (GMT) |
commit | 67ad0519fd165acee4a4d2a94fa502e9e4847bd0 (patch) | |
tree | 1dbf50b3dff8d5ca7e9344733968c72704eb15ff /tests/auto/qdbusabstractadaptor | |
download | Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.zip Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.gz Qt-67ad0519fd165acee4a4d2a94fa502e9e4847bd0.tar.bz2 |
Long live Qt!
Diffstat (limited to 'tests/auto/qdbusabstractadaptor')
-rw-r--r-- | tests/auto/qdbusabstractadaptor/.gitignore | 1 | ||||
-rw-r--r-- | tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro | 10 | ||||
-rw-r--r-- | tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp | 1440 |
3 files changed, 1451 insertions, 0 deletions
diff --git a/tests/auto/qdbusabstractadaptor/.gitignore b/tests/auto/qdbusabstractadaptor/.gitignore new file mode 100644 index 0000000..201dd9c --- /dev/null +++ b/tests/auto/qdbusabstractadaptor/.gitignore @@ -0,0 +1 @@ +tst_qdbusabstractadaptor diff --git a/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro b/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro new file mode 100644 index 0000000..16358c5 --- /dev/null +++ b/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro @@ -0,0 +1,10 @@ +load(qttest_p4) +QT = core +contains(QT_CONFIG,dbus): { + SOURCES += tst_qdbusabstractadaptor.cpp + QT += dbus +} else { + SOURCES += ../qdbusmarshall/dummy.cpp +} + + diff --git a/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp b/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp new file mode 100644 index 0000000..142b820 --- /dev/null +++ b/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp @@ -0,0 +1,1440 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, 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.0, 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. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <qcoreapplication.h> +#include <qdebug.h> + +#include <QtTest/QtTest> + +#include <QtDBus> + +#include "../qdbusmarshall/common.h" + +const char *slotSpy; +QString valueSpy; + +QT_BEGIN_NAMESPACE +namespace QTest { + char *toString(QDBusMessage::MessageType t) + { + switch (t) + { + case QDBusMessage::InvalidMessage: + return qstrdup("InvalidMessage"); + case QDBusMessage::MethodCallMessage: + return qstrdup("MethodCallMessage"); + case QDBusMessage::ReplyMessage: + return qstrdup("ReplyMessage"); + case QDBusMessage::ErrorMessage: + return qstrdup("ErrorMessage"); + case QDBusMessage::SignalMessage: + return qstrdup("SignalMessage"); + default: + return 0; + } + } +} +QT_END_NAMESPACE + +class tst_QDBusAbstractAdaptor: public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() { commonInit(); } + void methodCalls_data(); + void methodCalls(); + void methodCallScriptable(); + void signalEmissions_data(); + void signalEmissions(); + void sameSignalDifferentPaths(); + void sameObjectDifferentPaths(); + void scriptableSignalOrNot(); + void overloadedSignalEmission_data(); + void overloadedSignalEmission(); + void readProperties(); + void readPropertiesInvalidInterface(); + void readPropertiesEmptyInterface_data(); + void readPropertiesEmptyInterface(); + void readAllProperties(); + void readAllPropertiesInvalidInterface(); + void readAllPropertiesEmptyInterface_data(); + void readAllPropertiesEmptyInterface(); + void writeProperties(); + + void typeMatching_data(); + void typeMatching(); + + void methodWithMoreThanOneReturnValue(); +}; + +class QDBusSignalSpy: public QObject +{ + Q_OBJECT + +public slots: + void slot(const QDBusMessage &msg) + { + ++count; + interface = msg.interface(); + name = msg.member(); + signature = msg.signature(); + path = msg.path(); + value.clear(); + if (msg.arguments().count()) + value = msg.arguments().at(0); + } + +public: + QDBusSignalSpy() : count(0) { } + + int count; + QString interface; + QString name; + QString signature; + QString path; + QVariant value; +}; + +class Interface1: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.Interface1") +public: + Interface1(QObject *parent) : QDBusAbstractAdaptor(parent) + { } +}; + +class Interface2: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.Interface2") + Q_PROPERTY(QString prop1 READ prop1) + Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2 SCRIPTABLE true) + Q_PROPERTY(QUrl nonDBusProperty READ nonDBusProperty) +public: + Interface2(QObject *parent) : QDBusAbstractAdaptor(parent) + { setAutoRelaySignals(true); } + + QString prop1() const + { return QLatin1String("QString Interface2::prop1() const"); } + + QString prop2() const + { return QLatin1String("QString Interface2::prop2() const"); } + + void setProp2(const QString &value) + { + slotSpy = "void Interface2::setProp2(const QString &)"; + valueSpy = value; + } + + QUrl nonDBusProperty() const + { return QUrl(); } + + void emitSignal(const QString &, const QVariant &) + { emit signal(); } + +public slots: + void method() + { + slotSpy = "void Interface2::method()"; + } + + Q_SCRIPTABLE void scriptableMethod() + { + slotSpy = "void Interface2::scriptableMethod()"; + } + +signals: + void signal(); +}; + +class Interface3: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.Interface3") + Q_PROPERTY(QString prop1 READ prop1) + Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2) + Q_PROPERTY(QString interface3prop READ interface3prop) +public: + Interface3(QObject *parent) : QDBusAbstractAdaptor(parent) + { setAutoRelaySignals(true); } + + QString prop1() const + { return QLatin1String("QString Interface3::prop1() const"); } + + QString prop2() const + { return QLatin1String("QString Interface3::prop2() const"); } + + void setProp2(const QString &value) + { + slotSpy = "void Interface3::setProp2(const QString &)"; + valueSpy = value; + } + + QString interface3prop() const + { return QLatin1String("QString Interface3::interface3prop() const"); } + + void emitSignal(const QString &name, const QVariant &value) + { + if (name == "signalVoid") + emit signalVoid(); + else if (name == "signalInt") + emit signalInt(value.toInt()); + else if (name == "signalString") + emit signalString(value.toString()); + } + +public slots: + void methodVoid() { slotSpy = "void Interface3::methodVoid()"; } + void methodInt(int) { slotSpy = "void Interface3::methodInt(int)"; } + void methodString(QString) { slotSpy = "void Interface3::methodString(QString)"; } + + int methodStringString(const QString &s, QString &out) + { + slotSpy = "int Interface3::methodStringString(const QString &, QString &)"; + out = s; + return 42; + } + +signals: + void signalVoid(); + void signalInt(int); + void signalString(const QString &); +}; + +class Interface4: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.Interface4") + Q_PROPERTY(QString prop1 READ prop1) + Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2) + Q_PROPERTY(QString interface4prop READ interface4prop) +public: + Interface4(QObject *parent) : QDBusAbstractAdaptor(parent) + { setAutoRelaySignals(true); } + + QString prop1() const + { return QLatin1String("QString Interface4::prop1() const"); } + + QString prop2() const + { return QLatin1String("QString Interface4::prop2() const"); } + + QString interface4prop() const + { return QLatin1String("QString Interface4::interface4prop() const"); } + + void setProp2(const QString &value) + { + slotSpy = "void Interface4::setProp2(const QString &)"; + valueSpy = value; + } + + void emitSignal(const QString &, const QVariant &value) + { + switch (value.type()) + { + case QVariant::Invalid: + emit signal(); + break; + case QVariant::Int: + emit signal(value.toInt()); + break; + case QVariant::String: + emit signal(value.toString()); + break; + default: + break; + } + } + +public slots: + void method() { slotSpy = "void Interface4::method()"; } + void method(int) { slotSpy = "void Interface4::method(int)"; } + void method(QString) { slotSpy = "void Interface4::method(QString)"; } + +signals: + void signal(); + void signal(int); + void signal(const QString &); +}; + +class MyObject: public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.MyObject") +public: + Interface1 *if1; + Interface2 *if2; + Interface3 *if3; + Interface4 *if4; + + MyObject(int n = 4) + : if1(0), if2(0), if3(0), if4(0) + { + switch (n) + { + case 4: + if4 = new Interface4(this); + case 3: + if3 = new Interface3(this); + case 2: + if2 = new Interface2(this); + case 1: + if1 = new Interface1(this); + } + } + + void emitSignal(const QString &name, const QVariant &value) + { + if (name == "scriptableSignalVoid") + emit scriptableSignalVoid(); + else if (name == "scriptableSignalInt") + emit scriptableSignalInt(value.toInt()); + else if (name == "scriptableSignalString") + emit scriptableSignalString(value.toString()); + else if (name == "nonScriptableSignalVoid") + emit nonScriptableSignalVoid(); + } + +signals: + Q_SCRIPTABLE void scriptableSignalVoid(); + Q_SCRIPTABLE void scriptableSignalInt(int); + Q_SCRIPTABLE void scriptableSignalString(QString); + void nonScriptableSignalVoid(); +}; + +class TypesInterface: public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.TypesInterface") +public: + TypesInterface(QObject *parent) + : QDBusAbstractAdaptor(parent) + { } + + union + { + bool b; + uchar uc; + short s; + ushort us; + int i; + uint ui; + qlonglong ll; + qulonglong ull; + double d; + } dataSpy; + QVariant variantSpy; + QString stringSpy; + QVariantList listSpy; + QStringList stringlistSpy; + QByteArray bytearraySpy; + QVariantMap mapSpy; + StringStringMap ssmapSpy; + LLDateTimeMap lldtmapSpy; + MyStruct structSpy; + +public slots: + void methodBool(bool b) + { + slotSpy = "void TypesInterface::methodBool(bool)"; + dataSpy.b = b; + } + + void methodUChar(uchar uc) + { + slotSpy = "void TypesInterface::methodUChar(uchar)"; + dataSpy.uc = uc; + } + + void methodShort(short s) + { + slotSpy = "void TypesInterface::methodShort(short)"; + dataSpy.s = s; + } + + void methodUShort(ushort us) + { + slotSpy = "void TypesInterface::methodUShort(ushort)"; + dataSpy.us = us; + } + + void methodInt(int i) + { + slotSpy = "void TypesInterface::methodInt(int)"; + dataSpy.i = i; + } + + void methodUInt(uint ui) + { + slotSpy = "void TypesInterface::methodUInt(uint)"; + dataSpy.ui = ui; + } + + void methodLongLong(qlonglong ll) + { + slotSpy = "void TypesInterface::methodLongLong(qlonglong)"; + dataSpy.ll = ll; + } + + void methodULongLong(qulonglong ull) + { + slotSpy = "void TypesInterface::methodULongLong(qulonglong)"; + dataSpy.ull = ull; + } + + void methodDouble(double d) + { + slotSpy = "void TypesInterface::methodDouble(double)"; + dataSpy.d = d; + } + + void methodString(const QString &s) + { + slotSpy = "void TypesInterface::methodString(const QString &)"; + stringSpy = s; + } + + void methodObjectPath(const QDBusObjectPath &op) + { + slotSpy = "void TypesInterface::methodObjectPath(const QDBusObjectPath &)"; + stringSpy = op.path(); + } + + void methodSignature(const QDBusSignature &s) + { + slotSpy = "void TypesInterface::methodSignature(const QDBusSignature &)"; + stringSpy = s.signature(); + } + + void methodVariant(const QDBusVariant &v) + { + slotSpy = "void TypesInterface::methodVariant(const QDBusVariant &)"; + variantSpy = v.variant(); + } + + void methodList(const QVariantList &l) + { + slotSpy = "void TypesInterface::methodList(const QVariantList &)"; + listSpy = l; + } + + void methodStringList(const QStringList &sl) + { + slotSpy = "void TypesInterface::methodStringList(const QStringList &)"; + stringlistSpy = sl; + } + + void methodByteArray(const QByteArray &ba) + { + slotSpy = "void TypesInterface::methodByteArray(const QByteArray &)"; + bytearraySpy = ba; + } + + void methodMap(const QVariantMap &m) + { + slotSpy = "void TypesInterface::methodMap(const QVariantMap &)"; + mapSpy = m; + } + + void methodSSMap(const StringStringMap &ssmap) + { + slotSpy = "void TypesInterface::methodSSMap(const StringStringMap &)"; + ssmapSpy = ssmap; + } + + void methodLLDateTimeMap(const LLDateTimeMap &lldtmap) + { + slotSpy = "void TypesInterface::methodLLDateTimeMap(const LLDateTimeMap &)"; + lldtmapSpy = lldtmap; + } + + void methodStruct(const MyStruct &s) + { + slotSpy = "void TypesInterface::methodStruct(const MyStruct &)"; + structSpy = s; + } + + bool retrieveBool() + { + return dataSpy.b; + } + + uchar retrieveUChar() + { + return dataSpy.uc; + } + + short retrieveShort() + { + return dataSpy.s; + } + + ushort retrieveUShort() + { + return dataSpy.us; + } + + int retrieveInt() + { + return dataSpy.i; + } + + uint retrieveUInt() + { + return dataSpy.ui; + } + + qlonglong retrieveLongLong() + { + return dataSpy.ll; + } + + qulonglong retrieveULongLong() + { + return dataSpy.ull; + } + + double retrieveDouble() + { + return dataSpy.d; + } + + QString retrieveString() + { + return stringSpy; + } + + QDBusObjectPath retrieveObjectPath() + { + return QDBusObjectPath(stringSpy); + } + + QDBusSignature retrieveSignature() + { + return QDBusSignature(stringSpy); + } + + QDBusVariant retrieveVariant() + { + return QDBusVariant(variantSpy); + } + + QVariantList retrieveList() + { + return listSpy; + } + + QStringList retrieveStringList() + { + return stringlistSpy; + } + + QByteArray retrieveByteArray() + { + return bytearraySpy; + } + + QVariantMap retrieveMap() + { + return mapSpy; + } + + StringStringMap retrieveSSMap() + { + return ssmapSpy; + } + + LLDateTimeMap retrieveLLDateTimeMap() + { + return lldtmapSpy; + } + + MyStruct retrieveStruct() + { + return structSpy; + } +}; + +void tst_QDBusAbstractAdaptor::methodCalls_data() +{ + QTest::addColumn<int>("nInterfaces"); + QTest::newRow("0") << 0; + QTest::newRow("1") << 1; + QTest::newRow("2") << 2; + QTest::newRow("3") << 3; + QTest::newRow("4") << 4; +} + +void tst_QDBusAbstractAdaptor::methodCalls() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + //QDBusInterface emptycon.baseService(), "/", QString()); + QDBusInterface if1(con.baseService(), "/", "local.Interface1", con); + QDBusInterface if2(con.baseService(), "/", "local.Interface2", con); + QDBusInterface if3(con.baseService(), "/", "local.Interface3", con); + QDBusInterface if4(con.baseService(), "/", "local.Interface4", con); + + // must fail: no object + //QCOMPARE(empty->call("method").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage); + + QFETCH(int, nInterfaces); + MyObject obj(nInterfaces); + con.registerObject("/", &obj); + + // must fail: no such method + QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage); + if (!nInterfaces--) + return; + if (!nInterfaces--) + return; + + // simple call: one such method exists + QCOMPARE(if2.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpy, "void Interface2::method()"); + if (!nInterfaces--) + return; + + // multiple methods in multiple interfaces, no name overlap + QCOMPARE(if1.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if1.call(QDBus::BlockWithGui, "methodInt").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if1.call(QDBus::BlockWithGui, "methodString").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if2.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if2.call(QDBus::BlockWithGui, "methodInt").type(), QDBusMessage::ErrorMessage); + QCOMPARE(if2.call(QDBus::BlockWithGui, "methodString").type(), QDBusMessage::ErrorMessage); + + QCOMPARE(if3.call(QDBus::BlockWithGui, "methodVoid").type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpy, "void Interface3::methodVoid()"); + QCOMPARE(if3.call(QDBus::BlockWithGui, "methodInt", 42).type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpy, "void Interface3::methodInt(int)"); + QCOMPARE(if3.call(QDBus::BlockWithGui, "methodString", QString("")).type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpy, "void Interface3::methodString(QString)"); + + if (!nInterfaces--) + return; + + // method overloading: different interfaces + QCOMPARE(if4.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpy, "void Interface4::method()"); + + // method overloading: different parameters + QCOMPARE(if4.call(QDBus::BlockWithGui, "method.i", 42).type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpy, "void Interface4::method(int)"); + QCOMPARE(if4.call(QDBus::BlockWithGui, "method.s", QString()).type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpy, "void Interface4::method(QString)"); + +} + +void tst_QDBusAbstractAdaptor::methodCallScriptable() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + QDBusInterface if2(con.baseService(), "/", "local.Interface2", con); + + MyObject obj(2); + con.registerObject("/", &obj); + + QCOMPARE(if2.call(QDBus::BlockWithGui,"scriptableMethod").type(), QDBusMessage::ReplyMessage); + QCOMPARE(slotSpy, "void Interface2::scriptableMethod()"); +} + +static void emitSignal(MyObject *obj, const QString &iface, const QString &name, + const QVariant ¶meter) +{ + if (iface.endsWith('2')) + obj->if2->emitSignal(name, parameter); + else if (iface.endsWith('3')) + obj->if3->emitSignal(name, parameter); + else if (iface.endsWith('4')) + obj->if4->emitSignal(name, parameter); + else + obj->emitSignal(name, parameter); + + QTest::qWait(200); +} + +void tst_QDBusAbstractAdaptor::signalEmissions_data() +{ + QTest::addColumn<QString>("interface"); + QTest::addColumn<QString>("name"); + QTest::addColumn<QString>("signature"); + QTest::addColumn<QVariant>("parameter"); + + QTest::newRow("Interface2.signal") << "local.Interface2" << "signal" << QString() << QVariant(); + QTest::newRow("Interface3.signalVoid") << "local.Interface3" << "signalVoid" << QString() << QVariant(); + QTest::newRow("Interface3.signalInt") << "local.Interface3" << "signalInt" << "i" << QVariant(1); + QTest::newRow("Interface3.signalString") << "local.Interface3" << "signalString" << "s" << QVariant("foo"); + QTest::newRow("MyObject.scriptableSignalVoid") << "local.MyObject" << "scriptableSignalVoid" << QString() << QVariant(); + QTest::newRow("MyObject.scriptableSignalInt") << "local.MyObject" << "scriptableSignalInt" << "i" << QVariant(1); + QTest::newRow("MyObject.nySignalString") << "local.MyObject" << "scriptableSignalString" << "s" << QVariant("foo"); +} + +void tst_QDBusAbstractAdaptor::signalEmissions() +{ + QFETCH(QString, interface); + QFETCH(QString, name); + QFETCH(QVariant, parameter); + + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + con.registerService("com.trolltech.tst_QDBusAbstractAdaptor"); + + MyObject obj(3); + con.registerObject("/", &obj, QDBusConnection::ExportAdaptors + | QDBusConnection::ExportScriptableSignals); + + // connect all signals and emit only one + { + QDBusSignalSpy spy; + con.connect(con.baseService(), "/", "local.Interface2", "signal", + &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/", "local.Interface3", "signalVoid", + &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/", "local.Interface3", "signalInt", + &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/", "local.Interface3", "signalString", + &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/", "local.MyObject", "scriptableSignalVoid", + &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/", "local.MyObject", "scriptableSignalInt", + &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/", "local.MyObject", "scriptableSignalString", + &spy, SLOT(slot(QDBusMessage))); + + emitSignal(&obj, interface, name, parameter); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, interface); + QCOMPARE(spy.name, name); + QTEST(spy.signature, "signature"); + QCOMPARE(spy.value, parameter); + } + + // connect one signal and emit them all + { + QDBusSignalSpy spy; + con.connect(con.baseService(), "/", interface, name, &spy, SLOT(slot(QDBusMessage))); + emitSignal(&obj, "local.Interface2", "signal", QVariant()); + emitSignal(&obj, "local.Interface3", "signalVoid", QVariant()); + emitSignal(&obj, "local.Interface3", "signalInt", QVariant(1)); + emitSignal(&obj, "local.Interface3", "signalString", QVariant("foo")); + emitSignal(&obj, "local.MyObject", "scriptableSignalVoid", QVariant()); + emitSignal(&obj, "local.MyObject", "scriptableSignalInt", QVariant(1)); + emitSignal(&obj, "local.MyObject", "scriptableSignalString", QVariant("foo")); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, interface); + QCOMPARE(spy.name, name); + QTEST(spy.signature, "signature"); + QCOMPARE(spy.value, parameter); + } +} + +void tst_QDBusAbstractAdaptor::sameSignalDifferentPaths() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj(2); + + con.registerObject("/p1",&obj); + con.registerObject("/p2",&obj); + + QDBusSignalSpy spy; + con.connect(con.baseService(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); + obj.if2->emitSignal(QString(), QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, QString("local.Interface2")); + QCOMPARE(spy.name, QString("signal")); + QVERIFY(spy.signature.isEmpty()); + + // now connect the other one + spy.count = 0; + con.connect(con.baseService(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); + obj.if2->emitSignal(QString(), QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 2); +} + +void tst_QDBusAbstractAdaptor::sameObjectDifferentPaths() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj(2); + + con.registerObject("/p1",&obj); + con.registerObject("/p2",&obj, 0); // don't export anything + + QDBusSignalSpy spy; + con.connect(con.baseService(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage))); + obj.if2->emitSignal(QString(), QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, QString("local.Interface2")); + QCOMPARE(spy.name, QString("signal")); + QVERIFY(spy.signature.isEmpty()); +} + +void tst_QDBusAbstractAdaptor::scriptableSignalOrNot() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + { + MyObject obj(0); + + con.registerObject("/p1",&obj, QDBusConnection::ExportScriptableSignals); + con.registerObject("/p2",&obj, 0); // don't export anything + + QDBusSignalSpy spy; + con.connect(con.baseService(), "/p1", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/p2", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + obj.emitSignal("scriptableSignalVoid", QVariant()); + obj.emitSignal("nonScriptableSignalVoid", QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 1); // only /p1 must have emitted + QCOMPARE(spy.interface, QString("local.MyObject")); + QCOMPARE(spy.name, QString("scriptableSignalVoid")); + QCOMPARE(spy.path, QString("/p1")); + QVERIFY(spy.signature.isEmpty()); + } + + { + MyObject obj(0); + + con.registerObject("/p1",&obj, QDBusConnection::ExportScriptableSignals); + con.registerObject("/p2",&obj, QDBusConnection::ExportScriptableSignals + | QDBusConnection::ExportNonScriptableSignals); + + QDBusSignalSpy spy; + con.connect(con.baseService(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); + obj.emitSignal("nonScriptableSignalVoid", QVariant()); + QTest::qWait(200); + + QCOMPARE(spy.count, 1); // only /p2 must have emitted now + QCOMPARE(spy.interface, QString("local.MyObject")); + QCOMPARE(spy.name, QString("nonScriptableSignalVoid")); + QCOMPARE(spy.path, QString("/p2")); + QVERIFY(spy.signature.isEmpty()); + } + + { + QDBusSignalSpy spy; + con.connect(con.baseService(), "/p1", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/p2", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage))); + + { + MyObject obj(0); + + con.registerObject("/p1",&obj, QDBusConnection::ExportScriptableSignals); + con.registerObject("/p2",&obj, QDBusConnection::ExportScriptableSignals + | QDBusConnection::ExportNonScriptableSignals); + } // <--- QObject emits the destroyed(QObject*) signal at this point + + QTest::qWait(200); + + QCOMPARE(spy.count, 0); + } +} + +void tst_QDBusAbstractAdaptor::overloadedSignalEmission_data() +{ + QTest::addColumn<QString>("signature"); + QTest::addColumn<QVariant>("parameter"); + QTest::newRow("void") << QString("") << QVariant(); + QTest::newRow("int") << "i" << QVariant(1); + QTest::newRow("string") << "s" << QVariant("foo"); +} + +void tst_QDBusAbstractAdaptor::overloadedSignalEmission() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj; + con.registerObject("/", &obj); + + QString interface = "local.Interface4"; + QString name = "signal"; + QFETCH(QVariant, parameter); + //QDBusInterface *if4 = new QDBusInterface(con.baseService(), "/", interface, con); + + // connect all signals and emit only one + { + QDBusSignalSpy spy; + con.connect(con.baseService(), "/", "local.Interface4", "signal", "", + &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/", "local.Interface4", "signal", "i", + &spy, SLOT(slot(QDBusMessage))); + con.connect(con.baseService(), "/", "local.Interface4", "signal", "s", + &spy, SLOT(slot(QDBusMessage))); + + emitSignal(&obj, interface, name, parameter); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, interface); + QCOMPARE(spy.name, name); + QTEST(spy.signature, "signature"); + QCOMPARE(spy.value, parameter); + } + + QFETCH(QString, signature); + // connect one signal and emit them all + { + QDBusSignalSpy spy; + con.connect(con.baseService(), "/", interface, name, signature, &spy, SLOT(slot(QDBusMessage))); + emitSignal(&obj, "local.Interface4", "signal", QVariant()); + emitSignal(&obj, "local.Interface4", "signal", QVariant(1)); + emitSignal(&obj, "local.Interface4", "signal", QVariant("foo")); + + QCOMPARE(spy.count, 1); + QCOMPARE(spy.interface, interface); + QCOMPARE(spy.name, name); + QTEST(spy.signature, "signature"); + QCOMPARE(spy.value, parameter); + } +} + +void tst_QDBusAbstractAdaptor::readProperties() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj; + con.registerObject("/", &obj); + + QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con); + for (int i = 2; i <= 4; ++i) { + QString name = QString("Interface%1").arg(i); + + for (int j = 1; j <= 2; ++j) { + QString propname = QString("prop%1").arg(j); + QDBusReply<QVariant> reply = + properties.call(QDBus::BlockWithGui, "Get", "local." + name, propname); + QVariant value = reply; + + QCOMPARE(value.userType(), int(QVariant::String)); + QCOMPARE(value.toString(), QString("QString %1::%2() const").arg(name, propname)); + } + } +} + +void tst_QDBusAbstractAdaptor::readPropertiesInvalidInterface() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj; + con.registerObject("/", &obj); + + QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con); + + // test an invalid interface: + QDBusReply<QVariant> reply = properties.call(QDBus::BlockWithGui, "Get", "local.DoesntExist", "prop1"); + QVERIFY(!reply.isValid()); +} + +void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterface_data() +{ + QTest::addColumn<QVariantMap>("expectedProperties"); + QTest::addColumn<bool>("existing"); + + QVariantMap expectedProperties; + expectedProperties["prop1"] = QVariant(); + expectedProperties["prop2"] = QVariant(); + expectedProperties["interface3prop"] = "QString Interface3::interface3prop() const"; + expectedProperties["interface4prop"] = "QString Interface4::interface4prop() const"; + QTest::newRow("existing") << expectedProperties << true; + + expectedProperties.clear(); + expectedProperties["prop5"] = QVariant(); + expectedProperties["foobar"] = QVariant(); + QTest::newRow("non-existing") << expectedProperties << false; +} + +void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterface() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj; + con.registerObject("/", &obj); + + QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con); + + QFETCH(QVariantMap, expectedProperties); + QFETCH(bool, existing); + + QVariantMap::ConstIterator it = expectedProperties.constBegin(); + for ( ; it != expectedProperties.constEnd(); ++it) { + QDBusReply<QVariant> reply = properties.call(QDBus::BlockWithGui, "Get", "", it.key()); + + if (existing) { + QVERIFY2(reply.isValid(), qPrintable(it.key())); + } else { + QVERIFY2(!reply.isValid(), qPrintable(it.key())); + continue; + } + + QCOMPARE(int(reply.value().type()), int(QVariant::String)); + if (it.value().isValid()) + QCOMPARE(reply.value().toString(), it.value().toString()); + } +} + +void tst_QDBusAbstractAdaptor::readAllProperties() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj; + con.registerObject("/", &obj); + + QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con); + for (int i = 2; i <= 4; ++i) { + QString name = QString("Interface%1").arg(i); + QDBusReply<QVariantMap> reply = + properties.call(QDBus::BlockWithGui, "GetAll", "local." + name); + + for (int j = 1; j <= 2; ++j) { + QString propname = QString("prop%1").arg(j); + QVERIFY2(reply.value().contains(propname), + qPrintable(propname + " on " + name)); + QVariant value = reply.value().value(propname); + + QCOMPARE(value.userType(), int(QVariant::String)); + QCOMPARE(value.toString(), QString("QString %1::%2() const").arg(name, propname)); + } + } +} + +void tst_QDBusAbstractAdaptor::readAllPropertiesInvalidInterface() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj; + con.registerObject("/", &obj); + + QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con); + + // test an invalid interface: + QDBusReply<QVariantMap> reply = properties.call(QDBus::BlockWithGui, "GetAll", "local.DoesntExist"); + QVERIFY(!reply.isValid()); +} + +void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterface_data() +{ + readPropertiesEmptyInterface_data(); +} + +void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterface() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj; + con.registerObject("/", &obj); + + QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con); + + QDBusReply<QVariantMap> reply = properties.call(QDBus::BlockWithGui, "GetAll", ""); + QVERIFY(reply.isValid()); + + QVariantMap allprops = reply; + + QFETCH(QVariantMap, expectedProperties); + QFETCH(bool, existing); + + QVariantMap::ConstIterator it = expectedProperties.constBegin(); + if (existing) { + for ( ; it != expectedProperties.constEnd(); ++it) { + QVERIFY2(allprops.contains(it.key()), qPrintable(it.key())); + + QVariant propvalue = allprops.value(it.key()); + QVERIFY2(!propvalue.isNull(), qPrintable(it.key())); + QVERIFY2(propvalue.isValid(), qPrintable(it.key())); + + QString stringvalue = propvalue.toString(); + QVERIFY2(!stringvalue.isEmpty(), qPrintable(it.key())); + + if (it.value().isValid()) + QCOMPARE(stringvalue, it.value().toString()); + + // remove this property from the map + allprops.remove(it.key()); + } + + QVERIFY2(allprops.isEmpty(), + qPrintable(QStringList(allprops.keys()).join(" "))); + } else { + for ( ; it != expectedProperties.constEnd(); ++it) + QVERIFY2(!allprops.contains(it.key()), qPrintable(it.key())); + } +} + +void tst_QDBusAbstractAdaptor::writeProperties() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj; + con.registerObject("/", &obj); + + QDBusInterface properties(con.baseService(), "/", "org.freedesktop.DBus.Properties", con); + for (int i = 2; i <= 4; ++i) { + QString name = QString("Interface%1").arg(i); + + valueSpy.clear(); + properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop1"), + qVariantFromValue(QDBusVariant(name))); + QVERIFY(valueSpy.isEmpty()); // call mustn't have succeeded + + properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop2"), + qVariantFromValue(QDBusVariant(name))); + QCOMPARE(valueSpy, name); + QCOMPARE(QString(slotSpy), QString("void %1::setProp2(const QString &)").arg(name)); + } +} + +#if 0 +void tst_QDBusAbstractAdaptor::adaptorIntrospection_data() +{ + methodCalls_data(); +} + +void tst_QDBusAbstractAdaptor::adaptorIntrospection() +{ + QDBusConnection con = QDBus::sessionBus(); + QVERIFY(con.isConnected()); + + QObject obj; + con.registerObject("/", &obj); + + QFETCH(int, nInterfaces); + switch (nInterfaces) + { + case 4: + new Interface4(&obj); + case 3: + new Interface3(&obj); + case 2: + new Interface2(&obj); + case 1: + new Interface1(&obj); + } + + QDBusObject dobj = con.findObject(con.baseService(), "/"); + QVERIFY(dobj.isValid()); + + QString xml = dobj.introspect(); + QVERIFY(!xml.isEmpty()); + + QStringList interfaces = dobj.interfaces(); + QCOMPARE(interfaces.count(), nInterfaces + 2); + switch (nInterfaces) + { + case 4: { + QVERIFY(interfaces.contains("local.Interface4")); + QDBusInterface iface(dobj, "local.Interface4"); + QCOMPARE(iface.methodData(), Interface4::methodData); + QCOMPARE(iface.signalData(), Interface4::signalData); + QCOMPARE(iface.propertyData(), Interface4::propertyData); + } + case 3: { + QVERIFY(interfaces.contains("local.Interface3")); + QDBusInterface iface(dobj, "local.Interface3"); + QCOMPARE(iface.methodData(), Interface3::methodData); + QCOMPARE(iface.signalData(), Interface3::signalData); + QCOMPARE(iface.propertyData(), Interface3::propertyData); + } + case 2: { + QVERIFY(interfaces.contains("local.Interface2")); + QDBusInterface iface(dobj, "local.Interface2"); + QCOMPARE(iface.methodData(), Interface2::methodData); + QCOMPARE(iface.signalData(), Interface2::signalData); + QCOMPARE(iface.propertyData(), Interface2::propertyData); + } + case 1: { + QVERIFY(interfaces.contains("local.Interface1")); + QDBusInterface iface(dobj, "local.Interface1"); + QCOMPARE(iface.methodData(), Interface1::methodData); + QCOMPARE(iface.signalData(), Interface1::signalData); + QCOMPARE(iface.propertyData(), Interface1::propertyData); + } + } +} + +void tst_QDBusAbstractAdaptor::objectTreeIntrospection() +{ + QDBusConnection con = QDBus::sessionBus(); + QVERIFY(con.isConnected()); + + { + QDBusObject dobj = con.findObject(con.baseService(), "/"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(tree.childObjects.isEmpty()); + } + + QObject root; + con.registerObject("/", &root); + { + QDBusObject dobj = con.findObject(con.baseService(), "/"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(tree.childObjects.isEmpty()); + } + + QObject p1; + con.registerObject("/p1", &p1); + { + QDBusObject dobj = con.findObject(con.baseService(), "/"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(tree.childObjects.contains("p1")); + } + + con.unregisterObject("/"); + { + QDBusObject dobj = con.findObject(con.baseService(), "/"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(tree.childObjects.contains("p1")); + } + + con.registerObject("/p1/q/r", &root); + { + QDBusObject dobj = con.findObject(con.baseService(), "/p1"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(tree.childObjects.contains("q")); + } + { + QDBusObject dobj = con.findObject(con.baseService(), "/p1/q"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(tree.childObjects.contains("r")); + } + + con.unregisterObject("/p1", QDBusConnection::UnregisterTree); + { + QDBusObject dobj = con.findObject(con.baseService(), "/"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(tree.childObjects.isEmpty()); + } + + QObject p2; + con.registerObject("/p2", &p2, QDBusConnection::ExportChildObjects); + { + QDBusObject dobj = con.findObject(con.baseService(), "/"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(!tree.childObjects.contains("p1")); + QVERIFY(tree.childObjects.contains("p2")); + } + + QObject q; + q.setParent(&p2); + { + QDBusObject dobj = con.findObject(con.baseService(), "/p2"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(!tree.childObjects.contains("q")); + } + + q.setObjectName("q"); + { + QDBusObject dobj = con.findObject(con.baseService(), "/p2"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(tree.childObjects.contains("q")); + } + + q.setParent(0); + { + QDBusObject dobj = con.findObject(con.baseService(), "/p2"); + QString xml = dobj.introspect(); + + QDBusIntrospection::Object tree = + QDBusIntrospection::parseObject(xml); + QVERIFY(!tree.childObjects.contains("q")); + } +} +#endif + +void tst_QDBusAbstractAdaptor::typeMatching_data() +{ + QTest::addColumn<QString>("basename"); + QTest::addColumn<QString>("signature"); + QTest::addColumn<QVariant>("value"); + + QTest::newRow("bool") << "Bool" << "b" << QVariant(true); + QTest::newRow("byte") << "UChar" << "y" << qVariantFromValue(uchar(42)); + QTest::newRow("short") << "Short" << "n" << qVariantFromValue(short(-43)); + QTest::newRow("ushort") << "UShort" << "q" << qVariantFromValue(ushort(44)); + QTest::newRow("int") << "Int" << "i" << QVariant(42); + QTest::newRow("uint") << "UInt" << "u" << QVariant(42U); + QTest::newRow("qlonglong") << "LongLong" << "x" << QVariant(Q_INT64_C(42)); + QTest::newRow("qulonglong") << "ULongLong" << "t" << QVariant(Q_UINT64_C(42)); + QTest::newRow("double") << "Double" << "d" << QVariant(2.5); + QTest::newRow("string") << "String" << "s" << QVariant("Hello, World!"); + + QTest::newRow("variant") << "Variant" << "v" << qVariantFromValue(QDBusVariant("Hello again!")); + QTest::newRow("list") << "List" << "av" << QVariant(QVariantList() + << 42 + << QString("foo") + << QByteArray("bar") + << qVariantFromValue(QDBusVariant(QString("baz")))); + QTest::newRow("stringlist") << "StringList" << "as" << QVariant(QStringList() << "Hello" << "world"); + QTest::newRow("bytearray") << "ByteArray" << "ay" << QVariant(QByteArray("foo")); + + QVariantMap map; + map["one"] = 1; // int + map["The answer to life, the Universe and everything"] = 42u; // uint + map["In the beginning..."] = QString("There was nothing"); // string + map["but Unix came and said"] = QByteArray("\"Hello, World\""); // bytearray + map["two"] = qVariantFromValue(short(2)); // short + QTest::newRow("map") << "Map" << "a{sv}" << QVariant(map); + + StringStringMap ssmap; + ssmap["a"] = "A"; + ssmap["A"] = "a"; + QTest::newRow("ssmap") << "SSMap" << "a{ss}" << qVariantFromValue(ssmap); + + LLDateTimeMap lldtmap; + lldtmap[-1] = QDateTime(); + QDateTime now = QDateTime::currentDateTime(); + lldtmap[now.toTime_t()] = now; // array of struct of int64 and struct of 3 ints and struct of 4 ints and int + QTest::newRow("lldtmap") << "LLDateTimeMap" << "a{x((iii)(iiii)i)}" << qVariantFromValue(lldtmap); + + MyStruct s; + s.i = 42; + s.s = "A value"; + QTest::newRow("struct") << "Struct" << "(is)" << qVariantFromValue(s); +} + +void tst_QDBusAbstractAdaptor::typeMatching() +{ + QObject obj; + new TypesInterface(&obj); + + QDBusConnection con = QDBusConnection::sessionBus(); + con.registerObject("/types", &obj); + + QFETCH(QString, basename); + QFETCH(QString, signature); + QFETCH(QVariant, value); + + QDBusMessage reply; + QDBusInterface iface(con.baseService(), "/types", "local.TypesInterface", con); + + reply = iface.callWithArgumentList(QDBus::BlockWithGui, "method" + basename, + QVariantList() << value); + QCOMPARE(reply.type(), QDBusMessage::ReplyMessage); + + reply = iface.call(QDBus::BlockWithGui, "retrieve" + basename); + QCOMPARE(reply.type(), QDBusMessage::ReplyMessage); + QCOMPARE(reply.arguments().count(), 1); + + const QVariant &retval = reply.arguments().at(0); + QVERIFY(compare(retval, value)); +} + +void tst_QDBusAbstractAdaptor::methodWithMoreThanOneReturnValue() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + MyObject obj; + con.registerObject("/", &obj); + + QString testString = "This is a test string."; + + QDBusInterface remote(con.baseService(), "/", "local.Interface3", con); + QDBusMessage reply = remote.call(QDBus::BlockWithGui, "methodStringString", testString); + QVERIFY(reply.arguments().count() == 2); + + QDBusReply<int> intreply = reply; + QVERIFY(intreply.isValid()); + QCOMPARE(intreply.value(), 42); + + QCOMPARE(reply.arguments().at(1).userType(), int(QVariant::String)); + QCOMPARE(qdbus_cast<QString>(reply.arguments().at(1)), testString); +} + +QTEST_MAIN(tst_QDBusAbstractAdaptor) + +#include "tst_qdbusabstractadaptor.moc" |