qt5base-lts/tests/auto/dbus/qdbusabstractinterface/tst_qdbusabstractinterface.cpp
Rohan McGovern e88f9a92b7 Stabilize tst_qdbusabstractinterface and make it XFAIL
This test was written incorrectly in a way which happened to allow it to
pass most of the time (but not all the time).

Reset the state of test objects between each test function, and mark the
broken functions with QEXPECT_FAIL and a link to a task.

Replace the unusual WaitForPinger construct with the usual
QTRY_VERIFY/QTRY_COMPARE method of verifying asynchronous operations.

Task-number: QTBUG-24262
Change-Id: I82d09002307c0b500bf60cd5b583674321b37609
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2012-02-20 23:34:35 +01:00

1300 lines
39 KiB
C++

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