mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2024-11-23 20:10:48 +08:00
1395 lines
42 KiB
C++
1395 lines
42 KiB
C++
|
// Copyright (C) 2016 The Qt Company Ltd.
|
||
|
// Copyright (C) 2016 Intel Corporation.
|
||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||
|
|
||
|
#include <QTest>
|
||
|
#include <QTestEventLoop>
|
||
|
#include <QDebug>
|
||
|
#include <QCoreApplication>
|
||
|
#include <QSharedPointer>
|
||
|
#include <QSignalSpy>
|
||
|
#include <QProcess>
|
||
|
#include <QSemaphore>
|
||
|
#include <QDBusMetaType>
|
||
|
#include <QDBusConnectionInterface>
|
||
|
#include <QDBusInterface>
|
||
|
|
||
|
#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() override
|
||
|
{
|
||
|
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(QMetaType::QString));
|
||
|
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(QMetaType::QString));
|
||
|
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"
|