/**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #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 Pinger; class tst_QDBusAbstractInterface: public QObject { Q_OBJECT Interface targetObj; Pinger getPinger(QString service = "", const QString &path = "/") { QDBusConnection con = QDBusConnection::sessionBus(); if (!con.isConnected()) return Pinger(); if (service.isEmpty() && !service.isNull()) service = con.baseService(); 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 init(); void cleanup(); 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 callWithTimeout(); void stringPropRead(); void stringPropWrite(); void variantPropRead(); void variantPropWrite(); void complexPropRead(); void complexPropWrite(); void stringPropReadPeer(); void stringPropWritePeer(); void variantPropReadPeer(); void variantPropWritePeer(); void complexPropReadPeer(); void complexPropWritePeer(); void stringPropDirectRead(); void stringPropDirectWrite(); void variantPropDirectRead(); void variantPropDirectWrite(); void complexPropDirectRead(); void complexPropDirectWrite(); void stringPropDirectReadPeer(); void stringPropDirectWritePeer(); void variantPropDirectReadPeer(); void variantPropDirectWritePeer(); void complexPropDirectReadPeer(); void complexPropDirectWritePeer(); void getVoidSignal_data(); void getVoidSignal(); void getStringSignal_data(); void getStringSignal(); 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(); void propertyWriteErrors(); void directPropertyReadErrors_data(); 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; }; tst_QDBusAbstractInterface::tst_QDBusAbstractInterface() { // register the meta types qDBusRegisterMetaType(); qRegisterMetaType(); } void tst_QDBusAbstractInterface::initTestCase() { // enable debugging temporarily: //putenv("QDBUS_DEBUG=1"); // register the object QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); con.registerObject("/", &targetObj, QDBusConnection::ExportScriptableContents); } void tst_QDBusAbstractInterface::init() { QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); // verify service isn't registered by something else // (e.g. a left over qpinger from a previous test run) QVERIFY(!con.interface()->isServiceRegistered(serviceName)); // start peer server #ifdef Q_OS_WIN proc.start("qpinger"); #else proc.start("./qpinger/qpinger"); #endif QVERIFY(proc.waitForStarted()); // verify service is now registered QTRY_VERIFY(con.interface()->isServiceRegistered(serviceName)); // 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::cleanup() { QDBusConnection::disconnectFromPeer("peer"); // Kill peer, resetting the object exported by a separate process proc.terminate(); QVERIFY(proc.waitForFinished() || proc.state() == QProcess::NotRunning); // Reset the object exported by this process targetObj.m_stringProp = QString(); targetObj.m_variantProp = QDBusVariant(); targetObj.m_complexProp = RegisteredType(); // Wait until the service is certainly not registered QDBusConnection con = QDBusConnection::sessionBus(); if (con.isConnected()) { QTRY_VERIFY(!con.interface()->isServiceRegistered(serviceName)); } } void tst_QDBusAbstractInterface::makeVoidCall() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QDBusReply r = p->voidMethod(); QVERIFY(r.isValid()); } void tst_QDBusAbstractInterface::makeStringCall() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QDBusReply r = p->stringMethod(); QVERIFY(r.isValid()); QCOMPARE(r.value(), targetObj.stringMethod()); } void tst_QDBusAbstractInterface::makeComplexCall() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QDBusReply r = p->complexMethod(); QVERIFY(r.isValid()); QCOMPARE(r.value(), targetObj.complexMethod()); } void tst_QDBusAbstractInterface::makeMultiOutCall() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); int value; QDBusReply r = p->multiOutMethod(value); QVERIFY(r.isValid()); int expectedValue; QCOMPARE(r.value(), targetObj.multiOutMethod(expectedValue)); QCOMPARE(value, expectedValue); } void tst_QDBusAbstractInterface::makeVoidCallPeer() { Pinger p = getPingerPeer(); QVERIFY2(p, "Not connected to D-Bus"); QDBusReply r = p->voidMethod(); QVERIFY(r.isValid()); } void tst_QDBusAbstractInterface::makeStringCallPeer() { Pinger p = getPingerPeer(); QVERIFY2(p, "Not connected to D-Bus"); QDBusReply 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 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 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(); QVERIFY2(p, "Not connected to D-Bus"); QDBusPendingReply r = p->voidMethod(); r.waitForFinished(); QVERIFY(r.isValid()); } void tst_QDBusAbstractInterface::makeAsyncStringCall() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QDBusPendingReply r = p->stringMethod(); r.waitForFinished(); QVERIFY(r.isValid()); QCOMPARE(r.value(), targetObj.stringMethod()); } void tst_QDBusAbstractInterface::makeAsyncComplexCall() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QDBusPendingReply r = p->complexMethod(); r.waitForFinished(); QVERIFY(r.isValid()); QCOMPARE(r.value(), targetObj.complexMethod()); } void tst_QDBusAbstractInterface::makeAsyncMultiOutCall() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QDBusPendingReply r = p->multiOutMethod(); r.waitForFinished(); QVERIFY(r.isValid()); int expectedValue; QCOMPARE(r.value(), targetObj.multiOutMethod(expectedValue)); QCOMPARE(r.argumentAt<1>(), expectedValue); } void tst_QDBusAbstractInterface::makeAsyncVoidCallPeer() { Pinger p = getPingerPeer(); QVERIFY2(p, "Not connected to D-Bus"); QDBusPendingReply 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 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 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 r = p->multiOutMethod(); r.waitForFinished(); QVERIFY(r.isValid()); int expectedValue; QCOMPARE(r.value(), targetObj.multiOutMethod(expectedValue)); QCOMPARE(r.argumentAt<1>(), expectedValue); QCoreApplication::instance()->processEvents(); } static const char server_serviceName[] = "com.trolltech.autotests.dbusserver"; static const char server_objectPath[] = "/com/trolltech/server"; static const char server_interfaceName[] = "com.trolltech.QtDBus.Pinger"; class DBusServerThread : public QThread { public: DBusServerThread() { start(); m_ready.acquire(); } ~DBusServerThread() { quit(); wait(); } void run() { QDBusConnection con = QDBusConnection::connectToBus(QDBusConnection::SessionBus, "ThreadConnection"); if (!con.isConnected()) qWarning("Error registering to DBus"); if (!con.registerService(server_serviceName)) qWarning("Error registering service name"); Interface targetObj; con.registerObject(server_objectPath, &targetObj, QDBusConnection::ExportScriptableContents); m_ready.release(); exec(); QDBusConnection::disconnectFromBus( con.name() ); } private: QSemaphore m_ready; }; void tst_QDBusAbstractInterface::callWithTimeout() { QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY2(con.isConnected(), "Not connected to D-Bus"); DBusServerThread serverThread; QDBusMessage msg = QDBusMessage::createMethodCall(server_serviceName, server_objectPath, server_interfaceName, "sleepMethod"); msg << 100; { // Call with no timeout -> works QDBusMessage reply = con.call(msg); QCOMPARE((int)reply.type(), (int)QDBusMessage::ReplyMessage); QCOMPARE(reply.arguments().at(0).toInt(), 42); } { // Call with 1 sec timeout -> fails QDBusMessage reply = con.call(msg, QDBus::Block, 1); QCOMPARE(reply.type(), QDBusMessage::ErrorMessage); } // Now using QDBusInterface QDBusInterface iface(server_serviceName, server_objectPath, server_interfaceName, con); { // Call with no timeout QDBusMessage reply = iface.call("sleepMethod", 100); QCOMPARE(reply.type(), QDBusMessage::ReplyMessage); QCOMPARE(reply.arguments().at(0).toInt(), 42); } { // Call with 1 sec timeout -> fails iface.setTimeout(1); QDBusMessage reply = iface.call("sleepMethod", 100); QCOMPARE(reply.type(), QDBusMessage::ErrorMessage); } // Now using generated code com::trolltech::QtDBus::Pinger p(server_serviceName, server_objectPath, QDBusConnection::sessionBus()); { // Call with no timeout QDBusReply reply = p.sleepMethod(100); QVERIFY(reply.isValid()); QCOMPARE(int(reply), 42); } { // Call with 1 sec timeout -> fails p.setTimeout(1); QDBusReply reply = p.sleepMethod(100); QVERIFY(!reply.isValid()); } } void tst_QDBusAbstractInterface::stringPropRead() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QString expectedValue = targetObj.m_stringProp = "This is a test"; QVariant v = p->property("stringProp"); QVERIFY(v.isValid()); QCOMPARE(v.toString(), expectedValue); } void tst_QDBusAbstractInterface::stringPropWrite() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QString expectedValue = "This is a value"; QVERIFY(p->setProperty("stringProp", expectedValue)); QCOMPARE(targetObj.m_stringProp, expectedValue); } void tst_QDBusAbstractInterface::variantPropRead() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QDBusVariant expectedValue = targetObj.m_variantProp = QDBusVariant(QVariant(42)); QVariant v = p->property("variantProp"); QVERIFY(v.isValid()); QDBusVariant value = v.value(); QCOMPARE(value.variant().userType(), expectedValue.variant().userType()); QCOMPARE(value.variant(), expectedValue.variant()); } void tst_QDBusAbstractInterface::variantPropWrite() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QDBusVariant expectedValue = QDBusVariant(Q_INT64_C(-47)); QVERIFY(p->setProperty("variantProp", qVariantFromValue(expectedValue))); QCOMPARE(targetObj.m_variantProp.variant(), expectedValue.variant()); } void tst_QDBusAbstractInterface::complexPropRead() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); RegisteredType expectedValue = targetObj.m_complexProp = RegisteredType("This is a test"); QVariant v = p->property("complexProp"); QVERIFY(v.userType() == qMetaTypeId()); QCOMPARE(v.value(), targetObj.m_complexProp); } void tst_QDBusAbstractInterface::complexPropWrite() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); RegisteredType expectedValue = RegisteredType("This is a value"); QVERIFY(p->setProperty("complexProp", qVariantFromValue(expectedValue))); 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)); QEXPECT_FAIL("", "QTBUG-24262 peer tests are broken", Abort); 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(); 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))); QEXPECT_FAIL("", "QTBUG-24262 peer tests are broken", Abort); 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()); QCOMPARE(v.value(), 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))); QEXPECT_FAIL("", "QTBUG-24262 peer tests are broken", Abort); QCOMPARE(targetObj.m_complexProp, expectedValue); } void tst_QDBusAbstractInterface::stringPropDirectRead() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QString expectedValue = targetObj.m_stringProp = "This is a test"; QCOMPARE(p->stringProp(), expectedValue); } void tst_QDBusAbstractInterface::stringPropDirectWrite() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QString expectedValue = "This is a value"; p->setStringProp(expectedValue); QCOMPARE(targetObj.m_stringProp, expectedValue); } void tst_QDBusAbstractInterface::variantPropDirectRead() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); QDBusVariant expectedValue = targetObj.m_variantProp = QDBusVariant(42); QCOMPARE(p->variantProp().variant(), expectedValue.variant()); } void tst_QDBusAbstractInterface::variantPropDirectWrite() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); 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::complexPropDirectRead() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); RegisteredType expectedValue = targetObj.m_complexProp = RegisteredType("This is a test"); QCOMPARE(p->complexProp(), targetObj.m_complexProp); } void tst_QDBusAbstractInterface::complexPropDirectWrite() { Pinger p = getPinger(); QVERIFY2(p, "Not connected to D-Bus"); RegisteredType expectedValue = RegisteredType("This is a value"); p->setComplexProp(expectedValue); 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); QEXPECT_FAIL("", "QTBUG-24262 peer tests are broken", Abort); 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); QEXPECT_FAIL("", "QTBUG-24262 peer tests are broken", Abort); 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); QEXPECT_FAIL("", "QTBUG-24262 peer tests are broken", Abort); QCOMPARE(targetObj.m_complexProp, expectedValue); } void tst_QDBusAbstractInterface::getVoidSignal_data() { QTest::addColumn("service"); QTest::addColumn("path"); QTest::newRow("specific") << QDBusConnection::sessionBus().baseService() << "/"; QTest::newRow("service-wildcard") << QString() << "/"; QTest::newRow("path-wildcard") << QDBusConnection::sessionBus().baseService() << QString(); QTest::newRow("full-wildcard") << QString() << QString(); } void tst_QDBusAbstractInterface::getVoidSignal() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, 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())); emit targetObj.voidSignal(); QTestEventLoop::instance().enterLoop(2); QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(s.size() == 1); QVERIFY(s.at(0).size() == 0); } void tst_QDBusAbstractInterface::getStringSignal_data() { getVoidSignal_data(); } void tst_QDBusAbstractInterface::getStringSignal() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, 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"; emit targetObj.stringSignal(expectedValue); 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::getComplexSignal_data() { getVoidSignal_data(); } void tst_QDBusAbstractInterface::getComplexSignal() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, 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"); emit targetObj.complexSignal(expectedValue); QTestEventLoop::instance().enterLoop(2); QVERIFY(!QTestEventLoop::instance().timeout()); QVERIFY(s.size() == 1); QVERIFY(s[0].size() == 1); QCOMPARE(s[0][0].userType(), qMetaTypeId()); QCOMPARE(s[0][0].value(), expectedValue); } void tst_QDBusAbstractInterface::getVoidSignalPeer_data() { QTest::addColumn("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()); QCOMPARE(s[0][0].value(), expectedValue); } void tst_QDBusAbstractInterface::followSignal() { const QString serviceToFollow = "com.trolltech.tst_qdbusabstractinterface.FollowMe"; Pinger p = getPinger(serviceToFollow); QVERIFY2(p, "Not connected to D-Bus"); QDBusConnection con = p->connection(); QVERIFY(!con.interface()->isServiceRegistered(serviceToFollow)); Pinger control = getPinger(""); // 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())); QTestEventLoop::instance().connect(control.data(), SIGNAL(voidSignal()), SLOT(exitLoop())); QSignalSpy s(p.data(), SIGNAL(voidSignal())); emit targetObj.voidSignal(); QTestEventLoop::instance().enterLoop(200); QVERIFY(!QTestEventLoop::instance().timeout()); // signal must not have been received because the service isn't registered QVERIFY(s.isEmpty()); // now register the service QDBusReply r = con.interface()->registerService(serviceToFollow, QDBusConnectionInterface::DontQueueService, QDBusConnectionInterface::DontAllowReplacement); QVERIFY(r.isValid() && r.value() == QDBusConnectionInterface::ServiceRegistered); QVERIFY(con.interface()->isServiceRegistered(serviceToFollow)); QCoreApplication::instance()->processEvents(); // emit the signal again: emit targetObj.voidSignal(); QTestEventLoop::instance().enterLoop(2); QVERIFY(!QTestEventLoop::instance().timeout()); // now the signal must have been received: QCOMPARE(s.size(), 1); QVERIFY(s.at(0).size() == 0); s.clear(); // disconnect the signal disconnect(p.data(), SIGNAL(voidSignal()), &QTestEventLoop::instance(), 0); // emit the signal again: emit targetObj.voidSignal(); QTestEventLoop::instance().enterLoop(2); QVERIFY(!QTestEventLoop::instance().timeout()); // and now it mustn't have been received QVERIFY(s.isEmpty()); // cleanup: con.interface()->unregisterService(serviceToFollow); } void tst_QDBusAbstractInterface::createErrors_data() { QTest::addColumn("service"); QTest::addColumn("path"); QTest::addColumn("errorName"); QTest::newRow("invalid-service") << "this isn't valid" << "/" << "com.trolltech.QtDBus.Error.InvalidService"; QTest::newRow("invalid-path") << QDBusConnection::sessionBus().baseService() << "this isn't valid" << "com.trolltech.QtDBus.Error.InvalidObjectPath"; } void tst_QDBusAbstractInterface::createErrors() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, path); QVERIFY2(p, "Not connected to D-Bus"); QVERIFY(!p->isValid()); QTEST(p->lastError().name(), "errorName"); } void tst_QDBusAbstractInterface::createErrorsPeer_data() { QTest::addColumn("path"); QTest::addColumn("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(); QTest::newRow("service-wildcard") << QString() << "/" << "com.trolltech.QtDBus.Error.InvalidService"; QTest::newRow("path-wildcard") << QDBusConnection::sessionBus().baseService() << QString() << "com.trolltech.QtDBus.Error.InvalidObjectPath"; QTest::newRow("full-wildcard") << QString() << QString() << "com.trolltech.QtDBus.Error.InvalidService"; } void tst_QDBusAbstractInterface::callErrors() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, path); QVERIFY2(p, "Not connected to D-Bus"); // we shouldn't be able to make this call: QDBusReply r = p->stringMethod(); QVERIFY(!r.isValid()); QTEST(r.error().name(), "errorName"); QCOMPARE(p->lastError().name(), r.error().name()); } void tst_QDBusAbstractInterface::asyncCallErrors_data() { callErrors_data(); } void tst_QDBusAbstractInterface::asyncCallErrors() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, path); QVERIFY2(p, "Not connected to D-Bus"); // we shouldn't be able to make this call: QDBusPendingReply r = p->stringMethod(); QVERIFY(r.isError()); QTEST(r.error().name(), "errorName"); 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 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 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(); } void tst_QDBusAbstractInterface::propertyReadErrors() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, 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::propertyWriteErrors_data() { callErrors_data(); } void tst_QDBusAbstractInterface::propertyWriteErrors() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, 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::directPropertyReadErrors_data() { callErrors_data(); } void tst_QDBusAbstractInterface::directPropertyReadErrors() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, 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::directPropertyWriteErrors_data() { callErrors_data(); } void tst_QDBusAbstractInterface::directPropertyWriteErrors() { QFETCH(QString, service); QFETCH(QString, path); Pinger p = getPinger(service, 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"); } 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"