diff -r 000000000000 -r 1918ee327afb tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,599 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +/* -*- C++ -*- + */ +#include +#include +#include +#include + +#define USE_PRIVATE_CODE +#include "../qdbusmarshall/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("xmlData"); + QTest::addColumn("interfaceCount"); + QTest::addColumn("objectCount"); + + QTest::newRow("null") << QString() << 0 << 0; + QTest::newRow("empty") << QString("") << 0 << 0; + + QTest::newRow("junk") << "" << 0 << 0; + QTest::newRow("interface-inside-junk") << "" + << 0 << 0; + QTest::newRow("object-inside-junk") << "" + << 0 << 0; + + QTest::newRow("zero-interfaces") << "" << 0 << 0; + QTest::newRow("one-interface") << "" << 1 << 0; + + + QTest::newRow("two-interfaces") << "" + "" + << 2 << 0; + + + QTest::newRow("one-object") << "" << 0 << 1; + QTest::newRow("two-objects") << "" << 0 << 2; + + QTest::newRow("i1o1") << "" << 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 = "\n"; + QFETCH(QString, xmlData); + + parsing_common(docType + xmlData); +} + +void tst_QDBusXmlParser::objectWithContent_data() +{ + QTest::addColumn("xmlData"); + QTest::addColumn("probedObject"); + QTest::addColumn("interfaceCount"); + QTest::addColumn("objectCount"); + + QTest::newRow("zero") << "" << "obj" << 0 << 0; + + QString xmlData = "" + "" + ""; + QTest::newRow("one-interface") << xmlData << "obj" << 1 << 0; + QTest::newRow("one-interface2") << xmlData << "obj2" << 0 << 0; + + xmlData = "" + "" + "" + ""; + QTest::newRow("two-interfaces") << xmlData << "obj" << 2 << 0; + QTest::newRow("two-interfaces2") << xmlData << "obj2" << 0 << 0; + + xmlData = "" + "" + "" + "" + "" + ""; + QTest::newRow("two-nodes-two-interfaces") << xmlData << "obj" << 2 << 0; + QTest::newRow("two-nodes-one-interface") << xmlData << "obj2" << 1 << 0; + + xmlData = "" + "" + ""; + QTest::newRow("one-object") << xmlData << "obj" << 0 << 1; + QTest::newRow("one-object2") << xmlData << "obj2" << 0 << 0; + + xmlData = "" + "" + "" + ""; + QTest::newRow("two-objects") << xmlData << "obj" << 0 << 2; + QTest::newRow("two-objects2") << xmlData << "obj2" << 0 << 0; + + xmlData = "" + "" + "" + "" + "" + ""; + 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& 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("xmlDataFragment"); + QTest::addColumn("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") << "" << map; + + // add another method without arguments + method.name = "Bar"; + map << method; + QTest::newRow("two-methods") << "" + "" + << map; + + // invert the order of the XML declaration + QTest::newRow("two-methods-inverse") << "" + "" + << 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") << + "" + "" + "" + << map; + + // arguments + map.clear(); + method.annotations.clear(); + + method.name = "Method"; + method.inputArgs << arg("s"); + map << method; + QTest::newRow("one-in") << + "" + "" + "" << map; + + // two arguments + method.inputArgs << arg("v"); + map.clear(); + map << method; + QTest::newRow("two-in") << + "" + "" + "" + "" << map; + + // one invalid arg + QTest::newRow("two-in-one-invalid") << + "" + "" + "" // this line should be ignored + "" + "" << map; + + // one out argument + method.inputArgs.clear(); + method.outputArgs << arg("s"); + map.clear(); + map << method; + QTest::newRow("one-out") << + "" + "" + "" << map; + + // two in and one out + method.inputArgs << arg("s") << arg("v"); + map.clear(); + map << method; + QTest::newRow("two-in-one-out") << + "" + "" + "" + "" + "" << 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") << + "" + "" + "" << map; + + // two args with name + method.inputArgs << arg("i", "bar"); + map.clear(); + map << method; + QTest::newRow("two-in-with-name") << + "" + "" + "" + "" << 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") << + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" << map; +} + +void tst_QDBusXmlParser::methods() +{ + QString xmlHeader = "" + "", + xmlFooter = "" + ""; + + QFETCH(QString, xmlDataFragment); + + if (strcmp(QTest::currentDataTag(), "two-in-one-invalid") == 0) + QTest::ignoreMessage(QtWarningMsg, "Invalid D-BUS type signature '~' found while parsing introspection"); + 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("xmlDataFragment"); + QTest::addColumn("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") << "" << map; + + // add another signal without arguments + signal.name = "Bar"; + map << signal; + QTest::newRow("two-signals") << "" + "" + << map; + + // invert the order of the XML declaration + QTest::newRow("two-signals-inverse") << "" + "" + << 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") << + "" + "" + "" + << map; + + // one out argument + map.clear(); + signal.annotations.clear(); + signal.outputArgs << arg("s"); + signal.name = "Signal"; + map.clear(); + map << signal; + QTest::newRow("one-out") << + "" + "" + "" << map; + + // without saying which direction it is + QTest::newRow("one-out-no-direction") << + "" + "" + "" << map; + + // two args with name + signal.outputArgs << arg("i", "bar"); + map.clear(); + map << signal; + QTest::newRow("two-out-with-name") << + "" + "" + "" + "" << 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") << + "" + "" + "" + "" + "" + "" + "" + "" << map; +} + +void tst_QDBusXmlParser::signals_() +{ + QString xmlHeader = "" + "", + xmlFooter = "" + ""; + + 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("xmlDataFragment"); + QTest::addColumn("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") << "" << map; + + // one writable signal + prop.access = QDBusIntrospection::Property::Write; + map.clear(); + map << prop; + QTest::newRow("one-writable") << "" << map; + + // one read- & writable signal + prop.access = QDBusIntrospection::Property::ReadWrite; + map.clear(); + map << prop; + QTest::newRow("one-read-writable") << "" + << map; + + // two, mixed properties + prop.name = "bar"; + prop.type = "i"; + prop.access = QDBusIntrospection::Property::Read; + map << prop; + QTest::newRow("two") << + "" + "" << map; + + // invert the order of the declaration + QTest::newRow("two") << + "" + "" << 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") << + "" + "" + "" + "" + "" << map; + + // and now change the order + QTest::newRow("complex2") << + "" + "" + "" + "" + "" << map; +} + +void tst_QDBusXmlParser::properties() +{ + QString xmlHeader = "" + "", + xmlFooter = "" + ""; + + 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"