dbus/test/qt/tst_qdbusinterface.cpp
Thiago Macieira d54ababd5f * test/qt/*: Sync with KDE Subversion revision 523647.
Update the testcases to the new API. Remove testcases for
        classes that are no longer public or have been removed.
2006-03-28 18:58:58 +00:00

324 lines
9.4 KiB
C++

/* -*- C++ -*-
*
* Copyright (C) 2006 Trolltech AS. All rights reserved.
* Author: Thiago Macieira <thiago.macieira@trolltech.com>
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <qcoreapplication.h>
#include <qmetatype.h>
#include <QtTest/QtTest>
#include <dbus/qdbus.h>
#include <QtCore/qvariant.h>
#include "common.h"
Q_DECLARE_METATYPE(QVariantList)
#define TEST_INTERFACE_NAME "com.trolltech.QtDBus.MyObject"
#define TEST_SIGNAL_NAME "somethingHappened"
const char introspectionData[] =
"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
"<node>"
"<interface name=\"org.freedesktop.DBus.Introspectable\">"
"<method name=\"Introspect\">"
"<arg name=\"data\" direction=\"out\" type=\"s\"/>"
"</method>"
"</interface>"
"<interface name=\"" TEST_INTERFACE_NAME "\">"
"<method name=\"ping\">"
"<arg name=\"ping\" direction=\"in\" type=\"v\"/>"
"<arg name=\"pong\" direction=\"out\" type=\"v\"/>"
"</method>"
"<method name=\"ping\">"
"<arg name=\"ping1\" direction=\"in\" type=\"v\"/>"
"<arg name=\"ping2\" direction=\"in\" type=\"v\"/>"
"<arg name=\"pong1\" direction=\"out\" type=\"v\"/>"
"<arg name=\"pong2\" direction=\"out\" type=\"v\"/>"
"</method>"
"<signal name=\"" TEST_SIGNAL_NAME "\">"
"<arg type=\"s\"/>"
"</signal>"
"<property name=\"prop1\" access=\"readwrite\" type=\"i\" />"
"</interface>"
"<node name=\"subObject\"/>"
"</node>";
class IntrospectionAdaptor: public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.freedesktop.DBus.Introspectable")
public:
IntrospectionAdaptor(QObject *parent)
: QDBusAbstractAdaptor(parent)
{ }
public slots:
void Introspect(const QDBusMessage &msg)
{
QDBusMessage reply = QDBusMessage::methodReply(msg);
reply << ::introspectionData;
if (!msg.connection().send(reply))
exit(1);
}
};
class MyObject: public QObject
{
Q_OBJECT
public:
MyObject()
{
new IntrospectionAdaptor(this);
}
public slots:
void ping(const QDBusMessage &msg)
{
QDBusMessage reply = QDBusMessage::methodReply(msg);
reply << static_cast<QList<QVariant> >(msg);
if (!msg.connection().send(reply))
exit(1);
}
};
class Spy: public QObject
{
Q_OBJECT
public:
QString received;
int count;
Spy() : count(0)
{ }
public slots:
void spySlot(const QString& arg)
{
received = arg;
++count;
}
};
// helper function
void emitSignal(const QString &interface, const QString &name, const QString &arg)
{
QDBusMessage msg = QDBusMessage::signal("/", interface, name);
msg << arg;
QDBus::sessionBus().send(msg);
QTest::qWait(200);
}
class tst_QDBusInterface: public QObject
{
Q_OBJECT
MyObject obj;
private slots:
void initTestCase();
void call_data();
void call();
void introspect();
void signal();
};
void tst_QDBusInterface::initTestCase()
{
QDBusConnection &con = QDBus::sessionBus();
QVERIFY(con.isConnected());
con.registerObject("/", &obj, QDBusConnection::ExportAdaptors | QDBusConnection::ExportSlots);
}
void tst_QDBusInterface::call_data()
{
QTest::addColumn<QString>("method");
QTest::addColumn<QVariantList>("input");
QTest::addColumn<QVariantList>("output");
QVariantList input;
QTest::newRow("empty") << "ping" << input << input;
input << qVariantFromValue(1);
QTest::newRow("int") << "ping" << input << input;
QTest::newRow("int-int") << "ping.i" << input << input;
QTest::newRow("int-int16") << "ping.n" << input << (QVariantList() << qVariantFromValue(short(1)));
// try doing some conversions
QVariantList output;
output << qVariantFromValue(1U);
QTest::newRow("int-uint") << "ping.u" << input << output;
#if QT_VERSION >= 0x040200
output.clear();
output << qVariantFromValue(ushort(1));
QTest::newRow("int-uint16") << "ping.q" << input << output;
#endif
QTest::newRow("int-int64") << "ping.x" << input << (QVariantList() << qVariantFromValue(Q_INT64_C(1)));
QTest::newRow("int-uint64") << "ping.t" << input << (QVariantList() << qVariantFromValue(Q_UINT64_C(1)));
QTest::newRow("int-double") << "ping.d" << input << (QVariantList() << qVariantFromValue(1.0));
output.clear();
output << QString("1");
QTest::newRow("int-string") << "ping.s" << input << output;
// try from string now
input = output;
QTest::newRow("string") << "ping" << input << output;
QTest::newRow("string-string") << "ping.s" << input << output;
output.clear();
output << qVariantFromValue(1);
QTest::newRow("string-int") << "ping.i" << input << output;
#if QT_VERSION >= 0x040200
output.clear();
output << qVariantFromValue(short(1));
QTest::newRow("string-int16") << "ping.n" << input << input;
#endif
output.clear();
output << qVariantFromValue(1U);
QTest::newRow("string-uint") << "ping.u" << input << output;
#if QT_VERSION >= 0x040200
output.clear();
output << qVariantFromValue(ushort(1));
QTest::newRow("string-uint16") << "ping.q" << input << output;
#endif
QTest::newRow("string-int64") << "ping.x" << input << (QVariantList() << qVariantFromValue(1LL));
QTest::newRow("string-uint64") << "ping.t" << input << (QVariantList() << qVariantFromValue(1ULL));
QTest::newRow("string-double") << "ping.d" << input << (QVariantList() << qVariantFromValue(1.0));
// two args (must be strings!)
input.clear();
input << QString("Hello") << QString("World");
output = input;
QTest::newRow("two-strings") << "ping" << input << output;
QTest::newRow("two-strings") << "ping.ss" << input << output;
// this should drop one of the arguments
output.removeLast();
QTest::newRow("last-dropped") << "ping.s" << input << output;
}
void tst_QDBusInterface::call()
{
QDBusConnection &con = QDBus::sessionBus();
QDBusInterface *iface = con.findInterface(con.baseService(), QLatin1String("/"),
TEST_INTERFACE_NAME);
QFETCH(QString, method);
QFETCH(QVariantList, input);
QFETCH(QVariantList, output);
QDBusMessage reply;
// try first callWithArgs:
reply = iface->callWithArgs(method, input);
QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
if (!output.isEmpty()) {
QCOMPARE(reply.count(), output.count());
QVERIFY(compare(reply, output));
}
// try the template methods
if (input.isEmpty())
reply = iface->call(method);
else if (input.count() == 1)
switch (input.at(0).type())
{
case QVariant::Int:
reply = iface->call(method, input.at(0).toInt());
break;
case QVariant::UInt:
reply = iface->call(method, input.at(0).toUInt());
break;
case QVariant::String:
reply = iface->call(method, input.at(0).toString());
break;
default:
QFAIL("Unknown type. Please update the test case");
break;
}
else
reply = iface->call(method, input.at(0).toString(), input.at(1).toString());
QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
if (!output.isEmpty()) {
QCOMPARE(reply.count(), output.count());
QVERIFY(compare(reply, output));
}
}
void tst_QDBusInterface::introspect()
{
QDBusConnection &con = QDBus::sessionBus();
QDBusInterface *iface = con.findInterface(QDBus::sessionBus().baseService(), QLatin1String("/"),
TEST_INTERFACE_NAME);
const QMetaObject *mo = iface->metaObject();
qDebug("Improve to a better testcase of QDBusMetaObject");
QCOMPARE(mo->methodCount() - mo->methodOffset(), 3);
QVERIFY(mo->indexOfSignal(TEST_SIGNAL_NAME "(QString)") != -1);
QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 1);
QVERIFY(mo->indexOfProperty("prop1") != -1);
iface->deleteLater();
}
void tst_QDBusInterface::signal()
{
QDBusConnection &con = QDBus::sessionBus();
QDBusInterface *iface = con.findInterface(con.baseService(), QLatin1String("/"),
TEST_INTERFACE_NAME);
QString arg = "So long and thanks for all the fish";
{
Spy spy;
spy.connect(iface, SIGNAL(somethingHappened(QString)), SLOT(spySlot(QString)));
emitSignal(TEST_INTERFACE_NAME, TEST_SIGNAL_NAME, arg);
QCOMPARE(spy.count, 1);
QCOMPARE(spy.received, arg);
}
iface->deleteLater();
}
QTEST_MAIN(tst_QDBusInterface)
#include "tst_qdbusinterface.moc"