| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Copyright (C) 2016 Intel Corporation. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the test suite of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| ** 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 https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| #include <qcoreapplication.h> |
| #include <qdebug.h> |
| #include <qsharedpointer.h> |
| |
| #include <QtTest/QtTest> |
| |
| #include <QtDBus> |
| |
| #include "interface.h" |
| #include "pinger_interface.h" |
| |
| static const char serviceName[] = "org.qtproject.autotests.qpinger"; |
| static const char objectPath[] = "/org/qtproject/qpinger"; |
| static const char *interfaceName = serviceName; |
| |
| typedef QSharedPointer<org::qtproject::QtDBus::Pinger> Pinger; |
| |
| class tst_QDBusAbstractInterface: public QObject |
| { |
| Q_OBJECT |
| Interface targetObj; |
| QString peerAddress; |
| |
| 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::create(service, path, con); |
| } |
| |
| Pinger getPingerPeer(const QString &path = "/", const QString &service = "") |
| { |
| QDBusConnection con = QDBusConnection("peer"); |
| if (!con.isConnected()) |
| return Pinger(); |
| return Pinger::create(service, 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 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 connectDisconnect_data(); |
| void connectDisconnect(); |
| void connectDisconnectPeer_data(); |
| void connectDisconnectPeer(); |
| |
| 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(); |
| |
| void validity_data(); |
| void validity(); |
| |
| private: |
| QProcess proc; |
| }; |
| |
| class SignalReceiver : public QObject |
| { |
| Q_OBJECT |
| public: |
| int callCount; |
| SignalReceiver() : callCount(0) {} |
| public slots: |
| void receive() { ++callCount; } |
| }; |
| |
| tst_QDBusAbstractInterface::tst_QDBusAbstractInterface() |
| { |
| // register the meta types |
| qDBusRegisterMetaType<RegisteredType>(); |
| qRegisterMetaType<UnregisteredType>(); |
| } |
| |
| 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); |
| |
| // 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 |
| # define EXE ".exe" |
| #else |
| # define EXE "" |
| #endif |
| proc.setProcessChannelMode(QProcess::ForwardedErrorChannel); |
| proc.start(QFINDTESTDATA("qpinger/qpinger" EXE)); |
| QVERIFY2(proc.waitForStarted(), qPrintable(proc.errorString())); |
| QVERIFY(proc.waitForReadyRead()); |
| |
| // 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); |
| QCOMPARE(rpl.type(), QDBusMessage::ReplyMessage); |
| peerAddress = rpl.arguments().at(0).toString(); |
| } |
| |
| void tst_QDBusAbstractInterface::cleanupTestCase() |
| { |
| QDBusMessage msg = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "quit"); |
| QDBusConnection::sessionBus().call(msg); |
| proc.waitForFinished(200); |
| proc.close(); |
| } |
| |
| void tst_QDBusAbstractInterface::init() |
| { |
| QDBusConnection con = QDBusConnection::sessionBus(); |
| QVERIFY(con.isConnected()); |
| |
| // connect to peer server |
| QDBusConnection peercon = QDBusConnection::connectToPeer(peerAddress, "peer"); |
| QVERIFY(peercon.isConnected()); |
| |
| QDBusMessage req2 = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "waitForConnected"); |
| QDBusMessage rpl2 = con.call(req2); |
| QVERIFY2(rpl2.type() == QDBusMessage::ReplyMessage, rpl2.errorMessage().toLatin1()); |
| } |
| |
| void tst_QDBusAbstractInterface::cleanup() |
| { |
| QDBusConnection::disconnectFromPeer("peer"); |
| |
| // Reset the object exported by this process |
| targetObj.m_stringProp = QString(); |
| targetObj.m_variantProp = QDBusVariant(); |
| targetObj.m_complexProp = RegisteredType(); |
| |
| QDBusMessage resetCall = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "reset"); |
| QCOMPARE(QDBusConnection::sessionBus().call(resetCall).type(), QDBusMessage::ReplyMessage); |
| } |
| |
| void tst_QDBusAbstractInterface::makeVoidCall() |
| { |
| Pinger p = getPinger(); |
| QVERIFY2(p, "Not connected to D-Bus"); |
| |
| QDBusReply<void> r = p->voidMethod(); |
| QVERIFY(r.isValid()); |
| } |
| |
| void tst_QDBusAbstractInterface::makeStringCall() |
| { |
| Pinger p = getPinger(); |
| QVERIFY2(p, "Not connected to D-Bus"); |
| |
| QDBusReply<QString> r = p->stringMethod(); |
| QVERIFY(r.isValid()); |
| QCOMPARE(r.value(), targetObj.stringMethod()); |
| } |
| |
| static QHash<QString, QVariant> complexMethodArgs() |
| { |
| QHash<QString, QVariant> args; |
| args.insert("arg1", "Hello world"); |
| args.insert("arg2", 12345); |
| return args; |
| } |
| |
| void tst_QDBusAbstractInterface::makeComplexCall() |
| { |
| Pinger p = getPinger(); |
| QVERIFY2(p, "Not connected to D-Bus"); |
| |
| QDBusReply<RegisteredType> r = p->complexMethod(complexMethodArgs()); |
| QVERIFY(r.isValid()); |
| QCOMPARE(r.value(), targetObj.complexMethod(complexMethodArgs())); |
| } |
| |
| void tst_QDBusAbstractInterface::makeMultiOutCall() |
| { |
| Pinger p = getPinger(); |
| 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::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(complexMethodArgs()); |
| QVERIFY(r.isValid()); |
| QCOMPARE(r.value(), targetObj.complexMethod(complexMethodArgs())); |
| } |
| |
| 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(); |
| QVERIFY2(p, "Not connected to D-Bus"); |
| |
| QDBusPendingReply<void> r = p->voidMethod(); |
| r.waitForFinished(); |
| QVERIFY(r.isValid()); |
| } |
| |
| void tst_QDBusAbstractInterface::makeAsyncStringCall() |
| { |
| Pinger p = getPinger(); |
| QVERIFY2(p, "Not connected to D-Bus"); |
| |
| QDBusPendingReply<QString> 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<RegisteredType> r = p->complexMethod(complexMethodArgs()); |
| r.waitForFinished(); |
| QVERIFY(r.isValid()); |
| QCOMPARE(r.value(), targetObj.complexMethod(complexMethodArgs())); |
| } |
| |
| void tst_QDBusAbstractInterface::makeAsyncMultiOutCall() |
| { |
| Pinger p = getPinger(); |
| 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); |
| } |
| |
| 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")); |
| QCOMPARE(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(complexMethodArgs()); |
| r.waitForFinished(); |
| QVERIFY(r.isValid()); |
| QCOMPARE(r.value(), targetObj.complexMethod(complexMethodArgs())); |
| } |
| |
| 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(); |
| } |
| |
| static const char server_serviceName[] = "org.qtproject.autotests.dbusserver"; |
| static const char server_objectPath[] = "/org/qtproject/server"; |
| static const char server_interfaceName[] = "org.qtproject.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; // sleep 100 ms |
| |
| { |
| // 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 msec 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 msec timeout -> fails |
| iface.setTimeout(1); |
| QDBusMessage reply = iface.call("sleepMethod", 100); |
| QCOMPARE(reply.type(), QDBusMessage::ErrorMessage); |
| } |
| { |
| // Call with 300 msec timeout -> works |
| iface.setTimeout(300); |
| QDBusMessage reply = iface.call("sleepMethod", 100); |
| QCOMPARE(reply.arguments().at(0).toInt(), 42); |
| } |
| |
| // Now using generated code |
| org::qtproject::QtDBus::Pinger p(server_serviceName, server_objectPath, QDBusConnection::sessionBus()); |
| { |
| // Call with no timeout |
| QDBusReply<int> reply = p.sleepMethod(100); |
| QVERIFY(reply.isValid()); |
| QCOMPARE(int(reply), 42); |
| } |
| { |
| // Call with 1 msec timeout -> fails |
| p.setTimeout(1); |
| QDBusReply<int> 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<QDBusVariant>(); |
| 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", QVariant::fromValue(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"); |
| QCOMPARE(v.userType(), qMetaTypeId<RegisteredType>()); |
| QCOMPARE(v.value<RegisteredType>(), 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", QVariant::fromValue(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<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", QVariant::fromValue(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"); |
| QCOMPARE(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", QVariant::fromValue(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<QString>("service"); |
| QTest::addColumn<QString>("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()); |
| |
| QCOMPARE(s.size(), 1); |
| QCOMPARE(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()); |
| |
| QCOMPARE(s.size(), 1); |
| QCOMPARE(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()); |
| |
| QCOMPARE(s.size(), 1); |
| QCOMPARE(s[0].size(), 1); |
| QCOMPARE(s[0][0].userType(), qMetaTypeId<RegisteredType>()); |
| 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()); |
| |
| QCOMPARE(s.size(), 1); |
| QCOMPARE(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()); |
| |
| QCOMPARE(s.size(), 1); |
| QCOMPARE(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()); |
| |
| QCOMPARE(s.size(), 1); |
| QCOMPARE(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 = "org.qtproject.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(""); |
| |
| // connect our test signal |
| // FRAGILE CODE AHEAD: |
| // Connection order is important: we connect the control first because that |
| // needs to be delivered last, to ensure that we don't exitLoop() before |
| // the signal delivery to QSignalSpy is posted to the current thread. That |
| // happens because QDBusConnectionPrivate runs in a separate thread and |
| // uses a QMultiHash and insertMulti prepends to the list of items with the |
| // same key. |
| 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<QDBusConnectionInterface::RegisterServiceReply> 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); |
| QCOMPARE(s.at(0).size(), 0); |
| |
| // cleanup: |
| con.interface()->unregisterService(serviceToFollow); |
| } |
| |
| void tst_QDBusAbstractInterface::connectDisconnect_data() |
| { |
| QTest::addColumn<int>("connectCount"); |
| QTest::addColumn<int>("disconnectCount"); |
| |
| // we don't actually need multiple disconnects |
| // QObject::disconnect() disconnects all matching rules |
| // we'd have to use QMetaObject::disconnectOne if we wanted just one |
| QTest::newRow("null") << 0 << 0; |
| QTest::newRow("connect-disconnect") << 1 << 1; |
| QTest::newRow("connect-disconnect-wildcard") << 1 << -1; |
| QTest::newRow("connect-twice") << 2 << 0; |
| QTest::newRow("connect-twice-disconnect") << 2 << 1; |
| QTest::newRow("connect-twice-disconnect-wildcard") << 2 << -1; |
| } |
| |
| void tst_QDBusAbstractInterface::connectDisconnect() |
| { |
| QFETCH(int, connectCount); |
| QFETCH(int, disconnectCount); |
| |
| Pinger p = getPinger(); |
| QVERIFY2(p, "Not connected to D-Bus"); |
| |
| // connect the exitLoop slot first |
| // if the disconnect() below does something weird, we'll get a timeout |
| QTestEventLoop::instance().connect(p.data(), SIGNAL(voidSignal()), SLOT(exitLoop())); |
| |
| SignalReceiver sr; |
| for (int i = 0; i < connectCount; ++i) |
| sr.connect(p.data(), SIGNAL(voidSignal()), SLOT(receive())); |
| if (disconnectCount) |
| QObject::disconnect(p.data(), disconnectCount > 0 ? SIGNAL(voidSignal()) : 0, &sr, SLOT(receive())); |
| |
| emit targetObj.voidSignal(); |
| QTestEventLoop::instance().enterLoop(2); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| |
| if (disconnectCount != 0) |
| QCOMPARE(sr.callCount, 0); |
| else |
| QCOMPARE(sr.callCount, connectCount); |
| } |
| |
| void tst_QDBusAbstractInterface::connectDisconnectPeer_data() |
| { |
| connectDisconnect_data(); |
| } |
| |
| void tst_QDBusAbstractInterface::connectDisconnectPeer() |
| { |
| QFETCH(int, connectCount); |
| QFETCH(int, disconnectCount); |
| |
| Pinger p = getPingerPeer(); |
| QVERIFY2(p, "Not connected to D-Bus"); |
| |
| // connect the exitLoop slot first |
| // if the disconnect() below does something weird, we'll get a timeout |
| QTestEventLoop::instance().connect(p.data(), SIGNAL(voidSignal()), SLOT(exitLoop())); |
| |
| SignalReceiver sr; |
| for (int i = 0; i < connectCount; ++i) |
| sr.connect(p.data(), SIGNAL(voidSignal()), SLOT(receive())); |
| if (disconnectCount) |
| QObject::disconnect(p.data(), disconnectCount > 0 ? SIGNAL(voidSignal()) : 0, &sr, SLOT(receive())); |
| |
| QDBusMessage req = QDBusMessage::createMethodCall(serviceName, objectPath, interfaceName, "voidSignal"); |
| QVERIFY(QDBusConnection::sessionBus().send(req)); |
| QTestEventLoop::instance().enterLoop(2); |
| QVERIFY(!QTestEventLoop::instance().timeout()); |
| |
| if (disconnectCount != 0) |
| QCOMPARE(sr.callCount, 0); |
| else |
| QCOMPARE(sr.callCount, connectCount); |
| } |
| |
| void tst_QDBusAbstractInterface::createErrors_data() |
| { |
| QTest::addColumn<QString>("service"); |
| QTest::addColumn<QString>("path"); |
| QTest::addColumn<QString>("errorName"); |
| |
| QTest::newRow("invalid-service") << "this isn't valid" << "/" << "org.qtproject.QtDBus.Error.InvalidService"; |
| QTest::newRow("invalid-path") << QDBusConnection::sessionBus().baseService() << "this isn't valid" |
| << "org.qtproject.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<QString>("path"); |
| QTest::addColumn<QString>("errorName"); |
| |
| QTest::newRow("invalid-path") << "this isn't valid" << "org.qtproject.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() << "/" << "org.qtproject.QtDBus.Error.InvalidService"; |
| QTest::newRow("path-wildcard") << QDBusConnection::sessionBus().baseService() << QString() |
| << "org.qtproject.QtDBus.Error.InvalidObjectPath"; |
| QTest::newRow("full-wildcard") << QString() << QString() << "org.qtproject.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<QString> 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<QString> 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() << "org.qtproject.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(); |
| } |
| |
| 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"); |
| } |
| |
| void tst_QDBusAbstractInterface::validity_data() |
| { |
| QTest::addColumn<QString>("service"); |
| |
| QTest::newRow("null-service") << ""; |
| QTest::newRow("ignored-service") << "org.example.anyservice"; |
| } |
| |
| void tst_QDBusAbstractInterface::validity() |
| { |
| /* Test case for QTBUG-32374 */ |
| QFETCH(QString, service); |
| Pinger p = getPingerPeer("/", service); |
| QVERIFY2(p, "Not connected to D-Bus"); |
| |
| QVERIFY(p->isValid()); |
| } |
| |
| QTEST_MAIN(tst_QDBusAbstractInterface) |
| #include "tst_qdbusabstractinterface.moc" |