summaryrefslogtreecommitdiffstats
path: root/tests/auto/dbus/qdbusinterface
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/dbus/qdbusinterface')
-rw-r--r--tests/auto/dbus/qdbusinterface/.gitignore1
-rw-r--r--tests/auto/dbus/qdbusinterface/myobject.h164
-rw-r--r--tests/auto/dbus/qdbusinterface/qdbusinterface.pro11
-rw-r--r--tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.cpp155
-rw-r--r--tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.pro5
-rw-r--r--tests/auto/dbus/qdbusinterface/test/test.pro6
-rw-r--r--tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp1139
7 files changed, 1481 insertions, 0 deletions
diff --git a/tests/auto/dbus/qdbusinterface/.gitignore b/tests/auto/dbus/qdbusinterface/.gitignore
new file mode 100644
index 0000000000..98313ecf04
--- /dev/null
+++ b/tests/auto/dbus/qdbusinterface/.gitignore
@@ -0,0 +1 @@
+tst_qdbusinterface
diff --git a/tests/auto/dbus/qdbusinterface/myobject.h b/tests/auto/dbus/qdbusinterface/myobject.h
new file mode 100644
index 0000000000..3959823a77
--- /dev/null
+++ b/tests/auto/dbus/qdbusinterface/myobject.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MYOBJECT_H
+#define MYOBJECT_H
+
+#include <QtCore/QObject>
+#include <QtDBus/QtDBus>
+
+Q_DECLARE_METATYPE(QVariantList)
+
+class MyObject: public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "com.trolltech.QtDBus.MyObject")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"com.trolltech.QtDBus.MyObject\" >\n"
+" <property access=\"readwrite\" type=\"i\" name=\"prop1\" />\n"
+" <property name=\"complexProp\" type=\"ai\" access=\"readwrite\">\n"
+" <annotation name=\"com.trolltech.QtDBus.QtTypeName\" value=\"QList&lt;int&gt;\"/>\n"
+" </property>\n"
+" <signal name=\"somethingHappened\" >\n"
+" <arg direction=\"out\" type=\"s\" />\n"
+" </signal>\n"
+" <method name=\"ping\" >\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"ping\" />\n"
+" </method>\n"
+" <method name=\"ping_invokable\" >\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping_invokable\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"ping_invokable\" />\n"
+" </method>\n"
+" <method name=\"ping\" >\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping1\" />\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping2\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"pong1\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"pong2\" />\n"
+" </method>\n"
+" <method name=\"ping_invokable\" >\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping1_invokable\" />\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping2_invokable\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"pong1_invokable\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"pong2_invokable\" />\n"
+" </method>\n"
+" <method name=\"ping\" >\n"
+" <arg direction=\"in\" type=\"ai\" name=\"ping\" />\n"
+" <arg direction=\"out\" type=\"ai\" name=\"ping\" />\n"
+" <annotation name=\"com.trolltech.QtDBus.QtTypeName.In0\" value=\"QList&lt;int&gt;\"/>\n"
+" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"QList&lt;int&gt;\"/>\n"
+" </method>\n"
+" <method name=\"ping_invokable\" >\n"
+" <arg direction=\"in\" type=\"ai\" name=\"ping_invokable\" />\n"
+" <arg direction=\"out\" type=\"ai\" name=\"ping_invokable\" />\n"
+" <annotation name=\"com.trolltech.QtDBus.QtTypeName.In0\" value=\"QList&lt;int&gt;\"/>\n"
+" <annotation name=\"com.trolltech.QtDBus.QtTypeName.Out0\" value=\"QList&lt;int&gt;\"/>\n"
+" </method>\n"
+" </interface>\n"
+ "")
+ Q_PROPERTY(int prop1 READ prop1 WRITE setProp1)
+ Q_PROPERTY(QList<int> complexProp READ complexProp WRITE setComplexProp)
+
+public:
+ static int callCount;
+ static QVariantList callArgs;
+ MyObject()
+ {
+ QObject *subObject = new QObject(this);
+ subObject->setObjectName("subObject");
+ }
+
+ int m_prop1;
+ int prop1() const
+ {
+ ++callCount;
+ return m_prop1;
+ }
+ void setProp1(int value)
+ {
+ ++callCount;
+ m_prop1 = value;
+ }
+
+ QList<int> m_complexProp;
+ QList<int> complexProp() const
+ {
+ ++callCount;
+ return m_complexProp;
+ }
+ void setComplexProp(const QList<int> &value)
+ {
+ ++callCount;
+ m_complexProp = value;
+ }
+
+ Q_INVOKABLE void ping_invokable(QDBusMessage msg)
+ {
+ QDBusConnection sender = QDBusConnection::sender();
+ if (!sender.isConnected())
+ exit(1);
+
+ ++callCount;
+ callArgs = msg.arguments();
+
+ msg.setDelayedReply(true);
+ if (!sender.send(msg.createReply(callArgs)))
+ exit(1);
+ }
+
+public slots:
+
+ void ping(QDBusMessage msg)
+ {
+ QDBusConnection sender = QDBusConnection::sender();
+ if (!sender.isConnected())
+ exit(1);
+
+ ++callCount;
+ callArgs = msg.arguments();
+
+ msg.setDelayedReply(true);
+ if (!sender.send(msg.createReply(callArgs)))
+ exit(1);
+ }
+};
+
+#endif // INTERFACE_H
diff --git a/tests/auto/dbus/qdbusinterface/qdbusinterface.pro b/tests/auto/dbus/qdbusinterface/qdbusinterface.pro
new file mode 100644
index 0000000000..0aca06ceb4
--- /dev/null
+++ b/tests/auto/dbus/qdbusinterface/qdbusinterface.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+QT = core
+contains(QT_CONFIG,dbus): {
+ TEMPLATE = subdirs
+ CONFIG += ordered
+ SUBDIRS = qmyserver test
+} else {
+ SOURCES += ../qdbusmarshall/dummy.cpp
+}
+
+
diff --git a/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.cpp b/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.cpp
new file mode 100644
index 0000000000..dd15012222
--- /dev/null
+++ b/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore/QtCore>
+#include <QtDBus/QtDBus>
+
+#include "../myobject.h"
+
+static const char serviceName[] = "com.trolltech.autotests.qmyserver";
+static const char objectPath[] = "/com/trolltech/qmyserver";
+//static const char *interfaceName = serviceName;
+
+int MyObject::callCount = 0;
+QVariantList MyObject::callArgs;
+
+class MyServer : public QDBusServer
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "com.trolltech.autotests.qmyserver")
+
+public:
+ MyServer(QString addr = "unix:tmpdir=/tmp", QObject* parent = 0)
+ : QDBusServer(addr, parent),
+ m_conn("none")
+ {
+ connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&)));
+ }
+
+public slots:
+ QString address() const
+ {
+ return QDBusServer::address();
+ }
+
+ bool isConnected() const
+ {
+ return m_conn.isConnected();
+ }
+
+ void emitSignal(const QString &interface, const QString &name, const QString &arg)
+ {
+ QDBusMessage msg = QDBusMessage::createSignal("/", interface, name);
+ msg << arg;
+ m_conn.send(msg);
+ }
+
+ void reset()
+ {
+ MyObject::callCount = 0;
+ obj.m_complexProp.clear();
+ }
+
+ int callCount()
+ {
+ return MyObject::callCount;
+ }
+
+ QVariantList callArgs()
+ {
+ qDebug() << "callArgs" << MyObject::callArgs.count();
+ return MyObject::callArgs;
+ }
+
+ void setProp1(int val)
+ {
+ obj.m_prop1 = val;
+ }
+
+ int prop1()
+ {
+ return obj.m_prop1;
+ }
+
+ void setComplexProp(QList<int> val)
+ {
+ obj.m_complexProp = val;
+ }
+
+ QList<int> complexProp()
+ {
+ return obj.m_complexProp;
+ }
+
+
+private slots:
+ void handleConnection(const QDBusConnection& con)
+ {
+ m_conn = con;
+ m_conn.registerObject("/", &obj, QDBusConnection::ExportAllProperties
+ | QDBusConnection::ExportAllSlots
+ | QDBusConnection::ExportAllInvokables);
+ }
+
+private:
+ QDBusConnection m_conn;
+ MyObject obj;
+};
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ QDBusConnection con = QDBusConnection::sessionBus();
+ if (!con.isConnected())
+ exit(1);
+
+ if (!con.registerService(serviceName))
+ exit(2);
+
+ MyServer server;
+ con.registerObject(objectPath, &server, QDBusConnection::ExportAllSlots);
+
+ printf("ready.\n");
+
+ return app.exec();
+}
+
+#include "qmyserver.moc" \ No newline at end of file
diff --git a/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.pro b/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.pro
new file mode 100644
index 0000000000..f4fe02c4eb
--- /dev/null
+++ b/tests/auto/dbus/qdbusinterface/qmyserver/qmyserver.pro
@@ -0,0 +1,5 @@
+SOURCES = qmyserver.cpp
+HEADERS = ../myobject.h
+TARGET = qmyserver
+QT += dbus
+QT -= gui
diff --git a/tests/auto/dbus/qdbusinterface/test/test.pro b/tests/auto/dbus/qdbusinterface/test/test.pro
new file mode 100644
index 0000000000..2ef7a89c56
--- /dev/null
+++ b/tests/auto/dbus/qdbusinterface/test/test.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+SOURCES += ../tst_qdbusinterface.cpp
+HEADERS += ../myobject.h
+TARGET = ../tst_qdbusinterface
+
+QT = core core-private dbus
diff --git a/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp
new file mode 100644
index 0000000000..9156818158
--- /dev/null
+++ b/tests/auto/dbus/qdbusinterface/tst_qdbusinterface.cpp
@@ -0,0 +1,1139 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+/* -*- C++ -*-
+ */
+
+#include <qcoreapplication.h>
+#include <qmetatype.h>
+#include <QtTest/QtTest>
+#include <QtCore/qvariant.h>
+#include <QtDBus/QtDBus>
+
+#include "../qdbusmarshall/common.h"
+#include "myobject.h"
+
+#define TEST_INTERFACE_NAME "com.trolltech.QtDBus.MyObject"
+#define TEST_SIGNAL_NAME "somethingHappened"
+
+static const char serviceName[] = "com.trolltech.autotests.qmyserver";
+static const char objectPath[] = "/com/trolltech/qmyserver";
+static const char *interfaceName = serviceName;
+
+int MyObject::callCount = 0;
+QVariantList MyObject::callArgs;
+
+class MyObjectUnknownType: public QObject
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "com.trolltech.QtDBus.MyObject")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"com.trolltech.QtDBus.MyObjectUnknownTypes\" >\n"
+" <property access=\"readwrite\" type=\"~\" name=\"prop1\" />\n"
+" <signal name=\"somethingHappened\" >\n"
+" <arg direction=\"out\" type=\"~\" />\n"
+" </signal>\n"
+" <method name=\"ping\" >\n"
+" <arg direction=\"in\" type=\"~\" name=\"ping\" />\n"
+" <arg direction=\"out\" type=\"~\" name=\"ping\" />\n"
+" </method>\n"
+" <method name=\"regularMethod\" />\n"
+" </interface>\n"
+ "")
+};
+
+class Spy: public QObject
+{
+ Q_OBJECT
+public:
+ QString received;
+ int count;
+
+ Spy() : count(0)
+ { }
+
+public slots:
+ void spySlot(const QString& arg)
+ {
+ received = arg;
+ ++count;
+ }
+};
+
+class DerivedFromQDBusInterface: public QDBusInterface
+{
+ Q_OBJECT
+public:
+ DerivedFromQDBusInterface()
+ : QDBusInterface("com.example.Test", "/")
+ {}
+
+public slots:
+ void method() {}
+};
+
+// helper function
+void emitSignal(const QString &interface, const QString &name, const QString &arg)
+{
+ QDBusMessage msg = QDBusMessage::createSignal("/", interface, name);
+ msg << arg;
+ QDBusConnection::sessionBus().send(msg);
+
+ QTest::qWait(1000);
+}
+
+void emitSignalPeer(const QString &interface, const QString &name, const QString &arg)
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "emitSignal");
+ req << interface;
+ req << name;
+ req << arg;
+ QDBusConnection::sessionBus().send(req);
+
+ QTest::qWait(1000);
+}
+
+int callCountPeer()
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "callCount");
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+ return reply.arguments().at(0).toInt();
+}
+
+QVariantList callArgsPeer()
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "callArgs");
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+ return qdbus_cast<QVariantList>(reply.arguments().at(0));
+}
+
+void setProp1Peer(int val)
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "setProp1");
+ req << val;
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+}
+
+int prop1Peer()
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "prop1");
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+ return reply.arguments().at(0).toInt();
+}
+
+void setComplexPropPeer(QList<int> val)
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "setComplexProp");
+ req << qVariantFromValue(val);
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+}
+
+QList<int> complexPropPeer()
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "complexProp");
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+ return qdbus_cast<QList<int> >(reply.arguments().at(0));
+}
+
+void resetPeer()
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "reset");
+ QDBusConnection::sessionBus().call(req);
+}
+
+class tst_QDBusInterface: public QObject
+{
+ Q_OBJECT
+ MyObject obj;
+
+public slots:
+ void testServiceOwnerChanged(const QString &service)
+ {
+ if (service == "com.example.Test")
+ QTestEventLoop::instance().exitLoop();
+ }
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void notConnected();
+ void notValid();
+ void notValidDerived();
+ void invalidAfterServiceOwnerChanged();
+ void introspect();
+ void introspectUnknownTypes();
+ void introspectVirtualObject();
+ void callMethod();
+ void invokeMethod();
+ void invokeMethodWithReturn();
+ void invokeMethodWithMultiReturn();
+ void invokeMethodWithComplexReturn();
+
+ void introspectPeer();
+ void callMethodPeer();
+ void invokeMethodPeer();
+ void invokeMethodWithReturnPeer();
+ void invokeMethodWithMultiReturnPeer();
+ void invokeMethodWithComplexReturnPeer();
+
+ void signal();
+ void signalPeer();
+
+ void propertyRead();
+ void propertyWrite();
+ void complexPropertyRead();
+ void complexPropertyWrite();
+
+ void propertyReadPeer();
+ void propertyWritePeer();
+ void complexPropertyReadPeer();
+ void complexPropertyWritePeer();
+private:
+ QProcess proc;
+};
+
+class WaitForQMyServer: public QObject
+{
+ Q_OBJECT
+public:
+ WaitForQMyServer();
+ bool ok();
+public Q_SLOTS:
+ void ownerChange(const QString &name)
+ {
+ if (name == serviceName)
+ loop.quit();
+ }
+
+private:
+ QEventLoop loop;
+};
+
+WaitForQMyServer::WaitForQMyServer()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ if (!ok()) {
+ connect(con.interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
+ SLOT(ownerChange(QString)));
+ QTimer::singleShot(2000, &loop, SLOT(quit()));
+ loop.exec();
+ }
+}
+
+bool WaitForQMyServer::ok()
+{
+ return QDBusConnection::sessionBus().isConnected() &&
+ QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName);
+}
+
+void tst_QDBusInterface::initTestCase()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QVERIFY(con.isConnected());
+ QTest::qWait(500);
+
+ con.registerObject("/", &obj, QDBusConnection::ExportAllProperties
+ | QDBusConnection::ExportAllSlots
+ | QDBusConnection::ExportAllInvokables);
+
+ // start peer server
+ #ifdef Q_OS_WIN
+ proc.start("qmyserver");
+ #else
+ proc.start("./qmyserver/qmyserver");
+ #endif
+ QVERIFY(proc.waitForStarted());
+
+ WaitForQMyServer w;
+ QVERIFY(w.ok());
+ //QTest::qWait(2000);
+
+ // get peer server address
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "address");
+ QDBusMessage rpl = con.call(req);
+ QVERIFY(rpl.type() == QDBusMessage::ReplyMessage);
+ QString address = rpl.arguments().at(0).toString();
+
+ // connect to peer server
+ QDBusConnection peercon = QDBusConnection::connectToPeer(address, "peer");
+ QVERIFY(peercon.isConnected());
+
+ QDBusMessage req2 = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "isConnected");
+ QDBusMessage rpl2 = con.call(req2);
+ QVERIFY(rpl2.type() == QDBusMessage::ReplyMessage);
+ QVERIFY(rpl2.arguments().at(0).toBool());
+}
+
+void tst_QDBusInterface::cleanupTestCase()
+{
+ proc.close();
+ proc.kill();
+}
+
+void tst_QDBusInterface::notConnected()
+{
+ QDBusConnection connection("");
+ QVERIFY(!connection.isConnected());
+
+ QDBusInterface interface("org.freedesktop.DBus", "/", "org.freedesktop.DBus",
+ connection);
+
+ QVERIFY(!interface.isValid());
+ QVERIFY(!QMetaObject::invokeMethod(&interface, "ListNames", Qt::DirectConnection));
+}
+
+void tst_QDBusInterface::notValid()
+{
+ QDBusConnection connection("");
+ QVERIFY(!connection.isConnected());
+
+ QDBusInterface interface("com.example.Test", QString(), "org.example.Test",
+ connection);
+
+ QVERIFY(!interface.isValid());
+ QVERIFY(!QMetaObject::invokeMethod(&interface, "ListNames", Qt::DirectConnection));
+}
+
+void tst_QDBusInterface::notValidDerived()
+{
+ DerivedFromQDBusInterface c;
+ QVERIFY(!c.isValid());
+ QMetaObject::invokeMethod(&c, "method", Qt::DirectConnection);
+}
+
+void tst_QDBusInterface::invalidAfterServiceOwnerChanged()
+{
+ // this test is technically the same as tst_QDBusAbstractInterface::followSignal
+ QDBusConnection conn = QDBusConnection::sessionBus();
+ QDBusConnectionInterface *connIface = conn.interface();
+
+ QDBusInterface validInterface(conn.baseService(), "/");
+ QVERIFY(validInterface.isValid());
+ QDBusInterface invalidInterface("com.example.Test", "/");
+ QVERIFY(!invalidInterface.isValid());
+
+ QTestEventLoop::instance().connect(connIface, SIGNAL(serviceOwnerChanged(QString, QString, QString)),
+ SLOT(exitLoop()));
+ QVERIFY(connIface->registerService("com.example.Test") == QDBusConnectionInterface::ServiceRegistered);
+
+ QTestEventLoop::instance().enterLoop(5);
+
+ QVERIFY(!QTestEventLoop::instance().timeout());
+ QVERIFY(invalidInterface.isValid());
+}
+
+void tst_QDBusInterface::introspect()
+{
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ const QMetaObject *mo = iface.metaObject();
+
+ QCOMPARE(mo->methodCount() - mo->methodOffset(), 7);
+ QVERIFY(mo->indexOfSignal(TEST_SIGNAL_NAME "(QString)") != -1);
+
+ QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 2);
+ QVERIFY(mo->indexOfProperty("prop1") != -1);
+ QVERIFY(mo->indexOfProperty("complexProp") != -1);
+}
+
+void tst_QDBusInterface::introspectUnknownTypes()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ MyObjectUnknownType obj;
+ con.registerObject("/unknownTypes", &obj, QDBusConnection::ExportAllContents);
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/unknownTypes"),
+ "com.trolltech.QtDBus.MyObjectUnknownTypes");
+
+ const QMetaObject *mo = iface.metaObject();
+ QVERIFY(mo->indexOfMethod("regularMethod()") != -1); // this is the control
+ QVERIFY(mo->indexOfMethod("somethingHappened(QDBusRawType<0x7e>*)") != -1);
+
+ QVERIFY(mo->indexOfMethod("ping(QDBusRawType<0x7e>*)") != -1);
+ int midx = mo->indexOfMethod("ping(QDBusRawType<0x7e>*)");
+ QCOMPARE(mo->method(midx).typeName(), "QDBusRawType<0x7e>*");
+
+ QVERIFY(mo->indexOfProperty("prop1") != -1);
+ int pidx = mo->indexOfProperty("prop1");
+ QCOMPARE(mo->property(pidx).typeName(), "QDBusRawType<0x7e>*");
+
+
+
+ QDBusMessage message = QDBusMessage::createMethodCall(con.baseService(), "/unknownTypes", "org.freedesktop.DBus.Introspectable", "Introspect");
+ QDBusMessage reply = con.call(message, QDBus::Block, 5000);
+ qDebug() << "REPL: " << reply.arguments();
+
+}
+
+
+class VirtualObject: public QDBusVirtualObject
+{
+ Q_OBJECT
+public:
+ VirtualObject() :success(true) {}
+
+ QString introspect(const QString &path) const {
+ if (path == "/some/path/superNode")
+ return "zitroneneis";
+ if (path == "/some/path/superNode/foo")
+ return " <interface name=\"com.trolltech.QtDBus.VirtualObject\">\n"
+ " <method name=\"klingeling\" />\n"
+ " </interface>\n" ;
+ return QString();
+ }
+
+ bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection) {
+ ++callCount;
+ lastMessage = message;
+
+ if (success) {
+ QDBusMessage reply = message.createReply(replyArguments);
+ connection.send(reply);
+ }
+ emit messageReceived(message);
+ return success;
+ }
+signals:
+ void messageReceived(const QDBusMessage &message) const;
+
+public:
+ mutable QDBusMessage lastMessage;
+ QVariantList replyArguments;
+ mutable int callCount;
+ bool success;
+};
+
+void tst_QDBusInterface::introspectVirtualObject()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QVERIFY(con.isConnected());
+ VirtualObject obj;
+
+ obj.success = false;
+
+ QString path = "/some/path/superNode";
+ QVERIFY(con.registerVirtualObject(path, &obj, QDBusConnection::SubPath));
+
+ QDBusMessage message = QDBusMessage::createMethodCall(con.baseService(), path, "org.freedesktop.DBus.Introspectable", "Introspect");
+ QDBusMessage reply = con.call(message, QDBus::Block, 5000);
+ QVERIFY(reply.arguments().at(0).toString().contains(
+ QRegExp("<node>.*zitroneneis.*<interface name=") ));
+
+ QDBusMessage message2 = QDBusMessage::createMethodCall(con.baseService(), path + "/foo", "org.freedesktop.DBus.Introspectable", "Introspect");
+ QDBusMessage reply2 = con.call(message2, QDBus::Block, 5000);
+ QVERIFY(reply2.arguments().at(0).toString().contains(
+ QRegExp("<node>.*<interface name=\"com.trolltech.QtDBus.VirtualObject\">"
+ ".*<method name=\"klingeling\" />\n"
+ ".*</interface>.*<interface name=") ));
+}
+
+void tst_QDBusInterface::callMethod()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ MyObject::callCount = 0;
+
+ // call a SLOT method
+ QDBusMessage reply = iface.call("ping", qVariantFromValue(QDBusVariant("foo")));
+ QCOMPARE(MyObject::callCount, 1);
+ QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ QVariant v = MyObject::callArgs.at(0);
+ QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("foo"));
+
+ // verify reply
+ QCOMPARE(reply.arguments().count(), 1);
+ v = reply.arguments().at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("foo"));
+
+ // call an INVOKABLE method
+ reply = iface.call("ping_invokable", qVariantFromValue(QDBusVariant("bar")));
+ QCOMPARE(MyObject::callCount, 2);
+ QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ v = MyObject::callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("bar"));
+
+ // verify reply
+ QCOMPARE(reply.arguments().count(), 1);
+ v = reply.arguments().at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("bar"));
+}
+
+void tst_QDBusInterface::invokeMethod()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ MyObject::callCount = 0;
+
+ // make the SLOT call without a return type
+ QDBusVariant arg("foo");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_ARG(QDBusVariant, arg)));
+ QCOMPARE(MyObject::callCount, 1);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ QVariant v = MyObject::callArgs.at(0);
+ QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("foo"));
+
+ // make the INVOKABLE call without a return type
+ QDBusVariant arg2("bar");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_ARG(QDBusVariant, arg2)));
+ QCOMPARE(MyObject::callCount, 2);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ v = MyObject::callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("bar"));
+}
+
+void tst_QDBusInterface::invokeMethodWithReturn()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ MyObject::callCount = 0;
+ QDBusVariant retArg;
+
+ // make the SLOT call without a return type
+ QDBusVariant arg("foo");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg)));
+ QCOMPARE(MyObject::callCount, 1);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ QVariant v = MyObject::callArgs.at(0);
+ QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg.variant().toString());
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg.variant(), arg.variant());
+
+ // make the INVOKABLE call without a return type
+ QDBusVariant arg2("bar");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg2)));
+ QCOMPARE(MyObject::callCount, 2);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ v = MyObject::callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg2.variant().toString());
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg.variant(), arg2.variant());
+}
+
+void tst_QDBusInterface::invokeMethodWithMultiReturn()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ MyObject::callCount = 0;
+ QDBusVariant retArg, retArg2;
+
+ // make the SLOT call without a return type
+ QDBusVariant arg("foo"), arg2("bar");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping",
+ Q_RETURN_ARG(QDBusVariant, retArg),
+ Q_ARG(QDBusVariant, arg),
+ Q_ARG(QDBusVariant, arg2),
+ Q_ARG(QDBusVariant&, retArg2)));
+ QCOMPARE(MyObject::callCount, 1);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 2);
+ QVariant v = MyObject::callArgs.at(0);
+ QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg.variant().toString());
+
+ v = MyObject::callArgs.at(1);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg2.variant().toString());
+
+ // verify that we got the replies as expected
+ QCOMPARE(retArg.variant(), arg.variant());
+ QCOMPARE(retArg2.variant(), arg2.variant());
+
+ // make the INVOKABLE call without a return type
+ QDBusVariant arg3("hello"), arg4("world");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable",
+ Q_RETURN_ARG(QDBusVariant, retArg),
+ Q_ARG(QDBusVariant, arg3),
+ Q_ARG(QDBusVariant, arg4),
+ Q_ARG(QDBusVariant&, retArg2)));
+ QCOMPARE(MyObject::callCount, 2);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 2);
+ v = MyObject::callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg3.variant().toString());
+
+ v = MyObject::callArgs.at(1);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg4.variant().toString());
+
+ // verify that we got the replies as expected
+ QCOMPARE(retArg.variant(), arg3.variant());
+ QCOMPARE(retArg2.variant(), arg4.variant());
+}
+
+void tst_QDBusInterface::invokeMethodWithComplexReturn()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ MyObject::callCount = 0;
+ QList<int> retArg;
+
+ // make the SLOT call without a return type
+ QList<int> arg = QList<int>() << 42 << -47;
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg)));
+ QCOMPARE(MyObject::callCount, 1);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ QVariant v = MyObject::callArgs.at(0);
+ QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>());
+ QCOMPARE(qdbus_cast<QList<int> >(v), arg);
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg, arg);
+
+ // make the INVOKABLE call without a return type
+ QList<int> arg2 = QList<int>() << 24 << -74;
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg2)));
+ QCOMPARE(MyObject::callCount, 2);
+
+ // verify what the callee received
+ QCOMPARE(MyObject::callArgs.count(), 1);
+ v = MyObject::callArgs.at(0);
+ QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>());
+ QCOMPARE(qdbus_cast<QList<int> >(v), arg2);
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg, arg2);
+}
+
+void tst_QDBusInterface::introspectPeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ const QMetaObject *mo = iface.metaObject();
+
+ QCOMPARE(mo->methodCount() - mo->methodOffset(), 7);
+ QVERIFY(mo->indexOfSignal(TEST_SIGNAL_NAME "(QString)") != -1);
+
+ QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 2);
+ QVERIFY(mo->indexOfProperty("prop1") != -1);
+ QVERIFY(mo->indexOfProperty("complexProp") != -1);
+}
+
+void tst_QDBusInterface::callMethodPeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ resetPeer();
+
+ // call a SLOT method
+ QDBusMessage reply = iface.call("ping", qVariantFromValue(QDBusVariant("foo")));
+ QCOMPARE(callCountPeer(), 1);
+ QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
+
+ // verify what the callee received
+ QVariantList callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 1);
+ QVariant v = callArgs.at(0);
+ QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("foo"));
+
+ // verify reply
+ QCOMPARE(reply.arguments().count(), 1);
+ v = reply.arguments().at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("foo"));
+
+ // call an INVOKABLE method
+ reply = iface.call("ping_invokable", qVariantFromValue(QDBusVariant("bar")));
+ QCOMPARE(callCountPeer(), 2);
+ QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
+
+ // verify what the callee received
+ callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 1);
+ v = callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("bar"));
+
+ // verify reply
+ QCOMPARE(reply.arguments().count(), 1);
+ v = reply.arguments().at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("bar"));
+}
+
+void tst_QDBusInterface::invokeMethodPeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ resetPeer();
+
+ // make the SLOT call without a return type
+ QDBusVariant arg("foo");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_ARG(QDBusVariant, arg)));
+ QCOMPARE(callCountPeer(), 1);
+
+ // verify what the callee received
+ QVariantList callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 1);
+ QVariant v = callArgs.at(0);
+ QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("foo"));
+
+ // make the INVOKABLE call without a return type
+ QDBusVariant arg2("bar");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_ARG(QDBusVariant, arg2)));
+ QCOMPARE(callCountPeer(), 2);
+
+ // verify what the callee received
+ callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 1);
+ v = callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), QString("bar"));
+}
+
+void tst_QDBusInterface::invokeMethodWithReturnPeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ resetPeer();
+ QDBusVariant retArg;
+
+ // make the SLOT call without a return type
+ QDBusVariant arg("foo");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg)));
+ QCOMPARE(callCountPeer(), 1);
+
+ // verify what the callee received
+ QVariantList callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 1);
+ QVariant v = callArgs.at(0);
+ QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg.variant().toString());
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg.variant(), arg.variant());
+
+ // make the INVOKABLE call without a return type
+ QDBusVariant arg2("bar");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg2)));
+ QCOMPARE(callCountPeer(), 2);
+
+ // verify what the callee received
+ callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 1);
+ v = callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg2.variant().toString());
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg.variant(), arg2.variant());
+}
+
+void tst_QDBusInterface::invokeMethodWithMultiReturnPeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ resetPeer();
+ QDBusVariant retArg, retArg2;
+
+ // make the SLOT call without a return type
+ QDBusVariant arg("foo"), arg2("bar");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping",
+ Q_RETURN_ARG(QDBusVariant, retArg),
+ Q_ARG(QDBusVariant, arg),
+ Q_ARG(QDBusVariant, arg2),
+ Q_ARG(QDBusVariant&, retArg2)));
+ QCOMPARE(callCountPeer(), 1);
+
+ // verify what the callee received
+ QVariantList callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 2);
+ QVariant v = callArgs.at(0);
+ QDBusVariant dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg.variant().toString());
+
+ v = callArgs.at(1);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg2.variant().toString());
+
+ // verify that we got the replies as expected
+ QCOMPARE(retArg.variant(), arg.variant());
+ QCOMPARE(retArg2.variant(), arg2.variant());
+
+ // make the INVOKABLE call without a return type
+ QDBusVariant arg3("hello"), arg4("world");
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping_invokable",
+ Q_RETURN_ARG(QDBusVariant, retArg),
+ Q_ARG(QDBusVariant, arg3),
+ Q_ARG(QDBusVariant, arg4),
+ Q_ARG(QDBusVariant&, retArg2)));
+ QCOMPARE(callCountPeer(), 2);
+
+ // verify what the callee received
+ callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 2);
+ v = callArgs.at(0);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg3.variant().toString());
+
+ v = callArgs.at(1);
+ dv = qdbus_cast<QDBusVariant>(v);
+ QCOMPARE(dv.variant().type(), QVariant::String);
+ QCOMPARE(dv.variant().toString(), arg4.variant().toString());
+
+ // verify that we got the replies as expected
+ QCOMPARE(retArg.variant(), arg3.variant());
+ QCOMPARE(retArg2.variant(), arg4.variant());
+}
+
+void tst_QDBusInterface::invokeMethodWithComplexReturnPeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ resetPeer();
+ QList<int> retArg;
+
+ // make the SLOT call without a return type
+ QList<int> arg = QList<int>() << 42 << -47;
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg)));
+ QCOMPARE(callCountPeer(), 1);
+
+ // verify what the callee received
+ QVariantList callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 1);
+ QVariant v = callArgs.at(0);
+ QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>());
+ QCOMPARE(qdbus_cast<QList<int> >(v), arg);
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg, arg);
+
+ // make the INVOKABLE call without a return type
+ QList<int> arg2 = QList<int>() << 24 << -74;
+ QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList<int>, retArg), Q_ARG(QList<int>, arg2)));
+ QCOMPARE(callCountPeer(), 2);
+
+ // verify what the callee received
+ callArgs = callArgsPeer();
+ QCOMPARE(callArgs.count(), 1);
+ v = callArgs.at(0);
+ QCOMPARE(v.userType(), qMetaTypeId<QDBusArgument>());
+ QCOMPARE(qdbus_cast<QList<int> >(v), arg2);
+
+ // verify that we got the reply as expected
+ QCOMPARE(retArg, arg2);
+}
+
+void tst_QDBusInterface::signal()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ QString arg = "So long and thanks for all the fish";
+ {
+ Spy spy;
+ spy.connect(&iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+
+ emitSignal(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
+ QCOMPARE(spy.count, 1);
+ QCOMPARE(spy.received, arg);
+ }
+
+ QDBusInterface iface2(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+ {
+ Spy spy;
+ spy.connect(&iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+ spy.connect(&iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+
+ emitSignal(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
+ QCOMPARE(spy.count, 2);
+ QCOMPARE(spy.received, arg);
+ }
+
+ {
+ Spy spy, spy2;
+ spy.connect(&iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+ spy2.connect(&iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+
+ emitSignal(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
+ QCOMPARE(spy.count, 1);
+ QCOMPARE(spy.received, arg);
+ QCOMPARE(spy2.count, 1);
+ QCOMPARE(spy2.received, arg);
+ }
+}
+
+void tst_QDBusInterface::signalPeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ QString arg = "So long and thanks for all the fish";
+ {
+ Spy spy;
+ spy.connect(&iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+
+ emitSignalPeer(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
+ QCOMPARE(spy.count, 1);
+ QCOMPARE(spy.received, arg);
+ }
+
+ QDBusInterface iface2(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+ {
+ Spy spy;
+ spy.connect(&iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+ spy.connect(&iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+
+ emitSignalPeer(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
+ QCOMPARE(spy.count, 2);
+ QCOMPARE(spy.received, arg);
+ }
+
+ {
+ Spy spy, spy2;
+ spy.connect(&iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+ spy2.connect(&iface2, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
+
+ emitSignalPeer(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
+ QCOMPARE(spy.count, 1);
+ QCOMPARE(spy.received, arg);
+ QCOMPARE(spy2.count, 1);
+ QCOMPARE(spy2.received, arg);
+ }
+}
+
+void tst_QDBusInterface::propertyRead()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ int arg = obj.m_prop1 = 42;
+ MyObject::callCount = 0;
+
+ QVariant v = iface.property("prop1");
+ QVERIFY(v.isValid());
+ QCOMPARE(v.userType(), int(QVariant::Int));
+ QCOMPARE(v.toInt(), arg);
+ QCOMPARE(MyObject::callCount, 1);
+}
+
+void tst_QDBusInterface::propertyWrite()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ int arg = 42;
+ obj.m_prop1 = 0;
+ MyObject::callCount = 0;
+
+ QVERIFY(iface.setProperty("prop1", arg));
+ QCOMPARE(MyObject::callCount, 1);
+ QCOMPARE(obj.m_prop1, arg);
+}
+
+void tst_QDBusInterface::complexPropertyRead()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ QList<int> arg = obj.m_complexProp = QList<int>() << 42 << -47;
+ MyObject::callCount = 0;
+
+ QVariant v = iface.property("complexProp");
+ QVERIFY(v.isValid());
+ QCOMPARE(v.userType(), qMetaTypeId<QList<int> >());
+ QCOMPARE(v.value<QList<int> >(), arg);
+ QCOMPARE(MyObject::callCount, 1);
+}
+
+void tst_QDBusInterface::complexPropertyWrite()
+{
+ QDBusConnection con = QDBusConnection::sessionBus();
+ QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"),
+ TEST_INTERFACE_NAME);
+
+ QList<int> arg = QList<int>() << -47 << 42;
+ obj.m_complexProp.clear();
+ MyObject::callCount = 0;
+
+ QVERIFY(iface.setProperty("complexProp", qVariantFromValue(arg)));
+ QCOMPARE(MyObject::callCount, 1);
+ QCOMPARE(obj.m_complexProp, arg);
+}
+
+void tst_QDBusInterface::propertyReadPeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ resetPeer();
+ int arg = 42;
+ setProp1Peer(42);
+
+ QVariant v = iface.property("prop1");
+ QVERIFY(v.isValid());
+ QCOMPARE(v.userType(), int(QVariant::Int));
+ QCOMPARE(v.toInt(), arg);
+ QCOMPARE(callCountPeer(), 1);
+}
+
+void tst_QDBusInterface::propertyWritePeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ resetPeer();
+ int arg = 42;
+ setProp1Peer(0);
+
+ QVERIFY(iface.setProperty("prop1", arg));
+ QCOMPARE(callCountPeer(), 1);
+ QCOMPARE(prop1Peer(), arg);
+}
+
+void tst_QDBusInterface::complexPropertyReadPeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ resetPeer();
+ QList<int> arg = QList<int>() << 42 << -47;
+ setComplexPropPeer(arg);
+
+ QVariant v = iface.property("complexProp");
+ QVERIFY(v.isValid());
+ QCOMPARE(v.userType(), qMetaTypeId<QList<int> >());
+ QCOMPARE(v.value<QList<int> >(), arg);
+ QCOMPARE(callCountPeer(), 1);
+}
+
+void tst_QDBusInterface::complexPropertyWritePeer()
+{
+ QDBusConnection con("peer");
+ QDBusInterface iface(QString(), QLatin1String("/"),
+ TEST_INTERFACE_NAME, con);
+
+ resetPeer();
+ QList<int> arg = QList<int>() << -47 << 42;
+
+ QVERIFY(iface.setProperty("complexProp", qVariantFromValue(arg)));
+ QCOMPARE(callCountPeer(), 1);
+ QCOMPARE(complexPropPeer(), arg);
+}
+
+QTEST_MAIN(tst_QDBusInterface)
+
+#include "tst_qdbusinterface.moc"