diff options
-rw-r--r-- | src/dbus/qdbusconnection.cpp | 206 | ||||
-rw-r--r-- | src/dbus/qdbusconnection_p.h | 2 | ||||
-rw-r--r-- | src/dbus/qdbusconnectionmanager_p.h | 11 | ||||
-rw-r--r-- | src/dbus/qdbusintegrator.cpp | 1 | ||||
-rw-r--r-- | src/dbus/qdbusserver.cpp | 16 | ||||
-rw-r--r-- | src/dbus/qdbusserver.h | 1 | ||||
-rw-r--r-- | tests/auto/dbus/dbus.pro | 3 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusconnection/qdbusconnection.pro | 1 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp | 301 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h | 287 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusconnection_no_app/qdbusconnection_no_app.pro | 6 | ||||
-rw-r--r-- | tests/auto/dbus/qdbusconnection_no_app/tst_qdbusconnection_no_app.cpp | 37 |
12 files changed, 520 insertions, 352 deletions
diff --git a/src/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index 8ebdf4c66e..a5d674bb5a 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -59,6 +59,23 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QDBusConnectionManager, _q_manager) +struct QDBusConnectionManager::ConnectionRequestData +{ + enum RequestType { + ConnectToStandardBus, + ConnectToBusByAddress, + ConnectToPeerByAddress + } type; + + union { + QDBusConnection::BusType busType; + const QString *busAddress; + }; + const QString *name; + + QDBusConnectionPrivate *result; +}; + QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const { return connectionHash.value(name, 0); @@ -80,7 +97,11 @@ void QDBusConnectionManager::removeConnection(const QString &name) QDBusConnectionManager::QDBusConnectionManager() { - moveToThread(Q_NULLPTR); // we don't handle events + connect(this, &QDBusConnectionManager::connectionRequested, + this, &QDBusConnectionManager::executeConnectionRequest, Qt::BlockingQueuedConnection); + connect(this, &QDBusConnectionManager::serverRequested, + this, &QDBusConnectionManager::createServer, Qt::BlockingQueuedConnection); + moveToThread(this); // ugly, don't do this in other projects start(); } @@ -123,6 +144,103 @@ void QDBusConnectionManager::run() } } connectionHash.clear(); + + // allow deletion from any thread without warning + moveToThread(Q_NULLPTR); +} + +QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(QDBusConnection::BusType type, const QString &name) +{ + ConnectionRequestData data; + data.type = ConnectionRequestData::ConnectToStandardBus; + data.busType = type; + data.name = &name; + + emit connectionRequested(&data); + return data.result; +} + +QDBusConnectionPrivate *QDBusConnectionManager::connectToBus(const QString &address, const QString &name) +{ + ConnectionRequestData data; + data.type = ConnectionRequestData::ConnectToBusByAddress; + data.busAddress = &address; + data.name = &name; + + emit connectionRequested(&data); + return data.result; +} + +QDBusConnectionPrivate *QDBusConnectionManager::connectToPeer(const QString &address, const QString &name) +{ + ConnectionRequestData data; + data.type = ConnectionRequestData::ConnectToPeerByAddress; + data.busAddress = &address; + data.name = &name; + + emit connectionRequested(&data); + return data.result; +} + +void QDBusConnectionManager::executeConnectionRequest(QDBusConnectionManager::ConnectionRequestData *data) +{ + QMutexLocker locker(&mutex); + const QString &name = *data->name; + QDBusConnectionPrivate *&d = data->result; + + // check if the connection exists by name + d = connection(name); + if (d || name.isEmpty()) + return; + + d = new QDBusConnectionPrivate; + DBusConnection *c = 0; + QDBusErrorInternal error; + switch (data->type) { + case ConnectionRequestData::ConnectToStandardBus: + switch (data->busType) { + case QDBusConnection::SystemBus: + c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error); + break; + case QDBusConnection::SessionBus: + c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error); + break; + case QDBusConnection::ActivationBus: + c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error); + break; + } + break; + + case ConnectionRequestData::ConnectToBusByAddress: + case ConnectionRequestData::ConnectToPeerByAddress: + c = q_dbus_connection_open_private(data->busAddress->toUtf8().constData(), error); + if (c && data->type == ConnectionRequestData::ConnectToBusByAddress) { + // register on the bus + if (!q_dbus_bus_register(c, error)) { + q_dbus_connection_unref(c); + c = 0; + } + } + break; + } + + setConnection(name, d); + if (data->type == ConnectionRequestData::ConnectToPeerByAddress) { + d->setPeer(c, error); + } else { + // create the bus service + // will lock in QDBusConnectionPrivate::connectRelay() + d->setConnection(c, error); + d->createBusService(); + } +} + +void QDBusConnectionManager::createServer(const QString &address, void *server) +{ + QDBusErrorInternal error; + QDBusConnectionPrivate *d = new QDBusConnectionPrivate; + d->setServer(static_cast<QDBusServer *>(server), + q_dbus_server_listen(address.toUtf8().constData(), error), error); } /*! @@ -318,39 +436,7 @@ QDBusConnection QDBusConnection::connectToBus(BusType type, const QString &name) 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; - DBusConnection *c = 0; - QDBusErrorInternal error; - switch (type) { - case SystemBus: - c = q_dbus_bus_get_private(DBUS_BUS_SYSTEM, error); - break; - case SessionBus: - c = q_dbus_bus_get_private(DBUS_BUS_SESSION, error); - break; - case ActivationBus: - c = q_dbus_bus_get_private(DBUS_BUS_STARTER, error); - break; - } - d->setConnection(c, error); //setConnection does the error handling for us - - _q_manager()->setConnection(name, d); - - QDBusConnection retval(d); - - // create the bus service - // will lock in QDBusConnectionPrivate::connectRelay() - d->setBusService(retval); - d->moveToThread(_q_manager()); - - return retval; + return QDBusConnection(_q_manager()->connectToBus(type, name)); } /*! @@ -364,34 +450,7 @@ QDBusConnection QDBusConnection::connectToBus(const QString &address, 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; - // setConnection does the error handling for us - QDBusErrorInternal error; - DBusConnection *c = q_dbus_connection_open_private(address.toUtf8().constData(), error); - if (c) { - if (!q_dbus_bus_register(c, error)) { - q_dbus_connection_unref(c); - c = 0; - } - } - d->setConnection(c, error); - _q_manager()->setConnection(name, d); - - QDBusConnection retval(d); - - // create the bus service - // will lock in QDBusConnectionPrivate::connectRelay() - d->setBusService(retval); - d->moveToThread(_q_manager()); - - return retval; + return QDBusConnection(_q_manager()->connectToBus(address, name)); } /*! \since 4.8 @@ -406,25 +465,7 @@ QDBusConnection QDBusConnection::connectToPeer(const QString &address, 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); - d->moveToThread(_q_manager()); - - QDBusConnection retval(d); - - return retval; + return QDBusConnection(_q_manager()->connectToPeer(address, name)); } /*! @@ -1130,9 +1171,10 @@ QDBusConnection QDBusConnection::sender() /*! \internal */ -void QDBusConnectionPrivate::setBusService(const QDBusConnection &connection) +void QDBusConnectionPrivate::createBusService() { Q_ASSERT(mode == ClientMode); + QDBusConnection connection(this); busService = new QDBusConnectionInterface(connection, this); ref.deref(); // busService has increased the refcounting to us // avoid cyclic refcounting diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index f653c427e7..765e4281fd 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -190,7 +190,7 @@ public: explicit QDBusConnectionPrivate(QObject *parent = 0); ~QDBusConnectionPrivate(); - void setBusService(const QDBusConnection &connection); + void createBusService(); void setPeer(DBusConnection *connection, const QDBusErrorInternal &error); void setConnection(DBusConnection *connection, const QDBusErrorInternal &error); void setServer(QDBusServer *object, DBusServer *server, const QDBusErrorInternal &error); diff --git a/src/dbus/qdbusconnectionmanager_p.h b/src/dbus/qdbusconnectionmanager_p.h index c3c7999699..4527c562f8 100644 --- a/src/dbus/qdbusconnectionmanager_p.h +++ b/src/dbus/qdbusconnectionmanager_p.h @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE class QDBusConnectionManager : public QDaemonThread { Q_OBJECT + struct ConnectionRequestData; public: QDBusConnectionManager(); ~QDBusConnectionManager(); @@ -65,13 +66,23 @@ public: QDBusConnectionPrivate *connection(const QString &name) const; void removeConnection(const QString &name); void setConnection(const QString &name, QDBusConnectionPrivate *c); + QDBusConnectionPrivate *connectToBus(QDBusConnection::BusType type, const QString &name); + QDBusConnectionPrivate *connectToBus(const QString &address, const QString &name); + QDBusConnectionPrivate *connectToPeer(const QString &address, const QString &name); mutable QMutex mutex; +signals: + void connectionRequested(ConnectionRequestData *); + void serverRequested(const QString &address, void *server); + protected: void run() Q_DECL_OVERRIDE; private: + void executeConnectionRequest(ConnectionRequestData *data); + void createServer(const QString &address, void *server); + QHash<QString, QDBusConnectionPrivate *> connectionHash; mutable QMutex senderMutex; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index d5eaf39021..9b0a51107a 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1644,6 +1644,7 @@ void QDBusConnectionPrivate::setServer(QDBusServer *object, DBusServer *s, const { mode = ServerMode; serverObject = object; + object->d = this; if (!s) { handleError(error); return; diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp index a0b2c8283c..6c1b4c10ef 100644 --- a/src/dbus/qdbusserver.cpp +++ b/src/dbus/qdbusserver.cpp @@ -63,14 +63,10 @@ QDBusServer::QDBusServer(const QString &address, QObject *parent) d = 0; return; } - d = new QDBusConnectionPrivate; + emit QDBusConnectionManager::instance()->serverRequested(address, this); QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); - - QDBusErrorInternal error; - d->setServer(this, q_dbus_server_listen(address.toUtf8().constData(), error), error); - d->moveToThread(QDBusConnectionManager::instance()); } /*! @@ -83,23 +79,19 @@ QDBusServer::QDBusServer(QObject *parent) { #ifdef Q_OS_UNIX // Use Unix sockets on Unix systems only - static const char address[] = "unix:tmpdir=/tmp"; + const QString address = QStringLiteral("unix:tmpdir=/tmp"); #else - static const char address[] = "tcp:"; + const QString address = QStringLiteral("tcp:"); #endif if (!qdbus_loadLibDBus()) { d = 0; return; } - d = new QDBusConnectionPrivate; + emit QDBusConnectionManager::instance()->serverRequested(address, this); QObject::connect(d, SIGNAL(newServerConnection(QDBusConnectionPrivate*)), this, SLOT(_q_newConnection(QDBusConnectionPrivate*)), Qt::QueuedConnection); - - QDBusErrorInternal error; - d->setServer(this, q_dbus_server_listen(address, error), error); - d->moveToThread(QDBusConnectionManager::instance()); } /*! diff --git a/src/dbus/qdbusserver.h b/src/dbus/qdbusserver.h index 2c66472a4d..3cb2ec8c50 100644 --- a/src/dbus/qdbusserver.h +++ b/src/dbus/qdbusserver.h @@ -69,6 +69,7 @@ private: Q_DISABLE_COPY(QDBusServer) Q_PRIVATE_SLOT(d, void _q_newConnection(QDBusConnectionPrivate*)) QDBusConnectionPrivate *d; + friend class QDBusConnectionPrivate; }; QT_END_NAMESPACE diff --git a/tests/auto/dbus/dbus.pro b/tests/auto/dbus/dbus.pro index cd845d7043..bd1fef5193 100644 --- a/tests/auto/dbus/dbus.pro +++ b/tests/auto/dbus/dbus.pro @@ -3,6 +3,7 @@ SUBDIRS=\ qdbusabstractadaptor \ qdbusabstractinterface \ qdbusconnection \ + qdbusconnection_no_app \ qdbusconnection_no_bus \ qdbuscontext \ qdbusinterface \ @@ -16,7 +17,7 @@ SUBDIRS=\ qdbusservicewatcher \ qdbustype \ qdbusthreading \ - qdbusxmlparser \ + qdbusxmlparser !contains(QT_CONFIG,private_tests): SUBDIRS -= \ qdbusmarshall \ diff --git a/tests/auto/dbus/qdbusconnection/qdbusconnection.pro b/tests/auto/dbus/qdbusconnection/qdbusconnection.pro index 2fd62a234b..83ae29de0a 100644 --- a/tests/auto/dbus/qdbusconnection/qdbusconnection.pro +++ b/tests/auto/dbus/qdbusconnection/qdbusconnection.pro @@ -2,4 +2,5 @@ CONFIG += testcase TARGET = tst_qdbusconnection QT = core dbus testlib SOURCES += tst_qdbusconnection.cpp +HEADERS += tst_qdbusconnection.h DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index 4e04e4dbab..e91f87d6c8 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -31,34 +31,15 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + +#include "tst_qdbusconnection.h" + #include <qcoreapplication.h> #include <qdebug.h> #include <QtTest/QtTest> #include <QtDBus/QtDBus> -class BaseObject: public QObject -{ - Q_OBJECT - Q_CLASSINFO("D-Bus Interface", "local.BaseObject") -public: - BaseObject(QObject *parent = 0) : QObject(parent) { } -public slots: - void anotherMethod() { } -}; - -class MyObject: public BaseObject -{ - Q_OBJECT -public slots: - void method(const QDBusMessage &msg); - -public: - static QString path; - int callCount; - MyObject(QObject *parent = 0) : BaseObject(parent), callCount(0) {} -}; - void MyObject::method(const QDBusMessage &msg) { path = msg.path(); @@ -66,19 +47,6 @@ void MyObject::method(const QDBusMessage &msg) //qDebug() << msg; } -class MyObjectWithoutInterface: public QObject -{ - Q_OBJECT -public slots: - void method(const QDBusMessage &msg); - -public: - static QString path; - static QString interface; - int callCount; - MyObjectWithoutInterface(QObject *parent = 0) : QObject(parent), callCount(0) {} -}; - void MyObjectWithoutInterface::method(const QDBusMessage &msg) { path = msg.path(); @@ -87,72 +55,6 @@ void MyObjectWithoutInterface::method(const QDBusMessage &msg) //qDebug() << msg; } -class tst_QDBusConnection: public QObject -{ - Q_OBJECT - - int signalsReceived; -public slots: - void oneSlot() { ++signalsReceived; } - void exitLoop() { ++signalsReceived; QTestEventLoop::instance().exitLoop(); } - void secondCallWithCallback(); - -private slots: - void noConnection(); - void connectToBus(); - void connectToPeer(); - void connect(); - void send(); - void sendWithGui(); - void sendAsync(); - void sendSignal(); - void sendSignalToName(); - void sendSignalToOtherName(); - - void registerObject_data(); - void registerObject(); - void registerObjectWithInterface_data(); - void registerObjectWithInterface(); - void registerObjectPeer_data(); - void registerObjectPeer(); - void registerObject2(); - void registerObjectPeer2(); - - void registerQObjectChildren(); - void registerQObjectChildrenPeer(); - - void callSelf(); - void callSelfByAnotherName_data(); - void callSelfByAnotherName(); - void multipleInterfacesInQObject(); - - void slotsWithLessParameters(); - void nestedCallWithCallback(); - - void serviceRegistrationRaceCondition(); - - void registerVirtualObject(); - void callVirtualObject(); - void callVirtualObjectLocal(); - -public: - QString serviceName() const { return "org.qtproject.Qt.Autotests.QDBusConnection"; } - bool callMethod(const QDBusConnection &conn, const QString &path); - bool callMethod(const QDBusConnection &conn, const QString &path, const QString &interface); - bool callMethodPeer(const QDBusConnection &conn, const QString &path); -}; - -class QDBusSpy: public QObject -{ - Q_OBJECT -public slots: - void handlePing(const QString &str) { args.clear(); args << str; } - void asyncReply(const QDBusMessage &msg) { args = msg.arguments(); } - -public: - QList<QVariant> args; -}; - void tst_QDBusConnection::noConnection() { QDBusConnection con = QDBusConnection::connectToBus("unix:path=/dev/null", "testconnection"); @@ -188,12 +90,13 @@ void tst_QDBusConnection::sendSignal() msg << QLatin1String("ping"); QVERIFY(con.send(msg)); - - QTest::qWait(1000); } void tst_QDBusConnection::sendSignalToName() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); // because of the qWait() + QDBusSpy spy; QDBusConnection con = QDBusConnection::sessionBus(); @@ -216,6 +119,9 @@ void tst_QDBusConnection::sendSignalToName() void tst_QDBusConnection::sendSignalToOtherName() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); // because of the qWait() + QDBusSpy spy; QDBusConnection con = QDBusConnection::sessionBus(); @@ -253,6 +159,9 @@ void tst_QDBusConnection::send() void tst_QDBusConnection::sendWithGui() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); @@ -269,6 +178,9 @@ void tst_QDBusConnection::sendWithGui() void tst_QDBusConnection::sendAsync() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); @@ -290,6 +202,9 @@ void tst_QDBusConnection::connect() QDBusConnection con = QDBusConnection::sessionBus(); + if (!QCoreApplication::instance()) + return; // cannot receive signals in this thread without QCoreApplication + con.connect(con.baseService(), "/org/kde/selftest", "org.kde.selftest", "ping", &spy, SLOT(handlePing(QString))); @@ -483,59 +398,6 @@ void tst_QDBusConnection::registerObjectWithInterface() QVERIFY(!callMethod(con, path, interface)); } -class MyServer : public QDBusServer -{ - Q_OBJECT -public: - MyServer(QString path) : m_path(path), m_connections() - { - connect(this, SIGNAL(newConnection(QDBusConnection)), SLOT(handleConnection(QDBusConnection))); - } - - bool registerObject(const QDBusConnection& c) - { - QDBusConnection conn(c); - if (!conn.registerObject(m_path, &m_obj, QDBusConnection::ExportAllSlots)) - return false; - if (!(conn.objectRegisteredAt(m_path) == &m_obj)) - return false; - return true; - } - - bool registerObject() - { - Q_FOREACH (const QString &name, m_connections) { - if (!registerObject(QDBusConnection(name))) - return false; - } - return true; - } - - void unregisterObject() - { - Q_FOREACH (const QString &name, m_connections) { - QDBusConnection c(name); - c.unregisterObject(m_path); - } - } - -public slots: - void handleConnection(const QDBusConnection& c) - { - m_connections << c.name(); - QVERIFY(isConnected()); - QVERIFY(c.isConnected()); - QVERIFY(registerObject(c)); - QTestEventLoop::instance().exitLoop(); - } - -private: - MyObject m_obj; - QString m_path; - QStringList m_connections; -}; - - void tst_QDBusConnection::registerObjectPeer_data() { QTest::addColumn<QString>("path"); @@ -549,6 +411,9 @@ void tst_QDBusConnection::registerObjectPeer_data() void tst_QDBusConnection::registerObjectPeer() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + QFETCH(QString, path); MyServer server(path); @@ -623,7 +488,6 @@ void tst_QDBusConnection::registerObject2() MyObject obj; QVERIFY(con.registerObject("/", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethod(con, "/")); - qDebug() << obj.path; QCOMPARE(obj.path, QString("/")); } // make sure it's gone @@ -635,7 +499,6 @@ void tst_QDBusConnection::registerObject2() QVERIFY(con.registerObject("/p1", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(!callMethod(con, "/")); QVERIFY(callMethod(con, "/p1")); - qDebug() << obj.path; QCOMPARE(obj.path, QString("/p1")); // re-register it somewhere else @@ -699,36 +562,11 @@ void tst_QDBusConnection::registerObject2() } } -class MyServer2 : public QDBusServer -{ - Q_OBJECT -public: - MyServer2() : m_conn("none") - { - connect(this, SIGNAL(newConnection(QDBusConnection)), SLOT(handleConnection(QDBusConnection))); - } - - QDBusConnection connection() - { - return m_conn; - } - -public slots: - void handleConnection(const QDBusConnection& c) - { - m_conn = c; - QVERIFY(isConnected()); - QVERIFY(m_conn.isConnected()); - QTestEventLoop::instance().exitLoop(); - } - -private: - MyObject m_obj; - QDBusConnection m_conn; -}; - void tst_QDBusConnection::registerObjectPeer2() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + MyServer2 server; QDBusConnection con = QDBusConnection::connectToPeer(server.address(), "foo"); QTestEventLoop::instance().enterLoop(2); @@ -749,7 +587,6 @@ void tst_QDBusConnection::registerObjectPeer2() MyObject obj; QVERIFY(con.registerObject("/", &obj, QDBusConnection::ExportAllSlots)); QVERIFY(callMethodPeer(srv_con, "/")); - qDebug() << obj.path; QCOMPARE(obj.path, QString("/")); } // make sure it's gone @@ -761,7 +598,6 @@ void tst_QDBusConnection::registerObjectPeer2() 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 @@ -885,6 +721,9 @@ void tst_QDBusConnection::registerQObjectChildren() void tst_QDBusConnection::registerQObjectChildrenPeer() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + MyServer2 server; QDBusConnection con = QDBusConnection::connectToPeer(server.address(), "foo"); QTestEventLoop::instance().enterLoop(2); @@ -978,22 +817,6 @@ bool tst_QDBusConnection::callMethodPeer(const QDBusConnection &conn, const QStr return (MyObject::path == path); } -class TestObject : public QObject -{ -Q_OBJECT -public: - TestObject(QObject *parent = 0) : QObject(parent) {} - ~TestObject() {} - - QString func; - -public slots: - void test0() { func = "test0"; } - void test1(int i) { func = "test1 " + QString::number(i); } - int test2() { func = "test2"; return 43; } - int test3(int i) { func = "test2"; return i + 1; } -}; - void tst_QDBusConnection::callSelf() { TestObject testObject; @@ -1030,6 +853,9 @@ void tst_QDBusConnection::callSelfByAnotherName_data() void tst_QDBusConnection::callSelfByAnotherName() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + static int counter = 0; QString sname = serviceName() + QString::number(counter++); @@ -1102,6 +928,9 @@ void tst_QDBusConnection::multipleInterfacesInQObject() void tst_QDBusConnection::slotsWithLessParameters() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + QDBusConnection con = QDBusConnection::sessionBus(); QDBusMessage signal = QDBusMessage::createSignal("/", "org.qtproject.TestCase", @@ -1128,7 +957,6 @@ void tst_QDBusConnection::slotsWithLessParameters() void tst_QDBusConnection::secondCallWithCallback() { - qDebug("Hello"); QDBusConnection con = QDBusConnection::sessionBus(); QDBusMessage msg = QDBusMessage::createMethodCall(con.baseService(), "/test", QString(), "test0"); @@ -1137,6 +965,9 @@ void tst_QDBusConnection::secondCallWithCallback() void tst_QDBusConnection::nestedCallWithCallback() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + TestObject testObject; QDBusConnection connection = QDBusConnection::sessionBus(); QVERIFY(connection.registerObject("/test", &testObject, @@ -1152,22 +983,11 @@ void tst_QDBusConnection::nestedCallWithCallback() QCOMPARE(signalsReceived, 1); } -class RaceConditionSignalWaiter : public QObject -{ - Q_OBJECT -public: - int count; - RaceConditionSignalWaiter() : count (0) {} - virtual ~RaceConditionSignalWaiter() {} - -public slots: - void countUp() { ++count; emit done(); } -signals: - void done(); -}; - void tst_QDBusConnection::serviceRegistrationRaceCondition() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + // There was a race condition in the updating of list of name owners in // Qt D-Bus. When the user connects to a signal coming from a given // service, we must listen for NameOwnerChanged signals relevant to that @@ -1219,39 +1039,6 @@ void tst_QDBusConnection::serviceRegistrationRaceCondition() QCOMPARE(recv.count, 1); } -class VirtualObject: public QDBusVirtualObject -{ - Q_OBJECT -public: - VirtualObject() :success(true) {} - - QString introspect(const QString & /* path */) const - { - return QString(); - } - - bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection) { - ++callCount; - lastMessage = message; - - if (success) { - QDBusMessage reply = message.createReply(replyArguments); - connection.send(reply); - } - emit messageReceived(message); - return success; - } -signals: - void messageReceived(const QDBusMessage &message) const; - -public: - mutable QDBusMessage lastMessage; - QVariantList replyArguments; - mutable int callCount; - bool success; -}; - - void tst_QDBusConnection::registerVirtualObject() { QDBusConnection con = QDBusConnection::sessionBus(); @@ -1334,6 +1121,9 @@ void tst_QDBusConnection::registerVirtualObject() void tst_QDBusConnection::callVirtualObject() { + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); @@ -1391,7 +1181,6 @@ void tst_QDBusConnection::callVirtualObject() QVERIFY(!QTestEventLoop::instance().timeout()); QTest::qWait(100); QVERIFY(errorReply.isError()); - qDebug() << errorReply.reply().arguments(); QCOMPARE(errorReply.reply().errorName(), QString("org.freedesktop.DBus.Error.UnknownObject")); QDBusConnection::disconnectFromBus("con2"); @@ -1432,7 +1221,7 @@ void tst_QDBusConnection::callVirtualObjectLocal() QString MyObject::path; QString MyObjectWithoutInterface::path; QString MyObjectWithoutInterface::interface; -QTEST_MAIN(tst_QDBusConnection) - -#include "tst_qdbusconnection.moc" +#ifndef tst_QDBusConnection +QTEST_MAIN(tst_QDBusConnection) +#endif diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h new file mode 100644 index 0000000000..a53ba320f8 --- /dev/null +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_QDBUSCONNECTION_H +#define TST_QDBUSCONNECTION_H + +#include <QObject> +#include <QtDBus/QtDBus> +#include <QtTest/QtTest> + +class BaseObject: public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.BaseObject") +public: + BaseObject(QObject *parent = 0) : QObject(parent) { } +public slots: + void anotherMethod() { } +}; + +class MyObject: public BaseObject +{ + Q_OBJECT +public slots: + void method(const QDBusMessage &msg); + +public: + static QString path; + int callCount; + MyObject(QObject *parent = 0) : BaseObject(parent), callCount(0) {} +}; + +class MyObjectWithoutInterface: public QObject +{ + Q_OBJECT +public slots: + void method(const QDBusMessage &msg); + +public: + static QString path; + static QString interface; + int callCount; + MyObjectWithoutInterface(QObject *parent = 0) : QObject(parent), callCount(0) {} +}; + +class tst_QDBusConnection: public QObject +{ + Q_OBJECT + + int signalsReceived; +public slots: + void oneSlot() { ++signalsReceived; } + void exitLoop() { ++signalsReceived; QTestEventLoop::instance().exitLoop(); } + void secondCallWithCallback(); + +private slots: + void noConnection(); + void connectToBus(); + void connectToPeer(); + void connect(); + void send(); + void sendWithGui(); + void sendAsync(); + void sendSignal(); + void sendSignalToName(); + void sendSignalToOtherName(); + + void registerObject_data(); + void registerObject(); + void registerObjectWithInterface_data(); + void registerObjectWithInterface(); + void registerObjectPeer_data(); + void registerObjectPeer(); + void registerObject2(); + void registerObjectPeer2(); + + void registerQObjectChildren(); + void registerQObjectChildrenPeer(); + + void callSelf(); + void callSelfByAnotherName_data(); + void callSelfByAnotherName(); + void multipleInterfacesInQObject(); + + void slotsWithLessParameters(); + void nestedCallWithCallback(); + + void serviceRegistrationRaceCondition(); + + void registerVirtualObject(); + void callVirtualObject(); + void callVirtualObjectLocal(); + +public: + QString serviceName() const { return "org.qtproject.Qt.Autotests.QDBusConnection"; } + bool callMethod(const QDBusConnection &conn, const QString &path); + bool callMethod(const QDBusConnection &conn, const QString &path, const QString &interface); + bool callMethodPeer(const QDBusConnection &conn, const QString &path); +}; + +class QDBusSpy: public QObject +{ + Q_OBJECT +public slots: + void handlePing(const QString &str) { args.clear(); args << str; } + void asyncReply(const QDBusMessage &msg) { args = msg.arguments(); } + +public: + QList<QVariant> args; +}; + +class MyServer : public QDBusServer +{ + Q_OBJECT +public: + MyServer(QString path) : m_path(path), m_connections() + { + connect(this, SIGNAL(newConnection(QDBusConnection)), SLOT(handleConnection(QDBusConnection))); + } + + bool registerObject(const QDBusConnection& c) + { + QDBusConnection conn(c); + if (!conn.registerObject(m_path, &m_obj, QDBusConnection::ExportAllSlots)) + return false; + if (!(conn.objectRegisteredAt(m_path) == &m_obj)) + return false; + return true; + } + + bool registerObject() + { + Q_FOREACH (const QString &name, m_connections) { + if (!registerObject(QDBusConnection(name))) + return false; + } + return true; + } + + void unregisterObject() + { + Q_FOREACH (const QString &name, m_connections) { + QDBusConnection c(name); + c.unregisterObject(m_path); + } + } + +public slots: + void handleConnection(const QDBusConnection& c) + { + m_connections << c.name(); + QVERIFY(isConnected()); + QVERIFY(c.isConnected()); + QVERIFY(registerObject(c)); + QTestEventLoop::instance().exitLoop(); + } + +private: + MyObject m_obj; + QString m_path; + QStringList m_connections; +}; + +class MyServer2 : public QDBusServer +{ + Q_OBJECT +public: + MyServer2() : m_conn("none") + { + connect(this, SIGNAL(newConnection(QDBusConnection)), SLOT(handleConnection(QDBusConnection))); + } + + QDBusConnection connection() + { + return m_conn; + } + +public slots: + void handleConnection(const QDBusConnection& c) + { + m_conn = c; + QVERIFY(isConnected()); + QVERIFY(m_conn.isConnected()); + QTestEventLoop::instance().exitLoop(); + } + +private: + MyObject m_obj; + QDBusConnection m_conn; +}; + +class TestObject : public QObject +{ +Q_OBJECT +public: + TestObject(QObject *parent = 0) : QObject(parent) {} + ~TestObject() {} + + QString func; + +public slots: + void test0() { func = "test0"; } + void test1(int i) { func = "test1 " + QString::number(i); } + int test2() { func = "test2"; return 43; } + int test3(int i) { func = "test2"; return i + 1; } +}; + +class RaceConditionSignalWaiter : public QObject +{ + Q_OBJECT +public: + int count; + RaceConditionSignalWaiter() : count (0) {} + virtual ~RaceConditionSignalWaiter() {} + +public slots: + void countUp() { ++count; emit done(); } +signals: + void done(); +}; + +class VirtualObject: public QDBusVirtualObject +{ + Q_OBJECT +public: + VirtualObject() :success(true) {} + + QString introspect(const QString & /* path */) const + { + return QString(); + } + + bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection) { + ++callCount; + lastMessage = message; + + if (success) { + QDBusMessage reply = message.createReply(replyArguments); + connection.send(reply); + } + emit messageReceived(message); + return success; + } +signals: + void messageReceived(const QDBusMessage &message) const; + +public: + mutable QDBusMessage lastMessage; + QVariantList replyArguments; + mutable int callCount; + bool success; +}; + + +#endif // TST_QDBUSCONNECTION_H + diff --git a/tests/auto/dbus/qdbusconnection_no_app/qdbusconnection_no_app.pro b/tests/auto/dbus/qdbusconnection_no_app/qdbusconnection_no_app.pro new file mode 100644 index 0000000000..ba3a13caa9 --- /dev/null +++ b/tests/auto/dbus/qdbusconnection_no_app/qdbusconnection_no_app.pro @@ -0,0 +1,6 @@ +CONFIG += testcase +TARGET = tst_qdbusconnection_no_app +QT = core dbus testlib +SOURCES += tst_qdbusconnection_no_app.cpp +HEADERS += ../qdbusconnection/tst_qdbusconnection.h +DEFINES += SRCDIR=\\\"$$PWD/\\\" tst_QDBusConnection=tst_QDBusConnection_NoApplication diff --git a/tests/auto/dbus/qdbusconnection_no_app/tst_qdbusconnection_no_app.cpp b/tests/auto/dbus/qdbusconnection_no_app/tst_qdbusconnection_no_app.cpp new file mode 100644 index 0000000000..816f75f82e --- /dev/null +++ b/tests/auto/dbus/qdbusconnection_no_app/tst_qdbusconnection_no_app.cpp @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Intel Corporation. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// Ugly hack, look away +#include "../qdbusconnection/tst_qdbusconnection.cpp" + +QTEST_APPLESS_MAIN(tst_QDBusConnection_NoApplication) |