Remove dependency of QtDBus onto QtXml

Replace the QDom based code in qdbusxmlparser
with code using QXmlStreamReader.

Task-number: QTBUG-20856
Change-Id: I294e3ebd6faa813c20806be3ae225ac00befb622
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Harald Fernengel 2012-01-18 21:28:31 +01:00 committed by Qt by Nokia
parent 7c247d3e70
commit 0696071316
9 changed files with 313 additions and 433 deletions

View File

@ -2,8 +2,7 @@ load(qt_module)
TARGET = QtDBus
QPRO_PWD = $$PWD
QT = core-private \
xml
QT = core-private
CONFIG += link_pkgconfig module
MODULE_PRI = ../modules/qt_dbus.pri
@ -21,8 +20,7 @@ unix|win32-g++* {
QMAKE_PKGCONFIG_DESCRIPTION = Qt \
DBus \
module
QMAKE_PKGCONFIG_REQUIRES = QtCore \
QtXml
QMAKE_PKGCONFIG_REQUIRES = QtCore
}
win32 {
wince*:LIBS_PRIVATE += -lws2

View File

@ -407,23 +407,6 @@ QDBusIntrospection::parseObject(const QString &xml, const QString &service, cons
return *retval;
}
/*!
Parses the XML document fragment (given by \a xml) containing one object node and returns all
the information about the interfaces and sub-objects, found at the service \a service and path
\a path.
The Objects map returned will contain the absolute path names in the key.
*/
QDBusIntrospection::ObjectTree
QDBusIntrospection::parseObjectTree(const QString &xml, const QString &service, const QString &path)
{
QDBusXmlParser parser(service, path, xml);
QSharedDataPointer<QDBusIntrospection::ObjectTree> retval = parser.objectTree();
if (!retval)
return QDBusIntrospection::ObjectTree();
return *retval;
}
QT_END_NAMESPACE
#endif // QT_NO_DBUS

View File

@ -59,7 +59,7 @@
#include <QtCore/qmap.h>
#include <QtCore/qpair.h>
#include <QtCore/qshareddata.h>
#include <qdbusmacros.h>
#include "qdbusmacros.h"
QT_BEGIN_NAMESPACE
@ -150,26 +150,16 @@ public:
{
QString service;
QString path;
QString introspection;
QStringList interfaces;
QStringList childObjects;
};
struct ObjectTree: public Object
{
Interfaces interfaceData;
Objects childObjectData;
};
public:
static Interface parseInterface(const QString &xml);
static Interfaces parseInterfaces(const QString &xml);
static Object parseObject(const QString &xml, const QString &service = QString(),
const QString &path = QString());
static ObjectTree parseObjectTree(const QString &xml,
const QString &service,
const QString &path);
private:
QDBusIntrospection();

View File

@ -40,337 +40,319 @@
****************************************************************************/
#include "qdbusxmlparser_p.h"
#include "qdbusinterface.h"
#include "qdbusinterface_p.h"
#include "qdbusconnection_p.h"
#include "qdbusutil_p.h"
#include <QtXml/qdom.h>
#include <QtCore/qmap.h>
#include <QtCore/qvariant.h>
#include <QtCore/qtextstream.h>
#include <QtCore/qxmlstream.h>
#include <QtCore/qdebug.h>
#ifndef QT_NO_DBUS
//#define QDBUS_PARSER_DEBUG
#ifdef QDBUS_PARSER_DEBUG
# define qDBusParserError qWarning
# define qDBusParserError qDebug
#else
# define qDBusParserError if (true) {} else qDebug
#endif
QT_BEGIN_NAMESPACE
static QDBusIntrospection::Annotations
parseAnnotations(const QDomElement& elem)
static bool parseArg(const QXmlStreamAttributes &attributes, QDBusIntrospection::Argument &argData)
{
QDBusIntrospection::Annotations retval;
QDomNodeList list = elem.elementsByTagName(QLatin1String("annotation"));
for (int i = 0; i < list.count(); ++i)
{
QDomElement ann = list.item(i).toElement();
if (ann.isNull())
continue;
const QString argType = attributes.value(QLatin1String("type")).toString();
QString name = ann.attribute(QLatin1String("name")),
value = ann.attribute(QLatin1String("value"));
if (!QDBusUtil::isValidInterfaceName(name)) {
qDBusParserError("Invalid D-BUS annotation '%s' found while parsing introspection",
qPrintable(name));
continue;
}
retval.insert(name, value);
bool ok = QDBusUtil::isValidSingleSignature(argType);
if (!ok) {
qDBusParserError("Invalid D-BUS type signature '%s' found while parsing introspection",
qPrintable(argType));
}
return retval;
argData.name = attributes.value(QLatin1String("name")).toString();
argData.type = argType;
return ok;
}
static QDBusIntrospection::Arguments
parseArgs(const QDomElement& elem, const QLatin1String& direction, bool acceptEmpty)
static bool parseAnnotation(const QXmlStreamReader &xml, QDBusIntrospection::Annotations &annotations)
{
QDBusIntrospection::Arguments retval;
QDomNodeList list = elem.elementsByTagName(QLatin1String("arg"));
for (int i = 0; i < list.count(); ++i)
{
QDomElement arg = list.item(i).toElement();
if (arg.isNull())
continue;
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("annotation"));
if ((acceptEmpty && !arg.hasAttribute(QLatin1String("direction"))) ||
arg.attribute(QLatin1String("direction")) == direction) {
const QXmlStreamAttributes attributes = xml.attributes();
const QString name = attributes.value(QLatin1String("name")).toString();
QDBusIntrospection::Argument argData;
if (arg.hasAttribute(QLatin1String("name")))
argData.name = arg.attribute(QLatin1String("name")); // can be empty
argData.type = arg.attribute(QLatin1String("type"));
if (!QDBusUtil::isValidSingleSignature(argData.type)) {
qDBusParserError("Invalid D-BUS type signature '%s' found while parsing introspection",
qPrintable(argData.type));
if (!QDBusUtil::isValidInterfaceName(name)) {
qDBusParserError("Invalid D-BUS annotation '%s' found while parsing introspection",
qPrintable(name));
return false;
}
annotations.insert(name, attributes.value(QLatin1String("value")).toString());
return true;
}
static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &propertyData,
const QString &ifaceName)
{
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("property"));
QXmlStreamAttributes attributes = xml.attributes();
const QString propertyName = attributes.value(QLatin1String("name")).toString();
if (!QDBusUtil::isValidMemberName(propertyName)) {
qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
qPrintable(propertyName), qPrintable(ifaceName));
xml.skipCurrentElement();
return false;
}
// parse data
propertyData.name = propertyName;
propertyData.type = attributes.value(QLatin1String("type")).toString();
if (!QDBusUtil::isValidSingleSignature(propertyData.type)) {
// cannot be!
qDBusParserError("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection",
qPrintable(propertyData.type), qPrintable(ifaceName),
qPrintable(propertyName));
}
const QString access = attributes.value(QLatin1String("access")).toString();
if (access == QLatin1String("read"))
propertyData.access = QDBusIntrospection::Property::Read;
else if (access == QLatin1String("write"))
propertyData.access = QDBusIntrospection::Property::Write;
else if (access == QLatin1String("readwrite"))
propertyData.access = QDBusIntrospection::Property::ReadWrite;
else {
qDBusParserError("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection",
qPrintable(access), qPrintable(ifaceName),
qPrintable(propertyName));
return false; // invalid one!
}
while (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("annotation")) {
parseAnnotation(xml, propertyData.annotations);
} else if (xml.prefix().isEmpty()) {
qDBusParserError() << "Unknown element" << xml.name() << "while checking for annotations";
}
xml.skipCurrentElement();
}
if (!xml.isEndElement() || xml.name() != QLatin1String("property")) {
qDBusParserError() << "Invalid property specification" << xml.tokenString() << xml.name();
return false;
}
return true;
}
static bool parseMethod(QXmlStreamReader &xml, QDBusIntrospection::Method &methodData,
const QString &ifaceName)
{
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("method"));
const QXmlStreamAttributes attributes = xml.attributes();
const QString methodName = attributes.value(QLatin1String("name")).toString();
if (!QDBusUtil::isValidMemberName(methodName)) {
qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
qPrintable(methodName), qPrintable(ifaceName));
return false;
}
methodData.name = methodName;
QDBusIntrospection::Arguments outArguments;
QDBusIntrospection::Arguments inArguments;
QDBusIntrospection::Annotations annotations;
while (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("annotation")) {
parseAnnotation(xml, annotations);
} else if (xml.name() == QLatin1String("arg")) {
const QXmlStreamAttributes attributes = xml.attributes();
const QString direction = attributes.value(QLatin1String("direction")).toString();
QDBusIntrospection::Argument argument;
if (!attributes.hasAttribute(QLatin1String("direction"))
|| direction == QLatin1String("in")) {
parseArg(attributes, argument);
inArguments << argument;
} else if (direction == QLatin1String("out")) {
parseArg(attributes, argument);
outArguments << argument;
}
} else if (xml.prefix().isEmpty()) {
qDBusParserError() << "Unknown element" << xml.name() << "while checking for method arguments";
}
xml.skipCurrentElement();
}
retval << argData;
methodData.inputArgs = inArguments;
methodData.outputArgs = outArguments;
methodData.annotations = annotations;
return true;
}
static bool parseSignal(QXmlStreamReader &xml, QDBusIntrospection::Signal &signalData,
const QString &ifaceName)
{
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("signal"));
const QXmlStreamAttributes attributes = xml.attributes();
const QString signalName = attributes.value(QLatin1String("name")).toString();
if (!QDBusUtil::isValidMemberName(signalName)) {
qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
qPrintable(signalName), qPrintable(ifaceName));
return false;
}
signalData.name = signalName;
QDBusIntrospection::Arguments arguments;
QDBusIntrospection::Annotations annotations;
while (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("annotation")) {
parseAnnotation(xml, annotations);
} else if (xml.name() == QLatin1String("arg")) {
const QXmlStreamAttributes attributes = xml.attributes();
QDBusIntrospection::Argument argument;
if (!attributes.hasAttribute(QLatin1String("direction")) ||
attributes.value(QLatin1String("direction")) == QLatin1String("out")) {
parseArg(attributes, argument);
arguments << argument;
}
} else {
qDBusParserError() << "Unknown element" << xml.name() << "while checking for signal arguments";
}
xml.skipCurrentElement();
}
signalData.outputArgs = arguments;
signalData.annotations = annotations;
return true;
}
static void readInterface(QXmlStreamReader &xml, QDBusIntrospection::Object *objData,
QDBusIntrospection::Interfaces *interfaces)
{
const QString ifaceName = xml.attributes().value(QLatin1String("name")).toString();
if (!QDBusUtil::isValidInterfaceName(ifaceName)) {
qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection",
qPrintable(ifaceName));
return;
}
objData->interfaces.append(ifaceName);
QDBusIntrospection::Interface *ifaceData = new QDBusIntrospection::Interface;
ifaceData->name = ifaceName;
while (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("method")) {
QDBusIntrospection::Method methodData;
if (parseMethod(xml, methodData, ifaceName))
ifaceData->methods.insert(methodData.name, methodData);
} else if (xml.name() == QLatin1String("signal")) {
QDBusIntrospection::Signal signalData;
if (parseSignal(xml, signalData, ifaceName))
ifaceData->signals_.insert(signalData.name, signalData);
} else if (xml.name() == QLatin1String("property")) {
QDBusIntrospection::Property propertyData;
if (parseProperty(xml, propertyData, ifaceName))
ifaceData->properties.insert(propertyData.name, propertyData);
} else if (xml.name() == QLatin1String("annotation")) {
parseAnnotation(xml, ifaceData->annotations);
xml.skipCurrentElement(); // skip over annotation object
} else {
if (xml.prefix().isEmpty()) {
qDBusParserError() << "Unknown element while parsing interface" << xml.name();
}
xml.skipCurrentElement();
}
}
return retval;
interfaces->insert(ifaceName, QSharedDataPointer<QDBusIntrospection::Interface>(ifaceData));
if (!xml.isEndElement() || xml.name() != QLatin1String("interface")) {
qDBusParserError() << "Invalid Interface specification";
}
}
static void readNode(const QXmlStreamReader &xml, QDBusIntrospection::Object *objData, int nodeLevel)
{
const QString objName = xml.attributes().value(QLatin1String("name")).toString();
const QString fullName = objData->path.endsWith(QLatin1Char('/'))
? (objData->path + objName)
: QString(objData->path + QLatin1Char('/') + objName);
if (!QDBusUtil::isValidObjectPath(fullName)) {
qDBusParserError("Invalid D-BUS object path '%s' found while parsing introspection",
qPrintable(fullName));
return;
}
if (nodeLevel > 0)
objData->childObjects.append(objName);
}
QDBusXmlParser::QDBusXmlParser(const QString& service, const QString& path,
const QString& xmlData)
: m_service(service), m_path(path)
: m_service(service), m_path(path), m_object(new QDBusIntrospection::Object)
{
QDomDocument doc;
doc.setContent(xmlData);
m_node = doc.firstChildElement(QLatin1String("node"));
}
// qDBusParserError() << "parsing" << xmlData;
QDBusXmlParser::QDBusXmlParser(const QString& service, const QString& path,
const QDomElement& node)
: m_service(service), m_path(path), m_node(node)
{
}
m_object->service = m_service;
m_object->path = m_path;
QDBusIntrospection::Interfaces
QDBusXmlParser::interfaces() const
{
QDBusIntrospection::Interfaces retval;
QXmlStreamReader xml(xmlData);
if (m_node.isNull())
return retval;
int nodeLevel = -1;
QDomNodeList interfaceList = m_node.elementsByTagName(QLatin1String("interface"));
for (int i = 0; i < interfaceList.count(); ++i)
{
QDomElement iface = interfaceList.item(i).toElement();
QString ifaceName = iface.attribute(QLatin1String("name"));
if (iface.isNull())
continue; // for whatever reason
if (!QDBusUtil::isValidInterfaceName(ifaceName)) {
qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection",
qPrintable(ifaceName));
continue;
}
while (!xml.atEnd()) {
xml.readNext();
QDBusIntrospection::Interface *ifaceData = new QDBusIntrospection::Interface;
ifaceData->name = ifaceName;
{
// save the data
QTextStream ts(&ifaceData->introspection);
iface.save(ts,2);
}
// parse annotations
ifaceData->annotations = parseAnnotations(iface);
// parse methods
QDomNodeList list = iface.elementsByTagName(QLatin1String("method"));
for (int j = 0; j < list.count(); ++j)
{
QDomElement method = list.item(j).toElement();
QString methodName = method.attribute(QLatin1String("name"));
if (method.isNull())
continue;
if (!QDBusUtil::isValidMemberName(methodName)) {
qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
qPrintable(methodName), qPrintable(ifaceName));
continue;
switch (xml.tokenType()) {
case QXmlStreamReader::StartElement:
if (xml.name() == QLatin1String("node")) {
readNode(xml, m_object, ++nodeLevel);
} else if (xml.name() == QLatin1String("interface")) {
readInterface(xml, m_object, &m_interfaces);
} else {
if (xml.prefix().isEmpty()) {
qDBusParserError() << "skipping unknown element" << xml.name();
}
xml.skipCurrentElement();
}
QDBusIntrospection::Method methodData;
methodData.name = methodName;
// parse arguments
methodData.inputArgs = parseArgs(method, QLatin1String("in"), true);
methodData.outputArgs = parseArgs(method, QLatin1String("out"), false);
methodData.annotations = parseAnnotations(method);
// add it
ifaceData->methods.insert(methodName, methodData);
break;
case QXmlStreamReader::EndElement:
if (xml.name() == QLatin1String("node")) {
--nodeLevel;
} else {
qDBusParserError() << "Invalid Node declaration" << xml.name();
}
break;
case QXmlStreamReader::StartDocument:
case QXmlStreamReader::EndDocument:
case QXmlStreamReader::DTD:
// not interested
break;
case QXmlStreamReader::Comment:
// ignore comments and processing instructions
break;
default:
qDBusParserError() << "unknown token" << xml.name() << xml.tokenString();
break;
}
// parse signals
list = iface.elementsByTagName(QLatin1String("signal"));
for (int j = 0; j < list.count(); ++j)
{
QDomElement signal = list.item(j).toElement();
QString signalName = signal.attribute(QLatin1String("name"));
if (signal.isNull())
continue;
if (!QDBusUtil::isValidMemberName(signalName)) {
qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
qPrintable(signalName), qPrintable(ifaceName));
continue;
}
QDBusIntrospection::Signal signalData;
signalData.name = signalName;
// parse data
signalData.outputArgs = parseArgs(signal, QLatin1String("out"), true);
signalData.annotations = parseAnnotations(signal);
// add it
ifaceData->signals_.insert(signalName, signalData);
}
// parse properties
list = iface.elementsByTagName(QLatin1String("property"));
for (int j = 0; j < list.count(); ++j)
{
QDomElement property = list.item(j).toElement();
QString propertyName = property.attribute(QLatin1String("name"));
if (property.isNull())
continue;
if (!QDBusUtil::isValidMemberName(propertyName)) {
qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection",
qPrintable(propertyName), qPrintable(ifaceName));
continue;
}
QDBusIntrospection::Property propertyData;
// parse data
propertyData.name = propertyName;
propertyData.type = property.attribute(QLatin1String("type"));
propertyData.annotations = parseAnnotations(property);
if (!QDBusUtil::isValidSingleSignature(propertyData.type)) {
// cannot be!
qDBusParserError("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection",
qPrintable(propertyData.type), qPrintable(ifaceName),
qPrintable(propertyName));
}
QString access = property.attribute(QLatin1String("access"));
if (access == QLatin1String("read"))
propertyData.access = QDBusIntrospection::Property::Read;
else if (access == QLatin1String("write"))
propertyData.access = QDBusIntrospection::Property::Write;
else if (access == QLatin1String("readwrite"))
propertyData.access = QDBusIntrospection::Property::ReadWrite;
else {
qDBusParserError("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection",
qPrintable(access), qPrintable(ifaceName),
qPrintable(propertyName));
continue; // invalid one!
}
// add it
ifaceData->properties.insert(propertyName, propertyData);
}
// add it
retval.insert(ifaceName, QSharedDataPointer<QDBusIntrospection::Interface>(ifaceData));
}
return retval;
}
QSharedDataPointer<QDBusIntrospection::Object>
QDBusXmlParser::object() const
{
if (m_node.isNull())
return QSharedDataPointer<QDBusIntrospection::Object>();
QDBusIntrospection::Object* objData;
objData = new QDBusIntrospection::Object;
objData->service = m_service;
objData->path = m_path;
// check if we have anything to process
if (objData->introspection.isNull() && !m_node.firstChild().isNull()) {
// yes, introspect this object
QTextStream ts(&objData->introspection);
m_node.save(ts,2);
QDomNodeList objects = m_node.elementsByTagName(QLatin1String("node"));
for (int i = 0; i < objects.count(); ++i) {
QDomElement obj = objects.item(i).toElement();
QString objName = obj.attribute(QLatin1String("name"));
if (obj.isNull())
continue; // for whatever reason
if (!QDBusUtil::isValidObjectPath(m_path + QLatin1Char('/') + objName)) {
qDBusParserError("Invalid D-BUS object path '%s/%s' found while parsing introspection",
qPrintable(m_path), qPrintable(objName));
continue;
}
objData->childObjects.append(objName);
}
QDomNodeList interfaceList = m_node.elementsByTagName(QLatin1String("interface"));
for (int i = 0; i < interfaceList.count(); ++i) {
QDomElement iface = interfaceList.item(i).toElement();
QString ifaceName = iface.attribute(QLatin1String("name"));
if (iface.isNull())
continue;
if (!QDBusUtil::isValidInterfaceName(ifaceName)) {
qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection",
qPrintable(ifaceName));
continue;
}
objData->interfaces.append(ifaceName);
}
} else {
objData->introspection = QLatin1String("<node/>\n");
if (xml.hasError()) {
qDBusParserError() << "xml error" << xml.errorString() << "doc" << xmlData;
}
QSharedDataPointer<QDBusIntrospection::Object> retval;
retval = objData;
return retval;
}
QSharedDataPointer<QDBusIntrospection::ObjectTree>
QDBusXmlParser::objectTree() const
{
QSharedDataPointer<QDBusIntrospection::ObjectTree> retval;
if (m_node.isNull())
return retval;
retval = new QDBusIntrospection::ObjectTree;
retval->service = m_service;
retval->path = m_path;
QTextStream ts(&retval->introspection);
m_node.save(ts,2);
// interfaces are easy:
retval->interfaceData = interfaces();
retval->interfaces = retval->interfaceData.keys();
// sub-objects are slightly more difficult:
QDomNodeList objects = m_node.elementsByTagName(QLatin1String("node"));
for (int i = 0; i < objects.count(); ++i) {
QDomElement obj = objects.item(i).toElement();
QString objName = obj.attribute(QLatin1String("name"));
if (obj.isNull() || objName.isEmpty())
continue; // for whatever reason
// check if we have anything to process
if (!obj.firstChild().isNull()) {
// yes, introspect this object
QString xml;
QTextStream ts2(&xml);
obj.save(ts2,0);
// parse it
QString objAbsName = m_path;
if (!objAbsName.endsWith(QLatin1Char('/')))
objAbsName.append(QLatin1Char('/'));
objAbsName += objName;
QDBusXmlParser parser(m_service, objAbsName, obj);
retval->childObjectData.insert(objName, parser.objectTree());
}
retval->childObjects << objName;
}
return QSharedDataPointer<QDBusIntrospection::ObjectTree>( retval );
}
QT_END_NAMESPACE

View File

@ -54,7 +54,6 @@
//
#include <QtCore/qmap.h>
#include <QtXml/qdom.h>
#include <qdbusmacros.h>
#include "qdbusintrospection_p.h"
@ -69,17 +68,15 @@ class QDBusXmlParser
{
QString m_service;
QString m_path;
QDomElement m_node;
QSharedDataPointer<QDBusIntrospection::Object> m_object;
QDBusIntrospection::Interfaces m_interfaces;
public:
QDBusXmlParser(const QString& service, const QString& path,
const QString& xmlData);
QDBusXmlParser(const QString& service, const QString& path,
const QDomElement& node);
QDBusIntrospection::Interfaces interfaces() const;
QSharedDataPointer<QDBusIntrospection::Object> object() const;
QSharedDataPointer<QDBusIntrospection::ObjectTree> objectTree() const;
inline QDBusIntrospection::Interfaces interfaces() const { return m_interfaces; }
inline QSharedDataPointer<QDBusIntrospection::Object> object() const { return m_object; }
};
QT_END_NAMESPACE

View File

@ -11,6 +11,6 @@ QT.dbus.sources = $$QT_MODULE_BASE/src/dbus
QT.dbus.libs = $$QT_MODULE_LIB_BASE
QT.dbus.plugins = $$QT_MODULE_PLUGIN_BASE
QT.dbus.imports = $$QT_MODULE_IMPORT_BASE
QT.dbus.depends = core xml
QT.dbus.depends = core
QT.dbus.CONFIG = dbusadaptors dbusinterfaces
QT.dbus.DEFINES = QT_DBUS_LIB

View File

@ -50,7 +50,7 @@ src_platformsupport.target = sub-platformsupport
src_platformsupport.depends = src_corelib src_gui src_network
src_widgets.depends = src_corelib src_gui src_tools_uic
src_xml.depends = src_corelib
src_dbus.depends = src_corelib src_xml
src_dbus.depends = src_corelib
src_network.depends = src_corelib
src_opengl.depends = src_gui src_widgets
src_sql.depends = src_corelib

View File

@ -46,7 +46,7 @@
#include <QtTest/QtTest>
#include <QtCore/qvariant.h>
#include <QtDBus/QtDBus>
#include <qdebug.h>
#include "../qdbusmarshall/common.h"
#include "myobject.h"

View File

@ -61,9 +61,6 @@ private slots:
void parsingWithDoctype_data();
void parsingWithDoctype();
void objectWithContent_data();
void objectWithContent();
void methods_data();
void methods();
void signals__data();
@ -77,40 +74,49 @@ void tst_QDBusXmlParser::parsing_data()
QTest::addColumn<QString>("xmlData");
QTest::addColumn<int>("interfaceCount");
QTest::addColumn<int>("objectCount");
QTest::addColumn<int>("annotationCount");
QTest::newRow("null") << QString() << 0 << 0;
QTest::newRow("empty") << QString("") << 0 << 0;
QTest::newRow("null") << QString() << 0 << 0 << 0;
QTest::newRow("empty") << QString("") << 0 << 0 << 0;
QTest::newRow("junk") << "<junk/>" << 0 << 0;
QTest::newRow("junk") << "<junk/>" << 0 << 0 << 0;
QTest::newRow("interface-inside-junk") << "<junk><interface name=\"iface.iface1\" /></junk>"
<< 0 << 0;
<< 0 << 0 << 0;
QTest::newRow("object-inside-junk") << "<junk><node name=\"obj1\" /></junk>"
<< 0 << 0;
<< 0 << 0 << 0;
QTest::newRow("zero-interfaces") << "<node/>" << 0 << 0;
QTest::newRow("one-interface") << "<node><interface name=\"iface.iface1\" /></node>" << 1 << 0;
QTest::newRow("zero-interfaces") << "<node/>" << 0 << 0 << 0;
QTest::newRow("one-interface") << "<node><interface name=\"iface.iface1\" /></node>" << 1 << 0 << 0;
QTest::newRow("two-interfaces") << "<node><interface name=\"iface.iface1\" />"
"<interface name=\"iface.iface2\"></node>"
<< 2 << 0;
"<interface name=\"iface.iface2\" /></node>"
<< 2 << 0 << 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("one-object") << "<node><node name=\"obj1\"/></node>" << 0 << 1 << 0;
QTest::newRow("two-objects") << "<node><node name=\"obj1\"/><node name=\"obj2\"/></node>" << 0 << 2 << 0;
QTest::newRow("i1o1") << "<node><interface name=\"iface.iface1\"><node name=\"obj1\"></node>" << 1 << 1;
QTest::newRow("i1o1") << "<node><interface name=\"iface.iface1\"/><node name=\"obj1\"/></node>" << 1 << 1 << 0;
QTest::newRow("one-interface-annotated") << "<node><interface name=\"iface.iface1\">"
"<annotation name=\"foo.testing\" value=\"nothing to see here\" />"
"</interface></node>" << 1 << 0 << 1;
QTest::newRow("one-interface-docnamespace") << "<?xml version=\"1.0\" xmlns:doc=\"foo\" ?><node>"
"<interface name=\"iface.iface1\"><doc:something />"
"</interface></node>" << 1 << 0 << 0;
}
void tst_QDBusXmlParser::parsing_common(const QString &xmlData)
{
QDBusIntrospection::ObjectTree obj =
QDBusIntrospection::parseObjectTree(xmlData, "local.testing", "/");
QDBusIntrospection::Object obj =
QDBusIntrospection::parseObject(xmlData, "local.testing", "/");
QFETCH(int, interfaceCount);
QFETCH(int, objectCount);
QFETCH(int, annotationCount);
QCOMPARE(obj.interfaces.count(), interfaceCount);
QCOMPARE(obj.childObjects.count(), objectCount);
QCOMPARE(QDBusIntrospection::parseInterface(xmlData).annotations.count(), annotationCount);
// also verify the naming
int i = 0;
@ -140,92 +146,14 @@ void tst_QDBusXmlParser::parsingWithDoctype()
"\"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));
QString toParse;
if (xmlData.startsWith(QLatin1String("<?xml"))) {
int split = xmlData.indexOf(QLatin1Char('>')) + 1;
toParse = xmlData.left(split) + docType + xmlData.mid(split);
} else {
toParse = docType + xmlData;
}
parsing_common(toParse);
}
void tst_QDBusXmlParser::methods_data()
@ -261,7 +189,7 @@ void tst_QDBusXmlParser::methods_data()
QTest::newRow("method-with-annotation") <<
"<method name=\"Foo\"/>"
"<method name=\"Bar\"/>"
"<method name=\"Baz\"><annotation name=\"foo.testing\" value=\"nothing to see here\"></method>"
"<method name=\"Baz\"><annotation name=\"foo.testing\" value=\"nothing to see here\" /></method>"
<< map;
// arguments
@ -428,7 +356,7 @@ void tst_QDBusXmlParser::signals__data()
QTest::newRow("signal-with-annotation") <<
"<signal name=\"Foo\"/>"
"<signal name=\"Bar\"/>"
"<signal name=\"Baz\"><annotation name=\"foo.testing\" value=\"nothing to see here\"></signal>"
"<signal name=\"Baz\"><annotation name=\"foo.testing\" value=\"nothing to see here\" /></signal>"
<< map;
// one out argument
@ -563,6 +491,7 @@ void tst_QDBusXmlParser::properties_data()
"<property name=\"baz\" type=\"as\" access=\"write\">"
"<annotation name=\"foo.annotation\" value=\"Hello, World\" />"
"<annotation name=\"foo.annotation2\" value=\"Goodbye, World\" />"
"</property>"
"<property name=\"foo\" type=\"s\" access=\"readwrite\"/>" << map;
// and now change the order
@ -570,6 +499,7 @@ void tst_QDBusXmlParser::properties_data()
"<property name=\"baz\" type=\"as\" access=\"write\">"
"<annotation name=\"foo.annotation2\" value=\"Goodbye, World\" />"
"<annotation name=\"foo.annotation\" value=\"Hello, World\" />"
"</property>"
"<property name=\"bar\" type=\"i\" access=\"read\"/>"
"<property name=\"foo\" type=\"s\" access=\"readwrite\"/>" << map;
}