tests/auto/qdbusxmlparser/tst_qdbusxmlparser.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 /* -*- C++ -*-
       
    42  */
       
    43 #include <qcoreapplication.h>
       
    44 #include <qmetatype.h>
       
    45 #include <QtTest/QtTest>
       
    46 #include <QtDBus/QtDBus>
       
    47 
       
    48 #define USE_PRIVATE_CODE
       
    49 #include "../qdbusmarshall/common.h"
       
    50 
       
    51 class tst_QDBusXmlParser: public QObject
       
    52 {
       
    53     Q_OBJECT
       
    54 
       
    55 private:
       
    56     void parsing_common(const QString&);
       
    57 
       
    58 private slots:
       
    59     void parsing_data();
       
    60     void parsing();
       
    61     void parsingWithDoctype_data();
       
    62     void parsingWithDoctype();
       
    63 
       
    64     void objectWithContent_data();
       
    65     void objectWithContent();
       
    66 
       
    67     void methods_data();
       
    68     void methods();
       
    69     void signals__data();
       
    70     void signals_();
       
    71     void properties_data();
       
    72     void properties();
       
    73 };
       
    74 
       
    75 void tst_QDBusXmlParser::parsing_data()
       
    76 {
       
    77     QTest::addColumn<QString>("xmlData");
       
    78     QTest::addColumn<int>("interfaceCount");
       
    79     QTest::addColumn<int>("objectCount");
       
    80 
       
    81     QTest::newRow("null") << QString() << 0 << 0;
       
    82     QTest::newRow("empty") << QString("") << 0 << 0;
       
    83     
       
    84     QTest::newRow("junk") << "<junk/>" << 0 << 0;
       
    85     QTest::newRow("interface-inside-junk") << "<junk><interface name=\"iface.iface1\" /></junk>"
       
    86                                            << 0 << 0;
       
    87     QTest::newRow("object-inside-junk") << "<junk><node name=\"obj1\" /></junk>"
       
    88                                         << 0 << 0;
       
    89 
       
    90     QTest::newRow("zero-interfaces") << "<node/>" << 0 << 0;
       
    91     QTest::newRow("one-interface") << "<node><interface name=\"iface.iface1\" /></node>" << 1 << 0;
       
    92 
       
    93     
       
    94     QTest::newRow("two-interfaces") << "<node><interface name=\"iface.iface1\" />"
       
    95                                        "<interface name=\"iface.iface2\"></node>"
       
    96                                     << 2 << 0;        
       
    97 
       
    98 
       
    99     QTest::newRow("one-object") << "<node><node name=\"obj1\"/></node>" << 0 << 1;
       
   100     QTest::newRow("two-objects") << "<node><node name=\"obj1\"/><node name=\"obj2\"></node>" << 0 << 2;
       
   101 
       
   102     QTest::newRow("i1o1") << "<node><interface name=\"iface.iface1\"><node name=\"obj1\"></node>" << 1 << 1;
       
   103 
       
   104 }
       
   105 
       
   106 void tst_QDBusXmlParser::parsing_common(const QString &xmlData)
       
   107 {
       
   108     QDBusIntrospection::ObjectTree obj =
       
   109         QDBusIntrospection::parseObjectTree(xmlData, "local.testing", "/");
       
   110     QFETCH(int, interfaceCount);
       
   111     QFETCH(int, objectCount);
       
   112     QCOMPARE(obj.interfaces.count(), interfaceCount);
       
   113     QCOMPARE(obj.childObjects.count(), objectCount);
       
   114 
       
   115     // also verify the naming
       
   116     int i = 0;
       
   117     foreach (QString name, obj.interfaces)
       
   118         QCOMPARE(name, QString("iface.iface%1").arg(++i));
       
   119 
       
   120     i = 0;
       
   121     foreach (QString name, obj.childObjects)
       
   122         QCOMPARE(name, QString("obj%1").arg(++i));
       
   123 }
       
   124 
       
   125 void tst_QDBusXmlParser::parsing()
       
   126 {
       
   127     QFETCH(QString, xmlData);
       
   128 
       
   129     parsing_common(xmlData);
       
   130 }
       
   131 
       
   132 void tst_QDBusXmlParser::parsingWithDoctype_data()
       
   133 {
       
   134     parsing_data();
       
   135 }
       
   136 
       
   137 void tst_QDBusXmlParser::parsingWithDoctype()
       
   138 {
       
   139     QString docType = "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
       
   140                       "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n";
       
   141     QFETCH(QString, xmlData);
       
   142 
       
   143     parsing_common(docType + xmlData);
       
   144 }    
       
   145 
       
   146 void tst_QDBusXmlParser::objectWithContent_data()
       
   147 {
       
   148     QTest::addColumn<QString>("xmlData");
       
   149     QTest::addColumn<QString>("probedObject");
       
   150     QTest::addColumn<int>("interfaceCount");
       
   151     QTest::addColumn<int>("objectCount");
       
   152 
       
   153     QTest::newRow("zero") << "<node><node name=\"obj\"/></node>" << "obj" << 0 << 0;
       
   154 
       
   155     QString xmlData = "<node><node name=\"obj\">"
       
   156                       "<interface name=\"iface.iface1\" />"
       
   157                       "</node></node>";
       
   158     QTest::newRow("one-interface") << xmlData << "obj" << 1 << 0;
       
   159     QTest::newRow("one-interface2") << xmlData << "obj2" << 0 << 0;
       
   160 
       
   161     xmlData = "<node><node name=\"obj\">"
       
   162               "<interface name=\"iface.iface1\" />"
       
   163               "<interface name=\"iface.iface2\" />"
       
   164               "</node></node>";
       
   165     QTest::newRow("two-interfaces") << xmlData << "obj" << 2 << 0;
       
   166     QTest::newRow("two-interfaces2") << xmlData << "obj2" << 0 << 0;
       
   167 
       
   168     xmlData = "<node><node name=\"obj\">"
       
   169               "<interface name=\"iface.iface1\" />"
       
   170               "<interface name=\"iface.iface2\" />"
       
   171               "</node><node name=\"obj2\">"
       
   172               "<interface name=\"iface.iface1\" />"
       
   173               "</node></node>";
       
   174     QTest::newRow("two-nodes-two-interfaces") << xmlData << "obj" << 2 << 0;
       
   175     QTest::newRow("two-nodes-one-interface") << xmlData << "obj2" << 1 << 0;
       
   176 
       
   177     xmlData = "<node><node name=\"obj\">"
       
   178               "<node name=\"obj1\" />"
       
   179               "</node></node>";
       
   180     QTest::newRow("one-object") << xmlData << "obj" << 0 << 1;
       
   181     QTest::newRow("one-object2") << xmlData << "obj2" << 0 << 0;
       
   182 
       
   183     xmlData = "<node><node name=\"obj\">"
       
   184               "<node name=\"obj1\" />"
       
   185               "<node name=\"obj2\" />"
       
   186               "</node></node>";
       
   187     QTest::newRow("two-objects") << xmlData << "obj" << 0 << 2;
       
   188     QTest::newRow("two-objects2") << xmlData << "obj2" << 0 << 0;
       
   189 
       
   190     xmlData = "<node><node name=\"obj\">"
       
   191               "<node name=\"obj1\" />"
       
   192               "<node name=\"obj2\" />"
       
   193               "</node><node name=\"obj2\">"
       
   194               "<node name=\"obj1\" />"
       
   195               "</node></node>";
       
   196     QTest::newRow("two-nodes-two-objects") << xmlData << "obj" << 0 << 2;
       
   197     QTest::newRow("two-nodes-one-object") << xmlData << "obj2" << 0 << 1;
       
   198 }
       
   199 
       
   200 void tst_QDBusXmlParser::objectWithContent()
       
   201 {
       
   202     QFETCH(QString, xmlData);
       
   203     QFETCH(QString, probedObject);
       
   204 
       
   205     QDBusIntrospection::ObjectTree tree =
       
   206         QDBusIntrospection::parseObjectTree(xmlData, "local.testing", "/");
       
   207 
       
   208     const ObjectMap &om = tree.childObjectData;
       
   209 
       
   210     if (om.contains(probedObject)) {
       
   211         const QSharedDataPointer<QDBusIntrospection::ObjectTree>& obj = om.value(probedObject);
       
   212         QVERIFY(obj != 0);
       
   213     
       
   214         QFETCH(int, interfaceCount);
       
   215         QFETCH(int, objectCount);
       
   216 
       
   217         QCOMPARE(obj->interfaces.count(), interfaceCount);
       
   218         QCOMPARE(obj->childObjects.count(), objectCount);
       
   219 
       
   220         // verify the object names
       
   221         int i = 0;
       
   222         foreach (QString name, obj->interfaces)
       
   223             QCOMPARE(name, QString("iface.iface%1").arg(++i));
       
   224 
       
   225         i = 0;
       
   226         foreach (QString name, obj->childObjects)
       
   227             QCOMPARE(name, QString("obj%1").arg(++i));
       
   228     }
       
   229 }
       
   230 
       
   231 void tst_QDBusXmlParser::methods_data()
       
   232 {
       
   233     QTest::addColumn<QString>("xmlDataFragment");
       
   234     QTest::addColumn<MethodMap>("methodMap");
       
   235 
       
   236     MethodMap map;
       
   237     QTest::newRow("no-methods") << QString() << map;
       
   238 
       
   239     // one method without arguments
       
   240     QDBusIntrospection::Method method;
       
   241     method.name = "Foo";
       
   242     map << method;
       
   243     QTest::newRow("one-method") << "<method name=\"Foo\"/>" << map;
       
   244 
       
   245     // add another method without arguments
       
   246     method.name = "Bar";
       
   247     map << method;
       
   248     QTest::newRow("two-methods") << "<method name=\"Foo\"/>"
       
   249                                     "<method name=\"Bar\"/>"
       
   250                                  << map;
       
   251 
       
   252     // invert the order of the XML declaration
       
   253     QTest::newRow("two-methods-inverse") << "<method name=\"Bar\"/>"
       
   254                                             "<method name=\"Foo\"/>"
       
   255                                          << map;
       
   256 
       
   257     // add a third, with annotations
       
   258     method.name = "Baz";
       
   259     method.annotations.insert("foo.testing", "nothing to see here");
       
   260     map << method;
       
   261     QTest::newRow("method-with-annotation") <<
       
   262         "<method name=\"Foo\"/>"
       
   263         "<method name=\"Bar\"/>"
       
   264         "<method name=\"Baz\"><annotation name=\"foo.testing\" value=\"nothing to see here\"></method>"
       
   265                                             << map;
       
   266 
       
   267     // arguments
       
   268     map.clear();
       
   269     method.annotations.clear();
       
   270 
       
   271     method.name = "Method";
       
   272     method.inputArgs << arg("s");
       
   273     map << method;
       
   274     QTest::newRow("one-in") <<
       
   275         "<method name=\"Method\">"
       
   276         "<arg type=\"s\" direction=\"in\"/>"
       
   277         "</method>" << map;
       
   278 
       
   279     // two arguments
       
   280     method.inputArgs << arg("v");
       
   281     map.clear();
       
   282     map << method;
       
   283     QTest::newRow("two-in") <<
       
   284         "<method name=\"Method\">"
       
   285         "<arg type=\"s\" direction=\"in\"/>"
       
   286         "<arg type=\"v\" direction=\"in\"/>"
       
   287         "</method>" << map;
       
   288 
       
   289     // one invalid arg
       
   290     QTest::newRow("two-in-one-invalid") <<
       
   291         "<method name=\"Method\">"
       
   292         "<arg type=\"s\" direction=\"in\"/>"
       
   293         "<arg type=\"~\" name=\"invalid\" direction=\"in\"/>" // this line should be ignored
       
   294         "<arg type=\"v\" direction=\"in\"/>"
       
   295         "</method>" << map;
       
   296 
       
   297     // one out argument
       
   298     method.inputArgs.clear();
       
   299     method.outputArgs << arg("s");
       
   300     map.clear();
       
   301     map << method;
       
   302     QTest::newRow("one-out") <<
       
   303         "<method name=\"Method\">"
       
   304         "<arg type=\"s\" direction=\"out\"/>"
       
   305         "</method>" << map;
       
   306 
       
   307     // two in and one out
       
   308     method.inputArgs << arg("s") << arg("v");
       
   309     map.clear();
       
   310     map << method;
       
   311     QTest::newRow("two-in-one-out") <<
       
   312         "<method name=\"Method\">"
       
   313         "<arg type=\"s\" direction=\"in\"/>"
       
   314         "<arg type=\"v\" direction=\"in\"/>"
       
   315         "<arg type=\"s\" direction=\"out\"/>"
       
   316         "</method>" << map;
       
   317 
       
   318     // let's try an arg with name
       
   319     method.outputArgs.clear();
       
   320     method.inputArgs.clear();
       
   321     method.inputArgs << arg("s", "foo");
       
   322     map.clear();
       
   323     map << method;
       
   324     QTest::newRow("one-in-with-name") <<
       
   325         "<method name=\"Method\">"
       
   326         "<arg type=\"s\" name=\"foo\" direction=\"in\"/>"
       
   327         "</method>" << map;
       
   328 
       
   329     // two args with name
       
   330     method.inputArgs << arg("i", "bar");
       
   331     map.clear();
       
   332     map << method;
       
   333     QTest::newRow("two-in-with-name") <<
       
   334         "<method name=\"Method\">"
       
   335         "<arg type=\"s\" name=\"foo\" direction=\"in\"/>"
       
   336         "<arg type=\"i\" name=\"bar\" direction=\"in\"/>"
       
   337         "</method>" << map;
       
   338 
       
   339     // one complex
       
   340     map.clear();
       
   341     method = QDBusIntrospection::Method();
       
   342 
       
   343     // Method1(in STRING arg1, in BYTE arg2, out ARRAY of STRING)
       
   344     method.inputArgs << arg("s", "arg1") << arg("y", "arg2");
       
   345     method.outputArgs << arg("as");
       
   346     method.name = "Method1";
       
   347     map << method;
       
   348 
       
   349     // Method2(in ARRAY of DICT_ENTRY of (STRING,VARIANT) variantMap, in UINT32 index,
       
   350     //         out STRING key, out VARIANT value)
       
   351     // with annotation "foo.equivalent":"QVariantMap"
       
   352     method = QDBusIntrospection::Method();
       
   353     method.inputArgs << arg("a{sv}", "variantMap") << arg("u", "index");
       
   354     method.outputArgs << arg("s", "key") << arg("v", "value");
       
   355     method.annotations.insert("foo.equivalent", "QVariantMap");
       
   356     method.name = "Method2";
       
   357     map << method;
       
   358 
       
   359     QTest::newRow("complex") <<
       
   360         "<method name=\"Method1\">"
       
   361         "<arg name=\"arg1\" type=\"s\" direction=\"in\"/>"
       
   362         "<arg name=\"arg2\" type=\"y\" direction=\"in\"/>"
       
   363         "<arg type=\"as\" direction=\"out\"/>"
       
   364         "</method>"
       
   365         "<method name=\"Method2\">"
       
   366         "<arg name=\"variantMap\" type=\"a{sv}\" direction=\"in\"/>"
       
   367         "<arg name=\"index\" type=\"u\" direction=\"in\"/>"
       
   368         "<arg name=\"key\" type=\"s\" direction=\"out\"/>"
       
   369         "<arg name=\"value\" type=\"v\" direction=\"out\"/>"
       
   370         "<annotation name=\"foo.equivalent\" value=\"QVariantMap\"/>"
       
   371         "</method>" << map;
       
   372 }
       
   373 
       
   374 void tst_QDBusXmlParser::methods()
       
   375 {
       
   376     QString xmlHeader = "<node>"
       
   377                         "<interface name=\"iface.iface1\">",
       
   378             xmlFooter = "</interface>"
       
   379                         "</node>";
       
   380 
       
   381     QFETCH(QString, xmlDataFragment);
       
   382 
       
   383     if (strcmp(QTest::currentDataTag(), "two-in-one-invalid") == 0)
       
   384         QTest::ignoreMessage(QtWarningMsg, "Invalid D-BUS type signature '~' found while parsing introspection");
       
   385     QDBusIntrospection::Interface iface =
       
   386         QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter);
       
   387 
       
   388     QCOMPARE(iface.name, QString("iface.iface1"));
       
   389 
       
   390     QFETCH(MethodMap, methodMap);
       
   391     MethodMap parsedMap = iface.methods;
       
   392 
       
   393     QCOMPARE(methodMap.count(), parsedMap.count());
       
   394     QCOMPARE(methodMap, parsedMap);
       
   395 }             
       
   396 
       
   397 void tst_QDBusXmlParser::signals__data()
       
   398 {
       
   399     QTest::addColumn<QString>("xmlDataFragment");
       
   400     QTest::addColumn<SignalMap>("signalMap");
       
   401 
       
   402     SignalMap map;
       
   403     QTest::newRow("no-signals") << QString() << map;
       
   404 
       
   405     // one signal without arguments
       
   406     QDBusIntrospection::Signal signal;
       
   407     signal.name = "Foo";
       
   408     map << signal;
       
   409     QTest::newRow("one-signal") << "<signal name=\"Foo\"/>" << map;
       
   410 
       
   411     // add another signal without arguments
       
   412     signal.name = "Bar";
       
   413     map << signal;
       
   414     QTest::newRow("two-signals") << "<signal name=\"Foo\"/>"
       
   415                                     "<signal name=\"Bar\"/>"
       
   416                                  << map;
       
   417 
       
   418     // invert the order of the XML declaration
       
   419     QTest::newRow("two-signals-inverse") << "<signal name=\"Bar\"/>"
       
   420                                             "<signal name=\"Foo\"/>"
       
   421                                          << map;
       
   422 
       
   423     // add a third, with annotations
       
   424     signal.name = "Baz";
       
   425     signal.annotations.insert("foo.testing", "nothing to see here");
       
   426     map << signal;
       
   427     QTest::newRow("signal-with-annotation") <<
       
   428         "<signal name=\"Foo\"/>"
       
   429         "<signal name=\"Bar\"/>"
       
   430         "<signal name=\"Baz\"><annotation name=\"foo.testing\" value=\"nothing to see here\"></signal>"
       
   431                                             << map;
       
   432 
       
   433     // one out argument
       
   434     map.clear();
       
   435     signal.annotations.clear();
       
   436     signal.outputArgs << arg("s");
       
   437     signal.name = "Signal";
       
   438     map.clear();
       
   439     map << signal;
       
   440     QTest::newRow("one-out") <<
       
   441         "<signal name=\"Signal\">"
       
   442         "<arg type=\"s\" direction=\"out\"/>"
       
   443         "</signal>" << map;
       
   444 
       
   445     // without saying which direction it is
       
   446     QTest::newRow("one-out-no-direction") <<
       
   447         "<signal name=\"Signal\">"
       
   448         "<arg type=\"s\"/>"
       
   449         "</signal>" << map;    
       
   450 
       
   451     // two args with name
       
   452     signal.outputArgs << arg("i", "bar");
       
   453     map.clear();
       
   454     map << signal;
       
   455     QTest::newRow("two-out-with-name") <<
       
   456         "<signal name=\"Signal\">"
       
   457         "<arg type=\"s\" direction=\"out\"/>"
       
   458         "<arg type=\"i\" name=\"bar\"/>"
       
   459         "</signal>" << map;
       
   460 
       
   461     // one complex
       
   462     map.clear();
       
   463     signal = QDBusIntrospection::Signal();
       
   464 
       
   465     // Signal1(out ARRAY of STRING)
       
   466     signal.outputArgs << arg("as");
       
   467     signal.name = "Signal1";
       
   468     map << signal;
       
   469 
       
   470     // Signal2(out STRING key, out VARIANT value)
       
   471     // with annotation "foo.equivalent":"QVariantMap"
       
   472     signal = QDBusIntrospection::Signal();
       
   473     signal.outputArgs << arg("s", "key") << arg("v", "value");
       
   474     signal.annotations.insert("foo.equivalent", "QVariantMap");
       
   475     signal.name = "Signal2";
       
   476     map << signal;
       
   477 
       
   478     QTest::newRow("complex") <<
       
   479         "<signal name=\"Signal1\">"
       
   480         "<arg type=\"as\" direction=\"out\"/>"
       
   481         "</signal>"
       
   482         "<signal name=\"Signal2\">"
       
   483         "<arg name=\"key\" type=\"s\" direction=\"out\"/>"
       
   484         "<arg name=\"value\" type=\"v\" direction=\"out\"/>"
       
   485         "<annotation name=\"foo.equivalent\" value=\"QVariantMap\"/>"
       
   486         "</signal>" << map;
       
   487 }
       
   488 
       
   489 void tst_QDBusXmlParser::signals_()
       
   490 {
       
   491     QString xmlHeader = "<node>"
       
   492                         "<interface name=\"iface.iface1\">",
       
   493             xmlFooter = "</interface>"
       
   494                         "</node>";
       
   495 
       
   496     QFETCH(QString, xmlDataFragment);
       
   497 
       
   498     QDBusIntrospection::Interface iface =
       
   499         QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter);
       
   500 
       
   501     QCOMPARE(iface.name, QString("iface.iface1"));
       
   502 
       
   503     QFETCH(SignalMap, signalMap);
       
   504     SignalMap parsedMap = iface.signals_;
       
   505 
       
   506     QCOMPARE(signalMap.count(), parsedMap.count());
       
   507     QCOMPARE(signalMap, parsedMap);
       
   508 }
       
   509 
       
   510 void tst_QDBusXmlParser::properties_data()
       
   511 {
       
   512     QTest::addColumn<QString>("xmlDataFragment");
       
   513     QTest::addColumn<PropertyMap>("propertyMap");
       
   514 
       
   515     PropertyMap map;
       
   516     QTest::newRow("no-signals") << QString() << map;
       
   517 
       
   518     // one readable signal
       
   519     QDBusIntrospection::Property prop;
       
   520     prop.name = "foo";
       
   521     prop.type = "s";
       
   522     prop.access = QDBusIntrospection::Property::Read;
       
   523     map << prop;
       
   524     QTest::newRow("one-readable") << "<property name=\"foo\" type=\"s\" access=\"read\"/>" << map;
       
   525 
       
   526     // one writable signal
       
   527     prop.access = QDBusIntrospection::Property::Write;
       
   528     map.clear();
       
   529     map << prop;
       
   530     QTest::newRow("one-writable") << "<property name=\"foo\" type=\"s\" access=\"write\"/>" << map;
       
   531 
       
   532     // one read- & writable signal
       
   533     prop.access = QDBusIntrospection::Property::ReadWrite;
       
   534     map.clear();
       
   535     map << prop;
       
   536     QTest::newRow("one-read-writable") << "<property name=\"foo\" type=\"s\" access=\"readwrite\"/>"
       
   537                                        << map;
       
   538 
       
   539     // two, mixed properties
       
   540     prop.name = "bar";
       
   541     prop.type = "i";
       
   542     prop.access = QDBusIntrospection::Property::Read;
       
   543     map << prop;
       
   544     QTest::newRow("two") <<
       
   545         "<property name=\"foo\" type=\"s\" access=\"readwrite\"/>"
       
   546         "<property name=\"bar\" type=\"i\" access=\"read\"/>" << map;
       
   547 
       
   548     // invert the order of the declaration
       
   549     QTest::newRow("two") <<
       
   550         "<property name=\"bar\" type=\"i\" access=\"read\"/>"
       
   551         "<property name=\"foo\" type=\"s\" access=\"readwrite\"/>" << map;
       
   552 
       
   553     // add a third with annotations
       
   554     prop.name = "baz";
       
   555     prop.type = "as";
       
   556     prop.access = QDBusIntrospection::Property::Write;
       
   557     prop.annotations.insert("foo.annotation", "Hello, World");
       
   558     prop.annotations.insert("foo.annotation2", "Goodbye, World");
       
   559     map << prop;
       
   560     QTest::newRow("complex") <<
       
   561         "<property name=\"bar\" type=\"i\" access=\"read\"/>"
       
   562         "<property name=\"baz\" type=\"as\" access=\"write\">"
       
   563         "<annotation name=\"foo.annotation\" value=\"Hello, World\" />"
       
   564         "<annotation name=\"foo.annotation2\" value=\"Goodbye, World\" />"
       
   565         "<property name=\"foo\" type=\"s\" access=\"readwrite\"/>" << map;
       
   566 
       
   567     // and now change the order
       
   568     QTest::newRow("complex2") <<
       
   569         "<property name=\"baz\" type=\"as\" access=\"write\">"
       
   570         "<annotation name=\"foo.annotation2\" value=\"Goodbye, World\" />"
       
   571         "<annotation name=\"foo.annotation\" value=\"Hello, World\" />"
       
   572         "<property name=\"bar\" type=\"i\" access=\"read\"/>"
       
   573         "<property name=\"foo\" type=\"s\" access=\"readwrite\"/>" << map;
       
   574 }
       
   575 
       
   576 void tst_QDBusXmlParser::properties()
       
   577 {
       
   578     QString xmlHeader = "<node>"
       
   579                         "<interface name=\"iface.iface1\">",
       
   580             xmlFooter = "</interface>"
       
   581                         "</node>";
       
   582 
       
   583     QFETCH(QString, xmlDataFragment);
       
   584 
       
   585     QDBusIntrospection::Interface iface =
       
   586         QDBusIntrospection::parseInterface(xmlHeader + xmlDataFragment + xmlFooter);
       
   587 
       
   588     QCOMPARE(iface.name, QString("iface.iface1"));
       
   589 
       
   590     QFETCH(PropertyMap, propertyMap);
       
   591     PropertyMap parsedMap = iface.properties;
       
   592 
       
   593     QCOMPARE(propertyMap.count(), parsedMap.count());
       
   594     QCOMPARE(propertyMap, parsedMap);
       
   595 }
       
   596 
       
   597 QTEST_MAIN(tst_QDBusXmlParser)
       
   598 
       
   599 #include "tst_qdbusxmlparser.moc"