tests/auto/servicedatabase/tst_servicedatabase.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 Qt Mobility Components.
       
     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 #include <QtTest/QtTest>
       
    42 #include <QtCore>
       
    43 #define private public
       
    44 #include <qserviceinterfacedescriptor.h>
       
    45 #include <qserviceinterfacedescriptor_p.h>
       
    46 #include <servicedatabase_p.h>
       
    47 #include <qservicefilter.h>
       
    48 
       
    49 #define RESOLVERDATABASE "services.db"
       
    50 
       
    51 #if defined(Q_OS_SYMBIAN)
       
    52 # define TESTDATA_DIR "."
       
    53 #endif
       
    54 
       
    55 QTM_USE_NAMESPACE
       
    56 class ServiceDatabaseUnitTest: public QObject
       
    57 {
       
    58     Q_OBJECT
       
    59 
       
    60 private slots:
       
    61     void initTestCase();
       
    62     void testRegistration();
       
    63     void getInterfaces();
       
    64     void searchByInterfaceName();
       
    65     void searchByInterfaceAndService();
       
    66     void searchByCustomAttribute();
       
    67     void searchByCapability();
       
    68     void attributes();
       
    69     void getServiceNames();
       
    70     void defaultExternalIfaceIDs();
       
    71     void interfaceDefault();
       
    72     void setInterfaceDefault();
       
    73     void unregister();
       
    74     void securityTokens();
       
    75     void cleanupTestCase();
       
    76 
       
    77 private:
       
    78 
       
    79      bool compareDescriptor(QServiceInterfaceDescriptor interface,
       
    80                             QString interfaceName,
       
    81                             QString serviceName,
       
    82                             int majorVersion,
       
    83                             int minorVersion);
       
    84 
       
    85     bool compareDescriptor(QServiceInterfaceDescriptor interface,
       
    86                             QString interfaceName,
       
    87                             QString serviceName,
       
    88                             int majorVersion,
       
    89                             int minorVersion,
       
    90                             QStringList capabilities,
       
    91                             const QHash<QString,QString> customProps,
       
    92                             QString filePath="",
       
    93                             QString serviceDescription="",
       
    94                             QString interfaceDescription=""); 
       
    95 
       
    96     QStringList getInterfaceIDs(const QString &serviceName);
       
    97     QStringList getServiceIDs(const QString &serviceName);
       
    98     bool existsInInterfacePropertyTable(const QString &interfaceID);
       
    99     bool existsInServicePropertyTable(const QString &serviceID);
       
   100     bool existsInDefaultsTable(const QString &interfaceID);
       
   101     bool registerService(const ServiceMetaDataResults &service, const QString &securityToken = QString());
       
   102     bool unregisterService(const QString &serviceName, const QString &securityToken = QString());
       
   103 
       
   104     ServiceMetaData* parser;
       
   105     ServiceDatabase database;
       
   106 };
       
   107 
       
   108 void ServiceDatabaseUnitTest::initTestCase()
       
   109 {
       
   110 #if defined(Q_OS_SYMBIAN)
       
   111     database.m_databasePath = QDir::toNativeSeparators(QDir::currentPath().append("/services.db"));
       
   112 #endif
       
   113     database.close();
       
   114     QFile::remove(database.databasePath());
       
   115 }
       
   116 
       
   117 static const QString securityTokenOwner("SecurityTokenOwner");
       
   118 static const QString securityTokenStranger("SecurityTokenStranger");
       
   119 
       
   120 void ServiceDatabaseUnitTest::testRegistration()
       
   121 {
       
   122     QDir testdir = QDir(TESTDATA_DIR "/testdata" );
       
   123 
       
   124     ServiceMetaData parser(testdir.absoluteFilePath("ServiceAcme.xml"));
       
   125     QVERIFY(parser.extractMetadata());
       
   126     QVERIFY(!registerService(parser.parseResults()));
       
   127 
       
   128     QCOMPARE(database.lastError().code(), DBError::DatabaseNotOpen);
       
   129 #if defined(Q_OS_SYMBIAN)
       
   130     database.m_databasePath = QDir::toNativeSeparators(QDir::currentPath().append("/services.db"));
       
   131 #endif
       
   132     QVERIFY(database.open());
       
   133     QVERIFY(registerService(parser.parseResults()));
       
   134 
       
   135     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceOmni.xml")));
       
   136     QVERIFY(parser.extractMetadata());
       
   137     QVERIFY(registerService(parser.parseResults()));
       
   138 
       
   139     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceLuthorCorp.xml")));
       
   140     QVERIFY(parser.extractMetadata());
       
   141     QVERIFY(registerService(parser.parseResults()));
       
   142 
       
   143     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceWayneEnt.xml")));
       
   144     QVERIFY(parser.extractMetadata());
       
   145     QVERIFY(registerService(parser.parseResults()));
       
   146 
       
   147     parser.setDevice(new QFile(testdir.absoluteFilePath("ServicePrimatech.xml")));
       
   148     QVERIFY(parser.extractMetadata());
       
   149     QVERIFY(registerService(parser.parseResults()));
       
   150 
       
   151     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceCyberdyne.xml")));
       
   152     QVERIFY(parser.extractMetadata());
       
   153     QVERIFY(registerService(parser.parseResults()));
       
   154 
       
   155     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceSkynet.xml")));
       
   156     QVERIFY(parser.extractMetadata());
       
   157     QVERIFY(registerService(parser.parseResults()));
       
   158 
       
   159     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceAutobot.xml")));
       
   160     QVERIFY(parser.extractMetadata());
       
   161     QVERIFY(registerService(parser.parseResults()));
       
   162 
       
   163     //try to register an already registered service
       
   164     QVERIFY(!registerService(parser.parseResults()));
       
   165     QCOMPARE(database.lastError().code(), DBError::LocationAlreadyRegistered);
       
   166 
       
   167     //try to register a service with a dll that provides interface implementations
       
   168     //that are already provided by a currently registered service
       
   169     parser.setDevice(new QFile(testdir.absoluteFilePath("ServicePrimatech2error.xml")));
       
   170     QVERIFY(parser.extractMetadata());
       
   171     QVERIFY(!registerService(parser.parseResults()));
       
   172     QCOMPARE(database.lastError().code(), DBError::IfaceImplAlreadyRegistered);
       
   173 
       
   174     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceYamagatoError.xml")));
       
   175     QVERIFY(parser.extractMetadata());
       
   176     QVERIFY(!registerService(parser.parseResults()));
       
   177     QCOMPARE(database.lastError().code(), DBError::LocationAlreadyRegistered);
       
   178 
       
   179     //make sure errors above are corectly rolled back by
       
   180     //registering a valid service
       
   181     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceDecepticon.xml")));
       
   182     QVERIFY(parser.extractMetadata());
       
   183     QVERIFY(registerService(parser.parseResults()));
       
   184 
       
   185     QStringList xmlFiles;
       
   186     xmlFiles << "ServiceDharma_Swan.xml"
       
   187              << "ServiceDharma_Pearl.xml"
       
   188              << "ServiceDharma_Flame.xml";
       
   189 
       
   190     foreach(const QString &file, xmlFiles) {
       
   191         //Check that when we register a service we reseed
       
   192         //the random number generator so we don't have
       
   193         //any service id clashes.  To verify this is
       
   194         //happening we set the seed here to 1.
       
   195         qsrand(1);
       
   196         parser.setDevice(new QFile(testdir.absoluteFilePath(file)));
       
   197         QVERIFY(parser.extractMetadata());
       
   198         QVERIFY(registerService(parser.parseResults()));
       
   199     }
       
   200 
       
   201     QVERIFY(database.close());
       
   202     QVERIFY(database.close());  //verify we can close multiple times
       
   203                                 //without side effects
       
   204 }
       
   205 
       
   206 void ServiceDatabaseUnitTest::getInterfaces()
       
   207 {
       
   208     QServiceFilter filter;
       
   209     QList<QServiceInterfaceDescriptor> interfaces;
       
   210 
       
   211     filter.setServiceName("acme");
       
   212     interfaces = database.getInterfaces(filter);
       
   213     QCOMPARE(database.lastError().code(), DBError::DatabaseNotOpen);
       
   214     QVERIFY(database.close());  //check we can close the database even if it
       
   215                                 //has not been opened
       
   216 
       
   217     QVERIFY(database.open());
       
   218     interfaces = database.getInterfaces(filter);
       
   219     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   220     QCOMPARE(interfaces.count(), 5);
       
   221 
       
   222     QHash<QString,QString> customs;
       
   223     QStringList capabilities;
       
   224     compareDescriptor(interfaces[0], "com.acme.service.downloader", "acme", 1, 0, capabilities, customs, "C:/TestData/testservice.dll",
       
   225             "Acme services", "Interface that provides download support");
       
   226 
       
   227     QServiceInterfaceDescriptor interface;
       
   228     customs["coordinate"] = QString("global");
       
   229     QVERIFY(compareDescriptor(interfaces[1], "com.acme.service.location", "acme", 1,0, capabilities,customs,  "C:/TestData/testservice.dll"));
       
   230 
       
   231     customs.clear();
       
   232     customs["cpu"]=QString("");
       
   233     capabilities.append(QString("ReadUserData"));
       
   234     QVERIFY(compareDescriptor(interfaces[2], "com.acme.device.sysinfo", "acme", 2, 3, capabilities, customs, "C:/TestData/testservice.dll"));
       
   235 
       
   236     customs.clear();
       
   237     customs["smtp"]=QString("smtp.mail.com");
       
   238     capabilities.clear();
       
   239     capabilities.append("ReadUserData");
       
   240     capabilities.append("WriteUserData");
       
   241     QVERIFY(compareDescriptor(interfaces[3], "com.acme.device.sendMessage", "acme", 3, 0, capabilities,customs,  "C:/TestData/testservice.dll"));
       
   242 
       
   243     customs.clear();
       
   244     customs["imap"]=QString("imap.mail.com");
       
   245     customs["pop"]=QString("pop.mail.com");
       
   246     capabilities.clear();
       
   247     capabilities.append("ReadUserData");
       
   248     capabilities.append("WriteUserData");
       
   249     capabilities.append("ExecUserData");
       
   250     QVERIFY(compareDescriptor(interfaces[4], "com.acme.device.receiveMessage", "acme", 1, 1, capabilities, customs, "C:/TestData/testservice.dll"));
       
   251 
       
   252     //check that searching is case insensitive
       
   253     filter.setServiceName("OmNi");
       
   254     interfaces = database.getInterfaces(filter);
       
   255     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   256     QCOMPARE(interfaces.count(), 3);
       
   257 
       
   258     customs.clear();
       
   259     capabilities.clear();
       
   260     capabilities << "SurroundingsDD";
       
   261     QVERIFY(compareDescriptor(interfaces[0], "com.omni.device.Accelerometer", "OMNI", 1, 1, capabilities, customs, "C:/OmniInc/omniinc.dll",
       
   262                 "Omni mobile", "Interface that provides accelerometer readings(omni)"));
       
   263 
       
   264     capabilities.clear();
       
   265     QVERIFY(compareDescriptor(interfaces[1], "com.omni.device.Lights","OMNI", 9, 0, capabilities, customs, "C:/OmniInc/omniinc.dll"));
       
   266 
       
   267     capabilities.clear();
       
   268     capabilities << "MultimediaDD" << "NetworkServices" << "ReadUserData" << "WriteUserData";
       
   269     QVERIFY(compareDescriptor(interfaces[2], "com.omni.service.Video", "OMNI", 1, 4, capabilities, customs, "C:/OmniInc/omniinc.dll"));
       
   270 
       
   271     QVERIFY(database.close());
       
   272 }
       
   273 
       
   274 void ServiceDatabaseUnitTest::searchByInterfaceName()
       
   275 {
       
   276     QServiceFilter filter;
       
   277     QList<QServiceInterfaceDescriptor> interfaces;
       
   278 
       
   279     QVERIFY(database.open());
       
   280 
       
   281     QString iface = "com.omni.device.Accelerometer";
       
   282     // == search via interface name only ==
       
   283     filter.setInterface(iface);
       
   284     interfaces = database.getInterfaces(filter);
       
   285 
       
   286     QCOMPARE(interfaces.count(), 5);
       
   287     QHash<QString,QString> customs;
       
   288     QStringList capabilities;
       
   289     capabilities << "SurroundingsDD";
       
   290     QVERIFY(compareDescriptor(interfaces[0], iface, "OMNI", 1, 1, capabilities,customs,"C:/OmniInc/omniinc.dll",
       
   291                "Omni mobile", "Interface that provides accelerometer readings(omni)"));
       
   292     QVERIFY(compareDescriptor(interfaces[1], iface, "LuthorCorp", 1, 2, capabilities,customs,"C:/Metropolis/kryptonite.dll",
       
   293            "", "Interface that provides accelerometer readings")); //service description is empty tag in xml
       
   294     QVERIFY(compareDescriptor(interfaces[2], iface, "WayneEnt", 2, 0, capabilities,customs,"C:/Gotham/knight.dll",
       
   295             "", "Interface that provides accelerometer readings"));//no service description tag in xml
       
   296     QVERIFY(compareDescriptor(interfaces[3], iface, "Primatech", 1, 4, capabilities,customs,"C:/NewYork/kensei.dll",
       
   297                 "Primatech Cellular Services", "Interface that provides accelerometer readings"));
       
   298     QVERIFY(compareDescriptor(interfaces[4], iface, "Primatech", 1, 2, capabilities,customs,"C:/NewYork/kensei.dll",
       
   299                 "Primatech Cellular Services", "Interface that provides accelerometer readings"));
       
   300 
       
   301     //search with non-existent interface name
       
   302     filter.setInterface("com.omni.device.FluxCapacitor");
       
   303     interfaces = database.getInterfaces(filter);
       
   304 
       
   305     QCOMPARE(interfaces.count(), 0);
       
   306 
       
   307     // == search for an exact version match ==
       
   308     filter.setInterface(iface, "1.4", QServiceFilter::ExactVersionMatch);
       
   309     interfaces = database.getInterfaces(filter);
       
   310 
       
   311     QCOMPARE(interfaces.count(), 1);
       
   312     QVERIFY(compareDescriptor(interfaces[0], iface, "Primatech", 1, 4));
       
   313 
       
   314     //try exact version match but with multiple expected instances returned.
       
   315     filter.setInterface("com.oMNi.device.accelerometer", "1.2", QServiceFilter::ExactVersionMatch); //also test case insensitivity
       
   316     interfaces = database.getInterfaces(filter);
       
   317 
       
   318     QCOMPARE(interfaces.count(), 2);
       
   319     QVERIFY(compareDescriptor(interfaces[0], iface, "LuthorCorp", 1, 2));
       
   320     QVERIFY(compareDescriptor(interfaces[1], iface, "Primatech", 1, 2));
       
   321 
       
   322     //try exact match for an interface that exists but a version that doesn't
       
   323     filter.setInterface(iface,"1.3", QServiceFilter::ExactVersionMatch);
       
   324     interfaces = database.getInterfaces(filter);
       
   325     QCOMPARE(interfaces.count(), 0);
       
   326 
       
   327     // == search for a minimum version match ==
       
   328     filter.setInterface(iface,"1.2", QServiceFilter::MinimumVersionMatch);//use existent version
       
   329     interfaces = database.getInterfaces(filter);
       
   330     QCOMPARE(interfaces.count(), 4);
       
   331 
       
   332     QVERIFY(compareDescriptor(interfaces[0], iface, "LuthorCorp", 1, 2));
       
   333     QVERIFY(compareDescriptor(interfaces[1], iface, "WayneEnt", 2, 0));
       
   334     QVERIFY(compareDescriptor(interfaces[2], iface, "Primatech", 1, 4));
       
   335     QVERIFY(compareDescriptor(interfaces[3], iface, "Primatech", 1, 2));
       
   336 
       
   337     filter.setInterface(iface, "1.3", QServiceFilter::MinimumVersionMatch);//use non-existent version
       
   338     interfaces = database.getInterfaces(filter);
       
   339     QCOMPARE(interfaces.count(), 2);
       
   340     QVERIFY(compareDescriptor(interfaces[0], iface, "WayneEnt", 2, 0));
       
   341     QVERIFY(compareDescriptor(interfaces[1], iface, "Primatech", 1, 4));
       
   342 
       
   343     //try minimum version match that will find all available versions
       
   344     filter.setInterface(iface,"1.0", QServiceFilter::MinimumVersionMatch);
       
   345     interfaces = database.getInterfaces(filter);
       
   346     QCOMPARE(interfaces.count(), 5);
       
   347 
       
   348     //try minimum version match but no implementations are available
       
   349     filter.setInterface(iface,"9.0", QServiceFilter::MinimumVersionMatch);//use non-existent version
       
   350     interfaces = database.getInterfaces(filter);
       
   351     QCOMPARE(interfaces.count(), 0);
       
   352 
       
   353     //try setting an invalid version (should default to interface name search)
       
   354     filter.setInterface(iface,"-1.0", QServiceFilter::MinimumVersionMatch);//use non-existent version
       
   355     interfaces =database.getInterfaces(filter);
       
   356     QCOMPARE(interfaces.count(), 0);
       
   357 
       
   358     // == search for an interface spread over multiple plugins by a single service==
       
   359     iface = "com.dharma.electro.discharge";
       
   360     filter.setInterface(iface);
       
   361     interfaces = database.getInterfaces(filter);
       
   362     QCOMPARE(interfaces.count(), 4);
       
   363     capabilities.clear();
       
   364     QVERIFY(compareDescriptor(interfaces[0], iface, "DharmaInitiative", 4, 0, capabilities,customs, "C:/island/swan.dll"));
       
   365     QVERIFY(compareDescriptor(interfaces[1], iface, "DharmaInitiative", 8, 0, capabilities, customs,"C:/island/pearl.dll"));
       
   366     QVERIFY(compareDescriptor(interfaces[2], iface, "DharmaInitiative", 15, 0, capabilities, customs,"C:/island/flame.dll"));
       
   367     QVERIFY(compareDescriptor(interfaces[3], iface, "DharmaInitiative", 16, 0, capabilities, customs,"C:/island/flame.dll"));
       
   368 
       
   369     //try searching by minimum version for interface implementation spread over multiple plugins
       
   370     filter.setInterface(iface, "5.0", QServiceFilter::MinimumVersionMatch);
       
   371     interfaces = database.getInterfaces(filter);
       
   372     QCOMPARE(interfaces.count(), 3);
       
   373     QVERIFY(compareDescriptor(interfaces[0], iface, "DharmaInitiative", 8, 0, capabilities, customs,"C:/island/pearl.dll"));
       
   374     QVERIFY(compareDescriptor(interfaces[1], iface, "DharmaInitiative", 15, 0, capabilities, customs,"C:/island/flame.dll"));
       
   375     QVERIFY(compareDescriptor(interfaces[2], iface, "DharmaInitiative", 16, 0, capabilities, customs,"C:/island/flame.dll"));
       
   376 
       
   377     //try searching for a single version of an interface implementation
       
   378     filter.setInterface(iface, "8.0", QServiceFilter::ExactVersionMatch);
       
   379     interfaces = database.getInterfaces(filter);
       
   380     QCOMPARE(interfaces.count(), 1);
       
   381     QVERIFY(compareDescriptor(interfaces[0], iface, "DharmaInitiative", 8, 0, capabilities, customs,"C:/island/pearl.dll"));
       
   382 
       
   383     QVERIFY(database.close());
       
   384 }
       
   385 
       
   386 void ServiceDatabaseUnitTest::searchByInterfaceAndService()
       
   387 {
       
   388     QServiceFilter filter;
       
   389     QList<QServiceInterfaceDescriptor> interfaces;
       
   390 
       
   391     QVERIFY(database.open());
       
   392 
       
   393     // == search using only interface and service name ==
       
   394     filter.setServiceName("Omni");
       
   395     filter.setInterface("com.omni.device.Lights");
       
   396     interfaces = database.getInterfaces(filter);
       
   397     QVERIFY(compareDescriptor(interfaces[0], "com.omni.device.Lights", "OMNI", 9, 0));
       
   398 
       
   399     QCOMPARE(interfaces.count(), 1);
       
   400 
       
   401     //try searching with service that implements the same interface
       
   402     //more than once
       
   403     filter.setServiceName("Primatech");
       
   404     filter.setInterface("com.omni.device.Accelerometer");
       
   405     interfaces = database.getInterfaces(filter);
       
   406 
       
   407     QCOMPARE(interfaces.count(), 2);
       
   408     QVERIFY(compareDescriptor(interfaces[0], "com.omni.device.Accelerometer", "Primatech", 1, 4));
       
   409     QVERIFY(compareDescriptor(interfaces[1], "com.omni.device.Accelerometer", "Primatech", 1, 2));
       
   410 
       
   411     //try and existing service but non-existent interface
       
   412     filter.setServiceName("Primatech");
       
   413     filter.setInterface("com.omni.device.FluxCapacitor");
       
   414 
       
   415     interfaces = database.getInterfaces(filter);
       
   416     QCOMPARE(interfaces.count(), 0);
       
   417 
       
   418     //try an non-existing service but an existing interface
       
   419     filter.setServiceName("StarkInd");
       
   420     filter.setInterface("com.omni.device.Accelerometer");
       
   421 
       
   422     interfaces = database.getInterfaces(filter);
       
   423     QCOMPARE(interfaces.count(), 0);
       
   424 
       
   425     // == search using interface and service name and exact version match ==
       
   426     filter.setServiceName("Primatech");
       
   427     filter.setInterface("com.omni.device.Accelerometer", "1.2", QServiceFilter::ExactVersionMatch);
       
   428     interfaces = database.getInterfaces(filter);
       
   429 
       
   430     QCOMPARE(interfaces.count(), 1);
       
   431     QVERIFY(compareDescriptor(interfaces[0], "com.omni.device.Accelerometer", "Primatech", 1, 2));
       
   432 
       
   433     //try an exact match for and non-existent interface version
       
   434     filter.setInterface("com.omni.device.Accelerometer","1.3", QServiceFilter::ExactVersionMatch);
       
   435     interfaces = database.getInterfaces(filter);
       
   436 
       
   437     // == search using interface and service name and minimum version match ==
       
   438     filter.setServiceName("Cyberdyne");
       
   439     filter.setInterface("com.cyberdyne.terminator","1.6", QServiceFilter::MinimumVersionMatch);
       
   440     interfaces = database.getInterfaces(filter);
       
   441     QCOMPARE(interfaces.count(), 4);
       
   442 
       
   443     QVERIFY(compareDescriptor(interfaces[0], "com.cyberdyne.terminator", "Cyberdyne", 2, 1));
       
   444     QVERIFY(compareDescriptor(interfaces[1], "com.cyberdyne.terminator", "Cyberdyne", 2, 0));
       
   445     QVERIFY(compareDescriptor(interfaces[2], "com.cyberdyne.terminator", "Cyberdyne", 1, 7));
       
   446     QVERIFY(compareDescriptor(interfaces[3], "com.cyberdyne.terminator", "Cyberdyne", 1, 6));
       
   447 
       
   448     //try again with the same interface but a different service
       
   449     filter.setServiceName("Skynet");
       
   450     filter.setInterface("com.cyberdyne.terminator", "1.6", QServiceFilter::MinimumVersionMatch);
       
   451     interfaces = database.getInterfaces(filter);
       
   452     QCOMPARE(interfaces.count(), 4);
       
   453 
       
   454     QVERIFY(compareDescriptor(interfaces[0], "com.cyberdyne.terminator", "skynet", 3, 6));
       
   455     QVERIFY(compareDescriptor(interfaces[1], "com.cyberdyne.terminator", "skynet", 2, 0));
       
   456     QVERIFY(compareDescriptor(interfaces[2], "com.cyberdyne.terminator", "skynet", 1, 8));
       
   457     QVERIFY(compareDescriptor(interfaces[3], "com.cyberdyne.terminator", "skynet", 1, 6));
       
   458 
       
   459     //try with a non-existent interface version (but later versions exist)
       
   460     filter.setServiceName("Skynet");
       
   461     filter.setInterface("com.cyberdyne.terminator","1.9", QServiceFilter::MinimumVersionMatch);
       
   462     interfaces = database.getInterfaces(filter);
       
   463     QVERIFY(compareDescriptor(interfaces[0], "com.cyberdyne.terminator", "skynet", 3, 6));
       
   464     QVERIFY(compareDescriptor(interfaces[1], "com.cyberdyne.terminator", "skynet", 2, 0));
       
   465     QCOMPARE(interfaces.count(), 2);
       
   466 
       
   467     // == using wildcard matching when searching, ie service and/or interface field is empty
       
   468     filter.setServiceName("");
       
   469     filter.setInterface("");
       
   470     interfaces = database.getInterfaces(filter);
       
   471     QCOMPARE(interfaces.count(), 36);
       
   472 
       
   473     // == searches on a service which is made up of multiple plugins
       
   474     // try searching for all interfaces offered by the service
       
   475     filter.setServiceName("DharmaInitiative");
       
   476     filter.setInterface("");
       
   477     interfaces = database.getInterfaces(filter);
       
   478     QCOMPARE(interfaces.count(), 5);
       
   479 
       
   480     QHash<QString,QString> customs;
       
   481     QStringList capabilities;
       
   482     QVERIFY(compareDescriptor(interfaces[0], "com.dharma.electro.discharge", "DharmaInitiative", 4, 0, capabilities, customs, "C:/island/swan.dll",
       
   483                 "Department of Heuristics And Research on Material Applications(S)",
       
   484                 "Releases electromagnetic energy buildup every 108 minutes"));
       
   485     QVERIFY(compareDescriptor(interfaces[1], "com.dharma.electro.discharge", "DharmaInitiative", 8, 0, capabilities, customs, "C:/island/pearl.dll",
       
   486                 "Department of Heuristics And Research on Material Applications(P)",
       
   487                 "Releases electromagnetic energy buildup every 108 minutes"));
       
   488     QVERIFY(compareDescriptor(interfaces[2], "com.dharma.electro.discharge", "DharmaInitiative", 15, 0, capabilities, customs, "C:/island/flame.dll",
       
   489                 "Department of Heuristics And Research on Material Applications(F)",
       
   490                 "Releases electromagnetic energy buildup every 108 minutes"));
       
   491     QVERIFY(compareDescriptor(interfaces[3], "com.dharma.radio", "DharmaInitiative", 8, 15, capabilities, customs, "C:/island/flame.dll",
       
   492                 "Department of Heuristics And Research on Material Applications(F)",
       
   493                 "Enables communication off island"));
       
   494     QVERIFY(compareDescriptor(interfaces[4], "com.dharma.electro.discharge", "DharmaInitiative", 16, 0, capabilities, customs, "C:/island/flame.dll",
       
   495                 "Department of Heuristics And Research on Material Applications(F)",
       
   496                 "Releases electromagnetic energy buildup every 108 minutes"));
       
   497 
       
   498     // try searching for all implementations of a specific interface offered by the service
       
   499     filter.setServiceName("DharmaInitiative");
       
   500     filter.setInterface("com.dharma.electro.discharge");
       
   501     interfaces = database.getInterfaces(filter);
       
   502     QCOMPARE(interfaces.count(), 4);
       
   503     QVERIFY(compareDescriptor(interfaces[0], "com.dharma.electro.discharge", "DharmaInitiative", 4, 0, capabilities, customs, "C:/island/swan.dll"));
       
   504     QVERIFY(compareDescriptor(interfaces[1], "com.dharma.electro.discharge", "DharmaInitiative", 8, 0, capabilities, customs, "C:/island/pearl.dll"));
       
   505     QVERIFY(compareDescriptor(interfaces[2], "com.dharma.electro.discharge", "DharmaInitiative", 15, 0, capabilities, customs, "C:/island/flame.dll"));
       
   506     QVERIFY(compareDescriptor(interfaces[3], "com.dharma.electro.discharge", "DharmaInitiative", 16, 0, capabilities, customs, "C:/island/flame.dll"));
       
   507 
       
   508     //try doing a minimum version search
       
   509     filter.setServiceName("DharmaInitiative");
       
   510     filter.setInterface("com.dharma.electro.discharge", "7.9", QServiceFilter::MinimumVersionMatch);
       
   511     interfaces = database.getInterfaces(filter);
       
   512     QCOMPARE(interfaces.count(), 3);
       
   513     QVERIFY(compareDescriptor(interfaces[0], "com.dharma.electro.discharge", "DharmaInitiative", 8, 0, capabilities, customs, "C:/island/pearl.dll"));
       
   514     QVERIFY(compareDescriptor(interfaces[1], "com.dharma.electro.discharge", "DharmaInitiative", 15, 0, capabilities, customs, "C:/island/flame.dll"));
       
   515     QVERIFY(compareDescriptor(interfaces[2], "com.dharma.electro.discharge", "DharmaInitiative", 16, 0, capabilities, customs, "C:/island/flame.dll"));
       
   516 
       
   517     //try doing a exact version search
       
   518     filter.setServiceName("DharmaInitiative");
       
   519     filter.setInterface("com.dharma.electro.discharge", "15.0", QServiceFilter::ExactVersionMatch);
       
   520     interfaces = database.getInterfaces(filter);
       
   521     QCOMPARE(interfaces.count(), 1);
       
   522     QVERIFY(compareDescriptor(interfaces[0], "com.dharma.electro.discharge", "DharmaInitiative", 15, 0, capabilities, customs, "C:/island/flame.dll"));
       
   523 
       
   524     //trying setting invalid interface parameters, supply a version without an interface
       
   525     filter.setInterface("", "3.0", QServiceFilter::MinimumVersionMatch); //this call should be ignored
       
   526     interfaces = database.getInterfaces(filter);
       
   527     QCOMPARE(interfaces.count(), 1);
       
   528     QVERIFY(compareDescriptor(interfaces[0], "com.dharma.electro.discharge", "DharmaInitiative", 15, 0, capabilities, customs, "C:/island/flame.dll"));
       
   529 
       
   530     QVERIFY(database.close());
       
   531 }
       
   532 
       
   533 void ServiceDatabaseUnitTest::searchByCapability()
       
   534 {
       
   535     QServiceFilter filter;
       
   536     QList<QServiceInterfaceDescriptor> interfaces;
       
   537     QHash<QString,QString> customs;
       
   538     QHash<QString,QString> customsW = customs;
       
   539     customsW["weapon"] = "";
       
   540 
       
   541     QVERIFY(database.open());
       
   542 
       
   543     filter.setServiceName("Decepticon");
       
   544     interfaces = database.getInterfaces(filter);
       
   545     QCOMPARE(interfaces.count(),4);
       
   546 
       
   547     filter.setCapabilities(QServiceFilter::MatchLoadable, QStringList());
       
   548     interfaces = database.getInterfaces(filter);
       
   549     QCOMPARE(interfaces.count(),1);
       
   550     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Decepticon", 5, 3,
       
   551                 QStringList(), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   552 
       
   553     QStringList caps;
       
   554     caps << "hunt" << "spy";
       
   555     filter.setCapabilities(QServiceFilter::MatchMinimum, caps);
       
   556     interfaces = database.getInterfaces(filter);
       
   557     QCOMPARE(interfaces.count(),2);
       
   558     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Decepticon", 2, 0,
       
   559                 (QStringList()<<"hunt" << "spy" << "kill"), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   560     QVERIFY(compareDescriptor(interfaces[1], "com.cybertron.transform", "Decepticon", 2, 5,
       
   561                 (QStringList()<<"hunt" << "spy"), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   562 
       
   563     filter.setCapabilities(QServiceFilter::MatchLoadable, caps);
       
   564     interfaces = database.getInterfaces(filter);
       
   565     QCOMPARE(interfaces.count(),3);
       
   566     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Decepticon", 1, 1,
       
   567                 QStringList()<<"hunt", customsW, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   568     QVERIFY(compareDescriptor(interfaces[1], "com.cybertron.transform", "Decepticon", 5, 3,
       
   569                 QStringList() , customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   570     QVERIFY(compareDescriptor(interfaces[2], "com.cybertron.transform", "Decepticon", 2, 5,
       
   571                 (QStringList()<<"hunt" << "spy"), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   572     
       
   573     caps.clear();
       
   574     caps << "hunt";
       
   575     filter.setCapabilities(QServiceFilter::MatchMinimum, caps);
       
   576     interfaces = database.getInterfaces(filter);
       
   577     QCOMPARE(interfaces.count(),3);
       
   578     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Decepticon", 2, 0,
       
   579                 (QStringList()<<"hunt" << "spy" << "kill"), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   580     QVERIFY(compareDescriptor(interfaces[1], "com.cybertron.transform", "Decepticon", 1, 1,
       
   581                 QStringList()<<"hunt" , customsW, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   582     QVERIFY(compareDescriptor(interfaces[2], "com.cybertron.transform", "Decepticon", 2, 5,
       
   583                 (QStringList()<<"hunt" << "spy"), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   584 
       
   585 
       
   586     filter.setCapabilities(QServiceFilter::MatchLoadable, caps);
       
   587     interfaces = database.getInterfaces(filter);
       
   588     QCOMPARE(interfaces.count(),2);
       
   589     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Decepticon", 1, 1,
       
   590                 QStringList()<<"hunt", customsW, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   591     QVERIFY(compareDescriptor(interfaces[1], "com.cybertron.transform", "Decepticon", 5, 3,
       
   592                 QStringList(), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   593 
       
   594     caps.clear();
       
   595     filter.setCapabilities(QServiceFilter::MatchMinimum, caps);
       
   596     interfaces = database.getInterfaces(filter);
       
   597     QCOMPARE(interfaces.count(),4);
       
   598     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Decepticon", 2, 0,
       
   599                 (QStringList()<<"hunt" << "spy" << "kill"), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   600     QVERIFY(compareDescriptor(interfaces[1], "com.cybertron.transform", "Decepticon", 1, 1,
       
   601                 QStringList()<<"hunt", customsW, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   602     QVERIFY(compareDescriptor(interfaces[2], "com.cybertron.transform", "Decepticon", 5, 3,
       
   603                 QStringList(), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   604     QVERIFY(compareDescriptor(interfaces[3], "com.cybertron.transform", "Decepticon", 2, 5,
       
   605                 (QStringList()<<"hunt" << "spy"), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   606     
       
   607 
       
   608     filter.setCapabilities(QServiceFilter::MatchLoadable, caps);
       
   609     interfaces = database.getInterfaces(filter);
       
   610     QCOMPARE(interfaces.count(),1);
       
   611     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Decepticon", 5, 3,
       
   612                 QStringList(), customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   613 
       
   614     QServiceFilter emptyFilter;
       
   615     emptyFilter.setCapabilities(QServiceFilter::MatchLoadable);
       
   616     interfaces = database.getInterfaces(emptyFilter);
       
   617     QCOMPARE(interfaces.count(), 14); //show all services which don't require any caps
       
   618 }
       
   619 
       
   620 void ServiceDatabaseUnitTest::searchByCustomAttribute()
       
   621 {
       
   622     QServiceFilter filter;
       
   623     QList<QServiceInterfaceDescriptor> interfaces;
       
   624     QHash<QString,QString> customs;
       
   625     QStringList capabilities;
       
   626 
       
   627     QVERIFY(database.open());
       
   628 
       
   629     filter.setServiceName("Autobot");
       
   630     interfaces = database.getInterfaces(filter);
       
   631     QCOMPARE(interfaces.count(),5);
       
   632 
       
   633     filter.setCustomAttribute("bot", "automatic");
       
   634     QCOMPARE(filter.customAttribute("bot"), QString("automatic"));
       
   635     interfaces = database.getInterfaces(filter);
       
   636     QCOMPARE(interfaces.count(),3);
       
   637 
       
   638     customs["bot"] = "automatic";
       
   639     customs["extension"] = "multidrive";
       
   640     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Autobot", 2, 7,
       
   641                 capabilities, customs, "C:/Ark/matrix.dll", "Autobot Protection Services", "Transformation interface"));
       
   642 
       
   643     customs.clear();
       
   644     customs["bot"] = "automatic";
       
   645     QVERIFY(compareDescriptor(interfaces[1], "com.cybertron.transform", "Autobot", 2, 5,
       
   646                 capabilities, customs, "C:/Ark/matrix.dll", "Autobot Protection Services", "Transformation interface"));
       
   647 
       
   648     customs.clear();
       
   649     customs["bot"] = "automatic";
       
   650     customs["weapon"] = "";
       
   651     QVERIFY(compareDescriptor(interfaces[2], "com.cybertron.transform", "Autobot", 1, 9,
       
   652                 capabilities, customs, "C:/Ark/matrix.dll", "Autobot Protection Services", "Transformation interface"));
       
   653 
       
   654     filter.setCustomAttribute("extension","multidrive");
       
   655     QCOMPARE(filter.customAttribute("extension"), QString("multidrive"));
       
   656     QCOMPARE(filter.customAttribute("bot"), QString("automatic"));
       
   657     interfaces = database.getInterfaces(filter);
       
   658     QCOMPARE(interfaces.count(),1);
       
   659     
       
   660     customs.clear();
       
   661     customs["bot"] = "automatic";
       
   662     customs["extension"] = "multidrive";
       
   663     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Autobot", 2, 7,
       
   664                 capabilities, customs, "C:/Ark/matrix.dll", "Autobot Protection Services", "Transformation interface"));
       
   665 
       
   666     QServiceFilter manualFilter;
       
   667     manualFilter.setCustomAttribute("bot", "manual");
       
   668     interfaces = database.getInterfaces(manualFilter);
       
   669     QCOMPARE(interfaces.count(),2);
       
   670 
       
   671     customs.clear();
       
   672     customs["bot"]="manual";
       
   673     customs["weapon"]="laser";
       
   674     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Autobot", 1, 0,
       
   675                 capabilities, customs, "C:/Ark/matrix.dll", "Autobot Protection Services", "Transformation interface"));
       
   676     customs.clear();
       
   677     customs["bot"] = "manual";
       
   678     QVERIFY(compareDescriptor(interfaces[1], "com.cybertron.transform", "Autobot", 2, 0,
       
   679                 capabilities, customs, "C:/Ark/matrix.dll", "Autobot Protection Services", "Transformation interface"));
       
   680 
       
   681     QServiceFilter multidriveFilter;
       
   682     multidriveFilter.setCustomAttribute("extension", "multidrive");
       
   683     interfaces = database.getInterfaces(multidriveFilter);
       
   684     QCOMPARE(interfaces.count(),1);
       
   685 
       
   686     customs.clear();
       
   687     customs["bot"] = "automatic";
       
   688     customs["extension"] = "multidrive";
       
   689     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Autobot", 2, 7,
       
   690                 capabilities, customs, "C:/Ark/matrix.dll", "Autobot Protection Services", "Transformation interface"));
       
   691 
       
   692     //test whether querying a custom property will affect the filter
       
   693     filter.setServiceName("");
       
   694     filter.setInterface("");
       
   695     filter.clearCustomAttribute();
       
   696     interfaces = database.getInterfaces(filter);
       
   697     QCOMPARE(interfaces.count(), 36);
       
   698     QString customProperty = filter.customAttribute("spark");
       
   699     QVERIFY(customProperty.isEmpty());
       
   700     interfaces = database.getInterfaces(filter);
       
   701     QCOMPARE(interfaces.count(), 36);
       
   702 
       
   703     //test the removal of a custom property from the filter
       
   704     filter.setCustomAttribute("bot", "automatic");
       
   705     filter.setCustomAttribute("extension", "multidrive");
       
   706     QCOMPARE(filter.customAttributes().length(), 2);
       
   707     filter.clearCustomAttribute("bot");
       
   708     QCOMPARE(filter.customAttributes().length(), 1);
       
   709     filter.clearCustomAttribute("extension");
       
   710     QCOMPARE(filter.customAttributes().length(), 0);
       
   711 
       
   712     //test clearing of custom attributes
       
   713     filter.setCustomAttribute("bot", "automatic");
       
   714     filter.setCustomAttribute("extension", "multidrive");
       
   715     QCOMPARE(filter.customAttributes().length(),2);
       
   716     interfaces = database.getInterfaces(filter);
       
   717     QCOMPARE(interfaces.count(), 1);
       
   718     filter.clearCustomAttribute();
       
   719     QCOMPARE(filter.customAttributes().length(), 0);
       
   720     interfaces = database.getInterfaces(filter);
       
   721     QCOMPARE(interfaces.count(), 36);
       
   722 
       
   723     //test searching for an empty custom property
       
   724     filter.setCustomAttribute("weapon", "");
       
   725     interfaces = database.getInterfaces(filter);
       
   726     customs.clear();
       
   727     customs["bot"] = "automatic";
       
   728     customs["weapon"] = "";
       
   729     QCOMPARE(interfaces.length(), 2);
       
   730     QVERIFY(compareDescriptor(interfaces[0], "com.cybertron.transform", "Autobot", 1, 9,
       
   731                 capabilities, customs, "C:/Ark/matrix.dll", "Autobot Protection Services", "Transformation interface"));
       
   732     customs.clear();
       
   733     capabilities.clear();
       
   734     capabilities << "hunt";
       
   735     customs["weapon"]= "";
       
   736     QVERIFY(compareDescriptor(interfaces[1], "com.cybertron.transform", "Decepticon", 1, 1,
       
   737                 capabilities, customs, "C:/Cybertron/unicron.dll", "Decepticon Elimination Services", "Transformation interface"));
       
   738 
       
   739 
       
   740     filter.clearCustomAttribute();
       
   741 
       
   742     //test searching against a non-existent custom property
       
   743     filter.setCustomAttribute("fluxcapacitor", "fluxing");
       
   744     interfaces = database.getInterfaces(filter);
       
   745     QCOMPARE(interfaces.count(), 0);
       
   746     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   747 
       
   748     //try searching for custom property with service name and interface constraints
       
   749     filter.clearCustomAttribute();
       
   750     filter.setServiceName("autobot");
       
   751     filter.setInterface("com.cybertron.transform", "2.0");
       
   752     filter.setCustomAttribute("bot", "automatic");
       
   753     interfaces = database.getInterfaces(filter);
       
   754     QCOMPARE(interfaces.count(),2);
       
   755     QVERIFY(interfaces[0].majorVersion() == 2 && interfaces[0].minorVersion() == 7);
       
   756     QVERIFY(interfaces[1].majorVersion() == 2 && interfaces[1].minorVersion() == 5);
       
   757 
       
   758     //test that there is a difference between querying a custom
       
   759     //property with an empty value and a custom property that has not been set
       
   760     filter.clearCustomAttribute();
       
   761     filter.setCustomAttribute("AllSpark", "");
       
   762     QVERIFY(!filter.customAttribute("AllSpark").isNull());
       
   763     QVERIFY(filter.customAttribute("AllSpark").isEmpty());
       
   764     QVERIFY(filter.customAttribute("Non-existentProperty").isNull());
       
   765 
       
   766     QVERIFY(database.close());
       
   767 }
       
   768 
       
   769 void ServiceDatabaseUnitTest::attributes()
       
   770 {
       
   771     QVERIFY(database.open());
       
   772 
       
   773     // == Capability property ==
       
   774     //get empty list of capabilities from an interface registered with capabilities=""
       
   775     QServiceFilter filter;
       
   776     filter.setServiceName("acme");
       
   777     filter.setInterface("com.acme.service.location", "1.0", QServiceFilter::ExactVersionMatch);
       
   778     QList<QServiceInterfaceDescriptor> interfaces = database.getInterfaces(filter);
       
   779     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   780     QCOMPARE(interfaces.count(), 1);
       
   781     QServiceInterfaceDescriptor interface = interfaces[0];
       
   782     QCOMPARE(interface.attribute(QServiceInterfaceDescriptor::Capabilities).toStringList(), QStringList());
       
   783 
       
   784     //get empty list of capabilites from an interface registered without a
       
   785     //capabilities attribute
       
   786     filter.setServiceName("DHarmaInitiative");
       
   787     filter.setInterface("Com.dharma.electro.discharge", "16.0", QServiceFilter::ExactVersionMatch);
       
   788     interfaces = database.getInterfaces(filter);
       
   789     QCOMPARE(interfaces.count(), 1);
       
   790     interface = interfaces[0];
       
   791     QCOMPARE(interface.attribute(QServiceInterfaceDescriptor::Capabilities).toStringList(), QStringList());
       
   792 
       
   793     //get a list of capabilites from an interface with only 1 capability
       
   794     filter.setServiceName("Omni");
       
   795     filter.setInterface("com.omni.device.Accelerometer", "1.1", QServiceFilter::ExactVersionMatch);
       
   796     interfaces = database.getInterfaces(filter);
       
   797     QCOMPARE(interfaces.count(), 1);
       
   798     interface = interfaces[0];
       
   799     QStringList capabilities;
       
   800     capabilities  << "SurroundingsDD";
       
   801     QCOMPARE(interface.attribute(QServiceInterfaceDescriptor::Capabilities).toStringList(), capabilities);
       
   802 
       
   803     //get a list of capabilites from an interface with multiple capabilities
       
   804     filter.setServiceName("Omni");
       
   805     filter.setInterface("com.omni.service.Video", "1.4", QServiceFilter::ExactVersionMatch);
       
   806     interfaces = database.getInterfaces(filter);
       
   807     QCOMPARE(interfaces.count(), 1);
       
   808     interface = interfaces[0];
       
   809     capabilities.clear();
       
   810     capabilities  << "MultimediaDD" << "NetworkServices" << "ReadUserData" << "WriteUserData";
       
   811     QCOMPARE(interface.attribute(QServiceInterfaceDescriptor::Capabilities).toStringList(), capabilities);
       
   812 
       
   813     //get a list of capabilities from a default service
       
   814     interface = database.interfaceDefault("com.cyberdyne.terminator");
       
   815     capabilities.clear();
       
   816     capabilities << "NetworkServices";
       
   817     QCOMPARE(interface.attribute(QServiceInterfaceDescriptor::Capabilities).toStringList(), capabilities);
       
   818 
       
   819     // == Interface Description Property ==
       
   820     //get the interface description off an interface registered without a description tag
       
   821     filter.setServiceName("Skynet");
       
   822     filter.setInterface("com.cyberdyne.terminator", "1.8", QServiceFilter::ExactVersionMatch);
       
   823     interfaces = database.getInterfaces(filter);
       
   824     QCOMPARE(interfaces.count(), 1);
       
   825     interface = interfaces[0];
       
   826     QCOMPARE(interface.attribute(QServiceInterfaceDescriptor::InterfaceDescription).toString(), QString());
       
   827 
       
   828     //get the interface description off an interface registered with an
       
   829     //empty description tag
       
   830     filter.setServiceName("Skynet");
       
   831     filter.setInterface("com.cyberdyne.terminator", "1,6", QServiceFilter::ExactVersionMatch);
       
   832     interfaces = database.getInterfaces(filter);
       
   833     QCOMPARE(interfaces.count(), 1);
       
   834     interface = interfaces[0];
       
   835     QCOMPARE(interface.attribute(QServiceInterfaceDescriptor::InterfaceDescription).toString(), QString());
       
   836 
       
   837     //get the interface description of an interface
       
   838     filter.setServiceName("Skynet");
       
   839     filter.setInterface("com.cyberdyne.terminator", "1.5", QServiceFilter::ExactVersionMatch);
       
   840     interfaces = database.getInterfaces(filter);
       
   841     QCOMPARE(interfaces.count(), 1);
       
   842     interface = interfaces[0];
       
   843     QCOMPARE(interface.attribute(QServiceInterfaceDescriptor::InterfaceDescription).toString(),
       
   844             QString("Remote communications interface for the T-800v1.5"));
       
   845 
       
   846     //get a description from a default service
       
   847     interface = database.interfaceDefault("com.omni.device.Accelerometer");
       
   848     QCOMPARE(interface.attribute(QServiceInterfaceDescriptor::InterfaceDescription).toString(),
       
   849             QString("Interface that provides accelerometer readings(omni)"));
       
   850 
       
   851     QVERIFY(database.close());
       
   852 }
       
   853 
       
   854 void ServiceDatabaseUnitTest::getServiceNames()
       
   855 {
       
   856     QStringList services;
       
   857     services = database.getServiceNames("com.acme.device.sysinfo");
       
   858     QCOMPARE(database.lastError().code(), DBError::DatabaseNotOpen);
       
   859     QCOMPARE(services.count(), 0);
       
   860     QVERIFY(database.open());
       
   861 
       
   862     //try wildcard match to get all services
       
   863     services = database.getServiceNames("" );
       
   864     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   865     QCOMPARE(services.count(), 10);
       
   866 
       
   867     //try an interface that is implemented by only one service
       
   868     services = database.getServiceNames("com.acme.device.sysinfo");
       
   869     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   870     QCOMPARE(services.count(), 1);
       
   871     QCOMPARE(services[0], QString("acme"));
       
   872 
       
   873     //try an interface which  is implmented by multiple services
       
   874     services = database.getServiceNames("COM.omni.device.ACCELerometer"); //also test case insensitivity
       
   875     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   876     QCOMPARE(services.count(), 4);
       
   877     QVERIFY(services.contains("LuthorCorp"));
       
   878     QVERIFY(services.contains("OMNI"));
       
   879     QVERIFY(services.contains("Primatech"));
       
   880     QVERIFY(services.contains("WayneEnt"));
       
   881 
       
   882     //try again but with services that have multiple implementation versions of a particular implementation
       
   883     services = database.getServiceNames("com.cyberdyne.terminator");
       
   884     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   885     QCOMPARE(services.count(), 2);
       
   886     QVERIFY(services.contains("Cyberdyne"));
       
   887     QVERIFY(services.contains("skynet"));
       
   888 
       
   889     //try with an interface implemented in multiple plugins
       
   890     services = database.getServiceNames("com.dharma.electro.discharge");
       
   891     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   892     QCOMPARE(services.count(), 1);
       
   893     QVERIFY(services.contains("DharmaInitiative", Qt::CaseInsensitive));
       
   894 
       
   895     //try with a non-existing interface
       
   896     services = database.getServiceNames("com.omni.device.FluxCapacitor");
       
   897     QCOMPARE(database.lastError().code(), DBError::NoError);
       
   898     QCOMPARE(services.count(), 0);
       
   899 
       
   900     QVERIFY(database.close());
       
   901 }
       
   902 
       
   903 bool ServiceDatabaseUnitTest::compareDescriptor(QServiceInterfaceDescriptor interface,
       
   904     QString interfaceName, QString serviceName, int majorVersion, int minorVersion)
       
   905 {
       
   906     interface.d->attributes[QServiceInterfaceDescriptor::Capabilities] = QStringList();
       
   907 
       
   908     QHash<QString,QString> customs;
       
   909     return compareDescriptor(interface, interfaceName, serviceName, majorVersion, minorVersion,
       
   910             QStringList(), customs);
       
   911 }
       
   912 
       
   913 bool ServiceDatabaseUnitTest::compareDescriptor(QServiceInterfaceDescriptor interface,
       
   914     QString interfaceName, QString serviceName, int majorVersion, int minorVersion,
       
   915     QStringList capabilities, const QHash<QString,QString> customProps, QString filePath, QString serviceDescription,
       
   916     QString interfaceDescription)
       
   917 {
       
   918 
       
   919     if(interface.interfaceName().compare(interfaceName, Qt::CaseInsensitive) !=0) {
       
   920         qWarning() << "Interface name mismatch: expected =" << interfaceName
       
   921                     << " actual =" << interface.interfaceName();
       
   922         return false;
       
   923     }
       
   924 
       
   925     if (interface.serviceName().compare(serviceName, Qt::CaseInsensitive) != 0) {
       
   926         qWarning() << "Service name mismatch: expected =" << serviceName
       
   927                     << " actual =" << interface.serviceName();
       
   928         return false;
       
   929     }
       
   930 
       
   931     if (interface.majorVersion() != majorVersion) {
       
   932         qWarning() << "Major version mismatch: expected =" << majorVersion
       
   933                         << " actual =" << interface.majorVersion();
       
   934         return false;
       
   935     }
       
   936 
       
   937     if (interface.minorVersion() != minorVersion) {
       
   938         qWarning() << "Minor version mismatch: expected =" << minorVersion
       
   939                     << " actual =" << interface.minorVersion();
       
   940         return false;
       
   941     }
       
   942 
       
   943     if (capabilities.count() != 0 || interface.attribute(QServiceInterfaceDescriptor::Capabilities).toStringList().count() != 0 ) {
       
   944         QStringList securityCapabilities;
       
   945         securityCapabilities = interface.attribute(QServiceInterfaceDescriptor::Capabilities).toStringList();
       
   946 
       
   947         if(securityCapabilities.count() != capabilities.count()) {
       
   948             qWarning() << "Capabilities count mismatch: expected =" << capabilities.count()
       
   949                         << " actual="<< securityCapabilities.count()
       
   950                         << "\texpected capabilities =" << capabilities
       
   951                         << "actual capabilities =" << securityCapabilities;
       
   952             return false;
       
   953         }
       
   954 
       
   955         for (int i = 0; i < securityCapabilities.count(); ++i) {
       
   956             if (securityCapabilities[i] != capabilities[i]) {
       
   957                 qWarning() << "Capability mismatch: expected =" << capabilities[i]
       
   958                             << " actual =" << securityCapabilities[i];
       
   959                 return false;
       
   960             }
       
   961         }
       
   962     }
       
   963 
       
   964     if (!filePath.isEmpty()) {
       
   965         if (interface.attribute(QServiceInterfaceDescriptor::Location).toString() != filePath) {
       
   966             qWarning() << "File path mismatch: expected =" << filePath
       
   967                 << " actual =" << interface.attribute(QServiceInterfaceDescriptor::Location).toString();
       
   968             return false;
       
   969         }
       
   970     }
       
   971     if (!serviceDescription.isEmpty()) {
       
   972         if (interface.attribute(QServiceInterfaceDescriptor::ServiceDescription).toString() != serviceDescription) {
       
   973             qWarning() << "Service Description mismatch: expected =" << serviceDescription
       
   974                         << " actual=" << interface.attribute(QServiceInterfaceDescriptor::ServiceDescription).toString();
       
   975             return false;
       
   976         }
       
   977     }
       
   978     if (!interfaceDescription.isEmpty()) {
       
   979         if (interface.attribute(QServiceInterfaceDescriptor::InterfaceDescription).toString() != interfaceDescription) {
       
   980             qWarning() << "Interface Description mismatch: expected =" << interfaceDescription
       
   981                         << " actual =" << interface.attribute(QServiceInterfaceDescriptor::InterfaceDescription).toString();
       
   982             return false;
       
   983         }
       
   984 
       
   985     }
       
   986 
       
   987     if (interface.d->customAttributes.size() != customProps.size()) {
       
   988         qWarning() << "Number of Interface custom attributes don't match. expected: " 
       
   989             <<customProps.size() << "actual: " << interface.d->customAttributes.size();
       
   990             ;
       
   991         qWarning() << "expected:" << customProps << "actual:" << interface.d->customAttributes;
       
   992         return false;
       
   993     }
       
   994 
       
   995     QHash<QString, QString>::const_iterator i;
       
   996     for (i = customProps.constBegin(); i!=customProps.constEnd(); i++) {
       
   997         if (interface.customAttribute(i.key()) != i.value()) {
       
   998             qWarning() << "Interface custom property mismatch: expected =" << i.key() <<"("<<i.value()<<")" 
       
   999                         << " actual =" << i.key() << "(" << interface.customAttribute(i.key()) << ")";
       
  1000             return false;
       
  1001         }
       
  1002     }
       
  1003     return true;
       
  1004 }
       
  1005 
       
  1006 void ServiceDatabaseUnitTest::defaultExternalIfaceIDs()
       
  1007 {
       
  1008     database.open();
       
  1009     QServiceInterfaceDescriptor interface;
       
  1010     interface.d = new QServiceInterfaceDescriptorPrivate;
       
  1011     interface.d->serviceName = "StargateCommand";
       
  1012     interface.d->interfaceName = "gov.usa.stargate";
       
  1013     interface.d->major = 13;
       
  1014     interface.d->minor = 37;
       
  1015 
       
  1016     //see if we can set a "cross-reference" default interface
       
  1017     //ie user db referencing an interfaceID belonging to the system db
       
  1018     QVERIFY(database.setInterfaceDefault(interface, "FAKE-INTERFACE-ID"));
       
  1019     QString interfaceID;
       
  1020     QServiceInterfaceDescriptor descriptor = database.interfaceDefault("gov.usa.stargate", &interfaceID);
       
  1021     QCOMPARE(database.lastError().code(), DBError::ExternalIfaceIDFound);
       
  1022     QCOMPARE(interfaceID, QString("FAKE-INTERFACE-ID"));
       
  1023 
       
  1024     interface.d->interfaceName = "gov.ru.stargate";
       
  1025     QVERIFY(database.setInterfaceDefault(interface, "FAKE-INTERFACE-ID2"));
       
  1026     QList<QPair<QString,QString> > externalDefaultsInfo = database.externalDefaultsInfo();
       
  1027     QCOMPARE(externalDefaultsInfo[0].second, QString("FAKE-INTERFACE-ID"));
       
  1028     QCOMPARE(externalDefaultsInfo[1].second, QString("FAKE-INTERFACE-ID2"));
       
  1029 
       
  1030     //see if we can remove the "cross-reference" default interface
       
  1031     QVERIFY(database.removeExternalDefaultServiceInterface("FAKE-INTERFACE-ID"));
       
  1032     interfaceID.clear();
       
  1033     descriptor = database.interfaceDefault("gov.usa.stargate", &interfaceID);
       
  1034     QVERIFY(database.lastError().code() == DBError::NotFound);
       
  1035     QVERIFY(interfaceID.isEmpty());
       
  1036 
       
  1037     //try to delete an interfaceID that's actually a local interfaceID
       
  1038     QServiceFilter filter;
       
  1039     filter.setServiceName("omnI");
       
  1040     filter.setInterface("com.omni.Device.Lights");
       
  1041     QList<QServiceInterfaceDescriptor> interfaces;
       
  1042     interfaces = database.getInterfaces(filter);
       
  1043     QCOMPARE(interfaces.count(), 1);
       
  1044     interfaceID = database.getInterfaceID(interfaces[0]);
       
  1045     QVERIFY(!database.removeExternalDefaultServiceInterface(interfaceID));
       
  1046     QVERIFY(database.lastError().code()  ==  DBError::IfaceIDNotExternal);
       
  1047 
       
  1048     database.close();
       
  1049 }
       
  1050 
       
  1051 void ServiceDatabaseUnitTest::interfaceDefault()
       
  1052 {
       
  1053     QServiceInterfaceDescriptor interface;
       
  1054     bool ok;
       
  1055 
       
  1056     //try getting the default service interface implementation when database is not open
       
  1057     interface = database.interfaceDefault("com.cyberdyne.terminator");
       
  1058     QCOMPARE(database.lastError().code(), DBError::DatabaseNotOpen);
       
  1059     QVERIFY(!interface.isValid());
       
  1060 
       
  1061     //try getting a valid default, in this case only one implementation exists
       
  1062     QVERIFY(database.open());
       
  1063     interface = database.interfaceDefault("com.omni.device.Lights");
       
  1064     QVERIFY(database.lastError().code() == DBError::NoError);
       
  1065     QVERIFY(interface.isValid());
       
  1066     QStringList capabilities;
       
  1067     QHash<QString,QString> customs;
       
  1068     QVERIFY(compareDescriptor(interface, "com.omni.device.Lights",
       
  1069                                 "OMNI", 9, 0, capabilities, customs,
       
  1070                                 "C:/OmniInc/omniinc.dll",
       
  1071                                 "Omni mobile",
       
  1072                                 "Interface that provides access to device lights"));
       
  1073 
       
  1074     //try getting a valid default, in this case two services implement the interface
       
  1075     ok = false;
       
  1076     interface = database.interfaceDefault("com.CyBerDynE.Terminator");
       
  1077     QVERIFY(database.lastError().code() == DBError::NoError);
       
  1078     QVERIFY(interface.isValid());
       
  1079 
       
  1080     capabilities << "NetworkServices";
       
  1081     QVERIFY(compareDescriptor(interface, "com.cyberdyne.terminator",
       
  1082                                     "Cyberdyne", 2,1, capabilities, customs,
       
  1083                                     "C:/California/connor.dll",
       
  1084                                     "Cyberdyne Termination Services",
       
  1085                                     "Remote communications interface for the T-800"));
       
  1086 
       
  1087     //try getting a valid default, in this case multiple services implement the interface
       
  1088     ok = false;
       
  1089     interface = database.interfaceDefault("com.omni.device.Accelerometer");
       
  1090     QVERIFY(database.lastError().code() == DBError::NoError);
       
  1091     QVERIFY(interface.isValid());
       
  1092     capabilities.clear();
       
  1093     capabilities << "SurroundingsDD";
       
  1094     QVERIFY(compareDescriptor(interface, "com.omni.device.Accelerometer",
       
  1095                                     "OMNI", 1, 1, capabilities, customs,
       
  1096                                     "C:/OmniInc/omniinc.dll",
       
  1097                                     "Omni mobile",
       
  1098                                     "Interface that provides accelerometer readings(omni)"));
       
  1099 
       
  1100     //try searching for an interface that isn't registered
       
  1101     interface = database.interfaceDefault("com.omni.device.FluxCapacitor");
       
  1102     QVERIFY(database.lastError().code() == DBError::NotFound);
       
  1103     QVERIFY(!interface.isValid());
       
  1104 
       
  1105     //try getting the default interface impl for a service that is made up of multiple
       
  1106     //plugins
       
  1107     interface = database.interfaceDefault("com.dharma.electro.discharge");
       
  1108     QVERIFY(database.lastError().code() == DBError::NoError);
       
  1109     capabilities.clear();
       
  1110     QVERIFY(compareDescriptor(interface, "com.dharma.electro.discharge",
       
  1111                                 "DharmaInitiative", 4, 0,
       
  1112                                 capabilities, customs, "C:/island/swan.dll"));
       
  1113 
       
  1114     //trying getting the default using an empty interface name
       
  1115     interface = database.interfaceDefault("");
       
  1116     QVERIFY(database.lastError().code() == DBError::NotFound);
       
  1117     QVERIFY(!interface.isValid());
       
  1118     QVERIFY(database.close());
       
  1119 }
       
  1120 
       
  1121 void ServiceDatabaseUnitTest::setInterfaceDefault()
       
  1122 {
       
  1123     QServiceInterfaceDescriptor interface;
       
  1124     interface.d = new QServiceInterfaceDescriptorPrivate;
       
  1125     interface.d->serviceName = "cyberdyne";
       
  1126     interface.d->interfaceName = "com.cyberdyne.terminator";
       
  1127     interface.d->major = 1;
       
  1128     interface.d->minor = 6;
       
  1129 
       
  1130     QVERIFY(!database.setInterfaceDefault(interface));
       
  1131     QCOMPARE(database.lastError().code(), DBError::DatabaseNotOpen);
       
  1132 
       
  1133     QVERIFY(database.open());
       
  1134 
       
  1135     //try setting the default to a older version provided by the same
       
  1136     //service
       
  1137     QServiceInterfaceDescriptor defaultInterface;
       
  1138     defaultInterface = database.interfaceDefault("com.cyberdyne.terminator");
       
  1139     QVERIFY(compareDescriptor(defaultInterface, "com.cyberdyne.terminator",
       
  1140                                         "Cyberdyne", 2, 1));
       
  1141 
       
  1142     QVERIFY(database.setInterfaceDefault(interface));
       
  1143     defaultInterface = database.interfaceDefault("com.cyberdyne.terminator");
       
  1144     QVERIFY(compareDescriptor(defaultInterface, "com.cyberdyne.terminator",
       
  1145                                         "Cyberdyne", 1, 6));
       
  1146 
       
  1147     //try setting the default to another service
       
  1148     interface.d->serviceName = "SKYnet"; //check that behaviour is case insensitive
       
  1149     interface.d->interfaceName = "COM.cyberdyne.terminaTOR";
       
  1150     interface.d->major = 1;
       
  1151     interface.d->minor = 5;
       
  1152 
       
  1153     QVERIFY(database.setInterfaceDefault(interface));
       
  1154     defaultInterface = database.interfaceDefault("com.CYBERDYNE.terminator");
       
  1155     QVERIFY(compareDescriptor(defaultInterface, "com.cyberdyne.terminator",
       
  1156                                         "skynet", 1, 5));
       
  1157 
       
  1158     //try setting the default of a service that is made up of multiple plugins
       
  1159     interface.d->serviceName = "DharmaInitiative";
       
  1160     interface.d->interfaceName = "com.dharma.electro.discharge";
       
  1161     interface.d->major = 8;
       
  1162     interface.d->minor = 0;
       
  1163     QVERIFY(database.setInterfaceDefault(interface));
       
  1164     QStringList capabilities;
       
  1165     QHash<QString,QString> customs;
       
  1166     defaultInterface = database.interfaceDefault("com.dharma.electro.discharge");
       
  1167     QVERIFY(compareDescriptor(defaultInterface, "com.dharma.electro.discharge",
       
  1168                                 "DharmaInitiative", 8, 0, capabilities, customs,
       
  1169                                 "C:/island/pearl.dll"));
       
  1170 
       
  1171     //try setting the default to a implementation verison not supplied
       
  1172     //by the service
       
  1173     interface.d->serviceName = "SKYnet"; //check that behaviour is case insensitive
       
  1174     interface.d->interfaceName = "COM.cyberdyne.terminaTOR";
       
  1175     interface.d->major = 1;
       
  1176     interface.d->minor = 9;
       
  1177 
       
  1178     QVERIFY(!database.setInterfaceDefault(interface));
       
  1179     QCOMPARE(database.lastError().code(), DBError::NotFound);
       
  1180     defaultInterface = database.interfaceDefault("com.CYBERDYNE.terminator");
       
  1181     QVERIFY(compareDescriptor(defaultInterface, "com.cyberdyne.terminator",
       
  1182                                         "skynet", 1, 5));
       
  1183 
       
  1184     //try setting the default of an interface that doesn't exist
       
  1185     interface.d->serviceName = "SKYnet"; //check that behaviour is case insensitive
       
  1186     interface.d->interfaceName = "com.omni.device.FluxCapacitor";
       
  1187     interface.d->major = 1;
       
  1188     interface.d->minor = 5;
       
  1189 
       
  1190     QVERIFY(!database.setInterfaceDefault(interface));
       
  1191     QCOMPARE(database.lastError().code(), DBError::NotFound);
       
  1192     defaultInterface = database.interfaceDefault("com.CYBERDYNE.terminator");
       
  1193     QVERIFY(compareDescriptor(defaultInterface, "com.cyberdyne.terminator",
       
  1194                                         "skynet", 1, 5));
       
  1195 
       
  1196     //try setting an interface default to a service that does not implement the interface
       
  1197     interface.d->serviceName = "Primatech";
       
  1198     interface.d->interfaceName = "com.cyberdyne.terminator";
       
  1199     interface.d->major = 1;
       
  1200     interface.d->minor = 4;
       
  1201     QVERIFY(!database.setInterfaceDefault(interface));
       
  1202     QCOMPARE(database.lastError().code(), DBError::NotFound);
       
  1203     defaultInterface = database.interfaceDefault("com.CYBERDYNE.terminator");
       
  1204     QVERIFY(compareDescriptor(defaultInterface, "com.cyberdyne.terminator",
       
  1205                                         "skynet", 1, 5));
       
  1206 
       
  1207     //try setting an interface default to a non-existent service
       
  1208     interface.d->serviceName = "StarkInd"; //check that behaviour is case insensitive
       
  1209     interface.d->interfaceName = "COM.cyberdyne.terminaTOR";
       
  1210     interface.d->major = 1;
       
  1211     interface.d->minor = 5;
       
  1212     QVERIFY(!database.setInterfaceDefault(interface));
       
  1213     QCOMPARE(database.lastError().code(), DBError::NotFound);
       
  1214     defaultInterface = database.interfaceDefault("com.CYBERDYNE.terminator");
       
  1215     QVERIFY(compareDescriptor(defaultInterface, "com.cyberdyne.terminator",
       
  1216                                         "skynet", 1, 5));
       
  1217 
       
  1218     //try setting the default using an invalid interface
       
  1219     QServiceInterfaceDescriptor invalidInterface;
       
  1220     QVERIFY(!invalidInterface.isValid());
       
  1221     QVERIFY(!database.setInterfaceDefault(invalidInterface));
       
  1222     QCOMPARE(database.lastError().code(), DBError::NotFound);
       
  1223     defaultInterface = database.interfaceDefault("com.CYBERDYNE.terminator");
       
  1224     QVERIFY(compareDescriptor(defaultInterface, "com.cyberdyne.terminator",
       
  1225                                         "skynet", 1, 5));
       
  1226 
       
  1227     QVERIFY(database.close());
       
  1228 }
       
  1229 
       
  1230 void ServiceDatabaseUnitTest::unregister()
       
  1231 {
       
  1232     QVERIFY(!unregisterService("acme"));
       
  1233     QCOMPARE(database.lastError().code(), DBError::DatabaseNotOpen);
       
  1234 
       
  1235     QVERIFY(database.open());
       
  1236 
       
  1237     //try unregister a non-existing service
       
  1238     QVERIFY(!unregisterService("StarkInd"));
       
  1239     QCOMPARE(database.lastError().code(), DBError::NotFound);
       
  1240     QServiceFilter filter;
       
  1241 
       
  1242     // == check that the service to delete is already in the database ==
       
  1243     //try a search for descriptors by service name 
       
  1244     filter.setServiceName("omni");
       
  1245     QList<QServiceInterfaceDescriptor> interfaces;
       
  1246     interfaces = database.getInterfaces(filter);
       
  1247     QCOMPARE(interfaces.count(), 3);
       
  1248 
       
  1249     //search for service via interface name
       
  1250     QStringList services;
       
  1251     services = database.getServiceNames("com.omni.device.Accelerometer");
       
  1252     QCOMPARE(services.count(), 4);
       
  1253     QVERIFY(services.contains("OMNI"));
       
  1254 
       
  1255     //search for descriptors via interface name
       
  1256     filter.setServiceName("");
       
  1257     filter.setInterface("com.omni.device.Accelerometer");
       
  1258     interfaces = database.getInterfaces(filter);
       
  1259     QCOMPARE(interfaces.count(), 5);
       
  1260     bool serviceFound = false;
       
  1261     foreach (QServiceInterfaceDescriptor interface, interfaces) {
       
  1262         if(interface.serviceName() == "OMNI")
       
  1263             serviceFound = true;
       
  1264     }
       
  1265     QVERIFY(serviceFound);
       
  1266 
       
  1267     //confirm that it is the default service for a couple of interfaces
       
  1268     QServiceInterfaceDescriptor interface;
       
  1269     interface = database.interfaceDefault("com.omni.device.Accelerometer");
       
  1270     QVERIFY(interface.serviceName() == "OMNI");//other services implement this interface
       
  1271 
       
  1272     interface = database.interfaceDefault("com.omni.service.Video");
       
  1273     QVERIFY(interface.serviceName() == "OMNI");//no other services implmement this interface
       
  1274 
       
  1275     //confirm that interface and service attributes exist for the service
       
  1276     QStringList serviceIDs = getServiceIDs("omni");
       
  1277     foreach(const QString &serviceID, serviceIDs)
       
  1278         QVERIFY(existsInServicePropertyTable(serviceID));
       
  1279 
       
  1280     QStringList interfaceIDs = getInterfaceIDs("omni");
       
  1281     QCOMPARE(interfaceIDs.count(), 3);
       
  1282     foreach(const QString &interfaceID, interfaceIDs)
       
  1283         QVERIFY(existsInInterfacePropertyTable(interfaceID));
       
  1284 
       
  1285     QVERIFY(unregisterService("oMni")); //ensure case insensitive behaviour
       
  1286 
       
  1287     //  == check that deleted service and associated interfaces cannot be found ==
       
  1288     //try a search for descriptors by service name
       
  1289     QServiceFilter serviceFilter;
       
  1290     serviceFilter.setServiceName("omni");
       
  1291     interfaces = database.getInterfaces(serviceFilter);
       
  1292     QCOMPARE(interfaces.count(), 0);
       
  1293 
       
  1294     //search for service via interface name
       
  1295     services = database.getServiceNames("com.omni.device.Accelerometer");
       
  1296     QCOMPARE(services.count(), 3);
       
  1297     QVERIFY(!services.contains("OMNI"));
       
  1298 
       
  1299     //search for descriptors via interface name
       
  1300     filter.setServiceName("");
       
  1301     filter.setInterface("com.omni.device.Accelerometer");
       
  1302     interfaces = database.getInterfaces(filter);
       
  1303     QCOMPARE(interfaces.count(), 4);
       
  1304     serviceFound = false;
       
  1305     foreach (QServiceInterfaceDescriptor interface, interfaces) {
       
  1306         if(interface.serviceName() == "OMNI")
       
  1307             serviceFound = true;
       
  1308     }
       
  1309     QVERIFY(!serviceFound);
       
  1310 
       
  1311     //ensure a new default interface has been assigned for the following interface
       
  1312     interface = database.interfaceDefault("com.omni.device.Accelerometer");
       
  1313     QVERIFY(interface.isValid());
       
  1314     QCOMPARE(interface.serviceName(), QString("WayneEnt"));
       
  1315     QCOMPARE(interface.majorVersion(), 2);
       
  1316     QCOMPARE(interface.minorVersion(), 0);
       
  1317 
       
  1318     //ensure there is no longer a default for the following interface
       
  1319     interface = database.interfaceDefault("com.omni.service.Video");
       
  1320     QVERIFY(!interface.isValid());
       
  1321 
       
  1322     //ensure the associated interfaceIDs no longer exist in the Property
       
  1323     //and Defaults tables
       
  1324     foreach (const QString &serviceID, serviceIDs)
       
  1325         QVERIFY(!existsInServicePropertyTable(serviceID));
       
  1326     foreach (const QString &interfaceID, interfaceIDs)
       
  1327         QVERIFY(!existsInInterfacePropertyTable(interfaceID));
       
  1328     foreach(const QString &interfaceID, interfaceIDs)
       
  1329         QVERIFY(!existsInDefaultsTable(interfaceID));
       
  1330 
       
  1331     //  == unregister an service that implements a default interface
       
  1332     //     but whose default interface name differs in case
       
  1333     //     from the other implementations it provides ==
       
  1334     interface.d = new QServiceInterfaceDescriptorPrivate;
       
  1335     interface.d->serviceName = "Cyberdyne";
       
  1336     interface.d->interfaceName = "com.cyberdyne.terminator";
       
  1337     interface.d->major = 2;
       
  1338     interface.d->minor = 0;
       
  1339     QVERIFY(database.setInterfaceDefault(interface));
       
  1340 
       
  1341     interface = database.interfaceDefault("com.cyberdyne.terminator");
       
  1342     QVERIFY(interface.isValid());
       
  1343     QVERIFY(unregisterService("cyberDYNE"));
       
  1344     interface = database.interfaceDefault("com.cyberdyne.terminatOR");
       
  1345     QVERIFY(interface.isValid());
       
  1346     QVERIFY(compareDescriptor(interface, "com.cyberdyne.terminator",
       
  1347                                 "skynet", 3, 6));
       
  1348 
       
  1349     // == unregister a service that is made up of multiple plugins ==
       
  1350     // get the serviceIDs and interfaceIDs to make sure it's been deleted later on
       
  1351     serviceIDs = getServiceIDs("DharmaInitiative");
       
  1352     QVERIFY(serviceIDs.count() > 0);
       
  1353     interfaceIDs = getInterfaceIDs("DharmaInitiative");
       
  1354     QVERIFY(interfaceIDs.count() > 0);
       
  1355 
       
  1356     foreach(const QString &interfaceID, interfaceIDs)
       
  1357         QVERIFY(existsInInterfacePropertyTable(interfaceID));
       
  1358     foreach(const QString &serviceID, serviceIDs)
       
  1359         QVERIFY(existsInServicePropertyTable(serviceID));
       
  1360 
       
  1361     QVERIFY(unregisterService("DHARMAInitiative"));
       
  1362     interface = database.interfaceDefault("com.dharma.electro.discharge");
       
  1363     QVERIFY(!interface.isValid());
       
  1364     QCOMPARE(database.lastError().code(), DBError::NotFound);
       
  1365     filter.setServiceName("DharmaInitiative");
       
  1366     filter.setInterface("");
       
  1367     interfaces = database.getInterfaces(filter);
       
  1368     QCOMPARE(interfaces.count(), 0);
       
  1369 
       
  1370     foreach(const QString &serviceID, serviceIDs)
       
  1371         QVERIFY(!existsInServicePropertyTable(serviceID));
       
  1372     foreach(const QString &interfaceID, interfaceIDs)
       
  1373         QVERIFY(!existsInInterfacePropertyTable(interfaceID));
       
  1374     foreach(const QString &interfaceID, interfaceIDs)
       
  1375         QVERIFY(!existsInDefaultsTable(interfaceID));
       
  1376 
       
  1377     //  == check that the service can be registered again
       
  1378     //     after it has been unregistered ==
       
  1379     QDir testdir = QDir(TESTDATA_DIR "/testdata" );
       
  1380     ServiceMetaData parser(testdir.absoluteFilePath("ServiceDharma_Flame.xml"));
       
  1381     QVERIFY(parser.extractMetadata());
       
  1382     QVERIFY(registerService(parser.parseResults()));
       
  1383     interface = database.interfaceDefault("com.dharma.electro.discharge");
       
  1384     QVERIFY(interface.isValid());
       
  1385     filter.setServiceName("DharmaInitiative");
       
  1386     filter.setInterface("");
       
  1387     interfaces = database.getInterfaces(filter);
       
  1388     QCOMPARE(interfaces.count(), 3);
       
  1389 
       
  1390     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceDharma_Swan.xml")));
       
  1391     QVERIFY(parser.extractMetadata());
       
  1392     QVERIFY(registerService(parser.parseResults()));
       
  1393     filter.setServiceName("DharmaInitiative");
       
  1394     filter.setInterface("");
       
  1395     interfaces = database.getInterfaces(filter);
       
  1396     QCOMPARE(interfaces.count(), 4);
       
  1397     interface = database.interfaceDefault("com.dharma.electro.discharge");
       
  1398     QVERIFY(interface.isValid());
       
  1399     QStringList capabilities;
       
  1400     QHash<QString,QString> customs;
       
  1401     QVERIFY(compareDescriptor(interface, "com.dharma.electro.discharge",
       
  1402                     "DharmaInitiative", 16, 0, capabilities, customs, "C:/island/flame.dll"));
       
  1403 }
       
  1404 
       
  1405 QStringList ServiceDatabaseUnitTest::getInterfaceIDs(const QString &serviceName) {
       
  1406     QSqlDatabase sqlDatabase  = QSqlDatabase::database(database.m_connectionName);
       
  1407     QSqlQuery query(sqlDatabase);
       
  1408     QString statement("Select Interface.ID FROM Interface, Service "
       
  1409                         "WHERE Service.ID = Interface.ServiceID "
       
  1410                         "AND Service.Name = ? COLLATE NOCASE");
       
  1411     QList<QVariant> bindValues;
       
  1412     bindValues.append(serviceName);
       
  1413     database.executeQuery(&query, statement, bindValues);
       
  1414 
       
  1415     QStringList ids;
       
  1416     while   (query.next()) {
       
  1417         ids << query.value(0).toString();
       
  1418     }
       
  1419     return ids;
       
  1420 }
       
  1421 
       
  1422 QStringList ServiceDatabaseUnitTest::getServiceIDs(const QString &serviceName) {
       
  1423     QSqlDatabase sqlDatabase = QSqlDatabase::database(database.m_connectionName);
       
  1424     QSqlQuery query(sqlDatabase);
       
  1425     QString statement("SELECT Service.ID from Service "
       
  1426                         "WHERE Service.Name = ? COLLATE NOCASE");
       
  1427     QList<QVariant> bindValues;
       
  1428     bindValues.append(serviceName);
       
  1429     database.executeQuery(&query, statement, bindValues);
       
  1430 
       
  1431     QStringList ids;
       
  1432     while(query.next()) {
       
  1433         ids << query.value(0).toString();
       
  1434     }
       
  1435     return ids;
       
  1436 }
       
  1437 
       
  1438 bool ServiceDatabaseUnitTest::existsInInterfacePropertyTable(const QString &interfaceID)
       
  1439 {
       
  1440     QSqlDatabase sqlDatabase  = QSqlDatabase::database(database.m_connectionName);
       
  1441     QSqlQuery query(sqlDatabase);
       
  1442 
       
  1443     QString statement("SELECT InterfaceID FROM InterfaceProperty "
       
  1444                 "WHERE InterfaceID = ?");
       
  1445     QList<QVariant> bindValues;
       
  1446     bindValues.append(interfaceID);
       
  1447     database.executeQuery(&query, statement, bindValues);
       
  1448     if (query.next())
       
  1449         return true;
       
  1450     else
       
  1451         return false;
       
  1452 }
       
  1453 
       
  1454 bool ServiceDatabaseUnitTest::existsInServicePropertyTable(const QString &serviceID)
       
  1455 {
       
  1456     QSqlDatabase sqlDatabase  = QSqlDatabase::database(database.m_connectionName);
       
  1457     QSqlQuery query(sqlDatabase);
       
  1458 
       
  1459     QString statement("SELECT ServiceID from ServiceProperty "
       
  1460                         "WHERE ServiceID = ?");
       
  1461     QList<QVariant> bindValues;
       
  1462     bindValues.append(serviceID);
       
  1463     database.executeQuery(&query, statement, bindValues);
       
  1464     if (query.next())
       
  1465         return true;
       
  1466     else
       
  1467         return false;
       
  1468 }
       
  1469 
       
  1470 bool ServiceDatabaseUnitTest::existsInDefaultsTable(const QString &interfaceID)
       
  1471 {
       
  1472     QSqlDatabase sqlDatabase = QSqlDatabase::database(database.m_connectionName);
       
  1473     QSqlQuery query(sqlDatabase);
       
  1474     QString statement("SELECT InterfaceID From Defaults "
       
  1475                     "WHERE InterfaceID = ?");
       
  1476     QList<QVariant> bindValues;
       
  1477     bindValues.append(interfaceID);
       
  1478     database.executeQuery(&query, statement, bindValues);
       
  1479 
       
  1480     if (query.next())
       
  1481         return true;
       
  1482     else
       
  1483         return false;
       
  1484 }
       
  1485 
       
  1486 // Two small helper functions to assist with passing the security token to the servicedatabase.
       
  1487 // Do not use this function if you intentionally want to provide emtpy securityToken,
       
  1488 // but rather call database directly.
       
  1489 bool ServiceDatabaseUnitTest::registerService(const ServiceMetaDataResults &service, const QString &securityToken)
       
  1490 {
       
  1491 #ifdef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN
       
  1492     if (securityToken.isEmpty()) {
       
  1493         return database.registerService(service, securityTokenOwner);
       
  1494     } else {
       
  1495         return database.registerService(service, securityToken);
       
  1496     }
       
  1497 #else
       
  1498     Q_UNUSED(securityToken);
       
  1499     return database.registerService(service);
       
  1500 #endif
       
  1501 }
       
  1502 
       
  1503 bool ServiceDatabaseUnitTest::unregisterService(const QString &serviceName, const QString &securityToken)
       
  1504 {
       
  1505 #ifdef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN
       
  1506     if (securityToken.isEmpty()) {
       
  1507         return database.unregisterService(serviceName, securityTokenOwner);
       
  1508     } else {
       
  1509         return database.unregisterService(serviceName, securityToken);
       
  1510     }
       
  1511 #else
       
  1512     Q_UNUSED(securityToken);
       
  1513     return database.unregisterService(serviceName);
       
  1514 #endif
       
  1515 }
       
  1516 
       
  1517 void ServiceDatabaseUnitTest::securityTokens() {
       
  1518 #ifndef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN
       
  1519     QSKIP("Security tokens are not enabled (currently only enabled on Symbian).", SkipAll);
       
  1520 #endif
       
  1521     // Clear databases just in case
       
  1522     database.close();
       
  1523     QFile::remove(database.databasePath());
       
  1524     QDir testdir = QDir(TESTDATA_DIR "/testdata" );
       
  1525     QVERIFY(database.open());
       
  1526     database.m_databasePath = QDir::toNativeSeparators(QDir::currentPath().append("/services.db"));
       
  1527 
       
  1528     // Declare and setup testdata
       
  1529     ServiceMetaData parser(testdir.absoluteFilePath("ServiceAcme.xml"));
       
  1530     QVERIFY(parser.extractMetadata());
       
  1531 
       
  1532     // Actual teststeps
       
  1533     qDebug("---------- 1. Add and remove with same security token. (OK)");
       
  1534     QVERIFY(registerService(parser.parseResults(), securityTokenOwner));
       
  1535     QVERIFY(unregisterService("acme", securityTokenOwner));
       
  1536 
       
  1537     qDebug("---------- 2. Add and remove with empty security token. (NOK)");
       
  1538     QVERIFY(!database.registerService(parser.parseResults()));
       
  1539     QCOMPARE(database.lastError().code(), DBError::NoWritePermissions);
       
  1540     QVERIFY(!database.unregisterService("acme"));
       
  1541     QCOMPARE(database.lastError().code(), DBError::NoWritePermissions);
       
  1542 
       
  1543     qDebug("---------- 3. Add, then remove with different security token. (NOK)");
       
  1544     QVERIFY(registerService(parser.parseResults(), securityTokenOwner));
       
  1545     QVERIFY(!unregisterService("acme", securityTokenStranger));
       
  1546     QCOMPARE(database.lastError().code(), DBError::NoWritePermissions);
       
  1547     QVERIFY(unregisterService("acme", securityTokenOwner));
       
  1548 
       
  1549     qDebug("---------- 4. Add namesake but but differently located service with same security token. (OK)");
       
  1550     QStringList xmlFilesNamesakeServices;
       
  1551     xmlFilesNamesakeServices << "ServiceDharma_Swan.xml" << "ServiceDharma_Pearl.xml";
       
  1552     foreach(const QString &file, xmlFilesNamesakeServices) {
       
  1553         parser.setDevice(new QFile(testdir.absoluteFilePath(file)));
       
  1554         QVERIFY(parser.extractMetadata());
       
  1555         QVERIFY(registerService(parser.parseResults(), securityTokenOwner));
       
  1556     }
       
  1557     QVERIFY(!database.getServiceNames(QString()).isEmpty());
       
  1558     QVERIFY(unregisterService("DharmaInitiative", securityTokenOwner));
       
  1559     QVERIFY(database.getServiceNames(QString()).isEmpty());
       
  1560 
       
  1561     qDebug("---------- 5. Add namesake but differently located services with different security token. (NOK)");
       
  1562     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceDharma_Swan.xml")));
       
  1563     QVERIFY(parser.extractMetadata());
       
  1564     QVERIFY(registerService(parser.parseResults(), securityTokenOwner));
       
  1565     parser.setDevice(new QFile(testdir.absoluteFilePath("ServiceDharma_Pearl.xml")));
       
  1566     QVERIFY(parser.extractMetadata());
       
  1567     QVERIFY(!registerService(parser.parseResults(), securityTokenStranger));
       
  1568     QCOMPARE(database.lastError().code(), DBError::NoWritePermissions);
       
  1569     QVERIFY(unregisterService("DharmaInitiative", securityTokenOwner));
       
  1570 }
       
  1571 
       
  1572 void ServiceDatabaseUnitTest::cleanupTestCase()
       
  1573 {
       
  1574     database.close();
       
  1575     QFile::remove(database.databasePath());
       
  1576 }
       
  1577 QTEST_MAIN(ServiceDatabaseUnitTest)
       
  1578 
       
  1579 #include "tst_servicedatabase.moc"