dbus/test/qt Makefile.am, 1.3, 1.4 tst_hal.cpp, NONE,
1.1 tst_qdbusconnection.cpp, 1.3, 1.4 tst_qdbusinterface.cpp,
NONE, 1.1 tst_qdbusobject.cpp, NONE, 1.1 tst_qdbustype.cpp,
NONE, 1.1 tst_qdbusxmlparser.cpp, NONE, 1.1
Thiago J. Macieira
thiago at freedesktop.org
Wed Feb 15 09:06:43 PST 2006
Update of /cvs/dbus/dbus/test/qt
In directory gabe:/tmp/cvs-serv27712
Modified Files:
Makefile.am tst_qdbusconnection.cpp
Added Files:
tst_hal.cpp tst_qdbusinterface.cpp tst_qdbusobject.cpp
tst_qdbustype.cpp tst_qdbusxmlparser.cpp
Log Message:
Add new tests and update the existing one.
Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/test/qt/Makefile.am,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Makefile.am 1 Dec 2005 00:07:20 -0000 1.3
+++ Makefile.am 15 Feb 2006 17:06:41 -0000 1.4
@@ -1,7 +1,7 @@
INCLUDES=-I$(top_srcdir) -I$(top_srcdir)/qt $(DBUS_CLIENT_CFLAGS) $(DBUS_QT_CFLAGS) $(DBUS_QTESTLIB_CFLAGS) -DDBUS_COMPILATION
if DBUS_BUILD_TESTS
-TEST_BINARIES=qdbusconnection
+TEST_BINARIES=qdbusconnection qdbusobject qdbusinterface qdbustype qdbusxmlparser hal
TESTS=
else
TEST_BINARIES=
@@ -11,16 +11,25 @@
noinst_PROGRAMS= $(TEST_BINARIES)
-qdbusconnection_SOURCES= \
- tst_qdbusconnection.cpp
+qdbusconnection_SOURCES= tst_qdbusconnection.cpp
+qdbusobject_SOURCES= tst_qdbusobject.cpp
+qdbusinterface_SOURCES= tst_qdbusinterface.cpp
+qdbustype_SOURCES= tst_qdbustype.cpp
+qdbusxmlparser_SOURCES= tst_qdbusxmlparser.cpp
+hal_SOURCES = tst_hal.cpp
-tst_qdbusconnection.cpp: tst_qdbusconnection.moc
+tst_qdbusconnection.o: tst_qdbusconnection.moc
+tst_qdbusobject.o: tst_qdbusobject.moc
+tst_qdbusinterface.o: tst_qdbusinterface.moc
+tst_qdbustype.o: tst_qdbustype.moc
+tst_qdbusxmlparser.o: tst_qdbusxmlparser.moc
+tst_hal.o: tst_hal.moc
-tst_qdbusconnection.moc:
- $(QT_MOC) $(srcdir)/tst_qdbusconnection.cpp > tst_qdbusconnection.moc
+%.moc: %.cpp
+ $(QT_MOC) $< > $@
TEST_LIBS=$(DBUS_QTESTLIB_LIBS) $(top_builddir)/qt/libdbus-qt4-1.la
-qdbusconnection_LDADD=$(TEST_LIBS)
+LDADD=$(TEST_LIBS)
CLEANFILES=tst_qdbusconnection.moc
--- NEW FILE: tst_hal.cpp ---
#include <qcoreapplication.h>
#include <qdebug.h>
#include <QtTest/QtTest>
#include <dbus/qdbus.h>
class tst_Hal: public QObject
{
Q_OBJECT
private slots:
void getDevices();
void lock();
};
class Spy: public QObject
{
Q_OBJECT
public:
int count;
QDBusConnection conn;
Spy(QDBusConnection c) : count(0), conn(c)
{ }
public slots:
void spySlot(int, const QVariantList&)
{
++count;
QDBusMessage msg = QDBusMessage::methodCall("org.freedesktop.Hal",
"/org/freedesktop/Hal/devices/acpi_CPU0",
"org.freedesktop.Hal.Device", "GetProperty");
msg << "info.locked";
QDBusMessage reply = conn.sendWithReply(msg);
QVERIFY(!reply.isEmpty());
}
};
void tst_Hal::getDevices()
{
QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::SystemBus);
QVERIFY(con.isConnected());
QDBusMessage msg = QDBusMessage::methodCall("org.freedesktop.Hal",
"/org/freedesktop/Hal/Manager", "org.freedesktop.Hal.Manager",
"GetAllDevices");
QDBusMessage reply = con.sendWithReply(msg);
QVERIFY(!reply.isEmpty());
qDebug() << reply;
}
void tst_Hal::lock()
{
QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::SystemBus);
QVERIFY(con.isConnected());
Spy spy( con );
con.connect("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/acpi_CPU0",
"org.freedesktop.Hal.Device", "PropertyModified",
&spy, SLOT(spySlot(int, QVariantList)));
QDBusMessage msg = QDBusMessage::methodCall("org.freedesktop.Hal",
"/org/freedesktop/Hal/devices/acpi_CPU0", "org.freedesktop.Hal.Device",
"Lock");
msg << "No reason...";
QDBusMessage reply = con.sendWithReply(msg);
qDebug() << reply;
QCOMPARE(spy.count, 3);
QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
}
QTEST_MAIN(tst_Hal)
#include "tst_hal.moc"
Index: tst_qdbusconnection.cpp
===================================================================
RCS file: /cvs/dbus/dbus/test/qt/tst_qdbusconnection.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- tst_qdbusconnection.cpp 22 Jan 2006 19:42:18 -0000 1.3
+++ tst_qdbusconnection.cpp 15 Feb 2006 17:06:41 -0000 1.4
@@ -10,11 +10,19 @@
Q_OBJECT
private slots:
+ void init();
+ void cleanupTestCase();
void addConnection();
void connect();
void send();
void sendAsync();
void sendSignal();
+ void requestName_data();
+ void requestName();
+ void getNameOwner_data();
+ void getNameOwner();
+ void releaseName_data();
+ void releaseName();
};
class QDBusSpy: public QObject
@@ -29,10 +37,25 @@
int serial;
};
+void tst_QDBusConnection::init()
+{
+ if (qstrcmp(QTest::currentTestFunction(), "addConnection") == 0)
+ return;
+
+ QDBusConnection::addConnection(QDBusConnection::SessionBus);
+ QVERIFY(QDBusConnection().isConnected());
+}
+
+void tst_QDBusConnection::cleanupTestCase()
+{
+ QDBusConnection::closeConnection();
+
+ QVERIFY(!QDBusConnection().isConnected());
+}
+
void tst_QDBusConnection::sendSignal()
{
- QDBusConnection con = QDBusConnection::addConnection(
- QDBusConnection::SessionBus);
+ QDBusConnection con;
QVERIFY(con.isConnected());
@@ -47,8 +70,7 @@
void tst_QDBusConnection::send()
{
- QDBusConnection con = QDBusConnection::addConnection(
- QDBusConnection::SessionBus);
+ QDBusConnection con;
QVERIFY(con.isConnected());
@@ -64,7 +86,7 @@
void tst_QDBusConnection::sendAsync()
{
- QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::SessionBus);
+ QDBusConnection con;
QVERIFY(con.isConnected());
QDBusSpy spy;
@@ -85,10 +107,9 @@
{
QDBusSpy spy;
- QDBusConnection con = QDBusConnection::addConnection(
- QDBusConnection::SessionBus);
+ QDBusConnection con;
- con.connect("/org/kde/selftest", "org.kde.selftest", "ping", &spy,
+ con.connect(con.baseService(), "/org/kde/selftest", "org.kde.selftest", "ping", &spy,
SLOT(handlePing(QString)));
QDBusMessage msg = QDBusMessage::signal("/org/kde/selftest", "org.kde.selftest",
@@ -158,6 +179,89 @@
}
}
+void tst_QDBusConnection::requestName_data()
+{
+ QTest::addColumn<QString>("requestedName");
+ QTest::addColumn<int>("flags");
+ QTest::addColumn<bool>("expectedResult");
+
+ QTest::newRow("null") << QString() << (int)QDBusConnection::NoReplace << false;
+ QTest::newRow("empty") << QString("") << (int)QDBusConnection::NoReplace << false;
+ QTest::newRow("invalid") << "./invalid name" << (int)QDBusConnection::NoReplace << false;
+// QTest::newRow("existing") << "org.freedesktop.DBus"
+// << (int)QDBusConnection::NoReplace << false;
+
+ QTest::newRow("ok1") << "com.trolltech.QtDBUS.tst_qdbusconnection"
+ << (int)QDBusConnection::NoReplace << true;
+}
+
+void tst_QDBusConnection::requestName()
+{
+ QDBusConnection con;
+
+ QVERIFY(con.isConnected());
+
+ QFETCH(QString, requestedName);
+ QFETCH(int, flags);
+ QFETCH(bool, expectedResult);
+
+ bool result = con.requestName(requestedName, (QDBusConnection::NameRequestMode)flags);
+
+// QEXPECT_FAIL("existing", "For whatever reason, the bus lets us replace this name", Abort);
+ QCOMPARE(result, expectedResult);
+}
+
+void tst_QDBusConnection::getNameOwner_data()
+{
+ QTest::addColumn<QString>("name");
+ QTest::addColumn<QString>("expectedResult");
+
+ QTest::newRow("null") << QString() << QString();
+ QTest::newRow("empty") << QString("") << QString();
+
+ QTest::newRow("invalid") << ".invalid" << QString();
+ QTest::newRow("non-existent") << "com.trolltech.QtDBUS.foo" << QString();
+
+ QTest::newRow("bus") << "org.freedesktop.DBus" << "org.freedesktop.DBus";
+
+ QString base = QDBusConnection().baseService();
+ QTest::newRow("address") << base << base;
+ QTest::newRow("self") << "com.trolltech.QtDBUS.tst_qdbusconnection" << base;
+}
+
+void tst_QDBusConnection::getNameOwner()
+{
+ QFETCH(QString, name);
+ QFETCH(QString, expectedResult);
+
+ QDBusConnection con;
+ QVERIFY(con.isConnected());
+
+ QString result = con.getNameOwner(name);
+
+ QCOMPARE(result, expectedResult);
+}
+
+void tst_QDBusConnection::releaseName_data()
+{
+ requestName_data();
+}
+
+void tst_QDBusConnection::releaseName()
+{
+ QDBusConnection con;
+
+ QVERIFY(con.isConnected());
+
+ QFETCH(QString, requestedName);
+ //QFETCH(int, flags);
+ QFETCH(bool, expectedResult);
+
+ bool result = con.releaseName(requestedName);
+
+ QCOMPARE(result, expectedResult);
+}
+
QTEST_MAIN(tst_QDBusConnection)
#include "tst_qdbusconnection.moc"
--- NEW FILE: tst_qdbusinterface.cpp ---
/* -*- C++ -*-
*
* Copyright (C) 2006 Trolltech AS. All rights reserved.
* Author: Thiago Macieira <thiago.macieira at 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>
Q_DECLARE_METATYPE(QVariantList)
#define TEST_INTERFACE_NAME "com.trolltech.QtDBus.MyObject"
#define TEST_SERVICE_NAME "com.trolltech.QtDBus.tst_qdbusinterface"
#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 MyObject: public QObject
{
Q_OBJECT
public slots:
void ping(const QDBusMessage &msg)
{
QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::SessionBus);
QDBusMessage reply = QDBusMessage::methodReply(msg);
reply << static_cast<QList<QVariant> >(msg);
if (!con.send(reply))
exit(1);
}
void Introspect(const QDBusMessage &msg)
{
QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::SessionBus);
QDBusMessage reply = QDBusMessage::methodReply(msg);
reply << ::introspectionData;
if (!con.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;
QDBusConnection().send(msg);
QTest::qWait(200);
}
class tst_QDBusInterface: public QObject
{
Q_OBJECT
MyObject obj;
private slots:
void initTestCase();
void cleanupTestCase();
void call_data();
void call();
void introspect_data();
void introspect();
void signal();
};
void tst_QDBusInterface::initTestCase()
{
QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::SessionBus);
QVERIFY(con.isConnected());
QVERIFY(con.requestName( TEST_SERVICE_NAME ));
con.registerObject("/", "org.freedesktop.DBus.Introspectable", &obj);
con.registerObject("/", TEST_INTERFACE_NAME, &obj);
}
void tst_QDBusInterface::cleanupTestCase()
{
QDBusConnection::closeConnection();
QVERIFY(!QDBusConnection().isConnected());
}
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 << input;
// try doing some conversions
QVariantList output;
output << qVariantFromValue(1U);
QTest::newRow("int-uint") << "ping.u" << input << output;
QTest::newRow("int-uint16") << "ping.q" << input << output;
QTest::newRow("int-int64") << "ping.x" << input << (QVariantList() << qVariantFromValue(1LL));
QTest::newRow("int-uint64") << "ping.t" << input << (QVariantList() << qVariantFromValue(1ULL));
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 << input;
QTest::newRow("string-int16") << "ping.n" << input << input;
output.clear();
output << qVariantFromValue(1U);
QTest::newRow("string-uint") << "ping.u" << input << output;
QTest::newRow("string-uint16") << "ping.q" << input << output;
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;
QDBusInterface iface(con, 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());
QCOMPARE(static_cast<QVariantList>(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());
QCOMPARE(static_cast<QVariantList>(reply), output);
}
}
void tst_QDBusInterface::introspect_data()
{
QTest::addColumn<QString>("service");
QTest::newRow("base") << QDBusConnection().baseService();
QTest::newRow("name") << TEST_SERVICE_NAME;
}
void tst_QDBusInterface::introspect()
{
QFETCH(QString, service);
QDBusConnection con;
QDBusInterface iface(con, service, QLatin1String("/"),
TEST_INTERFACE_NAME);
QDBusIntrospection::Methods mm = iface.methodData();
QVERIFY(mm.count() == 2);
QDBusIntrospection::Signals sm = iface.signalData();
QVERIFY(sm.count() == 1);
QVERIFY(sm.contains(TEST_SIGNAL_NAME));
QDBusIntrospection::Properties pm = iface.propertyData();
QVERIFY(pm.count() == 1);
QVERIFY(pm.contains("prop1"));
}
void tst_QDBusInterface::signal()
{
QDBusConnection con;
QDBusInterface iface(con, con.baseService(), QLatin1String("/"),
TEST_INTERFACE_NAME);
QString signalName = TEST_SIGNAL_NAME;
QString arg = "So long and thanks for all the fish";
{
Spy spy;
iface.connect(signalName, &spy, SLOT(spySlot(QString)));
emitSignal(TEST_INTERFACE_NAME, signalName, arg);
QVERIFY(spy.count == 1);
QCOMPARE(spy.received, arg);
}
QDBusIntrospection::Signals sm = iface.signalData();
QVERIFY(sm.contains(signalName));
const QDBusIntrospection::Signal& signal = sm.value(signalName);
QCOMPARE(signal.name, signalName);
QVERIFY(!signal.outputArgs.isEmpty());
{
Spy spy;
iface.connect(signal, &spy, SLOT(spySlot(QString)));
emitSignal(TEST_INTERFACE_NAME, signalName, arg);
QVERIFY(spy.count == 1);
QCOMPARE(spy.received, arg);
}
}
QTEST_MAIN(tst_QDBusInterface)
#include "tst_qdbusinterface.moc"
--- NEW FILE: tst_qdbusobject.cpp ---
/* -*- C++ -*-
*
* Copyright (C) 2006 Trolltech AS. All rights reserved.
* Author: Thiago Macieira <thiago.macieira at 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>
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=\"com.trolltech.tst_qdbusobject.MyObject\">"
"<method name=\"ping\">"
"<arg name=\"ping\" direction=\"in\" type=\"v\"/>"
"<arg name=\"pong\" direction=\"out\" type=\"v\"/>"
"</method>"
"</interface>"
"<node name=\"subObject\"/>"
"</node>";
class MyObject: public QObject
{
Q_OBJECT
public slots:
void ping(const QDBusMessage &msg)
{
QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::SessionBus);
QDBusMessage reply = QDBusMessage::methodReply(msg);
reply << static_cast<QList<QVariant> >(msg);
if (!con.send(reply))
exit(1);
}
void Introspect(const QDBusMessage &msg)
{
QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::SessionBus);
QDBusMessage reply = QDBusMessage::methodReply(msg);
reply << ::introspectionData;
if (!con.send(reply))
exit(1);
}
};
class tst_QDBusObject: public QObject
{
Q_OBJECT
MyObject obj;
private slots:
void initTestCase(); // connect to D-Bus
void cleanupTestCase(); // disconnect from D-Bus
void construction_data();
void construction();
void introspection_data();
void introspection();
};
void tst_QDBusObject::initTestCase()
{
QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::SessionBus);
QVERIFY(con.isConnected());
QVERIFY(con.requestName("com.trolltech.tst_qdbusobject"));
con.registerObject("/", "org.freedesktop.DBus.Introspectable", &obj);
con.registerObject("/", "com.trolltech.tst_qdbusobject.MyObject", &obj);
}
void tst_QDBusObject::cleanupTestCase()
{
QDBusConnection::closeConnection();
QVERIFY(!QDBusConnection().isConnected());
}
void tst_QDBusObject::construction_data()
{
QTest::addColumn<QString>("service");
QTest::addColumn<QString>("path");
QTest::addColumn<bool>("isValid");
QTest::addColumn<bool>("exists");
QTest::newRow("null") << QString() << QString() << false << false;
QTest::newRow("invalid1") << "foo.foo1" << "" << false << false;
QTest::newRow("invalid2") << "foo.foo1" << "foo.bar" << false << false;
QTest::newRow("invalid3") << "foo.foo1" << "/foo.bar" << false << false;
QTest::newRow("invalid4") << "" << "/" << false << false;
QTest::newRow("invalid5") << "foo" << "/" << false << false;
QTest::newRow("invalid6") << ".foo" << "/" << false << false;
QTest::newRow("invalid7") << "org.freedesktop.DBus" << "" << false << false;
QTest::newRow("invalid8") << "org.freedesktop.DBus" << "foo.bar" << false << false;
QTest::newRow("invalid9") << "org.freedesktop.DBus" << "/foo.bar" << false << false;
QTest::newRow("existing") << "org.freedesktop.DBus" << "/" << true << true;
QTest::newRow("non-existing") << "org.freedesktop.DBus" << "/foo" << true << false;
}
void tst_QDBusObject::construction()
{
QDBusConnection con; // default
QFETCH(QString, service);
QFETCH(QString, path);
QFETCH(bool, isValid);
//QFETCH(bool, exists);
QDBusObject o(con, service, path);
QCOMPARE(o.isValid(), isValid);
if (isValid) {
QCOMPARE(o.service(), service);
QCOMPARE(o.path(), path);
}
else {
QVERIFY(o.service().isNull());
QVERIFY(o.path().isNull());
}
//QCOMPARE(o.exists(), exists);
}
void tst_QDBusObject::introspection_data()
{
QTest::addColumn<QString>("service");
QTest::addColumn<QString>("path");
QTest::addColumn<QStringList>("interfaces");
QStringList interfaces;
QTest::newRow("nowhere") << QString() << QString() << interfaces;
// IMPORTANT!
// Keep the interface list sorted!
interfaces << "org.freedesktop.DBus" << DBUS_INTERFACE_INTROSPECTABLE;
QTest::newRow("server") << "org.freedesktop.DBus" << "/" << interfaces;
QDBusConnection con;
interfaces.clear();
interfaces << "com.trolltech.tst_qdbusobject.MyObject" << DBUS_INTERFACE_INTROSPECTABLE;
QTest::newRow("self1") << con.baseService() << "/" << interfaces;
QTest::newRow("self2") << "com.trolltech.tst_qdbusobject" << "/" << interfaces;
}
void tst_QDBusObject::introspection()
{
QDBusConnection con;
QFETCH(QString, service);
QFETCH(QString, path);
QDBusObject o(con, service, path);
if (!o.isValid())
QVERIFY(o.introspect().isEmpty());
else {
QFETCH(QStringList, interfaces);
QStringList parsed = o.interfaces();
parsed.sort();
QCOMPARE(parsed.count(), interfaces.count());
QCOMPARE(parsed, interfaces);
}
}
QTEST_MAIN(tst_QDBusObject)
#include "tst_qdbusobject.moc"
--- NEW FILE: tst_qdbustype.cpp ---
/* -*- C++ -*-
*
* Copyright (C) 2006 Trolltech AS. All rights reserved.
* Author: Thiago Macieira <thiago.macieira at 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 <QtTest/QtTest>
#include <dbus/qdbus.h>
class tst_QDBusType: public QObject
{
Q_OBJECT
private slots:
void fromType_data();
void fromType();
void fromSignature_data();
void fromSignature();
void arrayOf_data();
void arrayOf();
void mapOf_data();
void mapOf();
};
inline QTestData &operator<<(QTestData &data, QVariant::Type t)
{
return data << int(t);
}
void tst_QDBusType::fromType_data()
{
fromSignature_data();
}
void tst_QDBusType:: arrayOf_data()
{
fromSignature_data();
}
void tst_QDBusType::mapOf_data()
{
fromSignature_data();
}
void tst_QDBusType::fromSignature_data()
{
QTest::addColumn<QString>("signature");
QTest::addColumn<char>("type");
QTest::addColumn<int>("qvariantType");
QTest::addColumn<bool>("isValid");
QTest::addColumn<bool>("isBasic");
QTest::addColumn<bool>("isContainer");
QTest::addColumn<int>("subtypeCount");
QTest::newRow("null") << QString() << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("empty") << QString("") << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("invalid") << QString("~") << '\0' << QVariant::Invalid << false << false << false << 0;
// integers:
QTest::newRow("byte") << "y" << 'y' << QVariant::UInt << true << true << false << 0;
QTest::newRow("boolean") << "b" << 'b' << QVariant::Bool << true << true << false << 0;
QTest::newRow("int16") << "n" << 'n' << QVariant::Int << true << true << false << 0;
QTest::newRow("uint16") << "q" << 'q' << QVariant::UInt << true << true << false << 0;
QTest::newRow("int32") << "i" << 'i' << QVariant::Int << true << true << false << 0;
QTest::newRow("uint32") << "u" << 'u' << QVariant::UInt << true << true << false << 0;
QTest::newRow("int64") << "x" << 'x' << QVariant::LongLong << true << true << false << 0;
QTest::newRow("uint64") << "t" << 't' << QVariant::ULongLong << true << true << false << 0;
// double:
QTest::newRow("double") << "d" << 'd' << QVariant::Double << true << true << false << 0;
// string types:
QTest::newRow("string") << "s" << 's' << QVariant::String << true << true << false << 0;
QTest::newRow("objpath") << "o" << 'o' << QVariant::String << true << true << false << 0;
QTest::newRow("signature")<<"g" << 'g' << QVariant::String << true << true << false << 0;
// variant
QTest::newRow("variant") << "v" << 'v' << QVariant::UserType << true << false << true << 0;
// compound types:
QTest::newRow("struct-empty") << "()" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("struct-invalid") << "(~)" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("struct-unterminated")<< "(iii" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("struct-bad-nest") << "(i(i)((i)i)" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("struct1") << "(i)" << 'r' << QVariant::List << true << false << true << 1;
QTest::newRow("struct2") << "(ii)" << 'r' << QVariant::List << true << false << true << 2;
QTest::newRow("array-empty") << "a" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("array-invalid") << "a~" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("array-simple") << "ab" << 'a' << QVariant::List << true << false << true << 1;
QTest::newRow("bytearray") << "ay" << 'a' << QVariant::ByteArray << true << false << true << 1;
QTest::newRow("stringlist") << "as" << 'a' << QVariant::StringList << true << false << true << 1;
QTest::newRow("map-empty") << "e" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("map-invalid1") << "a{}" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("map-invalid2") << "a{~}" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("map-invalid3") << "a{e}" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("map-invalid4") << "a{i}" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("map-invalid5") << "a{(i)d}" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("map-invalid6") << "{}" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("map-invalid7") << "{i}" << '\0' << QVariant::Invalid << false << false << false << 0;
//QTest::newRow("map-invalid8") << "{is}" << '\0' << QVariant::Invalid << false << false << false << 0; // this is valid when "a" is prepended
QTest::newRow("map-bad-nesting") << "a{i(s}" << '\0' << QVariant::Invalid << false << false << false << 0;
QTest::newRow("map-ok1") << "a{is}" << 'a' << QVariant::Map << true << false << true << 1;
QTest::newRow("map-ok2") << "a{sv}" << 'a' << QVariant::Map << true << false << true << 1;
// compound of compounds:
QTest::newRow("struct-struct") << "((i))" << 'r' << QVariant::List << true << false << true << 1;
QTest::newRow("struct-structs") << "((ii)d(i))" << 'r' << QVariant::List << true << false << true << 3;
QTest::newRow("map-struct") << "a{s(ii)}" << 'a' << QVariant::Map << true << false << true << 1;
QTest::newRow("map-stringlist") << "a{sas}" << 'a' << QVariant::Map << true << false << true << 1;
QTest::newRow("map-map") << "a{ia{sv}}" << 'a' << QVariant::Map << true << false << true << 1;
QTest::newRow("array-struct") << "a(ii)" << 'a' << QVariant::List << true << false << true << 1;
QTest::newRow("array-array") << "aai" << 'a' << QVariant::List << true << false << true << 1;
QTest::newRow("array-map") << "aa{sv}" << 'a' << QVariant::List << true << false << true << 1;
}
void tst_QDBusType::fromType()
{
QFETCH(QString, signature);
if (signature.length() != 1)
// can't transform to typecode
return;
QFETCH(char, type);
QFETCH(int, qvariantType);
QFETCH(bool, isValid);
QFETCH(bool, isBasic);
QFETCH(bool, isContainer);
QDBusType t(signature.at(0).toLatin1());
QCOMPARE((char)t.dbusType(), type);
QCOMPARE(t.qvariantType(), QVariant::Type(qvariantType));
QCOMPARE(t.isValid(), isValid);
QCOMPARE(t.isBasic(), isBasic);
QCOMPARE(t.isContainer(), isContainer);
}
void tst_QDBusType::fromSignature()
{
QFETCH(QString, signature);
QFETCH(char, type);
QFETCH(int, qvariantType);
QFETCH(bool, isValid);
QFETCH(bool, isBasic);
QFETCH(bool, isContainer);
QFETCH(int, subtypeCount);
QDBusType t(signature);
QCOMPARE((char)t.dbusType(), type);
QCOMPARE(t.qvariantType(), QVariant::Type(qvariantType));
QCOMPARE(t.isValid(), isValid);
QCOMPARE(t.isBasic(), isBasic);
QCOMPARE(t.isContainer(), isContainer);
if (isValid)
QCOMPARE(QLatin1String(t.dbusSignature()), signature);
QCOMPARE(t.subTypes().count(), subtypeCount);
}
void tst_QDBusType::arrayOf()
{
QFETCH(QString, signature);
QFETCH(char, type);
QFETCH(int, qvariantType);
QFETCH(bool, isValid);
QFETCH(bool, isBasic);
QFETCH(bool, isContainer);
QFETCH(int, subtypeCount);
QDBusType arr("a" + signature.toLatin1());
QCOMPARE(arr.isValid(), isValid);
QVERIFY(!arr.isBasic());
if (isValid) {
QVERIFY(arr.isContainer());
QVERIFY(arr.isArray());
QCOMPARE((char)arr.dbusType(), 'a');
QCOMPARE(arr.subTypes().count(), 1);
// handle special cases:
if (type == 'y')
QCOMPARE(arr.qvariantType(), QVariant::ByteArray);
else if (type == 's' || type == 'o' || type == 'g')
QCOMPARE(arr.qvariantType(), QVariant::StringList);
else
QCOMPARE(arr.qvariantType(), QVariant::List);
// handle the array element now:
QDBusType t = arr.arrayElement();
QCOMPARE((char)t.dbusType(), type);
QCOMPARE(t.qvariantType(), QVariant::Type(qvariantType));
QCOMPARE(t.isValid(), isValid);
QCOMPARE(t.isBasic(), isBasic);
QCOMPARE(t.isContainer(), isContainer);
QCOMPARE(QLatin1String(t.dbusSignature()), signature);
QCOMPARE(t.subTypes().count(), subtypeCount);
}
}
void tst_QDBusType::mapOf()
{
QFETCH(QString, signature);
QFETCH(char, type);
QFETCH(int, qvariantType);
QFETCH(bool, isValid);
QFETCH(bool, isBasic);
QFETCH(bool, isContainer);
QFETCH(int, subtypeCount);
QDBusType map("a{s" + signature.toLatin1() + '}');
QCOMPARE(map.isValid(), isValid);
QVERIFY(!map.isBasic());
if (isValid) {
QVERIFY(map.isContainer());
QVERIFY(map.isArray());
QVERIFY(map.isMap());
QCOMPARE((char)map.dbusType(), 'a');
QCOMPARE(map.subTypes().count(), 1);
// handle the array element now:
QDBusType dict_entry = map.arrayElement();
QVERIFY(dict_entry.isValid());
QVERIFY(dict_entry.isContainer());
QVERIFY(!dict_entry.isMap());
QVERIFY(!dict_entry.isArray());
QVERIFY(map.mapKey().isBasic());
// handle the value:
QDBusType t = map.mapValue();
QCOMPARE((char)t.dbusType(), type);
QCOMPARE(t.qvariantType(), QVariant::Type(qvariantType));
QCOMPARE(t.isValid(), isValid);
QCOMPARE(t.isBasic(), isBasic);
QCOMPARE(t.isContainer(), isContainer);
QCOMPARE(QLatin1String(t.dbusSignature()), signature);
QCOMPARE(t.subTypes().count(), subtypeCount);
}
}
QTEST_MAIN(tst_QDBusType)
#include "tst_qdbustype.moc"
--- NEW FILE: tst_qdbusxmlparser.cpp ---
/* -*- C++ -*-
*
* Copyright (C) 2006 Trolltech AS. All rights reserved.
* Author: Thiago Macieira <thiago.macieira at 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>
class tst_QDBusXmlParser: public QObject
{
Q_OBJECT
private:
void parsing_common(const QString&);
private slots:
void parsing_data();
void parsing();
void parsingWithDoctype_data();
void parsingWithDoctype();
void objectWithContent_data();
void objectWithContent();
void methods_data();
void methods();
void signals__data();
void signals_();
void properties_data();
void properties();
};
// just to make it easier:
typedef QDBusIntrospection::Interfaces InterfaceMap;
typedef QDBusIntrospection::Objects ObjectMap;
typedef QDBusIntrospection::Arguments ArgumentList;
typedef QDBusIntrospection::Annotations AnnotationsMap;
typedef QDBusIntrospection::Methods MethodMap;
typedef QDBusIntrospection::Signals SignalMap;
typedef QDBusIntrospection::Properties PropertyMap;
Q_DECLARE_METATYPE(QDBusIntrospection::Method)
Q_DECLARE_METATYPE(QDBusIntrospection::Signal)
Q_DECLARE_METATYPE(QDBusIntrospection::Property)
Q_DECLARE_METATYPE(MethodMap)
Q_DECLARE_METATYPE(SignalMap)
Q_DECLARE_METATYPE(PropertyMap)
inline QDBusIntrospection::Argument arg(const char* type, const char *name = 0)
{
QDBusIntrospection::Argument retval;
retval.type = QDBusType(type);
retval.name = QLatin1String(name);
return retval;
}
template<typename T>
inline QMap<QString, T>& operator<<(QMap<QString, T>& map, const T& m)
{ map.insert(m.name, m); return map; }
inline const char* mapName(const MethodMap&)
{ return "MethodMap"; }
inline const char* mapName(const SignalMap&)
{ return "SignalMap"; }
inline const char* mapName(const PropertyMap&)
{ return "PropertyMap"; }
QString printable(const QDBusIntrospection::Method& m)
{
QString result = m.name + "(";
foreach (QDBusIntrospection::Argument arg, m.inputArgs)
result += QString("in %1 %2, ")
.arg(arg.type.toString(QDBusType::ConventionalNames))
.arg(arg.name);
foreach (QDBusIntrospection::Argument arg, m.outputArgs)
result += QString("out %1 %2, ")
.arg(arg.type.toString(QDBusType::ConventionalNames))
.arg(arg.name);
AnnotationsMap::const_iterator it = m.annotations.begin();
for ( ; it != m.annotations.end(); ++it)
result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value());
if (result.length() > 1)
result.truncate(result.length() - 2);
result += ")";
return result;
}
QString printable(const QDBusIntrospection::Signal& s)
{
QString result = s.name + "(";
foreach (QDBusIntrospection::Argument arg, s.outputArgs)
result += QString("out %1 %2, ")
.arg(arg.type.toString(QDBusType::ConventionalNames))
.arg(arg.name);
AnnotationsMap::const_iterator it = s.annotations.begin();
for ( ; it != s.annotations.end(); ++it)
result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value());
if (result.length() > 1)
result.truncate(result.length() - 2);
result += ")";
return result;
}
QString printable(const QDBusIntrospection::Property& p)
{
QString result;
if (p.access == QDBusIntrospection::Property::Read)
result = "read %1 %2, ";
else if (p.access == QDBusIntrospection::Property::Write)
result = "write %1 %2, ";
else
result = "readwrite %1 %2, ";
result = result.arg(p.type.toString(QDBusType::ConventionalNames)).arg(p.name);
AnnotationsMap::const_iterator it = p.annotations.begin();
for ( ; it != p.annotations.end(); ++it)
result += QString("%1 \"%2\", ").arg(it.key()).arg(it.value());
if (result.length() > 1)
result.truncate(result.length() - 2);
return result;
}
template<typename T>
char* printableMap(const QMap<QString, T>& map)
{
QString contents = "\n";
typename QMap<QString, T>::const_iterator it = map.begin();
for ( ; it != map.end(); ++it) {
if (it.key() != it.value().name)
contents += it.value().name + ":";
contents += printable(it.value());
contents += ";\n";
}
QString result("%1(size = %2): {%3}");
return qstrdup(qPrintable(result
.arg(mapName(map))
.arg(map.size())
.arg(contents)));
}
namespace QTest {
template<>
inline char* toString(const MethodMap& map)
{
return printableMap(map);
}
template<>
inline char* toString(const SignalMap& map)
{
return printableMap(map);
}
template<>
inline char* toString(const PropertyMap& map)
{
return printableMap(map);
}
}
void tst_QDBusXmlParser::parsing_data()
{
QTest::addColumn<QString>("xmlData");
QTest::addColumn<int>("interfaceCount");
QTest::addColumn<int>("objectCount");
QTest::newRow("null") << QString() << 0 << 0;
QTest::newRow("empty") << QString("") << 0 << 0;
QTest::newRow("junk") << "<junk/>" << 0 << 0;
QTest::newRow("interface-inside-junk") << "<junk><interface name=\"iface.iface1\" /></junk>"
<< 0 << 0;
QTest::newRow("object-inside-junk") << "<junk><node name=\"obj1\" /></junk>"
<< 0 << 0;
QTest::newRow("zero-interfaces") << "<node/>" << 0 << 0;
QTest::newRow("one-interface") << "<node><interface name=\"iface.iface1\" /></node>" << 1 << 0;
QTest::newRow("two-interfaces") << "<node><interface name=\"iface.iface1\" />"
"<interface name=\"iface.iface2\"></node>"
<< 2 << 0;
QTest::newRow("one-object") << "<node><node name=\"obj1\"/></node>" << 0 << 1;
QTest::newRow("two-objects") << "<node><node name=\"obj1\"/><node name=\"obj2\"></node>" << 0 << 2;
QTest::newRow("i1o1") << "<node><interface name=\"iface.iface1\"><node name=\"obj1\"></node>" << 1 << 1;
}
void tst_QDBusXmlParser::parsing_common(const QString &xmlData)
{
QDBusIntrospection::ObjectTree obj =
QDBusIntrospection::parseObjectTree(xmlData, "local.testing", "/");
QFETCH(int, interfaceCount);
QFETCH(int, objectCount);
QCOMPARE(obj.interfaces.count(), interfaceCount);
QCOMPARE(obj.childObjects.count(), objectCount);
// also verify the naming
int i = 0;
foreach (QString name, obj.interfaces)
QCOMPARE(name, QString("iface.iface%1").arg(++i));
i = 0;
foreach (QString name, obj.childObjects)
QCOMPARE(name, QString("obj%1").arg(++i));
}
void tst_QDBusXmlParser::parsing()
{
QFETCH(QString, xmlData);
parsing_common(xmlData);
}
void tst_QDBusXmlParser::parsingWithDoctype_data()
{
parsing_data();
}
void tst_QDBusXmlParser::parsingWithDoctype()
{
QString docType = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
"\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n";
QFETCH(QString, xmlData);
parsing_common(docType + xmlData);
}
void tst_QDBusXmlParser::objectWithContent_data()
{
QTest::addColumn<QString>("xmlData");
QTest::addColumn<QString>("probedObject");
QTest::addColumn<int>("interfaceCount");
QTest::addColumn<int>("objectCount");
QTest::newRow("zero") << "<node><node name=\"obj\"/></node>" << "obj" << 0 << 0;
QString xmlData = "<node><node name=\"obj\">"
"<interface name=\"iface.iface1\" />"
"</node></node>";
QTest::newRow("one-interface") << xmlData << "obj" << 1 << 0;
QTest::newRow("one-interface2") << xmlData << "obj2" << 0 << 0;
xmlData = "<node><node name=\"obj\">"
"<interface name=\"iface.iface1\" />"
"<interface name=\"iface.iface2\" />"
"</node></node>";
QTest::newRow("two-interfaces") << xmlData << "obj" << 2 << 0;
QTest::newRow("two-interfaces2") << xmlData << "obj2" << 0 << 0;
xmlData = "<node><node name=\"obj\">"
"<interface name=\"iface.iface1\" />"
"<interface name=\"iface.iface2\" />"
"</node><node name=\"obj2\">"
"<interface name=\"iface.iface1\" />"
"</node></node>";
QTest::newRow("two-nodes-two-interfaces") << xmlData << "obj" << 2 << 0;
QTest::newRow("two-nodes-one-interface") << xmlData << "obj2" << 1 << 0;
xmlData = "<node><node name=\"obj\">"
"<node name=\"obj1\" />"
"</node></node>";
QTest::newRow("one-object") << xmlData << "obj" << 0 << 1;
QTest::newRow("one-object2") << xmlData << "obj2" << 0 << 0;
xmlData = "<node><node name=\"obj\">"
"<node name=\"obj1\" />"
"<node name=\"obj2\" />"
"</node></node>";
QTest::newRow("two-objects") << xmlData << "obj" << 0 << 2;
QTest::newRow("two-objects2") << xmlData << "obj2" << 0 << 0;
xmlData = "<node><node name=\"obj\">"
"<node name=\"obj1\" />"
"<node name=\"obj2\" />"
"</node><node name=\"obj2\">"
"<node name=\"obj1\" />"
"</node></node>";
QTest::newRow("two-nodes-two-objects") << xmlData << "obj" << 0 << 2;
QTest::newRow("two-nodes-one-object") << xmlData << "obj2" << 0 << 1;
}
void tst_QDBusXmlParser::objectWithContent()
{
QFETCH(QString, xmlData);
QFETCH(QString, probedObject);
QDBusIntrospection::ObjectTree tree =
QDBusIntrospection::parseObjectTree(xmlData, "local.testing", "/");
const ObjectMap &om = tree.childObjectData;
if (om.contains(probedObject)) {
const QSharedDataPointer<QDBusIntrospection::ObjectTree>& obj = om.value(probedObject);
QVERIFY(obj != 0);
QFETCH(int, interfaceCount);
QFETCH(int, objectCount);
QCOMPARE(obj->interfaces.count(), interfaceCount);
QCOMPARE(obj->childObjects.count(), objectCount);
// verify the object names
int i = 0;
foreach (QString name, obj->interfaces)
QCOMPARE(name, QString("iface.iface%1").arg(++i));
i = 0;
foreach (QString name, obj->childObjects)
QCOMPARE(name, QString("obj%1").arg(++i));
}
}
void tst_QDBusXmlParser::methods_data()
{
QTest::addColumn<QString>("xmlDataFragment");
QTest::addColumn<MethodMap>("methodMap");
MethodMap map;
QTest::newRow("no-methods") << QString() << map;
// one method without arguments
QDBusIntrospection::Method method;
method.name = "Foo";
map << method;
QTest::newRow("one-method") << "<method name=\"Foo\"/>" << map;
// add another method without arguments
method.name = "Bar";
map << method;
QTest::newRow("two-methods") << "<method name=\"Foo\"/>"
"<method name=\"Bar\"/>"
<< map;
// invert the order of the XML declaration
QTest::newRow("two-methods-inverse") << "<method name=\"Bar\"/>"
"<method name=\"Foo\"/>"
<< map;
// add a third, with annotations
method.name = "Baz";
method.annotations.insert("foo.testing", "nothing to see here");
map << method;
QTest::newRow("method-with-annotation") <<
"<method name=\"Foo\"/>"
"<method name=\"Bar\"/>"
"<method name=\"Baz\"><annotation name=\"foo.testing\" value=\"nothing to see here\"></method>"
<< map;
// arguments
map.clear();
method.annotations.clear();
method.name = "Method";
method.inputArgs << arg("s");
map << method;
QTest::newRow("one-in") <<
"<method name=\"Method\">"
"<arg type=\"s\" direction=\"in\"/>"
"</method>" << map;
// two arguments
method.inputArgs << arg("v");
map.clear();
map << method;
QTest::newRow("two-in") <<
"<method name=\"Method\">"
"<arg type=\"s\" direction=\"in\"/>"
"<arg type=\"v\" direction=\"in\"/>"
"</method>" << map;
// one invalid arg
QTest::newRow("two-in-one-invalid") <<
"<method name=\"Method\">"
"<arg type=\"s\" direction=\"in\"/>"
"<arg type=\"~\" name=\"invalid\" direction=\"in\"/>" // this line should be ignored
"<arg type=\"v\" direction=\"in\"/>"
"</method>" << map;
// one out argument
method.inputArgs.clear();
method.outputArgs << arg("s");
map.clear();
map << method;
QTest::newRow("one-out") <<
"<method name=\"Method\">"
"<arg type=\"s\" direction=\"out\"/>"
"</method>" << map;
// two in and one out
method.inputArgs << arg("s") << arg("v");
map.clear();
map << method;
QTest::newRow("two-in-one-out") <<
"<method name=\"Method\">"
"<arg type=\"s\" direction=\"in\"/>"
"<arg type=\"v\" direction=\"in\"/>"
"<arg type=\"s\" direction=\"out\"/>"
"</method>" << map;
// let's try an arg with name
method.outputArgs.clear();
method.inputArgs.clear();
method.inputArgs << arg("s", "foo");
map.clear();
map << method;
QTest::newRow("one-in-with-name") <<
"<method name=\"Method\">"
"<arg type=\"s\" name=\"foo\" direction=\"in\"/>"
"</method>" << map;
// two args with name
method.inputArgs << arg("i", "bar");
map.clear();
map << method;
QTest::newRow("two-in-with-name") <<
"<method name=\"Method\">"
"<arg type=\"s\" name=\"foo\" direction=\"in\"/>"
"<arg type=\"i\" name=\"bar\" direction=\"in\"/>"
"</method>" << map;
// one complex
map.clear();
method = QDBusIntrospection::Method();
// Method1(in STRING arg1, in BYTE arg2, out ARRAY of STRING)
method.inputArgs << arg("s", "arg1") << arg("y", "arg2");
method.outputArgs << arg("as");
method.name = "Method1";
map << method;
// Method2(in ARRAY of DICT_ENTRY of (STRING,VARIANT) variantMap, in UINT32 index,
// out STRING key, out VARIANT value)
// with annotation "foo.equivalent":"QVariantMap"
method = QDBusIntrospection::Method();
method.inputArgs << arg("a{sv}", "variantMap") << arg("u", "index");
method.outputArgs << arg("s", "key") << arg("v", "value");
method.annotations.insert("foo.equivalent", "QVariantMap");
method.name = "Method2";
map << method;
QTest::newRow("complex") <<
"<method name=\"Method1\">"
"<arg name=\"arg1\" type=\"s\" direction=\"in\"/>"
"<arg name=\"arg2\" type=\"y\" direction=\"in\"/>"
"<arg type=\"as\" direction=\"out\"/>"
"</method>"
"<method name=\"Method2\">"
"<arg name=\"variantMap\" type=\"a{sv}\" direction=\"in\"/>"
"<arg name=\"index\" type=\"u\" direction=\"in\"/>"
"<arg name=\"key\" type=\"s\" direction=\"out\"/>"
"<arg name=\"value\" type=\"v\" direction=\"out\"/>"
"<annotation name=\"foo.equivalent\" value=\"QVariantMap\"/>"
"</method>" << map;
}
void tst_QDBusXmlParser::methods()
{
QString xmlHeader = "<node>"
"<interface name=\"iface.iface1\">",
xmlFooter = "</interface>"
"</node>";
QFETCH(QString, xmlDataFragment);
QDBusIntrospection::Interface iface =
QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter);
QCOMPARE(iface.name, QString("iface.iface1"));
QFETCH(MethodMap, methodMap);
MethodMap parsedMap = iface.methods;
QCOMPARE(methodMap.count(), parsedMap.count());
QCOMPARE(methodMap, parsedMap);
}
void tst_QDBusXmlParser::signals__data()
{
QTest::addColumn<QString>("xmlDataFragment");
QTest::addColumn<SignalMap>("signalMap");
SignalMap map;
QTest::newRow("no-signals") << QString() << map;
// one signal without arguments
QDBusIntrospection::Signal signal;
signal.name = "Foo";
map << signal;
QTest::newRow("one-signal") << "<signal name=\"Foo\"/>" << map;
// add another signal without arguments
signal.name = "Bar";
map << signal;
QTest::newRow("two-signals") << "<signal name=\"Foo\"/>"
"<signal name=\"Bar\"/>"
<< map;
// invert the order of the XML declaration
QTest::newRow("two-signals-inverse") << "<signal name=\"Bar\"/>"
"<signal name=\"Foo\"/>"
<< map;
// add a third, with annotations
signal.name = "Baz";
signal.annotations.insert("foo.testing", "nothing to see here");
map << signal;
QTest::newRow("signal-with-annotation") <<
"<signal name=\"Foo\"/>"
"<signal name=\"Bar\"/>"
"<signal name=\"Baz\"><annotation name=\"foo.testing\" value=\"nothing to see here\"></signal>"
<< map;
// one out argument
map.clear();
signal.annotations.clear();
signal.outputArgs << arg("s");
signal.name = "Signal";
map.clear();
map << signal;
QTest::newRow("one-out") <<
"<signal name=\"Signal\">"
"<arg type=\"s\" direction=\"out\"/>"
"</signal>" << map;
// without saying which direction it is
QTest::newRow("one-out-no-direction") <<
"<signal name=\"Signal\">"
"<arg type=\"s\"/>"
"</signal>" << map;
// two args with name
signal.outputArgs << arg("i", "bar");
map.clear();
map << signal;
QTest::newRow("two-out-with-name") <<
"<signal name=\"Signal\">"
"<arg type=\"s\" direction=\"out\"/>"
"<arg type=\"i\" name=\"bar\"/>"
"</signal>" << map;
// one complex
map.clear();
signal = QDBusIntrospection::Signal();
// Signal1(out ARRAY of STRING)
signal.outputArgs << arg("as");
signal.name = "Signal1";
map << signal;
// Signal2(out STRING key, out VARIANT value)
// with annotation "foo.equivalent":"QVariantMap"
signal = QDBusIntrospection::Signal();
signal.outputArgs << arg("s", "key") << arg("v", "value");
signal.annotations.insert("foo.equivalent", "QVariantMap");
signal.name = "Signal2";
map << signal;
QTest::newRow("complex") <<
"<signal name=\"Signal1\">"
"<arg type=\"as\" direction=\"out\"/>"
"</signal>"
"<signal name=\"Signal2\">"
"<arg name=\"key\" type=\"s\" direction=\"out\"/>"
"<arg name=\"value\" type=\"v\" direction=\"out\"/>"
"<annotation name=\"foo.equivalent\" value=\"QVariantMap\"/>"
"</signal>" << map;
}
void tst_QDBusXmlParser::signals_()
{
QString xmlHeader = "<node>"
"<interface name=\"iface.iface1\">",
xmlFooter = "</interface>"
"</node>";
QFETCH(QString, xmlDataFragment);
QDBusIntrospection::Interface iface =
QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter);
QCOMPARE(iface.name, QString("iface.iface1"));
QFETCH(SignalMap, signalMap);
SignalMap parsedMap = iface.signals_;
QCOMPARE(signalMap.count(), parsedMap.count());
QCOMPARE(signalMap, parsedMap);
}
void tst_QDBusXmlParser::properties_data()
{
QTest::addColumn<QString>("xmlDataFragment");
QTest::addColumn<PropertyMap>("propertyMap");
PropertyMap map;
QTest::newRow("no-signals") << QString() << map;
// one readable signal
QDBusIntrospection::Property prop;
prop.name = "foo";
prop.type = QDBusType("s");
prop.access = QDBusIntrospection::Property::Read;
map << prop;
QTest::newRow("one-readable") << "<property name=\"foo\" type=\"s\" access=\"read\"/>" << map;
// one writable signal
prop.access = QDBusIntrospection::Property::Write;
map.clear();
map << prop;
QTest::newRow("one-writable") << "<property name=\"foo\" type=\"s\" access=\"write\"/>" << map;
// one read- & writable signal
prop.access = QDBusIntrospection::Property::ReadWrite;
map.clear();
map << prop;
QTest::newRow("one-read-writable") << "<property name=\"foo\" type=\"s\" access=\"readwrite\"/>"
<< map;
// two, mixed properties
prop.name = "bar";
prop.type = QDBusType("i");
prop.access = QDBusIntrospection::Property::Read;
map << prop;
QTest::newRow("two") <<
"<property name=\"foo\" type=\"s\" access=\"readwrite\"/>"
"<property name=\"bar\" type=\"i\" access=\"read\"/>" << map;
// invert the order of the declaration
QTest::newRow("two") <<
"<property name=\"bar\" type=\"i\" access=\"read\"/>"
"<property name=\"foo\" type=\"s\" access=\"readwrite\"/>" << map;
// add a third with annotations
prop.name = "baz";
prop.type = QDBusType("as");
prop.access = QDBusIntrospection::Property::Write;
prop.annotations.insert("foo.annotation", "Hello, World");
prop.annotations.insert("foo.annotation2", "Goodbye, World");
map << prop;
QTest::newRow("complex") <<
"<property name=\"bar\" type=\"i\" access=\"read\"/>"
"<property name=\"baz\" type=\"as\" access=\"write\">"
"<annotation name=\"foo.annotation\" value=\"Hello, World\" />"
"<annotation name=\"foo.annotation2\" value=\"Goodbye, World\" />"
"<property name=\"foo\" type=\"s\" access=\"readwrite\"/>" << map;
// and now change the order
QTest::newRow("complex2") <<
"<property name=\"baz\" type=\"as\" access=\"write\">"
"<annotation name=\"foo.annotation2\" value=\"Goodbye, World\" />"
"<annotation name=\"foo.annotation\" value=\"Hello, World\" />"
"<property name=\"bar\" type=\"i\" access=\"read\"/>"
"<property name=\"foo\" type=\"s\" access=\"readwrite\"/>" << map;
}
void tst_QDBusXmlParser::properties()
{
QString xmlHeader = "<node>"
"<interface name=\"iface.iface1\">",
xmlFooter = "</interface>"
"</node>";
QFETCH(QString, xmlDataFragment);
QDBusIntrospection::Interface iface =
QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter);
QCOMPARE(iface.name, QString("iface.iface1"));
QFETCH(PropertyMap, propertyMap);
PropertyMap parsedMap = iface.properties;
QCOMPARE(propertyMap.count(), parsedMap.count());
QCOMPARE(propertyMap, parsedMap);
}
QTEST_MAIN(tst_QDBusXmlParser)
#include "tst_qdbusxmlparser.moc"
More information about the dbus-commit
mailing list