summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-04-18 22:17:02 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-04-18 22:17:02 (GMT)
commit685df07ff7e357f6848c50cffa311641afdca307 (patch)
tree760e1e6f7189513785133071ab408260f09210b4
parenta359d21a84acc4b7eb73931e47acd4440327be19 (diff)
parent4c8c5ef3866723124fe8cf2c8bdd3b846549b129 (diff)
downloadQt-685df07ff7e357f6848c50cffa311641afdca307.zip
Qt-685df07ff7e357f6848c50cffa311641afdca307.tar.gz
Qt-685df07ff7e357f6848c50cffa311641afdca307.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1: QtDBus: Add unit tests for QDBusAbstractAdaptor QtDBus: Add unit tests for QDBusInterface QtDBus: Add unit tests for QDBusAbstractInterface QtDBus: Register QDBusServer connection name in QDBusConnectionManager QtDBus: Skip bus name check for peer-to-peer connection QtDBus: Fix minor coding style issues QtDBus: Add default constructor to QDBusServer QtDBus: Add unit tests for peer-to-peer connection QtDBus: Add method QDBusConnection::disconnectFromPeer() QtDBus: Add method QDBusConnection::connectToPeer() QtDBus: Fix QDBusConnection::disconnectFromBus() for peer-to-peer connections QtDBus: Fix bus in peer-to-peer connections should not be used QtDBus: Fix empty service name in peer-to-peer connections QtDBus: Fix registering objects using path '/' in peer-to-peer connections QtDBus: Fix QDBusServer to handle correctly new dbus connections QtDBus: Cleaning comments, spacing, etc.
-rw-r--r--src/dbus/qdbusabstractinterface.cpp9
-rw-r--r--src/dbus/qdbusconnection.cpp93
-rw-r--r--src/dbus/qdbusconnection.h2
-rw-r--r--src/dbus/qdbusconnection_p.h2
-rw-r--r--src/dbus/qdbusconnectionmanager_p.h88
-rw-r--r--src/dbus/qdbusintegrator.cpp93
-rw-r--r--src/dbus/qdbusserver.cpp25
-rw-r--r--src/dbus/qdbusserver.h3
-rw-r--r--tests/auto/qdbusabstractadaptor/myobject.h286
-rw-r--r--tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro9
-rw-r--r--tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.cpp167
-rw-r--r--tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.pro5
-rw-r--r--tests/auto/qdbusabstractadaptor/test/test.pro7
-rw-r--r--tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp985
-rw-r--r--tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml2
-rw-r--r--tests/auto/qdbusabstractinterface/interface.h1
-rw-r--r--tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro17
-rw-r--r--tests/auto/qdbusabstractinterface/qpinger/qpinger.cpp131
-rw-r--r--tests/auto/qdbusabstractinterface/qpinger/qpinger.pro5
-rw-r--r--tests/auto/qdbusabstractinterface/test/test.pro13
-rw-r--r--tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp573
-rw-r--r--tests/auto/qdbusconnection/tst_qdbusconnection.cpp382
-rw-r--r--tests/auto/qdbusinterface/myobject.h164
-rw-r--r--tests/auto/qdbusinterface/qdbusinterface.pro7
-rw-r--r--tests/auto/qdbusinterface/qmyserver/qmyserver.cpp155
-rw-r--r--tests/auto/qdbusinterface/qmyserver/qmyserver.pro5
-rw-r--r--tests/auto/qdbusinterface/test/test.pro7
-rw-r--r--tests/auto/qdbusinterface/tst_qdbusinterface.cpp629
28 files changed, 3373 insertions, 492 deletions
diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp
index e48e1c0..9e82c09 100644
--- a/src/dbus/qdbusabstractinterface.cpp
+++ b/src/dbus/qdbusabstractinterface.cpp
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
static QDBusError checkIfValid(const QString &service, const QString &path,
- const QString &interface, bool isDynamic)
+ const QString &interface, bool isDynamic, bool isPeer)
{
// We should be throwing exceptions here... oh well
QDBusError error;
@@ -69,7 +69,7 @@ static QDBusError checkIfValid(const QString &service, const QString &path,
// use assertion here because this should never happen, at all
Q_ASSERT_X(!interface.isEmpty(), "QDBusAbstractInterface", "Interface name cannot be empty");
}
- if (!QDBusUtil::checkBusName(service, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
+ if (!QDBusUtil::checkBusName(service, (isDynamic && !isPeer) ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
return error;
if (!QDBusUtil::checkObjectPath(path, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error))
return error;
@@ -86,7 +86,8 @@ QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv
const QDBusConnection& con,
bool isDynamic)
: connection(con), service(serv), path(p), interface(iface),
- lastError(checkIfValid(serv, p, iface, isDynamic)),
+ lastError(checkIfValid(serv, p, iface, isDynamic, (connectionPrivate() &&
+ connectionPrivate()->mode == QDBusConnectionPrivate::PeerMode))),
isValid(!lastError.isValid())
{
if (!isValid)
@@ -107,7 +108,7 @@ bool QDBusAbstractInterfacePrivate::canMakeCalls() const
{
// recheck only if we have a wildcard (i.e. empty) service or path
// if any are empty, set the error message according to QDBusUtil
- if (service.isEmpty())
+ if (service.isEmpty() && connectionPrivate()->mode != QDBusConnectionPrivate::PeerMode)
return QDBusUtil::checkBusName(service, QDBusUtil::EmptyNotAllowed, &lastError);
if (path.isEmpty())
return QDBusUtil::checkObjectPath(path, QDBusUtil::EmptyNotAllowed, &lastError);
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp
index 4883a4d..c8cf6ea 100644
--- a/src/dbus/qdbusconnection.cpp
+++ b/src/dbus/qdbusconnection.cpp
@@ -52,6 +52,7 @@
#include "qdbusconnection_p.h"
#include "qdbusinterface_p.h"
#include "qdbusutil_p.h"
+#include "qdbusconnectionmanager_p.h"
#include "qdbusthreaddebug_p.h"
@@ -59,27 +60,6 @@
QT_BEGIN_NAMESPACE
-class QDBusConnectionManager
-{
-public:
- QDBusConnectionManager() {}
- ~QDBusConnectionManager();
-
- QDBusConnectionPrivate *connection(const QString &name) const;
- void removeConnection(const QString &name);
- void setConnection(const QString &name, QDBusConnectionPrivate *c);
-
- QDBusConnectionPrivate *sender() const;
- void setSender(const QDBusConnectionPrivate *s);
-
- mutable QMutex mutex;
-private:
- QHash<QString, QDBusConnectionPrivate *> connectionHash;
-
- mutable QMutex senderMutex;
- QString senderName; // internal; will probably change
-};
-
Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager)
QDBusConnectionPrivate *QDBusConnectionManager::sender() const
@@ -126,6 +106,11 @@ QDBusConnectionManager::~QDBusConnectionManager()
connectionHash.clear();
}
+QDBusConnectionManager* QDBusConnectionManager::instance()
+{
+ return _q_manager();
+}
+
Q_DBUS_EXPORT void qDBusBindToApplication();
void qDBusBindToApplication()
{
@@ -371,7 +356,7 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name)
}
/*!
- Opens a peer-to-peer connection on address \a address and associate with it the
+ Opens a connection to a private bus on address \a address and associate with it the
connection name \a name. Returns a QDBusConnection object associated with that connection.
*/
QDBusConnection QDBusConnection::connectToBus(const QString &address,
@@ -379,7 +364,7 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address,
{
// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
// "Cannot create connection without a Q[Core]Application instance");
- if (!qdbus_loadLibDBus()){
+ if (!qdbus_loadLibDBus()) {
QDBusConnectionPrivate *d = 0;
return QDBusConnection(d);
}
@@ -411,9 +396,43 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address,
return retval;
}
+/*!
+ \since 4.8
+
+ Opens a peer-to-peer connection on address \a address and associate with it the
+ connection name \a name. Returns a QDBusConnection object associated with that connection.
+*/
+QDBusConnection QDBusConnection::connectToPeer(const QString &address,
+ const QString &name)
+{
+// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
+// "Cannot create connection without a Q[Core]Application instance");
+ if (!qdbus_loadLibDBus()) {
+ QDBusConnectionPrivate *d = 0;
+ return QDBusConnection(d);
+ }
+
+ QMutexLocker locker(&_q_manager()->mutex);
+
+ QDBusConnectionPrivate *d = _q_manager()->connection(name);
+ if (d || name.isEmpty())
+ return QDBusConnection(d);
+
+ d = new QDBusConnectionPrivate;
+ // setPeer does the error handling for us
+ QDBusErrorInternal error;
+ DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error);
+
+ d->setPeer(c, error);
+ _q_manager()->setConnection(name, d);
+
+ QDBusConnection retval(d);
+
+ return retval;
+}
/*!
- Closes the connection of name \a name.
+ Closes the bus connection of name \a name.
Note that if there are still QDBusConnection objects associated
with the same connection, the connection will not be closed until
@@ -424,6 +443,30 @@ void QDBusConnection::disconnectFromBus(const QString &name)
{
if (_q_manager()) {
QMutexLocker locker(&_q_manager()->mutex);
+ QDBusConnectionPrivate *d = _q_manager()->connection(name);
+ if (d && d->mode != QDBusConnectionPrivate::ClientMode)
+ return;
+ _q_manager()->removeConnection(name);
+ }
+}
+
+/*!
+ \since 4.8
+
+ Closes the peer connection of name \a name.
+
+ Note that if there are still QDBusConnection objects associated
+ with the same connection, the connection will not be closed until
+ all references are dropped. However, no further references can be
+ created using the QDBusConnection constructor.
+*/
+void QDBusConnection::disconnectFromPeer(const QString &name)
+{
+ if (_q_manager()) {
+ QMutexLocker locker(&_q_manager()->mutex);
+ QDBusConnectionPrivate *d = _q_manager()->connection(name);
+ if (d && d->mode != QDBusConnectionPrivate::PeerMode)
+ return;
_q_manager()->removeConnection(name);
}
}
@@ -814,7 +857,7 @@ void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode)
// find the object
while (node) {
- if (pathComponents.count() == i) {
+ if (pathComponents.count() == i || !path.compare(QLatin1String("/"))) {
// found it
node->obj = 0;
node->flags = 0;
diff --git a/src/dbus/qdbusconnection.h b/src/dbus/qdbusconnection.h
index 6ab0ea2..15e08a7 100644
--- a/src/dbus/qdbusconnection.h
+++ b/src/dbus/qdbusconnection.h
@@ -172,7 +172,9 @@ public:
static QDBusConnection connectToBus(BusType type, const QString &name);
static QDBusConnection connectToBus(const QString &address, const QString &name);
+ static QDBusConnection connectToPeer(const QString &address, const QString &name);
static void disconnectFromBus(const QString &name);
+ static void disconnectFromPeer(const QString &name);
static QDBusConnection sessionBus();
static QDBusConnection systemBus();
diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h
index 36f7c53..355a6e6 100644
--- a/src/dbus/qdbusconnection_p.h
+++ b/src/dbus/qdbusconnection_p.h
@@ -216,7 +216,7 @@ public:
inline void serverConnection(const QDBusConnection &connection)
{ emit newServerConnection(connection); }
-
+
private:
void checkThread();
bool handleError(const QDBusErrorInternal &error);
diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h
new file mode 100644
index 0000000..dd8b4aa
--- /dev/null
+++ b/src/dbus/qdbusconnectionmanager_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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 QtDBus module 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the public API. This header file may
+// change from version to version without notice, or even be
+// removed.
+//
+// We mean it.
+//
+//
+
+#ifndef QDBUSCONNECTIONMANAGER_P_H
+#define QDBUSCONNECTIONMANAGER_P_H
+
+#include "qdbusconnection_p.h"
+
+#ifndef QT_NO_DBUS
+
+QT_BEGIN_NAMESPACE
+
+class QDBusConnectionManager
+{
+public:
+ QDBusConnectionManager() {}
+ ~QDBusConnectionManager();
+ static QDBusConnectionManager* instance();
+
+ QDBusConnectionPrivate *connection(const QString &name) const;
+ void removeConnection(const QString &name);
+ void setConnection(const QString &name, QDBusConnectionPrivate *c);
+
+ QDBusConnectionPrivate *sender() const;
+ void setSender(const QDBusConnectionPrivate *s);
+
+ mutable QMutex mutex;
+private:
+ QHash<QString, QDBusConnectionPrivate *> connectionHash;
+
+ mutable QMutex senderMutex;
+ QString senderName; // internal; will probably change
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_DBUS
+#endif
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 5d53390..b2095c7 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -377,28 +377,23 @@ static void qDBusUpdateDispatchStatus(DBusConnection *connection, DBusDispatchSt
static void qDBusNewConnection(DBusServer *server, DBusConnection *connection, void *data)
{
- // ### We may want to separate the server from the QDBusConnectionPrivate
+ // ### We may want to separate the server from the QDBusConnectionPrivate
Q_ASSERT(server); Q_UNUSED(server);
Q_ASSERT(connection);
Q_ASSERT(data);
// keep the connection alive
q_dbus_connection_ref(connection);
- QDBusConnectionPrivate *d = new QDBusConnectionPrivate;
-
- // setConnection does the error handling for us
+ QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
+
+ // setPeer does the error handling for us
QDBusErrorInternal error;
d->setPeer(connection, error);
QDBusConnection retval = QDBusConnectionPrivate::q(d);
- d->setBusService(retval);
-
- //d->name = QString::number(reinterpret_cast<int>(d));
- //d->setConnection(d->name, d);
// make QDBusServer emit the newConnection signal
- QDBusConnectionPrivate *server_d = static_cast<QDBusConnectionPrivate *>(data);
- server_d->serverConnection(retval);
+ d->serverConnection(retval);
}
} // extern "C"
@@ -435,6 +430,11 @@ static bool findObject(const QDBusConnectionPrivate::ObjectTreeNode *root,
const QString &fullpath, int &usedLength,
QDBusConnectionPrivate::ObjectTreeNode &result)
{
+ if (!fullpath.compare(QLatin1String("/")) && root->obj) {
+ usedLength = 1;
+ result = *root;
+ return root;
+ }
int start = 0;
int length = fullpath.length();
if (fullpath.at(0) == QLatin1Char('/'))
@@ -1036,11 +1036,10 @@ void QDBusConnectionPrivate::closeConnection()
mode = InvalidMode; // prevent reentrancy
baseService.clear();
- if (oldMode == ServerMode) {
- if (server) {
- q_dbus_server_disconnect(server);
- }
- } else if (oldMode == ClientMode || oldMode == PeerMode) {
+ if (server)
+ q_dbus_server_disconnect(server);
+
+ if (oldMode == ClientMode || oldMode == PeerMode) {
if (connection) {
q_dbus_connection_close(connection);
// send the "close" message
@@ -1629,7 +1628,7 @@ void QDBusConnectionPrivate::setServer(DBusServer *s, const QDBusErrorInternal &
this, 0);
//qDebug() << "time_functions_set" << time_functions_set;
Q_UNUSED(time_functions_set);
-
+
q_dbus_server_set_new_connection_function(server, qDBusNewConnection, this, 0);
dbus_bool_t data_set = q_dbus_server_set_data(server, server_slot, this, 0);
@@ -1646,7 +1645,7 @@ void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal
connection = c;
mode = PeerMode;
-
+
q_dbus_connection_set_exit_on_disconnect(connection, false);
q_dbus_connection_set_watch_functions(connection,
qDBusAddWatch,
@@ -2098,21 +2097,23 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook
matchRefCounts.insert(hook.matchRule, 1);
if (connection) {
- qDBusDebug("Adding rule: %s", hook.matchRule.constData());
- q_dbus_bus_add_match(connection, hook.matchRule, NULL);
-
- // Successfully connected the signal
- // Do we need to watch for this name?
- if (shouldWatchService(hook.service)) {
- WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
- if (++data.refcount == 1) {
- // we need to watch for this service changing
- connectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
- QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
- this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString)));
- data.owner = getNameOwnerNoCache(hook.service);
- qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
- << data.owner << ")";
+ if (mode != QDBusConnectionPrivate::PeerMode) {
+ qDBusDebug("Adding rule: %s", hook.matchRule.constData());
+ q_dbus_bus_add_match(connection, hook.matchRule, NULL);
+
+ // Successfully connected the signal
+ // Do we need to watch for this name?
+ if (shouldWatchService(hook.service)) {
+ WatchedServicesHash::mapped_type &data = watchedServices[hook.service];
+ if (++data.refcount == 1) {
+ // we need to watch for this service changing
+ connectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
+ QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
+ this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString)));
+ data.owner = getNameOwnerNoCache(hook.service);
+ qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:"
+ << data.owner << ")";
+ }
}
}
}
@@ -2176,18 +2177,20 @@ QDBusConnectionPrivate::disconnectSignal(SignalHookHash::Iterator &it)
// we don't care about errors here
if (connection && erase) {
- qDBusDebug("Removing rule: %s", hook.matchRule.constData());
- q_dbus_bus_remove_match(connection, hook.matchRule, NULL);
-
- // Successfully disconnected the signal
- // Were we watching for this name?
- WatchedServicesHash::Iterator sit = watchedServices.find(hook.service);
- if (sit != watchedServices.end()) {
- if (--sit.value().refcount == 0) {
- watchedServices.erase(sit);
- disconnectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
- QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
- this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ if (mode != QDBusConnectionPrivate::PeerMode) {
+ qDBusDebug("Removing rule: %s", hook.matchRule.constData());
+ q_dbus_bus_remove_match(connection, hook.matchRule, NULL);
+
+ // Successfully disconnected the signal
+ // Were we watching for this name?
+ WatchedServicesHash::Iterator sit = watchedServices.find(hook.service);
+ if (sit != watchedServices.end()) {
+ if (--sit.value().refcount == 0) {
+ watchedServices.erase(sit);
+ disconnectSignal(dbusServiceString(), QString(), dbusInterfaceString(),
+ QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(),
+ this, SLOT(_q_serviceOwnerChanged(QString,QString,QString)));
+ }
}
}
@@ -2390,7 +2393,7 @@ void QDBusConnectionPrivate::unregisterServiceNoLock(const QString &serviceName)
bool QDBusConnectionPrivate::isServiceRegisteredByThread(const QString &serviceName) const
{
- if (serviceName == baseService)
+ if (!serviceName.isEmpty() && serviceName == baseService)
return true;
QStringList copy = serviceNames;
return copy.contains(serviceName);
diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp
index 9b61555..abc5cb3 100644
--- a/src/dbus/qdbusserver.cpp
+++ b/src/dbus/qdbusserver.cpp
@@ -41,6 +41,7 @@
#include "qdbusserver.h"
#include "qdbusconnection_p.h"
+#include "qdbusconnectionmanager_p.h"
#ifndef QT_NO_DBUS
@@ -62,24 +63,37 @@ QT_BEGIN_NAMESPACE
QDBusServer::QDBusServer(const QString &address, QObject *parent)
: QObject(parent)
{
+ if (address.isEmpty())
+ return;
+
if (!qdbus_loadLibDBus()) {
d = 0;
return;
}
d = new QDBusConnectionPrivate(this);
- if (address.isEmpty())
- return;
+ QMutexLocker locker(&QDBusConnectionManager::instance()->mutex);
+ QDBusConnectionManager::instance()->setConnection(QLatin1String("QDBusServer-") + QString::number(reinterpret_cast<qulonglong>(d)), d);
QObject::connect(d, SIGNAL(newServerConnection(QDBusConnection)),
this, SIGNAL(newConnection(QDBusConnection)));
- // server = q_dbus_server_listen( "unix:tmpdir=/tmp", &error);
QDBusErrorInternal error;
d->setServer(q_dbus_server_listen(address.toUtf8().constData(), error), error);
}
/*!
+ Destructs a QDBusServer
+*/
+QDBusServer::~QDBusServer()
+{
+ if (QDBusConnectionManager::instance()) {
+ QMutexLocker locker(&QDBusConnectionManager::instance()->mutex);
+ QDBusConnectionManager::instance()->removeConnection(d->name);
+ }
+}
+
+/*!
Returns true if this QDBusServer object is connected.
If it isn't connected, you need to call the constructor again.
@@ -113,11 +127,12 @@ QString QDBusServer::address() const
return addr;
}
+
/*!
\fn void QDBusServer::newConnection(const QDBusConnection &connection)
- This signal is currently not used, but if and when it is
- used, \a connection will be the new connection.
+ This signal is emitted when a new client connection \a connection is
+ established to the server.
*/
QT_END_NAMESPACE
diff --git a/src/dbus/qdbusserver.h b/src/dbus/qdbusserver.h
index f101011..fcb78bd 100644
--- a/src/dbus/qdbusserver.h
+++ b/src/dbus/qdbusserver.h
@@ -61,7 +61,8 @@ class Q_DBUS_EXPORT QDBusServer: public QObject
{
Q_OBJECT
public:
- QDBusServer(const QString &address, QObject *parent = 0);
+ QDBusServer(const QString &address = "unix:tmpdir=/tmp", QObject *parent = 0);
+ virtual ~QDBusServer();
bool isConnected() const;
QDBusError lastError() const;
diff --git a/tests/auto/qdbusabstractadaptor/myobject.h b/tests/auto/qdbusabstractadaptor/myobject.h
new file mode 100644
index 0000000..7353fa6
--- /dev/null
+++ b/tests/auto/qdbusabstractadaptor/myobject.h
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** 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$
+** 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MYOBJECT_H
+#define MYOBJECT_H
+
+#include <QtCore/QObject>
+#include <QtDBus/QtDBus>
+
+extern const char *slotSpy;
+extern QString valueSpy;
+
+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();
+};
+
+#endif // MYOBJECT_H \ No newline at end of file
diff --git a/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro b/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro
index 16358c5..c3e3f7f 100644
--- a/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro
+++ b/tests/auto/qdbusabstractadaptor/qdbusabstractadaptor.pro
@@ -1,10 +1,9 @@
load(qttest_p4)
QT = core
contains(QT_CONFIG,dbus): {
- SOURCES += tst_qdbusabstractadaptor.cpp
- QT += dbus
+ TEMPLATE = subdirs
+ CONFIG += ordered
+ SUBDIRS = qmyserver test
} else {
- SOURCES += ../qdbusmarshall/dummy.cpp
+ SOURCES += ../qdbusmarshall/dummy.cpp
}
-
-
diff --git a/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.cpp b/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.cpp
new file mode 100644
index 0000000..238bc38
--- /dev/null
+++ b/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** 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$
+** 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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;
+
+const char *slotSpy;
+QString valueSpy;
+
+Q_DECLARE_METATYPE(QDBusConnection::RegisterOptions)
+
+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"),
+ obj(NULL)
+ {
+ connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&)));
+ }
+
+ ~MyServer()
+ {
+ if (obj)
+ obj->deleteLater();
+ }
+
+public slots:
+ QString address() const
+ {
+ return QDBusServer::address();
+ }
+
+ bool isConnected() const
+ {
+ return m_conn.isConnected();
+ }
+
+ void emitSignal(const QString& interface, const QString& name, const QDBusVariant& parameter)
+ {
+ if (interface.endsWith('2'))
+ obj->if2->emitSignal(name, parameter.variant());
+ else if (interface.endsWith('3'))
+ obj->if3->emitSignal(name, parameter.variant());
+ else if (interface.endsWith('4'))
+ obj->if4->emitSignal(name, parameter.variant());
+ else
+ obj->emitSignal(name, parameter.variant());
+ }
+
+ void emitSignal2(const QString& interface, const QString& name)
+ {
+ if (interface.endsWith('2'))
+ obj->if2->emitSignal(name, QVariant());
+ else if (interface.endsWith('3'))
+ obj->if3->emitSignal(name, QVariant());
+ else if (interface.endsWith('4'))
+ obj->if4->emitSignal(name, QVariant());
+ else
+ obj->emitSignal(name, QVariant());
+ }
+
+ void newMyObject(int nInterfaces = 4)
+ {
+ if (obj)
+ obj->deleteLater();
+ obj = new MyObject(nInterfaces);
+ }
+
+ void registerMyObject(const QString & path, int options)
+ {
+ m_conn.registerObject(path, obj, (QDBusConnection::RegisterOptions)options);
+ }
+
+ QString slotSpyServer()
+ {
+ return QLatin1String(slotSpy);
+ }
+
+ QString valueSpyServer()
+ {
+ return valueSpy;
+ }
+
+ void clearValueSpy()
+ {
+ valueSpy.clear();
+ }
+
+private slots:
+ void handleConnection(const QDBusConnection& con)
+ {
+ m_conn = con;
+ }
+
+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/qdbusabstractadaptor/qmyserver/qmyserver.pro b/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.pro
new file mode 100644
index 0000000..f4fe02c
--- /dev/null
+++ b/tests/auto/qdbusabstractadaptor/qmyserver/qmyserver.pro
@@ -0,0 +1,5 @@
+SOURCES = qmyserver.cpp
+HEADERS = ../myobject.h
+TARGET = qmyserver
+QT += dbus
+QT -= gui
diff --git a/tests/auto/qdbusabstractadaptor/test/test.pro b/tests/auto/qdbusabstractadaptor/test/test.pro
new file mode 100644
index 0000000..014a9e8
--- /dev/null
+++ b/tests/auto/qdbusabstractadaptor/test/test.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+SOURCES += ../tst_qdbusabstractadaptor.cpp
+HEADERS += ../myobject.h
+TARGET = ../tst_qdbusabstractadaptor
+
+QT = core
+QT += dbus
diff --git a/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp b/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp
index a64b3d2..9250350 100644
--- a/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp
+++ b/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp
@@ -46,6 +46,11 @@
#include <QtDBus>
#include "../qdbusmarshall/common.h"
+#include "myobject.h"
+
+static const char serviceName[] = "com.trolltech.autotests.qmyserver";
+static const char objectPath[] = "/com/trolltech/qmyserver";
+static const char *interfaceName = serviceName;
const char *slotSpy;
QString valueSpy;
@@ -73,273 +78,6 @@ namespace QTest {
}
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
@@ -593,6 +331,191 @@ public slots:
}
};
+void newMyObjectPeer(int nInterfaces = 4)
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "newMyObject");
+ req << nInterfaces;
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+}
+
+void registerMyObjectPeer(const QString & path, QDBusConnection::RegisterOptions options = QDBusConnection::ExportAdaptors)
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "registerMyObject");
+ req << path;
+ req << (int)options;
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+}
+
+void emitSignalPeer(const QString &interface, const QString &name, const QVariant &parameter)
+{
+ if (parameter.isValid())
+ {
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "emitSignal");
+ req << interface;
+ req << name;
+ req << QVariant::fromValue(QDBusVariant(parameter));
+ QDBusConnection::sessionBus().send(req);
+ }
+ else
+ {
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "emitSignal2");
+ req << interface;
+ req << name;
+ QDBusConnection::sessionBus().send(req);
+ }
+
+ QTest::qWait(1000);
+}
+
+const char* slotSpyPeer()
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "slotSpyServer");
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+ return reply.arguments().at(0).toString().toLatin1().data();
+}
+
+QString valueSpyPeer()
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "valueSpyServer");
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+ return reply.arguments().at(0).toString();
+}
+
+void clearValueSpyPeer()
+{
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "clearValueSpy");
+ QDBusMessage reply = QDBusConnection::sessionBus().call(req);
+}
+
+class tst_QDBusAbstractAdaptor: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ 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 methodCallsPeer_data();
+ void methodCallsPeer();
+ void methodCallScriptablePeer();
+ void signalEmissionsPeer_data();
+ void signalEmissionsPeer();
+ void sameSignalDifferentPathsPeer();
+ void sameObjectDifferentPathsPeer();
+ void scriptableSignalOrNotPeer();
+ void overloadedSignalEmissionPeer_data();
+ void overloadedSignalEmissionPeer();
+ void readPropertiesPeer();
+ void readPropertiesInvalidInterfacePeer();
+ void readPropertiesEmptyInterfacePeer_data();
+ void readPropertiesEmptyInterfacePeer();
+ void readAllPropertiesPeer();
+ void readAllPropertiesInvalidInterfacePeer();
+ void readAllPropertiesEmptyInterfacePeer_data();
+ void readAllPropertiesEmptyInterfacePeer();
+ void writePropertiesPeer();
+
+ void typeMatching_data();
+ void typeMatching();
+
+ void methodWithMoreThanOneReturnValue();
+ void methodWithMoreThanOneReturnValuePeer();
+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_QDBusAbstractAdaptor::initTestCase()
+{
+ commonInit();
+
+ // 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 = QDBusConnection::sessionBus().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 = QDBusConnection::sessionBus().call(req2);
+ QVERIFY(rpl2.type() == QDBusMessage::ReplyMessage);
+ QVERIFY(rpl2.arguments().at(0).toBool());
+}
+
+void tst_QDBusAbstractAdaptor::cleanupTestCase()
+{
+ proc.close();
+ proc.kill();
+}
+
void tst_QDBusAbstractAdaptor::methodCalls_data()
{
QTest::addColumn<int>("nInterfaces");
@@ -1151,6 +1074,512 @@ void tst_QDBusAbstractAdaptor::writeProperties()
}
}
+void tst_QDBusAbstractAdaptor::methodCallsPeer_data()
+{
+ methodCalls_data();
+}
+
+void tst_QDBusAbstractAdaptor::methodCallsPeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ {
+ // must fail: no object
+ QDBusInterface if1(QString(), "/", "local.Interface1", con);
+ QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage);
+ }
+
+ QFETCH(int, nInterfaces);
+ newMyObjectPeer(nInterfaces);
+ registerMyObjectPeer("/");
+
+ QDBusInterface if1(QString(), "/", "local.Interface1", con);
+ QDBusInterface if2(QString(), "/", "local.Interface2", con);
+ QDBusInterface if3(QString(), "/", "local.Interface3", con);
+ QDBusInterface if4(QString(), "/", "local.Interface4", con);
+
+ // 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(slotSpyPeer(), "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(slotSpyPeer(), "void Interface3::methodVoid()");
+ QCOMPARE(if3.call(QDBus::BlockWithGui, "methodInt", 42).type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(slotSpyPeer(), "void Interface3::methodInt(int)");
+ QCOMPARE(if3.call(QDBus::BlockWithGui, "methodString", QString("")).type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(slotSpyPeer(), "void Interface3::methodString(QString)");
+
+ if (!nInterfaces--)
+ return;
+
+ // method overloading: different interfaces
+ QCOMPARE(if4.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(slotSpyPeer(), "void Interface4::method()");
+
+ // method overloading: different parameters
+ QCOMPARE(if4.call(QDBus::BlockWithGui, "method.i", 42).type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(slotSpyPeer(), "void Interface4::method(int)");
+ QCOMPARE(if4.call(QDBus::BlockWithGui, "method.s", QString()).type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(slotSpyPeer(), "void Interface4::method(QString)");
+}
+
+void tst_QDBusAbstractAdaptor::methodCallScriptablePeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer(2);
+ registerMyObjectPeer("/");
+
+ QDBusInterface if2(QString(), "/", "local.Interface2", con);
+
+ QCOMPARE(if2.call(QDBus::BlockWithGui,"scriptableMethod").type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(slotSpyPeer(), "void Interface2::scriptableMethod()");
+}
+
+void tst_QDBusAbstractAdaptor::signalEmissionsPeer_data()
+{
+ signalEmissions_data();
+}
+
+void tst_QDBusAbstractAdaptor::signalEmissionsPeer()
+{
+ QFETCH(QString, interface);
+ QFETCH(QString, name);
+ QFETCH(QVariant, parameter);
+
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer(3);
+ registerMyObjectPeer("/", QDBusConnection::ExportAdaptors
+ | QDBusConnection::ExportScriptableSignals);
+
+ // connect all signals and emit only one
+ {
+ QDBusSignalSpy spy;
+ con.connect(QString(), "/", "local.Interface2", "signal",
+ &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/", "local.Interface3", "signalVoid",
+ &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/", "local.Interface3", "signalInt",
+ &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/", "local.Interface3", "signalString",
+ &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/", "local.MyObject", "scriptableSignalVoid",
+ &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/", "local.MyObject", "scriptableSignalInt",
+ &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/", "local.MyObject", "scriptableSignalString",
+ &spy, SLOT(slot(QDBusMessage)));
+
+ emitSignalPeer(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(QString(), "/", interface, name, &spy, SLOT(slot(QDBusMessage)));
+ emitSignalPeer("local.Interface2", "signal", QVariant());
+ emitSignalPeer("local.Interface3", "signalVoid", QVariant());
+ emitSignalPeer("local.Interface3", "signalInt", QVariant(1));
+ emitSignalPeer("local.Interface3", "signalString", QVariant("foo"));
+ emitSignalPeer("local.MyObject", "scriptableSignalVoid", QVariant());
+ emitSignalPeer("local.MyObject", "scriptableSignalInt", QVariant(1));
+ emitSignalPeer("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::sameSignalDifferentPathsPeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer(2);
+
+ registerMyObjectPeer("/p1");
+ registerMyObjectPeer("/p2");
+
+ QDBusSignalSpy spy;
+ con.connect(QString(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
+ emitSignalPeer("local.Interface2", 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(QString(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
+ emitSignalPeer("local.Interface2", QString(), QVariant());
+ QTest::qWait(200);
+
+ QCOMPARE(spy.count, 2);
+}
+
+void tst_QDBusAbstractAdaptor::sameObjectDifferentPathsPeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer(2);
+
+ registerMyObjectPeer("/p1");
+ registerMyObjectPeer("/p2", 0); // don't export anything
+
+ QDBusSignalSpy spy;
+ con.connect(QString(), "/p1", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/p2", "local.Interface2", "signal", &spy, SLOT(slot(QDBusMessage)));
+ emitSignalPeer("local.Interface2", 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::scriptableSignalOrNotPeer()
+{
+ QDBusConnection con("peer");;
+ QVERIFY(con.isConnected());
+
+ {
+ newMyObjectPeer(0);
+
+ registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals);
+ registerMyObjectPeer("/p2", 0); // don't export anything
+
+ QDBusSignalSpy spy;
+ con.connect(QString(), "/p1", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/p2", "local.MyObject", "scriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
+ emitSignalPeer("local.MyObject", "scriptableSignalVoid", QVariant());
+ emitSignalPeer("local.MyObject", "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());
+ }
+
+ {
+ newMyObjectPeer(0);
+
+ registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals);
+ registerMyObjectPeer("/p2", QDBusConnection::ExportScriptableSignals
+ | QDBusConnection::ExportNonScriptableSignals);
+
+ QDBusSignalSpy spy;
+ con.connect(QString(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage)));
+ emitSignalPeer("local.MyObject", "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(QString(), "/p1", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/p2", "local.MyObject", "destroyed", &spy, SLOT(slot(QDBusMessage)));
+
+ {
+ newMyObjectPeer(0);
+
+ registerMyObjectPeer("/p1", QDBusConnection::ExportScriptableSignals);
+ registerMyObjectPeer("/p2", QDBusConnection::ExportScriptableSignals
+ | QDBusConnection::ExportNonScriptableSignals);
+ } // <--- QObject emits the destroyed(QObject*) signal at this point
+
+ QTest::qWait(200);
+
+ QCOMPARE(spy.count, 0);
+ }
+}
+
+void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer_data()
+{
+ overloadedSignalEmission_data();
+}
+
+void tst_QDBusAbstractAdaptor::overloadedSignalEmissionPeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer();
+ registerMyObjectPeer("/");
+
+ QString interface = "local.Interface4";
+ QString name = "signal";
+ QFETCH(QVariant, parameter);
+ //QDBusInterface *if4 = new QDBusInterface(QString(), "/", interface, con);
+
+ // connect all signals and emit only one
+ {
+ QDBusSignalSpy spy;
+ con.connect(QString(), "/", "local.Interface4", "signal", "",
+ &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/", "local.Interface4", "signal", "i",
+ &spy, SLOT(slot(QDBusMessage)));
+ con.connect(QString(), "/", "local.Interface4", "signal", "s",
+ &spy, SLOT(slot(QDBusMessage)));
+
+ emitSignalPeer(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(QString(), "/", interface, name, signature, &spy, SLOT(slot(QDBusMessage)));
+ emitSignalPeer("local.Interface4", "signal", QVariant());
+ emitSignalPeer("local.Interface4", "signal", QVariant(1));
+ emitSignalPeer("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::readPropertiesPeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer();
+ registerMyObjectPeer("/");
+
+ QDBusInterface properties(QString(), "/", "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::readPropertiesInvalidInterfacePeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer();
+ registerMyObjectPeer("/");
+
+ QDBusInterface properties(QString(), "/", "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::readPropertiesEmptyInterfacePeer_data()
+{
+ readPropertiesEmptyInterface_data();
+}
+
+void tst_QDBusAbstractAdaptor::readPropertiesEmptyInterfacePeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer();
+ registerMyObjectPeer("/");
+
+ QDBusInterface properties(QString(), "/", "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::readAllPropertiesPeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer();
+ registerMyObjectPeer("/");
+
+ QDBusInterface properties(QString(), "/", "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::readAllPropertiesInvalidInterfacePeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer();
+ registerMyObjectPeer("/");
+
+ QDBusInterface properties(QString(), "/", "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::readAllPropertiesEmptyInterfacePeer_data()
+{
+ readAllPropertiesEmptyInterface_data();
+}
+
+void tst_QDBusAbstractAdaptor::readAllPropertiesEmptyInterfacePeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer();
+ registerMyObjectPeer("/");
+
+ QDBusInterface properties(QString(), "/", "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::writePropertiesPeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer();
+ registerMyObjectPeer("/");
+
+ QDBusInterface properties(QString(), "/", "org.freedesktop.DBus.Properties", con);
+ for (int i = 2; i <= 4; ++i) {
+ QString name = QString("Interface%1").arg(i);
+
+ clearValueSpyPeer();
+ properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop1"),
+ qVariantFromValue(QDBusVariant(name)));
+ QVERIFY(valueSpyPeer().isEmpty()); // call mustn't have succeeded
+
+ properties.call(QDBus::BlockWithGui, "Set", "local." + name, QString("prop2"),
+ qVariantFromValue(QDBusVariant(name)));
+ QCOMPARE(valueSpyPeer(), name);
+ QCOMPARE(QString(slotSpyPeer()), QString("void %1::setProp2(const QString &)").arg(name));
+ }
+}
+
#if 0
void tst_QDBusAbstractAdaptor::adaptorIntrospection_data()
{
@@ -1438,6 +1867,28 @@ void tst_QDBusAbstractAdaptor::methodWithMoreThanOneReturnValue()
QCOMPARE(qdbus_cast<QString>(reply.arguments().at(1)), testString);
}
+void tst_QDBusAbstractAdaptor::methodWithMoreThanOneReturnValuePeer()
+{
+ QDBusConnection con("peer");
+ QVERIFY(con.isConnected());
+
+ newMyObjectPeer();
+ registerMyObjectPeer("/");
+
+ QString testString = "This is a test string.";
+
+ QDBusInterface remote(QString(), "/", "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"
diff --git a/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml b/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml
index fb2aab8..1667591 100644
--- a/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml
+++ b/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml
@@ -24,7 +24,7 @@
</method>
<method name="multiOutMethod">
<arg type="s" direction="out"/>
- <arg type="i" direction="out"/
+ <arg type="i" direction="out"/>
</method>
</interface>
</node>
diff --git a/tests/auto/qdbusabstractinterface/interface.h b/tests/auto/qdbusabstractinterface/interface.h
index 9a14222..62f81af 100644
--- a/tests/auto/qdbusabstractinterface/interface.h
+++ b/tests/auto/qdbusabstractinterface/interface.h
@@ -84,6 +84,7 @@ class Interface: public QObject
Q_PROPERTY(RegisteredType complexProp READ complexProp WRITE setComplexProp SCRIPTABLE true)
friend class tst_QDBusAbstractInterface;
+ friend class PingerServer;
QString m_stringProp;
QDBusVariant m_variantProp;
RegisteredType m_complexProp;
diff --git a/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro b/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro
index a4853b8..f9077b9 100644
--- a/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro
+++ b/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro
@@ -1,15 +1,10 @@
load(qttest_p4)
-QT = core
-contains(QT_CONFIG,dbus): {
- SOURCES += tst_qdbusabstractinterface.cpp interface.cpp
- HEADERS += interface.h
- QT += dbus
-
- # These are generated sources
- # To regenerate, see the command-line at the top of the files
- SOURCES += pinger.cpp
- HEADERS += pinger.h
+contains(QT_CONFIG,dbus): {
+ TEMPLATE = subdirs
+ CONFIG += ordered
+ SUBDIRS = qpinger test
+} else {
+ SOURCES += ../qdbusmarshall/dummy.cpp
}
-else:SOURCES += ../qdbusmarshall/dummy.cpp
OTHER_FILES += com.trolltech.QtDBus.Pinger.xml
diff --git a/tests/auto/qdbusabstractinterface/qpinger/qpinger.cpp b/tests/auto/qdbusabstractinterface/qpinger/qpinger.cpp
new file mode 100644
index 0000000..3b605c8
--- /dev/null
+++ b/tests/auto/qdbusabstractinterface/qpinger/qpinger.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** 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$
+** 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore/QtCore>
+#include <QtDBus/QtDBus>
+#include "../interface.h"
+
+static const char serviceName[] = "com.trolltech.autotests.qpinger";
+static const char objectPath[] = "/com/trolltech/qpinger";
+//static const char *interfaceName = serviceName;
+
+class PingerServer : public QDBusServer
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "com.trolltech.autotests.qpinger")
+public:
+ PingerServer(QString addr = "unix:tmpdir=/tmp", QObject* parent = 0)
+ : QDBusServer(addr, parent),
+ m_conn("none")
+ {
+ connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&)));
+ reset();
+ }
+
+public slots:
+ QString address() const
+ {
+ return QDBusServer::address();
+ }
+
+ bool isConnected() const
+ {
+ return m_conn.isConnected();
+ }
+
+ void reset()
+ {
+ targetObj.m_stringProp = "This is a test";
+ targetObj.m_variantProp = QDBusVariant(QVariant(42));
+ targetObj.m_complexProp = RegisteredType("This is a test");
+ }
+
+ void voidSignal()
+ {
+ emit targetObj.voidSignal();
+ }
+
+ void stringSignal(const QString& value)
+ {
+ emit targetObj.stringSignal(value);
+ }
+
+ void complexSignal(const QString& value)
+ {
+ RegisteredType reg(value);
+ emit targetObj.complexSignal(reg);
+ }
+
+private slots:
+ void handleConnection(const QDBusConnection& con)
+ {
+ m_conn = con;
+ m_conn.registerObject("/", &targetObj, QDBusConnection::ExportScriptableContents);
+ }
+
+private:
+ Interface targetObj;
+ QDBusConnection m_conn;
+};
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ // register the meta types
+ qDBusRegisterMetaType<RegisteredType>();
+ qRegisterMetaType<UnregisteredType>();
+
+ QDBusConnection con = QDBusConnection::sessionBus();
+ if (!con.isConnected())
+ exit(1);
+
+ if (!con.registerService(serviceName))
+ exit(2);
+
+ PingerServer server;
+ con.registerObject(objectPath, &server, QDBusConnection::ExportAllSlots);
+
+ printf("ready.\n");
+
+ return app.exec();
+}
+
+#include "qpinger.moc"
diff --git a/tests/auto/qdbusabstractinterface/qpinger/qpinger.pro b/tests/auto/qdbusabstractinterface/qpinger/qpinger.pro
new file mode 100644
index 0000000..27545bb
--- /dev/null
+++ b/tests/auto/qdbusabstractinterface/qpinger/qpinger.pro
@@ -0,0 +1,5 @@
+SOURCES = qpinger.cpp ../interface.cpp
+HEADERS = ../interface.h
+TARGET = qpinger
+QT += dbus
+QT -= gui
diff --git a/tests/auto/qdbusabstractinterface/test/test.pro b/tests/auto/qdbusabstractinterface/test/test.pro
new file mode 100644
index 0000000..98bcaa7
--- /dev/null
+++ b/tests/auto/qdbusabstractinterface/test/test.pro
@@ -0,0 +1,13 @@
+load(qttest_p4)
+SOURCES += ../tst_qdbusabstractinterface.cpp ../interface.cpp
+HEADERS += ../interface.h
+
+# These are generated sources
+# To regenerate, see the command-line at the top of the files
+SOURCES += ../pinger.cpp
+HEADERS += ../pinger.h
+
+TARGET = ../tst_qdbusabstractinterface
+
+QT = core
+QT += dbus
diff --git a/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp b/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp
index e8ce1f9..6f93d8a 100644
--- a/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp
+++ b/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp
@@ -49,6 +49,10 @@
#include "interface.h"
#include "pinger.h"
+static const char serviceName[] = "com.trolltech.autotests.qpinger";
+static const char objectPath[] = "/com/trolltech/qpinger";
+static const char *interfaceName = serviceName;
+
typedef QSharedPointer<com::trolltech::QtDBus::Pinger> Pinger;
class tst_QDBusAbstractInterface: public QObject
@@ -66,22 +70,47 @@ class tst_QDBusAbstractInterface: public QObject
return Pinger(new com::trolltech::QtDBus::Pinger(service, path, con));
}
+ Pinger getPingerPeer(const QString &path = "/")
+ {
+ QDBusConnection con = QDBusConnection("peer");
+ if (!con.isConnected())
+ return Pinger();
+ return Pinger(new com::trolltech::QtDBus::Pinger("", path, con));
+ }
+
+ void resetServer()
+ {
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "reset");
+ QDBusConnection::sessionBus().send(req);
+ }
+
public:
tst_QDBusAbstractInterface();
private slots:
void initTestCase();
+ void cleanupTestCase();
void makeVoidCall();
void makeStringCall();
void makeComplexCall();
void makeMultiOutCall();
+ void makeVoidCallPeer();
+ void makeStringCallPeer();
+ void makeComplexCallPeer();
+ void makeMultiOutCallPeer();
+
void makeAsyncVoidCall();
void makeAsyncStringCall();
void makeAsyncComplexCall();
void makeAsyncMultiOutCall();
+ void makeAsyncVoidCallPeer();
+ void makeAsyncStringCallPeer();
+ void makeAsyncComplexCallPeer();
+ void makeAsyncMultiOutCallPeer();
+
void stringPropRead();
void stringPropWrite();
void variantPropRead();
@@ -89,6 +118,13 @@ private slots:
void complexPropRead();
void complexPropWrite();
+ void stringPropReadPeer();
+ void stringPropWritePeer();
+ void variantPropReadPeer();
+ void variantPropWritePeer();
+ void complexPropReadPeer();
+ void complexPropWritePeer();
+
void stringPropDirectRead();
void stringPropDirectWrite();
void variantPropDirectRead();
@@ -96,6 +132,13 @@ private slots:
void complexPropDirectRead();
void complexPropDirectWrite();
+ void stringPropDirectReadPeer();
+ void stringPropDirectWritePeer();
+ void variantPropDirectReadPeer();
+ void variantPropDirectWritePeer();
+ void complexPropDirectReadPeer();
+ void complexPropDirectWritePeer();
+
void getVoidSignal_data();
void getVoidSignal();
void getStringSignal_data();
@@ -103,16 +146,31 @@ private slots:
void getComplexSignal_data();
void getComplexSignal();
+ void getVoidSignalPeer_data();
+ void getVoidSignalPeer();
+ void getStringSignalPeer_data();
+ void getStringSignalPeer();
+ void getComplexSignalPeer_data();
+ void getComplexSignalPeer();
+
void followSignal();
void createErrors_data();
void createErrors();
+ void createErrorsPeer_data();
+ void createErrorsPeer();
+
void callErrors_data();
void callErrors();
void asyncCallErrors_data();
void asyncCallErrors();
+ void callErrorsPeer_data();
+ void callErrorsPeer();
+ void asyncCallErrorsPeer_data();
+ void asyncCallErrorsPeer();
+
void propertyReadErrors_data();
void propertyReadErrors();
void propertyWriteErrors_data();
@@ -121,8 +179,53 @@ private slots:
void directPropertyReadErrors();
void directPropertyWriteErrors_data();
void directPropertyWriteErrors();
+
+ void propertyReadErrorsPeer_data();
+ void propertyReadErrorsPeer();
+ void propertyWriteErrorsPeer_data();
+ void propertyWriteErrorsPeer();
+ void directPropertyReadErrorsPeer_data();
+ void directPropertyReadErrorsPeer();
+ void directPropertyWriteErrorsPeer_data();
+ void directPropertyWriteErrorsPeer();
+private:
+ QProcess proc;
+};
+
+class WaitForQPinger: public QObject
+{
+ Q_OBJECT
+public:
+ WaitForQPinger();
+ bool ok();
+public Q_SLOTS:
+ void ownerChange(const QString &name)
+ {
+ if (name == serviceName)
+ loop.quit();
+ }
+
+private:
+ QEventLoop loop;
};
+WaitForQPinger::WaitForQPinger()
+{
+ 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 WaitForQPinger::ok()
+{
+ return QDBusConnection::sessionBus().isConnected() &&
+ QDBusConnection::sessionBus().interface()->isServiceRegistered(serviceName);
+}
+
tst_QDBusAbstractInterface::tst_QDBusAbstractInterface()
{
// register the meta types
@@ -139,6 +242,39 @@ void tst_QDBusAbstractInterface::initTestCase()
QDBusConnection con = QDBusConnection::sessionBus();
QVERIFY(con.isConnected());
con.registerObject("/", &targetObj, QDBusConnection::ExportScriptableContents);
+
+ // start peer server
+ #ifdef Q_OS_WIN
+ proc.start("qpinger");
+ #else
+ proc.start("./qpinger/qpinger");
+ #endif
+ QVERIFY(proc.waitForStarted());
+
+ WaitForQPinger 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_QDBusAbstractInterface::cleanupTestCase()
+{
+ proc.close();
+ proc.kill();
}
void tst_QDBusAbstractInterface::makeVoidCall()
@@ -184,6 +320,49 @@ void tst_QDBusAbstractInterface::makeMultiOutCall()
QCOMPARE(value, expectedValue);
}
+void tst_QDBusAbstractInterface::makeVoidCallPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ QDBusReply<void> r = p->voidMethod();
+ QVERIFY(r.isValid());
+}
+
+void tst_QDBusAbstractInterface::makeStringCallPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ QDBusReply<QString> r = p->stringMethod();
+ QVERIFY(r.isValid());
+ QCOMPARE(r.value(), targetObj.stringMethod());
+}
+
+void tst_QDBusAbstractInterface::makeComplexCallPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ QDBusReply<RegisteredType> r = p->complexMethod();
+ QVERIFY(r.isValid());
+ QCOMPARE(r.value(), targetObj.complexMethod());
+}
+
+void tst_QDBusAbstractInterface::makeMultiOutCallPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ int value;
+ QDBusReply<QString> r = p->multiOutMethod(value);
+ QVERIFY(r.isValid());
+
+ int expectedValue;
+ QCOMPARE(r.value(), targetObj.multiOutMethod(expectedValue));
+ QCOMPARE(value, expectedValue);
+}
+
void tst_QDBusAbstractInterface::makeAsyncVoidCall()
{
Pinger p = getPinger();
@@ -230,6 +409,55 @@ void tst_QDBusAbstractInterface::makeAsyncMultiOutCall()
QCOMPARE(r.argumentAt<1>(), expectedValue);
}
+void tst_QDBusAbstractInterface::makeAsyncVoidCallPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ QDBusPendingReply<void> r = p->voidMethod();
+ r.waitForFinished();
+ QVERIFY(r.isValid());
+}
+void tst_QDBusAbstractInterface::makeAsyncStringCallPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ QDBusMessage reply = p->call(QDBus::BlockWithGui, QLatin1String("voidMethod"));
+ QVERIFY(reply.type() == QDBusMessage::ReplyMessage);
+
+ QDBusPendingReply<QString> r = p->stringMethod();
+ r.waitForFinished();
+ QVERIFY(r.isValid());
+ QCOMPARE(r.value(), targetObj.stringMethod());
+}
+
+void tst_QDBusAbstractInterface::makeAsyncComplexCallPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ QDBusPendingReply<RegisteredType> r = p->complexMethod();
+ r.waitForFinished();
+ QVERIFY(r.isValid());
+ QCOMPARE(r.value(), targetObj.complexMethod());
+}
+
+void tst_QDBusAbstractInterface::makeAsyncMultiOutCallPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ QDBusPendingReply<QString, int> r = p->multiOutMethod();
+ r.waitForFinished();
+ QVERIFY(r.isValid());
+
+ int expectedValue;
+ QCOMPARE(r.value(), targetObj.multiOutMethod(expectedValue));
+ QCOMPARE(r.argumentAt<1>(), expectedValue);
+ QCoreApplication::instance()->processEvents();
+}
+
void tst_QDBusAbstractInterface::stringPropRead()
{
Pinger p = getPinger();
@@ -295,6 +523,77 @@ void tst_QDBusAbstractInterface::complexPropWrite()
QCOMPARE(targetObj.m_complexProp, expectedValue);
}
+void tst_QDBusAbstractInterface::stringPropReadPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ QString expectedValue = "This is a test";
+ QVariant v = p->property("stringProp");
+ QVERIFY(v.isValid());
+ QCOMPARE(v.toString(), expectedValue);
+}
+
+void tst_QDBusAbstractInterface::stringPropWritePeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ QString expectedValue = "This is a value";
+ QVERIFY(p->setProperty("stringProp", expectedValue));
+ QCOMPARE(targetObj.m_stringProp, expectedValue);
+}
+
+void tst_QDBusAbstractInterface::variantPropReadPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ QDBusVariant expectedValue = QDBusVariant(QVariant(42));
+ QVariant v = p->property("variantProp");
+ QVERIFY(v.isValid());
+ QDBusVariant value = v.value<QDBusVariant>();
+ QCOMPARE(value.variant().userType(), expectedValue.variant().userType());
+ QCOMPARE(value.variant(), expectedValue.variant());
+}
+
+void tst_QDBusAbstractInterface::variantPropWritePeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ QDBusVariant expectedValue = QDBusVariant(Q_INT64_C(-47));
+ QVERIFY(p->setProperty("variantProp", qVariantFromValue(expectedValue)));
+ QCOMPARE(targetObj.m_variantProp.variant(), expectedValue.variant());
+}
+
+void tst_QDBusAbstractInterface::complexPropReadPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ RegisteredType expectedValue = RegisteredType("This is a test");
+ QVariant v = p->property("complexProp");
+ QVERIFY(v.userType() == qMetaTypeId<RegisteredType>());
+ QCOMPARE(v.value<RegisteredType>(), expectedValue);
+}
+
+void tst_QDBusAbstractInterface::complexPropWritePeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ RegisteredType expectedValue = RegisteredType("This is a value");
+ QVERIFY(p->setProperty("complexProp", qVariantFromValue(expectedValue)));
+ QCOMPARE(targetObj.m_complexProp, expectedValue);
+}
+
void tst_QDBusAbstractInterface::stringPropDirectRead()
{
Pinger p = getPinger();
@@ -353,6 +652,70 @@ void tst_QDBusAbstractInterface::complexPropDirectWrite()
QCOMPARE(targetObj.m_complexProp, expectedValue);
}
+void tst_QDBusAbstractInterface::stringPropDirectReadPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ QString expectedValue = "This is a test";
+ QCOMPARE(p->stringProp(), expectedValue);
+}
+
+void tst_QDBusAbstractInterface::stringPropDirectWritePeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ QString expectedValue = "This is a value";
+ p->setStringProp(expectedValue);
+ QCOMPARE(targetObj.m_stringProp, expectedValue);
+}
+
+void tst_QDBusAbstractInterface::variantPropDirectReadPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ QDBusVariant expectedValue = QDBusVariant(42);
+ QCOMPARE(p->variantProp().variant(), expectedValue.variant());
+}
+
+void tst_QDBusAbstractInterface::variantPropDirectWritePeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ QDBusVariant expectedValue = QDBusVariant(Q_INT64_C(-47));
+ p->setVariantProp(expectedValue);
+ QCOMPARE(targetObj.m_variantProp.variant().userType(), expectedValue.variant().userType());
+ QCOMPARE(targetObj.m_variantProp.variant(), expectedValue.variant());
+}
+
+void tst_QDBusAbstractInterface::complexPropDirectReadPeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ RegisteredType expectedValue = RegisteredType("This is a test");
+ QCOMPARE(p->complexProp(), expectedValue);
+}
+
+void tst_QDBusAbstractInterface::complexPropDirectWritePeer()
+{
+ Pinger p = getPingerPeer();
+ QVERIFY2(p, "Not connected to D-Bus");
+ resetServer();
+
+ RegisteredType expectedValue = RegisteredType("This is a value");
+ p->setComplexProp(expectedValue);
+ QCOMPARE(targetObj.m_complexProp, expectedValue);
+}
+
void tst_QDBusAbstractInterface::getVoidSignal_data()
{
QTest::addColumn<QString>("service");
@@ -437,6 +800,89 @@ void tst_QDBusAbstractInterface::getComplexSignal()
QCOMPARE(s[0][0].value<RegisteredType>(), expectedValue);
}
+void tst_QDBusAbstractInterface::getVoidSignalPeer_data()
+{
+ QTest::addColumn<QString>("path");
+
+ QTest::newRow("specific") << "/";
+ QTest::newRow("wildcard") << QString();
+}
+
+void tst_QDBusAbstractInterface::getVoidSignalPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ // we need to connect the signal somewhere in order for D-Bus to enable the rules
+ QTestEventLoop::instance().connect(p.data(), SIGNAL(voidSignal()), SLOT(exitLoop()));
+ QSignalSpy s(p.data(), SIGNAL(voidSignal()));
+
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "voidSignal");
+ QVERIFY(QDBusConnection::sessionBus().send(req));
+ QTestEventLoop::instance().enterLoop(2);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QVERIFY(s.size() == 1);
+ QVERIFY(s.at(0).size() == 0);
+}
+
+void tst_QDBusAbstractInterface::getStringSignalPeer_data()
+{
+ getVoidSignalPeer_data();
+}
+
+void tst_QDBusAbstractInterface::getStringSignalPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ // we need to connect the signal somewhere in order for D-Bus to enable the rules
+ QTestEventLoop::instance().connect(p.data(), SIGNAL(stringSignal(QString)), SLOT(exitLoop()));
+ QSignalSpy s(p.data(), SIGNAL(stringSignal(QString)));
+
+ QString expectedValue = "Good morning";
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "stringSignal");
+ req << expectedValue;
+ QVERIFY(QDBusConnection::sessionBus().send(req));
+ QTestEventLoop::instance().enterLoop(2);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QVERIFY(s.size() == 1);
+ QVERIFY(s[0].size() == 1);
+ QCOMPARE(s[0][0].userType(), int(QVariant::String));
+ QCOMPARE(s[0][0].toString(), expectedValue);
+}
+
+void tst_QDBusAbstractInterface::getComplexSignalPeer_data()
+{
+ getVoidSignalPeer_data();
+}
+
+void tst_QDBusAbstractInterface::getComplexSignalPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ // we need to connect the signal somewhere in order for D-Bus to enable the rules
+ QTestEventLoop::instance().connect(p.data(), SIGNAL(complexSignal(RegisteredType)), SLOT(exitLoop()));
+ QSignalSpy s(p.data(), SIGNAL(complexSignal(RegisteredType)));
+
+ RegisteredType expectedValue("Good evening");
+ QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "complexSignal");
+ req << "Good evening";
+ QVERIFY(QDBusConnection::sessionBus().send(req));
+ QTestEventLoop::instance().enterLoop(2);
+ QVERIFY(!QTestEventLoop::instance().timeout());
+
+ QVERIFY(s.size() == 1);
+ QVERIFY(s[0].size() == 1);
+ QCOMPARE(s[0][0].userType(), qMetaTypeId<RegisteredType>());
+ QCOMPARE(s[0][0].value<RegisteredType>(), expectedValue);
+}
+
void tst_QDBusAbstractInterface::followSignal()
{
const QString serviceToFollow = "com.trolltech.tst_qdbusabstractinterface.FollowMe";
@@ -514,6 +960,24 @@ void tst_QDBusAbstractInterface::createErrors()
QTEST(p->lastError().name(), "errorName");
}
+void tst_QDBusAbstractInterface::createErrorsPeer_data()
+{
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<QString>("errorName");
+
+ QTest::newRow("invalid-path") << "this isn't valid" << "com.trolltech.QtDBus.Error.InvalidObjectPath";
+}
+
+void tst_QDBusAbstractInterface::createErrorsPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ QVERIFY(!p->isValid());
+ QTEST(p->lastError().name(), "errorName");
+}
+
void tst_QDBusAbstractInterface::callErrors_data()
{
createErrors_data();
@@ -556,6 +1020,43 @@ void tst_QDBusAbstractInterface::asyncCallErrors()
QCOMPARE(p->lastError().name(), r.error().name());
}
+void tst_QDBusAbstractInterface::callErrorsPeer_data()
+{
+ createErrorsPeer_data();
+ QTest::newRow("path-wildcard") << QString() << "com.trolltech.QtDBus.Error.InvalidObjectPath";
+}
+
+void tst_QDBusAbstractInterface::callErrorsPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ // we shouldn't be able to make this call:
+ QDBusReply<QString> r = p->stringMethod();
+ QVERIFY(!r.isValid());
+ QTEST(r.error().name(), "errorName");
+ QCOMPARE(p->lastError().name(), r.error().name());
+}
+
+void tst_QDBusAbstractInterface::asyncCallErrorsPeer_data()
+{
+ callErrorsPeer_data();
+}
+
+void tst_QDBusAbstractInterface::asyncCallErrorsPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ // we shouldn't be able to make this call:
+ QDBusPendingReply<QString> r = p->stringMethod();
+ QVERIFY(r.isError());
+ QTEST(r.error().name(), "errorName");
+ QCOMPARE(p->lastError().name(), r.error().name());
+}
+
void tst_QDBusAbstractInterface::propertyReadErrors_data()
{
callErrors_data();
@@ -632,5 +1133,77 @@ void tst_QDBusAbstractInterface::directPropertyWriteErrors()
QTEST(p->lastError().name(), "errorName");
}
+void tst_QDBusAbstractInterface::propertyReadErrorsPeer_data()
+{
+ callErrorsPeer_data();
+}
+
+void tst_QDBusAbstractInterface::propertyReadErrorsPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ // we shouldn't be able to get this value:
+ QVariant v = p->property("stringProp");
+ QVERIFY(v.isNull());
+ QVERIFY(!v.isValid());
+ QTEST(p->lastError().name(), "errorName");
+}
+
+void tst_QDBusAbstractInterface::propertyWriteErrorsPeer_data()
+{
+ callErrorsPeer_data();
+}
+
+void tst_QDBusAbstractInterface::propertyWriteErrorsPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ // we shouldn't be able to get this value:
+ if (p->isValid())
+ QCOMPARE(int(p->lastError().type()), int(QDBusError::NoError));
+ QVERIFY(!p->setProperty("stringProp", ""));
+ QTEST(p->lastError().name(), "errorName");
+}
+
+void tst_QDBusAbstractInterface::directPropertyReadErrorsPeer_data()
+{
+ callErrorsPeer_data();
+}
+
+void tst_QDBusAbstractInterface::directPropertyReadErrorsPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ // we shouldn't be able to get this value:
+ QString v = p->stringProp();
+ QVERIFY(v.isNull());
+ QTEST(p->lastError().name(), "errorName");
+}
+
+void tst_QDBusAbstractInterface::directPropertyWriteErrorsPeer_data()
+{
+ callErrorsPeer_data();
+}
+
+void tst_QDBusAbstractInterface::directPropertyWriteErrorsPeer()
+{
+ QFETCH(QString, path);
+ Pinger p = getPingerPeer(path);
+ QVERIFY2(p, "Not connected to D-Bus");
+
+ // we shouldn't be able to get this value:
+ // but there's no direct way of verifying that the setting failed
+ if (p->isValid())
+ QCOMPARE(int(p->lastError().type()), int(QDBusError::NoError));
+ p->setStringProp("");
+ QTEST(p->lastError().name(), "errorName");
+}
+
QTEST_MAIN(tst_QDBusAbstractInterface)
#include "tst_qdbusabstractinterface.moc"
diff --git a/tests/auto/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/qdbusconnection/tst_qdbusconnection.cpp
index 8e3a44b..d4a9dab 100644
--- a/tests/auto/qdbusconnection/tst_qdbusconnection.cpp
+++ b/tests/auto/qdbusconnection/tst_qdbusconnection.cpp
@@ -86,6 +86,7 @@ public slots:
private slots:
void noConnection();
void connectToBus();
+ void connectToPeer();
void connect();
void send();
void sendWithGui();
@@ -94,9 +95,13 @@ private slots:
void registerObject_data();
void registerObject();
+ void registerObjectPeer_data();
+ void registerObjectPeer();
void registerObject2();
+ void registerObjectPeer2();
void registerQObjectChildren();
+ void registerQObjectChildrenPeer();
void callSelf();
void callSelfByAnotherName_data();
@@ -111,6 +116,7 @@ private slots:
public:
QString serviceName() const { return "com.trolltech.Qt.Autotests.QDBusConnection"; }
bool callMethod(const QDBusConnection &conn, const QString &path);
+ bool callMethodPeer(const QDBusConnection &conn, const QString &path);
};
class QDBusSpy: public QObject
@@ -259,6 +265,14 @@ void tst_QDBusConnection::connectToBus()
QVERIFY(!con.lastError().isValid());
}
+ QDBusConnection::disconnectFromPeer("bubu");
+
+ {
+ QDBusConnection con("bubu");
+ QVERIFY(con.isConnected());
+ QVERIFY(!con.lastError().isValid());
+ }
+
QDBusConnection::disconnectFromBus("bubu");
{
@@ -277,6 +291,65 @@ void tst_QDBusConnection::connectToBus()
}
}
+void tst_QDBusConnection::connectToPeer()
+{
+ {
+ QDBusConnection con = QDBusConnection::connectToPeer(
+ "", "newconn");
+ QVERIFY(!con.isConnected());
+ QVERIFY(con.lastError().isValid());
+ }
+
+ QDBusServer server("unix:tmpdir=/tmp", 0);
+
+ {
+ QDBusConnection con = QDBusConnection::connectToPeer(
+ "unix:abstract=/tmp/dbus-XXXXXXXXXX,guid=00000000000000000000000000000000", "newconn2");
+ QVERIFY(!con.isConnected());
+ QVERIFY(con.lastError().isValid());
+ }
+
+ {
+ QDBusConnection con = QDBusConnection::connectToPeer(
+ server.address(), "bubu");
+
+ QVERIFY(con.isConnected());
+ QVERIFY(!con.lastError().isValid());
+
+ QDBusConnection con2("foo");
+ QVERIFY(!con2.isConnected());
+ QVERIFY(!con2.lastError().isValid());
+
+ con2 = con;
+ QVERIFY(con.isConnected());
+ QVERIFY(con2.isConnected());
+ QVERIFY(!con.lastError().isValid());
+ QVERIFY(!con2.lastError().isValid());
+ }
+
+ {
+ QDBusConnection con("bubu");
+ QVERIFY(con.isConnected());
+ QVERIFY(!con.lastError().isValid());
+ }
+
+ QDBusConnection::disconnectFromBus("bubu");
+
+ {
+ QDBusConnection con("bubu");
+ QVERIFY(con.isConnected());
+ QVERIFY(!con.lastError().isValid());
+ }
+
+ QDBusConnection::disconnectFromPeer("bubu");
+
+ {
+ QDBusConnection con("bubu");
+ QVERIFY(!con.isConnected());
+ QVERIFY(!con.lastError().isValid());
+ }
+}
+
void tst_QDBusConnection::registerObject_data()
{
QTest::addColumn<QString>("path");
@@ -308,6 +381,106 @@ void tst_QDBusConnection::registerObject()
QVERIFY(!callMethod(con, path));
}
+class MyServer : public QDBusServer
+{
+ Q_OBJECT
+public:
+ MyServer(QString path, QString addr, QObject* parent) : QDBusServer(addr, parent),
+ m_path(path),
+ m_conn("none")
+ {
+ connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&)));
+ }
+
+ bool registerObject()
+ {
+ if( !m_conn.registerObject(m_path, &m_obj, QDBusConnection::ExportAllSlots) )
+ return false;
+ if(! (m_conn.objectRegisteredAt(m_path) == &m_obj))
+ return false;
+ return true;
+ }
+
+ void unregisterObject()
+ {
+ m_conn.unregisterObject(m_path);
+ }
+
+public slots:
+ void handleConnection(const QDBusConnection& c)
+ {
+ m_conn = c;
+ QVERIFY(isConnected());
+ QVERIFY(m_conn.isConnected());
+ QVERIFY(registerObject());
+ }
+
+private:
+ MyObject m_obj;
+ QString m_path;
+ QDBusConnection m_conn;
+};
+
+
+void tst_QDBusConnection::registerObjectPeer_data()
+{
+ QTest::addColumn<QString>("path");
+
+ QTest::newRow("/") << "/";
+ QTest::newRow("/p1") << "/p1";
+ QTest::newRow("/p2") << "/p2";
+ QTest::newRow("/p1/q") << "/p1/q";
+ QTest::newRow("/p1/q/r") << "/p1/q/r";
+}
+
+void tst_QDBusConnection::registerObjectPeer()
+{
+ QFETCH(QString, path);
+
+ MyServer server(path, "unix:tmpdir=/tmp", 0);
+
+ {
+ QDBusConnection con = QDBusConnection::connectToPeer(server.address(), "foo");
+
+ QCoreApplication::processEvents();
+ QVERIFY(con.isConnected());
+
+ MyObject obj;
+ QVERIFY(callMethodPeer(con, path));
+ QCOMPARE(obj.path, path);
+ }
+
+ {
+ QDBusConnection con("foo");
+ QVERIFY(con.isConnected());
+ QVERIFY(callMethodPeer(con, path));
+ }
+
+ server.unregisterObject();
+
+ {
+ QDBusConnection con("foo");
+ QVERIFY(con.isConnected());
+ QVERIFY(!callMethodPeer(con, path));
+ }
+
+ server.registerObject();
+
+ {
+ QDBusConnection con("foo");
+ QVERIFY(con.isConnected());
+ QVERIFY(callMethodPeer(con, path));
+ }
+
+ QDBusConnection::disconnectFromPeer("foo");
+
+ {
+ QDBusConnection con("foo");
+ QVERIFY(!con.isConnected());
+ QVERIFY(!callMethodPeer(con, path));
+ }
+}
+
void tst_QDBusConnection::registerObject2()
{
QDBusConnection con = QDBusConnection::sessionBus();
@@ -401,6 +574,134 @@ void tst_QDBusConnection::registerObject2()
}
}
+class MyServer2 : public QDBusServer
+{
+ Q_OBJECT
+public:
+ MyServer2(QString addr, QObject* parent) : QDBusServer(addr, parent),
+ m_conn("none")
+ {
+ connect(this, SIGNAL(newConnection(const QDBusConnection&)), SLOT(handleConnection(const QDBusConnection&)));
+ }
+
+ QDBusConnection connection()
+ {
+ return m_conn;
+ }
+
+public slots:
+ void handleConnection(const QDBusConnection& c)
+ {
+ m_conn = c;
+ QVERIFY(isConnected());
+ QVERIFY(m_conn.isConnected());
+ }
+
+private:
+ MyObject m_obj;
+ QDBusConnection m_conn;
+};
+
+void tst_QDBusConnection::registerObjectPeer2()
+{
+ MyServer2 server("unix:tmpdir=/tmp", 0);
+ QDBusConnection con = QDBusConnection::connectToPeer(server.address(), "foo");
+ QCoreApplication::processEvents();
+ QVERIFY(con.isConnected());
+
+ QDBusConnection srv_con = server.connection();
+
+ // make sure nothing is using our paths:
+ QVERIFY(!callMethodPeer(srv_con, "/"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1"));
+ QVERIFY(!callMethodPeer(srv_con, "/p2"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1/q"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1/q/r"));
+
+ {
+ // register one object at root:
+ MyObject obj;
+ QVERIFY(con.registerObject("/", &obj, QDBusConnection::ExportAllSlots));
+ QVERIFY(callMethodPeer(srv_con, "/"));
+ qDebug() << obj.path;
+ QCOMPARE(obj.path, QString("/"));
+ }
+ // make sure it's gone
+ QVERIFY(!callMethodPeer(srv_con, "/"));
+
+ {
+ // register one at an element:
+ MyObject obj;
+ QVERIFY(con.registerObject("/p1", &obj, QDBusConnection::ExportAllSlots));
+ QVERIFY(!callMethodPeer(srv_con, "/"));
+ QVERIFY(callMethodPeer(srv_con, "/p1"));
+ qDebug() << obj.path;
+ QCOMPARE(obj.path, QString("/p1"));
+
+ // re-register it somewhere else
+ QVERIFY(con.registerObject("/p2", &obj, QDBusConnection::ExportAllSlots));
+ QVERIFY(callMethodPeer(srv_con, "/p1"));
+ QCOMPARE(obj.path, QString("/p1"));
+ QVERIFY(callMethodPeer(srv_con, "/p2"));
+ QCOMPARE(obj.path, QString("/p2"));
+ }
+ // make sure it's gone
+ QVERIFY(!callMethodPeer(srv_con, "/p1"));
+ QVERIFY(!callMethodPeer(srv_con, "/p2"));
+
+ {
+ // register at a deep path
+ MyObject obj;
+ QVERIFY(con.registerObject("/p1/q/r", &obj, QDBusConnection::ExportAllSlots));
+ QVERIFY(!callMethodPeer(srv_con, "/"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1/q"));
+ QVERIFY(callMethodPeer(srv_con, "/p1/q/r"));
+ QCOMPARE(obj.path, QString("/p1/q/r"));
+ }
+ // make sure it's gone
+ QVERIFY(!callMethodPeer(srv_con, "/p1/q/r"));
+
+ {
+ MyObject obj;
+ QVERIFY(con.registerObject("/p1/q2", &obj, QDBusConnection::ExportAllSlots));
+ QVERIFY(callMethodPeer(srv_con, "/p1/q2"));
+ QCOMPARE(obj.path, QString("/p1/q2"));
+
+ // try unregistering
+ con.unregisterObject("/p1/q2");
+ QVERIFY(!callMethodPeer(srv_con, "/p1/q2"));
+
+ // register it again
+ QVERIFY(con.registerObject("/p1/q2", &obj, QDBusConnection::ExportAllSlots));
+ QVERIFY(callMethodPeer(srv_con, "/p1/q2"));
+ QCOMPARE(obj.path, QString("/p1/q2"));
+
+ // now try removing things around it:
+ con.unregisterObject("/p2");
+ QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unrelated object shouldn't affect
+
+ con.unregisterObject("/p1");
+ QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering just the parent shouldn't affect it
+
+ con.unregisterObject("/p1/q2/r");
+ QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering non-existing child shouldn't affect it either
+
+ con.unregisterObject("/p1/q");
+ QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering sibling (before) shouldn't affect
+
+ con.unregisterObject("/p1/r");
+ QVERIFY(callMethodPeer(srv_con, "/p1/q2")); // unregistering sibling (after) shouldn't affect
+
+ // now remove it:
+ con.unregisterObject("/p1", QDBusConnection::UnregisterTree);
+ QVERIFY(!callMethodPeer(srv_con, "/p1/q2")); // we removed the full tree
+ }
+
+ QDBusConnection::disconnectFromPeer("foo");
+}
+
+
void tst_QDBusConnection::registerQObjectChildren()
{
// make sure no one is there
@@ -456,6 +757,68 @@ void tst_QDBusConnection::registerQObjectChildren()
QVERIFY(!callMethod(con, "/p1/c/cc"));
}
+void tst_QDBusConnection::registerQObjectChildrenPeer()
+{
+ MyServer2 server("unix:tmpdir=/tmp", 0);
+ QDBusConnection con = QDBusConnection::connectToPeer(server.address(), "foo");
+ QCoreApplication::processEvents();
+ QVERIFY(con.isConnected());
+
+ QDBusConnection srv_con = server.connection();
+
+ QVERIFY(!callMethodPeer(srv_con, "/p1"));
+
+ {
+ MyObject obj, *a, *b, *c, *cc;
+
+ a = new MyObject(&obj);
+ a->setObjectName("a");
+
+ b = new MyObject(&obj);
+ b->setObjectName("b");
+
+ c = new MyObject(&obj);
+ c->setObjectName("c");
+
+ cc = new MyObject(c);
+ cc->setObjectName("cc");
+
+ con.registerObject("/p1", &obj, QDBusConnection::ExportAllSlots |
+ QDBusConnection::ExportChildObjects);
+
+ // make calls
+ QVERIFY(callMethodPeer(srv_con, "/p1"));
+ QCOMPARE(obj.callCount, 1);
+ QVERIFY(callMethodPeer(srv_con, "/p1/a"));
+ QCOMPARE(a->callCount, 1);
+ QVERIFY(callMethodPeer(srv_con, "/p1/b"));
+ QCOMPARE(b->callCount, 1);
+ QVERIFY(callMethodPeer(srv_con, "/p1/c"));
+ QCOMPARE(c->callCount, 1);
+ QVERIFY(callMethodPeer(srv_con, "/p1/c/cc"));
+ QCOMPARE(cc->callCount, 1);
+
+ QVERIFY(!callMethodPeer(srv_con, "/p1/d"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1/c/abc"));
+
+ // pull an object, see if it goes away:
+ delete b;
+ QVERIFY(!callMethodPeer(srv_con, "/p1/b"));
+
+ delete c;
+ QVERIFY(!callMethodPeer(srv_con, "/p1/c"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1/c/cc"));
+ }
+
+ QVERIFY(!callMethodPeer(srv_con, "/p1"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1/a"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1/b"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1/c"));
+ QVERIFY(!callMethodPeer(srv_con, "/p1/c/cc"));
+
+ QDBusConnection::disconnectFromPeer("foo");
+}
+
bool tst_QDBusConnection::callMethod(const QDBusConnection &conn, const QString &path)
{
QDBusMessage msg = QDBusMessage::createMethodCall(conn.baseService(), path, "", "method");
@@ -475,6 +838,25 @@ bool tst_QDBusConnection::callMethod(const QDBusConnection &conn, const QString
return true;
}
+bool tst_QDBusConnection::callMethodPeer(const QDBusConnection &conn, const QString &path)
+{
+ QDBusMessage msg = QDBusMessage::createMethodCall("", path, "", "method");
+ QDBusMessage reply = conn.call(msg, QDBus::BlockWithGui);
+
+ if (reply.type() != QDBusMessage::ReplyMessage)
+ return false;
+ if (MyObject::path == path) {
+ QTest::compare_helper(true, "COMPARE()", __FILE__, __LINE__);
+ } else {
+ QTest::compare_helper(false, "Compared values are not the same",
+ QTest::toString(MyObject::path), QTest::toString(path),
+ "MyObject::path", "path", __FILE__, __LINE__);
+ return false;
+ }
+
+ return true;
+}
+
class TestObject : public QObject
{
Q_OBJECT
diff --git a/tests/auto/qdbusinterface/myobject.h b/tests/auto/qdbusinterface/myobject.h
new file mode 100644
index 0000000..68b8d1a
--- /dev/null
+++ b/tests/auto/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$
+** 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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/qdbusinterface/qdbusinterface.pro b/tests/auto/qdbusinterface/qdbusinterface.pro
index ac14ab7..0aca06c 100644
--- a/tests/auto/qdbusinterface/qdbusinterface.pro
+++ b/tests/auto/qdbusinterface/qdbusinterface.pro
@@ -1,10 +1,11 @@
load(qttest_p4)
QT = core
contains(QT_CONFIG,dbus): {
- SOURCES += tst_qdbusinterface.cpp
- QT += dbus
+ TEMPLATE = subdirs
+ CONFIG += ordered
+ SUBDIRS = qmyserver test
} else {
- SOURCES += ../qdbusmarshall/dummy.cpp
+ SOURCES += ../qdbusmarshall/dummy.cpp
}
diff --git a/tests/auto/qdbusinterface/qmyserver/qmyserver.cpp b/tests/auto/qdbusinterface/qmyserver/qmyserver.cpp
new file mode 100644
index 0000000..c68f7bf
--- /dev/null
+++ b/tests/auto/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$
+** 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $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/qdbusinterface/qmyserver/qmyserver.pro b/tests/auto/qdbusinterface/qmyserver/qmyserver.pro
new file mode 100644
index 0000000..f4fe02c
--- /dev/null
+++ b/tests/auto/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/qdbusinterface/test/test.pro b/tests/auto/qdbusinterface/test/test.pro
new file mode 100644
index 0000000..3252188
--- /dev/null
+++ b/tests/auto/qdbusinterface/test/test.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+SOURCES += ../tst_qdbusinterface.cpp
+HEADERS += ../myobject.h
+TARGET = ../tst_qdbusinterface
+
+QT = core
+QT += dbus
diff --git a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp
index 39f0677..04b3d72 100644
--- a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp
+++ b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
/* -*- C++ -*-
*/
+
#include <qcoreapplication.h>
#include <qmetatype.h>
#include <QtTest/QtTest>
@@ -47,125 +48,15 @@
#include <QtDBus/QtDBus>
#include "../qdbusmarshall/common.h"
-
-Q_DECLARE_METATYPE(QVariantList)
+#include "myobject.h"
#define TEST_INTERFACE_NAME "com.trolltech.QtDBus.MyObject"
#define TEST_SIGNAL_NAME "somethingHappened"
-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");
- }
+static const char serviceName[] = "com.trolltech.autotests.qmyserver";
+static const char objectPath[] = "/com/trolltech/qmyserver";
+static const char *interfaceName = serviceName;
- 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);
- }
-};
int MyObject::callCount = 0;
QVariantList MyObject::callArgs;
@@ -228,10 +119,70 @@ void emitSignal(const QString &interface, const QString &name, const QString &ar
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)
{
@@ -241,6 +192,7 @@ public slots:
private slots:
void initTestCase();
+ void cleanupTestCase();
void notConnected();
void notValid();
@@ -254,14 +206,63 @@ private slots:
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();
@@ -271,6 +272,39 @@ void tst_QDBusInterface::initTestCase()
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()
@@ -369,7 +403,7 @@ void tst_QDBusInterface::callMethod()
TEST_INTERFACE_NAME);
MyObject::callCount = 0;
-
+
// call a SLOT method
QDBusMessage reply = iface.call("ping", qVariantFromValue(QDBusVariant("foo")));
QCOMPARE(MyObject::callCount, 1);
@@ -388,7 +422,7 @@ void tst_QDBusInterface::callMethod()
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);
@@ -416,7 +450,7 @@ void tst_QDBusInterface::invokeMethod()
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)));
@@ -428,7 +462,7 @@ void tst_QDBusInterface::invokeMethod()
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)));
@@ -465,7 +499,7 @@ void tst_QDBusInterface::invokeMethodWithReturn()
// 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)));
@@ -490,7 +524,7 @@ void tst_QDBusInterface::invokeMethodWithMultiReturn()
MyObject::callCount = 0;
QDBusVariant retArg, retArg2;
-
+
// make the SLOT call without a return type
QDBusVariant arg("foo"), arg2("bar");
QVERIFY(QMetaObject::invokeMethod(&iface, "ping",
@@ -515,7 +549,7 @@ void tst_QDBusInterface::invokeMethodWithMultiReturn()
// 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",
@@ -550,7 +584,7 @@ void tst_QDBusInterface::invokeMethodWithComplexReturn()
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)));
@@ -564,7 +598,7 @@ void tst_QDBusInterface::invokeMethodWithComplexReturn()
// 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)));
@@ -580,6 +614,250 @@ void tst_QDBusInterface::invokeMethodWithComplexReturn()
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();
@@ -621,6 +899,47 @@ void tst_QDBusInterface::signal()
}
}
+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();
@@ -683,7 +1002,69 @@ void tst_QDBusInterface::complexPropertyWrite()
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"
-