summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago@kde.org>2006-06-11 12:18:23 +0000
committerThiago Macieira <thiago@kde.org>2006-06-11 12:18:23 +0000
commitfd5ac15ebc643635e436b64cf1e656284380b1a5 (patch)
treef1630dd4f97b5f56c61150ee2a0186831d81c256
parent3b50a8c9fe65839b79f8df988aee6124abd4f0c4 (diff)
* test/qt/*: Update the testcases, including testing the new
functionality of sending null QByteArray and QString over the bus. Add new headertest test and restore the old qdbusxmlparser test.
-rw-r--r--ChangeLog7
-rw-r--r--test/qt/Makefile.am19
-rw-r--r--test/qt/common.h24
-rw-r--r--test/qt/qpong.cpp12
-rw-r--r--test/qt/tst_hal.cpp1
-rw-r--r--test/qt/tst_headertest.cpp16
-rw-r--r--test/qt/tst_qdbusabstractadaptor.cpp78
-rw-r--r--test/qt/tst_qdbusconnection.cpp2
-rw-r--r--test/qt/tst_qdbusinterface.cpp87
-rw-r--r--test/qt/tst_qdbusmarshall.cpp (renamed from test/qt/ping.cpp)54
-rw-r--r--test/qt/tst_qdbusxmlparser.cpp578
11 files changed, 745 insertions, 133 deletions
diff --git a/ChangeLog b/ChangeLog
index 2f1f1a6a..8f48ca5c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2006-06-11 Thiago Macieira <thiago.macieira@trolltech.com>
+ * test/qt/*: Update the testcases, including testing the new
+ functionality of sending null QByteArray and QString over the
+ bus. Add new headertest test and restore the old
+ qdbusxmlparser test.
+
+2006-06-11 Thiago Macieira <thiago.macieira@trolltech.com>
+
* qt/tools/dbuscpp2xml.cpp: Compile on Windows.
* qt/tools/dbusidl2cpp.cpp: Add missing newline.
diff --git a/test/qt/Makefile.am b/test/qt/Makefile.am
index f7a8efa9..8ebd3323 100644
--- a/test/qt/Makefile.am
+++ b/test/qt/Makefile.am
@@ -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 qpong ping qdbusinterface qdbusabstractadaptor hal
+TEST_BINARIES = tst_headertest tst_qdbusxmlparser tst_qdbusconnection qpong tst_qdbusmarshall tst_qdbusinterface tst_qdbusabstractadaptor tst_hal
TESTS=
else
TEST_BINARIES=
@@ -11,14 +11,17 @@ endif
noinst_PROGRAMS= $(TEST_BINARIES)
qpong_SOURCES= qpong.cpp
-ping_SOURCES= ping.cpp
-qdbusconnection_SOURCES= tst_qdbusconnection.cpp
-qdbusinterface_SOURCES= tst_qdbusinterface.cpp
-qdbusabstractadaptor_SOURCES= tst_qdbusabstractadaptor.cpp common.h
-hal_SOURCES = tst_hal.cpp
+tst_headertest_SOURCES = tst_headertest.cpp
+tst_qdbusconnection_SOURCES = tst_qdbusconnection.cpp
+tst_qdbusxmlparser_SOURCES = tst_qdbusxmlparser.cpp
+tst_qdbusmarshall_SOURCES = tst_qdbusmarshall.cpp
+tst_qdbusinterface_SOURCES = tst_qdbusinterface.cpp
+tst_qdbusabstractadaptor_SOURCES = tst_qdbusabstractadaptor.cpp common.h
+tst_hal_SOURCES = tst_hal.cpp
qpong.o: qpong.moc
-ping.o: ping.moc
+tst_qdbusxmlparser.o: tst_qdbusxmlparser.moc
+tst_qdbusmarshall.o: tst_qdbusmarshall.moc
tst_qdbusconnection.o: tst_qdbusconnection.moc
tst_qdbusinterface.o: tst_qdbusinterface.moc
tst_qdbusabstractadaptor.o: tst_qdbusabstractadaptor.moc
@@ -27,7 +30,7 @@ tst_hal.o: tst_hal.moc
%.moc: %.cpp
$(QT_MOC) $< > $@
-TEST_LIBS=$(DBUS_QTESTLIB_LIBS) $(top_builddir)/qt/libdbus-qt4-1.la
+TEST_LIBS=$(DBUS_QTESTLIB_LIBS) $(top_builddir)/qt/src/libdbus-qt4-1.la
LDADD=$(TEST_LIBS)
diff --git a/test/qt/common.h b/test/qt/common.h
index 943d3d95..58beae4e 100644
--- a/test/qt/common.h
+++ b/test/qt/common.h
@@ -9,8 +9,8 @@ Q_DECLARE_METATYPE(QList<uint>)
Q_DECLARE_METATYPE(QList<qlonglong>)
Q_DECLARE_METATYPE(QList<qulonglong>)
Q_DECLARE_METATYPE(QList<double>)
-#if 0
-#include "../qdbusintrospection_p.h"
+#ifdef USE_PRIVATE_CODE
+#include "../../qt/src/qdbusintrospection_p.h"
// just to make it easier:
typedef QDBusIntrospection::Interfaces InterfaceMap;
@@ -157,6 +157,20 @@ bool compare(const QList<double> &l1, const QList<double> &l2)
return true;
}
+bool compare(const QString &s1, const QString &s2)
+{
+ if (s1.isEmpty() && s2.isEmpty())
+ return true; // regardless of whether one of them is null
+ return s1 == s2;
+}
+
+bool compare(const QByteArray &ba1, const QByteArray &ba2)
+{
+ if (ba1.isEmpty() && ba2.isEmpty())
+ return true; // regardless of whether one of them is null
+ return ba1 == ba2;
+}
+
bool compare(const QVariant &v1, const QVariant &v2)
{
if (v1.userType() != v2.userType())
@@ -169,6 +183,12 @@ bool compare(const QVariant &v1, const QVariant &v2)
else if (id == QVariant::Map)
return compare(v1.toMap(), v2.toMap());
+ else if (id == QVariant::String)
+ return compare(v1.toString(), v2.toString());
+
+ else if (id == QVariant::ByteArray)
+ return compare(v1.toByteArray(), v2.toByteArray());
+
else if (id < int(QVariant::UserType)) // yes, v1.type()
// QVariant can compare
return v1 == v2;
diff --git a/test/qt/qpong.cpp b/test/qt/qpong.cpp
index 4a3e9763..cad04eb6 100644
--- a/test/qt/qpong.cpp
+++ b/test/qt/qpong.cpp
@@ -1,6 +1,5 @@
#include <QtCore/QtCore>
#include <dbus/qdbus.h>
-#include <dbus/dbus.h>
class Pong: public QObject
{
@@ -22,13 +21,10 @@ int main(int argc, char *argv[])
QCoreApplication app(argc, argv);
QDBusConnection &con = QDBus::sessionBus();
- QDBusMessage msg = QDBusMessage::methodCall(DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "RequestName");
- msg << "org.kde.selftest" << 0U;
- msg = con.sendWithReply(msg);
- if (msg.type() != QDBusMessage::ReplyMessage)
+ if (!con.isConnected())
+ exit(1);
+
+ if (con.busService()->requestName("org.kde.selftest", QDBusBusService::DoNotQueueName).isError())
exit(2);
Pong pong;
diff --git a/test/qt/tst_hal.cpp b/test/qt/tst_hal.cpp
index f98eb98a..a69daf2f 100644
--- a/test/qt/tst_hal.cpp
+++ b/test/qt/tst_hal.cpp
@@ -2,7 +2,6 @@
#include <qdebug.h>
#include <QtTest/QtTest>
-#define DBUS_API_SUBJECT_TO_CHANGE
#include <dbus/qdbus.h>
class tst_Hal: public QObject
diff --git a/test/qt/tst_headertest.cpp b/test/qt/tst_headertest.cpp
new file mode 100644
index 00000000..eb90c555
--- /dev/null
+++ b/test/qt/tst_headertest.cpp
@@ -0,0 +1,16 @@
+#define QT_NO_KEYWORDS
+#define signals Choke!
+#define slots Choke!
+#define emit Choke!
+#define foreach Choke!
+#define forever Choke!
+
+#define QT_NO_CAST_FROM_ASCII
+#define QT_NO_CAST_TO_ASCII
+
+#include <dbus/qdbus.h>
+
+int main(int, char **)
+{
+ return 0;
+}
diff --git a/test/qt/tst_qdbusabstractadaptor.cpp b/test/qt/tst_qdbusabstractadaptor.cpp
index ec3f0470..d47c5436 100644
--- a/test/qt/tst_qdbusabstractadaptor.cpp
+++ b/test/qt/tst_qdbusabstractadaptor.cpp
@@ -7,6 +7,10 @@
#include "common.h"
+#ifdef Q_CC_MSVC
+#define __PRETTY_FUNCTION__ __FUNCDNAME__
+#endif
+
const char *slotSpy;
QString valueSpy;
@@ -79,7 +83,7 @@ public:
class Interface1: public QDBusAbstractAdaptor
{
Q_OBJECT
- Q_CLASSINFO("D-Bus Interface", "local.Interface1");
+ Q_CLASSINFO("D-Bus Interface", "local.Interface1")
public:
Interface1(QObject *parent) : QDBusAbstractAdaptor(parent)
{ }
@@ -88,9 +92,9 @@ public:
class Interface2: public QDBusAbstractAdaptor
{
Q_OBJECT
- Q_CLASSINFO("D-Bus Interface", "local.Interface2");
- Q_PROPERTY(QString prop1 READ prop1);
- Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2);
+ Q_CLASSINFO("D-Bus Interface", "local.Interface2")
+ Q_PROPERTY(QString prop1 READ prop1)
+ Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2)
public:
Interface2(QObject *parent) : QDBusAbstractAdaptor(parent)
{ setAutoRelaySignals(true); }
@@ -117,9 +121,9 @@ signals:
class Interface3: public QDBusAbstractAdaptor
{
Q_OBJECT
- Q_CLASSINFO("D-Bus Interface", "local.Interface3");
- Q_PROPERTY(QString prop1 READ prop1);
- Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2);
+ Q_CLASSINFO("D-Bus Interface", "local.Interface3")
+ Q_PROPERTY(QString prop1 READ prop1)
+ Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2)
public:
Interface3(QObject *parent) : QDBusAbstractAdaptor(parent)
{ setAutoRelaySignals(true); }
@@ -157,9 +161,9 @@ signals:
class Interface4: public QDBusAbstractAdaptor
{
Q_OBJECT
- Q_CLASSINFO("D-Bus Interface", "local.Interface4");
- Q_PROPERTY(QString prop1 READ prop1);
- Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2);
+ Q_CLASSINFO("D-Bus Interface", "local.Interface4")
+ Q_PROPERTY(QString prop1 READ prop1)
+ Q_PROPERTY(QString prop2 READ prop2 WRITE setProp2)
public:
Interface4(QObject *parent) : QDBusAbstractAdaptor(parent)
{ setAutoRelaySignals(true); }
@@ -452,51 +456,51 @@ void tst_QDBusAbstractAdaptor::methodCalls()
// must fail: no object
//QCOMPARE(empty->call("method").type(), QDBusMessage::ErrorMessage);
- QCOMPARE(if1->call("method").type(), QDBusMessage::ErrorMessage);
+ QCOMPARE(if1->call(QDBusInterface::UseEventLoop, "method").type(), QDBusMessage::ErrorMessage);
QFETCH(int, nInterfaces);
MyObject obj(nInterfaces);
con.registerObject("/", &obj);
// must fail: no such method
- QCOMPARE(if1->call("method").type(), QDBusMessage::ErrorMessage);
+ QCOMPARE(if1->call(QDBusInterface::UseEventLoop, "method").type(), QDBusMessage::ErrorMessage);
if (!nInterfaces--)
return;
if (!nInterfaces--)
return;
// simple call: one such method exists
- QCOMPARE(if2->call("method").type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(if2->call(QDBusInterface::UseEventLoop, "method").type(), QDBusMessage::ReplyMessage);
QCOMPARE(slotSpy, "void Interface2::method()");
if (!nInterfaces--)
return;
// multiple methods in multiple interfaces, no name overlap
- QCOMPARE(if1->call("methodVoid").type(), QDBusMessage::ErrorMessage);
- QCOMPARE(if1->call("methodInt").type(), QDBusMessage::ErrorMessage);
- QCOMPARE(if1->call("methodString").type(), QDBusMessage::ErrorMessage);
- QCOMPARE(if2->call("methodVoid").type(), QDBusMessage::ErrorMessage);
- QCOMPARE(if2->call("methodInt").type(), QDBusMessage::ErrorMessage);
- QCOMPARE(if2->call("methodString").type(), QDBusMessage::ErrorMessage);
-
- QCOMPARE(if3->call("methodVoid").type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(if1->call(QDBusInterface::UseEventLoop, "methodVoid").type(), QDBusMessage::ErrorMessage);
+ QCOMPARE(if1->call(QDBusInterface::UseEventLoop, "methodInt").type(), QDBusMessage::ErrorMessage);
+ QCOMPARE(if1->call(QDBusInterface::UseEventLoop, "methodString").type(), QDBusMessage::ErrorMessage);
+ QCOMPARE(if2->call(QDBusInterface::UseEventLoop, "methodVoid").type(), QDBusMessage::ErrorMessage);
+ QCOMPARE(if2->call(QDBusInterface::UseEventLoop, "methodInt").type(), QDBusMessage::ErrorMessage);
+ QCOMPARE(if2->call(QDBusInterface::UseEventLoop, "methodString").type(), QDBusMessage::ErrorMessage);
+
+ QCOMPARE(if3->call(QDBusInterface::UseEventLoop, "methodVoid").type(), QDBusMessage::ReplyMessage);
QCOMPARE(slotSpy, "void Interface3::methodVoid()");
- QCOMPARE(if3->call("methodInt", 42).type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(if3->call(QDBusInterface::UseEventLoop, "methodInt", 42).type(), QDBusMessage::ReplyMessage);
QCOMPARE(slotSpy, "void Interface3::methodInt(int)");
- QCOMPARE(if3->call("methodString", QString("")).type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(if3->call(QDBusInterface::UseEventLoop, "methodString", QString("")).type(), QDBusMessage::ReplyMessage);
QCOMPARE(slotSpy, "void Interface3::methodString(QString)");
if (!nInterfaces--)
return;
// method overloading: different interfaces
- QCOMPARE(if4->call("method").type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(if4->call(QDBusInterface::UseEventLoop, "method").type(), QDBusMessage::ReplyMessage);
QCOMPARE(slotSpy, "void Interface4::method()");
// method overloading: different parameters
- QCOMPARE(if4->call("method.i", 42).type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(if4->call(QDBusInterface::UseEventLoop, "method.i", 42).type(), QDBusMessage::ReplyMessage);
QCOMPARE(slotSpy, "void Interface4::method(int)");
- QCOMPARE(if4->call("method.s", QString()).type(), QDBusMessage::ReplyMessage);
+ QCOMPARE(if4->call(QDBusInterface::UseEventLoop, "method.s", QString()).type(), QDBusMessage::ReplyMessage);
QCOMPARE(slotSpy, "void Interface4::method(QString)");
}
@@ -679,18 +683,19 @@ void tst_QDBusAbstractAdaptor::readProperties()
MyObject obj;
con.registerObject("/", &obj);
+ QDBusInterfacePtr properties(con, con.baseService(), "/", "org.freedesktop.DBus.Properties");
for (int i = 2; i <= 4; ++i) {
QString name = QString("Interface%1").arg(i);
- QDBusInterface *iface = con.findInterface(con.baseService(), "/", "local." + name);
for (int j = 1; j <= 2; ++j) {
QString propname = QString("prop%1").arg(j);
- QVariant value = iface->property(propname.toLatin1());
+ QDBusReply<QVariant> reply =
+ properties->call(QDBusInterface::UseEventLoop, "Get", "local." + name, propname);
+ QVariant value = reply;
QCOMPARE(value.userType(), int(QVariant::String));
QCOMPARE(value.toString(), QString("QString %1::%2() const").arg(name, propname));
}
- iface->deleteLater();
}
}
@@ -702,21 +707,21 @@ void tst_QDBusAbstractAdaptor::writeProperties()
MyObject obj;
con.registerObject("/", &obj);
+ QDBusInterfacePtr properties(con, con.baseService(), "/", "org.freedesktop.DBus.Properties");
for (int i = 2; i <= 4; ++i) {
QString name = QString("Interface%1").arg(i);
- QDBusInterface *iface = con.findInterface(con.baseService(), "/", "local." + name);
QVariant value(name);
valueSpy.clear();
- iface->setProperty("prop1", value);
+ properties->call(QDBusInterface::UseEventLoop, "Set", "local." + name, QString("prop1"),
+ value);
QVERIFY(valueSpy.isEmpty()); // call mustn't have succeeded
- iface->setProperty("prop2", value);
+ properties->call(QDBusInterface::UseEventLoop, "Set", "local." + name, QString("prop2"),
+ value);
QCOMPARE(valueSpy, name);
QCOMPARE(QString(slotSpy), QString("void %1::setProp2(const QString&)").arg(name));
-
- iface->deleteLater();
}
}
@@ -964,10 +969,11 @@ void tst_QDBusAbstractAdaptor::typeMatching()
QDBusMessage reply;
QDBusInterface *iface = con.findInterface(con.baseService(), "/types", "local.TypesInterface");
- reply = iface->callWithArgs("method" + basename + '.' + signature, QVariantList() << value);
+ reply = iface->callWithArgs("method" + basename + '.' + signature, QVariantList() << value,
+ QDBusInterface::UseEventLoop);
QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
- reply = iface->call("retrieve" + basename);
+ reply = iface->call(QDBusInterface::UseEventLoop, "retrieve" + basename);
QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
QCOMPARE(reply.count(), 1);
diff --git a/test/qt/tst_qdbusconnection.cpp b/test/qt/tst_qdbusconnection.cpp
index 224a02c6..a887cd93 100644
--- a/test/qt/tst_qdbusconnection.cpp
+++ b/test/qt/tst_qdbusconnection.cpp
@@ -246,7 +246,7 @@ void tst_QDBusConnection::registerObject()
bool tst_QDBusConnection::callMethod(const QDBusConnection &conn, const QString &path)
{
QDBusMessage msg = QDBusMessage::methodCall(conn.baseService(), path, "local.any", "method");
- QDBusMessage reply = conn.sendWithReply(msg);
+ QDBusMessage reply = conn.sendWithReply(msg, QDBusConnection::UseEventLoop);
return reply.type() == QDBusMessage::ReplyMessage;
}
diff --git a/test/qt/tst_qdbusinterface.cpp b/test/qt/tst_qdbusinterface.cpp
index 46dde97a..a63b8e0b 100644
--- a/test/qt/tst_qdbusinterface.cpp
+++ b/test/qt/tst_qdbusinterface.cpp
@@ -34,63 +34,33 @@ 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
+ Q_CLASSINFO("D-Bus Interface", "com.trolltech.QtDBus.MyObject")
+ Q_CLASSINFO("D-Bus Introspection", ""
+" <interface name=\"com.trolltech.QtDBus.MyObject\" >\n"
+" <property access=\"readwrite\" type=\"i\" name=\"prop1\" />\n"
+" <signal name=\"somethingHappened\" >\n"
+" <arg direction=\"out\" type=\"s\" />\n"
+" </signal>\n"
+" <method name=\"ping\" >\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"ping\" />\n"
+" </method>\n"
+" <method name=\"ping\" >\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping1\" />\n"
+" <arg direction=\"in\" type=\"v\" name=\"ping2\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"pong1\" />\n"
+" <arg direction=\"out\" type=\"v\" name=\"pong2\" />\n"
+" </method>\n"
+" </interface>\n"
+ "")
public:
MyObject()
{
- new IntrospectionAdaptor(this);
+ QObject *subObject = new QObject(this);
+ subObject->setObjectName("subObject");
}
public slots:
@@ -152,7 +122,8 @@ void tst_QDBusInterface::initTestCase()
QDBusConnection &con = QDBus::sessionBus();
QVERIFY(con.isConnected());
- con.registerObject("/", &obj, QDBusConnection::ExportAdaptors | QDBusConnection::ExportSlots);
+ con.registerObject("/", &obj, QDBusConnection::ExportAdaptors | QDBusConnection::ExportSlots |
+ QDBusConnection::ExportChildObjects);
}
void tst_QDBusInterface::call_data()
@@ -241,7 +212,7 @@ void tst_QDBusInterface::call()
QDBusMessage reply;
// try first callWithArgs:
- reply = iface->callWithArgs(method, input);
+ reply = iface->callWithArgs(method, input, QDBusInterface::UseEventLoop);
QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
if (!output.isEmpty()) {
@@ -251,20 +222,20 @@ void tst_QDBusInterface::call()
// try the template methods
if (input.isEmpty())
- reply = iface->call(method);
+ reply = iface->call(QDBusInterface::UseEventLoop, method);
else if (input.count() == 1)
switch (input.at(0).type())
{
case QVariant::Int:
- reply = iface->call(method, input.at(0).toInt());
+ reply = iface->call(QDBusInterface::UseEventLoop, method, input.at(0).toInt());
break;
case QVariant::UInt:
- reply = iface->call(method, input.at(0).toUInt());
+ reply = iface->call(QDBusInterface::UseEventLoop, method, input.at(0).toUInt());
break;
case QVariant::String:
- reply = iface->call(method, input.at(0).toString());
+ reply = iface->call(QDBusInterface::UseEventLoop, method, input.at(0).toString());
break;
default:
@@ -272,7 +243,7 @@ void tst_QDBusInterface::call()
break;
}
else
- reply = iface->call(method, input.at(0).toString(), input.at(1).toString());
+ reply = iface->call(QDBusInterface::UseEventLoop, method, input.at(0).toString(), input.at(1).toString());
QCOMPARE(reply.type(), QDBusMessage::ReplyMessage);
if (!output.isEmpty()) {
diff --git a/test/qt/ping.cpp b/test/qt/tst_qdbusmarshall.cpp
index 1cdbfca5..306f7b6a 100644
--- a/test/qt/ping.cpp
+++ b/test/qt/tst_qdbusmarshall.cpp
@@ -3,8 +3,9 @@
#include <dbus/qdbus.h>
#include "common.h"
+#include <limits>
-class Ping: public QObject
+class tst_QDBusMarshall: public QObject
{
Q_OBJECT
@@ -35,19 +36,20 @@ private:
QProcess proc;
};
-void Ping::initTestCase()
+void tst_QDBusMarshall::initTestCase()
{
proc.start("./qpong");
QVERIFY(proc.waitForStarted());
QTest::qWait(2000);
}
-void Ping::cleanupTestCase()
+void tst_QDBusMarshall::cleanupTestCase()
{
proc.close();
+ proc.kill();
}
-void Ping::sendBasic_data()
+void tst_QDBusMarshall::sendBasic_data()
{
QTest::addColumn<QVariant>("value");
QTest::addColumn<QString>("sig");
@@ -65,9 +67,10 @@ void Ping::sendBasic_data()
QTest::newRow("double") << QVariant(42.5) << "d";
QTest::newRow("string") << QVariant("ping") << "s";
QTest::newRow("emptystring") << QVariant("") << "s";
+ QTest::newRow("nullstring") << QVariant(QString()) << "s";
}
-void Ping::sendVariant_data()
+void tst_QDBusMarshall::sendVariant_data()
{
sendBasic_data();
@@ -80,7 +83,7 @@ void Ping::sendVariant_data()
QTest::newRow("variant-variant") << nested2 << "v";
}
-void Ping::sendArrays_data()
+void tst_QDBusMarshall::sendArrays_data()
{
QTest::addColumn<QVariant>("value");
QTest::addColumn<QString>("sig");
@@ -91,10 +94,24 @@ void Ping::sendArrays_data()
strings << "hello" << "world";
QTest::newRow("stringlist") << QVariant(strings) << "as";
- QByteArray bytearray(""); // empty, not null
+ strings.clear();
+ strings << "" << "" << "";
+ QTest::newRow("list-of-emptystrings") << QVariant(strings) << "as";
+
+ strings.clear();
+ strings << QString() << QString() << QString() << QString();
+ QTest::newRow("list-of-nullstrings") << QVariant(strings) << "as";
+
+ QByteArray bytearray;
+ QTest::newRow("nullbytearray") << QVariant(bytearray) << "ay";
+ bytearray = ""; // empty, not null
QTest::newRow("emptybytearray") << QVariant(bytearray) << "ay";
bytearray = "foo";
QTest::newRow("bytearray") << QVariant(bytearray) << "ay";
+ bytearray.clear();
+ for (int i = 0; i < 4096; ++i)
+ bytearray += QByteArray(1024, char(i));
+ QTest::newRow("hugebytearray") << QVariant(bytearray) << "ay";
QList<bool> bools;
QTest::newRow("emptyboollist") << qVariantFromValue(bools) << "ab";
@@ -152,12 +169,12 @@ void Ping::sendArrays_data()
QTest::newRow("variantlist") << QVariant(variants) << "av";
}
-void Ping::sendArrayOfArrays_data()
+void tst_QDBusMarshall::sendArrayOfArrays_data()
{
sendArrays_data();
}
-void Ping::sendStringMap_data()
+void tst_QDBusMarshall::sendStringMap_data()
{
sendBasic_data();
@@ -172,12 +189,12 @@ void Ping::sendStringMap_data()
sendArrays_data();
}
-void Ping::sendStringMapOfMap_data()
+void tst_QDBusMarshall::sendStringMapOfMap_data()
{
sendStringMap_data();
}
-void Ping::sendBasic()
+void tst_QDBusMarshall::sendBasic()
{
QFETCH(QVariant, value);
@@ -198,7 +215,7 @@ void Ping::sendBasic()
QVERIFY(compare(reply.at(i), msg.at(i)));
}
-void Ping::sendVariant()
+void tst_QDBusMarshall::sendVariant()
{
QFETCH(QVariant, value);
QVariant tmp = value;
@@ -221,7 +238,7 @@ void Ping::sendVariant()
QVERIFY(compare(reply.at(i), msg.at(i)));
}
-void Ping::sendArrays()
+void tst_QDBusMarshall::sendArrays()
{
QFETCH(QVariant, value);
@@ -242,7 +259,7 @@ void Ping::sendArrays()
QVERIFY(compare(reply.at(i), msg.at(i)));
}
-void Ping::sendArrayOfArrays()
+void tst_QDBusMarshall::sendArrayOfArrays()
{
QFETCH(QVariant, value);
@@ -264,7 +281,7 @@ void Ping::sendArrayOfArrays()
QVERIFY(compare(reply.at(i), msg.at(i)));
}
-void Ping::sendStringMap()
+void tst_QDBusMarshall::sendStringMap()
{
QFETCH(QVariant, value);
@@ -290,7 +307,7 @@ void Ping::sendStringMap()
QVERIFY(compare(reply.at(i), msg.at(i)));
}
-void Ping::sendStringMapOfMap()
+void tst_QDBusMarshall::sendStringMapOfMap()
{
QFETCH(QVariant, value);
@@ -316,11 +333,10 @@ void Ping::sendStringMapOfMap()
QFETCH(QString, sig);
QCOMPARE(reply.signature(), "a{sa{s" + sig + "}}");
- QEXPECT_FAIL("", "libdbus returns an empty set for un unknown reason", Abort);
for (int i = 0; i < reply.count(); ++i)
QVERIFY(compare(reply.at(i), msg.at(i)));
}
-QTEST_MAIN(Ping)
-#include "ping.moc"
+QTEST_MAIN(tst_QDBusMarshall)
+#include "tst_qdbusmarshall.moc"
diff --git a/test/qt/tst_qdbusxmlparser.cpp b/test/qt/tst_qdbusxmlparser.cpp
new file mode 100644
index 00000000..bf1ddec5
--- /dev/null
+++ b/test/qt/tst_qdbusxmlparser.cpp
@@ -0,0 +1,578 @@
+/* -*- 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>
+
+#define USE_PRIVATE_CODE
+#include "common.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();
+};
+
+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 = "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 = "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 = "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"