diff -r 000000000000 -r 876b1a06bc25 tests/auto/databasemanager/tst_databasemanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/auto/databasemanager/tst_databasemanager.cpp Wed Aug 25 15:49:42 2010 +0300 @@ -0,0 +1,1316 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#define private public +#include +#include +#include "../qsfwtestutil.h" +#include + +#if defined(Q_OS_SYMBIAN) +# define TESTDATA_DIR "." +#endif + +QTM_USE_NAMESPACE + +class tst_DatabaseManager: public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void registerService(); + void getInterfaces(); + void getServiceNames(); + void defaultService(); + void unregisterService(); +#ifdef Q_OS_UNIX + void permissions(); + void onlyUserDbAvailable(); + void defaultServiceCornerCases(); +#endif + void nonWritableSystemDb(); + void CWRTXmlCompatability(); + void cleanupTestCase(); +private: + bool compareDescriptor(QServiceInterfaceDescriptor interface, + QString interfaceName, + QString serviceName, + int majorVersion, + int minorVersion); + + bool compareDescriptor(QServiceInterfaceDescriptor interface, + QString interfaceName, + QString serviceName, + int majorVersion, + int minorVersion, + QStringList capabilities, + QString filePath="", + QString serviceDescription="", + QString interfaceDescription=""); + + void clean(); + void modifyPermissionSet(QFile::Permissions &permsSet, + int perm); + + DatabaseManager *m_dbm; + QDir m_testdir; +}; + +void tst_DatabaseManager::initTestCase() +{ + QSfwTestUtil::setupTempUserDb(); + QSfwTestUtil::setupTempSystemDb(); + QSfwTestUtil::removeDirectory(QSfwTestUtil::tempSettingsPath()); + m_dbm = new DatabaseManager; +} + +void tst_DatabaseManager::registerService() +{ + m_testdir = QDir(TESTDATA_DIR "/testdata"); + ServiceMetaData parser(""); + + QStringList userServiceFiles; + userServiceFiles << "ServiceAcme.xml" << "ServiceLuthorCorp.xml" + << "ServicePrimatech.xml" + << "ServiceDharma_Swan.xml" + << "ServiceDharma_Pearl.xml" + << "ServiceDharma_Flame.xml" + << "ServiceDecepticon.xml"; + + foreach (const QString &serviceFile, userServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + } + + QStringList systemServiceFiles; + systemServiceFiles << "ServiceOmni.xml" << "ServiceWayneEnt.xml" + << "ServiceDharma_Hydra.xml" + << "ServiceDharma_Orchid.xml" + << "ServiceAutobot.xml"; + foreach (const QString &serviceFile, systemServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::SystemScope)); + } +} + +void tst_DatabaseManager::getInterfaces() +{ + QString iface("com.omni.device.accelerometer"); + QServiceFilter filter(iface); + QList descriptors; + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 5); + QVERIFY(compareDescriptor(descriptors[0], iface, "LuthorCorp", 1,2)); + QCOMPARE(descriptors[0].scope(), QService::UserScope); + QVERIFY(compareDescriptor(descriptors[1], iface, "Primatech", 1, 4)); + QCOMPARE(descriptors[1].scope(), QService::UserScope); + QVERIFY(compareDescriptor(descriptors[2], iface, "Primatech", 1, 2)); + QCOMPARE(descriptors[2].scope(), QService::UserScope); + QVERIFY(compareDescriptor(descriptors[3], iface, "OMNI", 1, 1)); + QCOMPARE(descriptors[3].scope(), QService::SystemScope); + QVERIFY(compareDescriptor(descriptors[4], iface, "WayneEnt", 2, 0)); + QCOMPARE(descriptors[4].scope(), QService::SystemScope); + + //check that we can get descriptors for a service spread + //over the user and system databases + filter.setServiceName("DharmaInitiative"); + filter.setInterface(""); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(),10); + + QStringList capabilities; + QVERIFY(compareDescriptor(descriptors[0], "com.dharma.electro.discharge", "DharmaInitiative", 4, 0, capabilities, "C:/island/swan.dll")); + QCOMPARE(descriptors[0].scope(), QService::UserScope); + QVERIFY(compareDescriptor(descriptors[1], "com.dharma.electro.discharge","DharmaInitiative", 8, 0, capabilities, "C:/island/pearl.dll")); + QCOMPARE(descriptors[1].scope(), QService::UserScope); + QVERIFY(compareDescriptor(descriptors[2], "com.dharma.electro.discharge", "DharmaInitiative", 15, 0, capabilities, "C:/island/flame.dll")); + QCOMPARE(descriptors[2].scope(), QService::UserScope); + QVERIFY(compareDescriptor(descriptors[3], "com.dharma.radio", "DharmaInitiative", 8, 15, capabilities, "C:/island/flame.dll")); + QCOMPARE(descriptors[3].scope(), QService::UserScope); + QVERIFY(compareDescriptor(descriptors[4], "com.dharma.electro.discharge", "DharmaInitiative", 16, 0, capabilities, "C:/island/flame.dll")); + QCOMPARE(descriptors[4].scope(), QService::UserScope); + QVERIFY(compareDescriptor(descriptors[5], "com.dharma.electro.discharge", "DharmaInitiative", 23, 0, capabilities, "C:/island/hydra.dll")); + QCOMPARE(descriptors[5].scope(), QService::SystemScope); + QVERIFY(compareDescriptor(descriptors[6], "com.dharma.electro.discharge", "DharmaInitiative", 42, 0, capabilities, "C:/island/hydra.dll")); + QCOMPARE(descriptors[6].scope(), QService::SystemScope); + QVERIFY(compareDescriptor(descriptors[7], "com.dharma.cage", "DharmaInitiative", 3, 16, capabilities, "C:/island/hydra.dll")); + QCOMPARE(descriptors[7].scope(), QService::SystemScope); + //note; the following system interface implementation overlaps with an interface implementation already provided in the user database + QVERIFY(compareDescriptor(descriptors[8], "com.dharma.electro.discharge", "DharmaInitiative", 4, 0, capabilities, "C:/island/orchid.dll")); + QCOMPARE(descriptors[8].scope(), QService::SystemScope); + QVERIFY(compareDescriptor(descriptors[9], "com.dharma.wheel", "DharmaInitiative", 1, 0, capabilities, "C:/island/orchid.dll")); + QCOMPARE(descriptors[9].scope(), QService::SystemScope); + + //do a system database only search + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::SystemScope); + QCOMPARE(descriptors.count(), 5); + QVERIFY(compareDescriptor(descriptors[0], "com.dharma.electro.discharge", "DharmaInitiative", 23, 0, capabilities, "C:/island/hydra.dll")); + QCOMPARE(descriptors[0].scope(), QService::SystemScope); + QVERIFY(compareDescriptor(descriptors[1], "com.dharma.electro.discharge", "DharmaInitiative", 42, 0, capabilities, "C:/island/hydra.dll")); + QCOMPARE(descriptors[1].scope(), QService::SystemScope); + QVERIFY(compareDescriptor(descriptors[2], "com.dharma.cage", "DharmaInitiative", 3, 16, capabilities, "C:/island/hydra.dll")); + QCOMPARE(descriptors[2].scope(), QService::SystemScope); + QVERIFY(compareDescriptor(descriptors[3], "com.dharma.electro.discharge", "DharmaInitiative", 4, 0, capabilities, "C:/island/orchid.dll")); + QCOMPARE(descriptors[3].scope(), QService::SystemScope); + QVERIFY(compareDescriptor(descriptors[4], "com.dharma.wheel", "DharmaInitiative", 1, 0, capabilities, "C:/island/orchid.dll")); + QCOMPARE(descriptors[4].scope(), QService::SystemScope); + + //search for a non-existent interface + filter.setServiceName(""); + filter.setInterface("com.omni.device.fluxcapacitor"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 0); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); +} + +void tst_DatabaseManager::getServiceNames() +{ + //try getting a lost of service names only in user database + QStringList serviceNames; + serviceNames = m_dbm->getServiceNames("", DatabaseManager::UserOnlyScope); + QStringList expectedNames; + expectedNames << "acme" << "LuthorCorp" << "Primatech" << "DharmaInitiative" << "Decepticon"; + QCOMPARE(serviceNames.count(), expectedNames.count()); + foreach(const QString &expectedName, expectedNames) + QVERIFY(serviceNames.contains(expectedName, Qt::CaseInsensitive)); + + //try getting a list of service names in the system database + serviceNames = m_dbm->getServiceNames("", DatabaseManager::SystemScope); + expectedNames.clear(); + expectedNames << "OMNI" << "WayneEnt" << "DharmaInitiative" << "Autobot"; + QCOMPARE(serviceNames.count(), expectedNames.count()); + foreach(const QString &expectedName, expectedNames) + QVERIFY(serviceNames.contains(expectedName, Qt::CaseInsensitive)); + + //try getting a list of service names from both databases + //and ensure there are no duplicates + serviceNames = m_dbm->getServiceNames("", DatabaseManager::UserScope); + expectedNames.clear(); + expectedNames << "acme" << "LuthorCorp" << "Primatech" << "omni" << "WayneEnt" + << "DharmaInitiative" << "Autobot" << "Decepticon"; + QCOMPARE(serviceNames.count(), expectedNames.count()); + foreach(const QString &expectedName, expectedNames) + QVERIFY(serviceNames.contains(expectedName, Qt::CaseInsensitive)); + + //try getting names of services that implement particular interface + serviceNames = m_dbm->getServiceNames("com.omni.device.accelerometer", DatabaseManager::UserScope); + expectedNames.clear(); + expectedNames << "LuthorCorp" << "Primatech" << "omni" << "WayneEnt"; + QCOMPARE(serviceNames.count(), expectedNames.count()); + foreach(const QString &expectedName, expectedNames) + QVERIFY(serviceNames.contains(expectedName, Qt::CaseInsensitive)); +} + +void tst_DatabaseManager::defaultService() +{ + QServiceInterfaceDescriptor descriptor; + + //get a user default service at user scope + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor,"com.omni.device.accelerometer", "LuthorCorp", 1, 2)); + QVERIFY(descriptor.scope()==QService::UserScope); + + //get a sytem default from user scope + descriptor = m_dbm->interfaceDefault("com.Dharma.wheel", DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor,"com.dharma.wheel", "DharmaInitiative", 1,0)); + QVERIFY(descriptor.scope() == QService::SystemScope); + + //get a system default service at system scope + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::SystemScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", "omni", 1, 1)); + + //set a user default from a user interface implementation + QList descriptors; + QServiceFilter filter; + filter.setServiceName("Primatech"); + filter.setInterface("com.omni.device.accelerometer", "1.4"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 1); + + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::UserScope)); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor,"com.omni.device.accelerometer", "Primatech", 1, 4)); + QVERIFY(descriptor.scope() == QService::UserScope); + + //set a system default from a system interface implementation + filter.setServiceName("WayneEnt"); + filter.setInterface("com.omni.device.accelerometer","2.0"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::SystemScope); + QCOMPARE(descriptors.count(), 1); + + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::SystemScope)); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::SystemScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", "WayneEnt", 2,0)); + QVERIFY(descriptor.scope() == QService::SystemScope ); + + //set a user default with a system interface descriptor + filter.setServiceName("omni"); + filter.setInterface("com.omni.device.accelerometer","1.1"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::SystemScope); + QCOMPARE(descriptors.count(), 1); + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::UserScope)); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(descriptor.isValid()); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", "omni", 1, 1)); + QVERIFY(descriptor.scope() == QService::SystemScope ); + + //set a system default using a user interface descriptor + filter.setServiceName("Primatech"); + filter.setInterface("com.omni.device.accelerometer","1.4"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 1); + + QVERIFY(!m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::InvalidDescriptorScope); + + // == try setting defaults using setInterfaceDefault(serviceName, interfaceName, ...) + //set a local default in the user scope database + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", "omni", 1, 1)); + QVERIFY(m_dbm->setInterfaceDefault("LuthorCorp", "com.omni.device.accelerometer", + DatabaseManager::UserScope)); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", "LuthorCorp", 1, 2)); + + //set a system default in the user scope database + descriptor = m_dbm->interfaceDefault("com.dharma.electro.disCHARGE", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 4, 0)); + QVERIFY(descriptor.scope() == QService::UserScope); + m_dbm->setInterfaceDefault("DharmaInitiative", "com.dharma.electro.discharge", + DatabaseManager::UserScope); + + descriptor = m_dbm->interfaceDefault("com.dharma.electro.discharge", + DatabaseManager::UserScope); + QVERIFY(m_dbm->lastError().code() == DBError::NoError); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 42, 0)); + + //set a user default in the user scope database but where there + //exist interface implementations in both user and system databases + //also check that the system scope default has not changed + filter.setServiceName("Autobot"); + filter.setInterface("com.cybertron.transform", "2.5", QServiceFilter::ExactVersionMatch ); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 1); + m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::UserScope); + descriptor = m_dbm->interfaceDefault("com.cybertron.transform", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptors[0], "com.cybertron.transform", + "Autobot", 2, 5)); + descriptor = m_dbm->interfaceDefault("com.cybertron.transform", + DatabaseManager::SystemScope); + QVERIFY(compareDescriptor(descriptors[0], "com.cybertron.transform", + "Autobot", 2, 5)); + + m_dbm->setInterfaceDefault("Decepticon", "com.cybertron.transform", DatabaseManager::UserScope); + descriptor = m_dbm->interfaceDefault("com.cybertron.transform", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.cybertron.transform", + "Decepticon", 5,3)); + descriptor = m_dbm->interfaceDefault("com.cybertron.transform", + DatabaseManager::SystemScope); + QVERIFY(compareDescriptor(descriptors[0], "com.cybertron.transform", + "Autobot", 2, 5)); + + //Look up a default service for a non-existent interface + descriptor = m_dbm->interfaceDefault("com.omni.device.fluxcapacitor", DatabaseManager::UserScope); + QVERIFY(!descriptor.isValid()); + QCOMPARE(m_dbm->lastError().code(), DBError::NotFound); +} + +void tst_DatabaseManager::unregisterService() +{ + //try remove a service that only exists in the user database + QServiceFilter filter; + filter.setServiceName("acme"); + QVERIFY(m_dbm->getInterfaces(filter, DatabaseManager::UserScope).count() > 0); + m_dbm->unregisterService("acme", DatabaseManager::UserScope); + QCOMPARE(m_dbm->getInterfaces(filter, DatabaseManager::UserScope).count(), 0); + + //try remove a service that only exists in the system database + filter.setServiceName("omni"); + QVERIFY(m_dbm->getInterfaces(filter, DatabaseManager::SystemScope).count() > 0); + QVERIFY(m_dbm->getInterfaces(filter, DatabaseManager::UserScope).count() > 0); + m_dbm->unregisterService("omni", DatabaseManager::SystemScope); + QCOMPARE(m_dbm->getInterfaces(filter, DatabaseManager::SystemScope).count(), 0); + QCOMPARE(m_dbm->getInterfaces(filter, DatabaseManager::UserScope).count(), 0); + + //try remove a service from the user database that also exists in the system database + filter.setServiceName("dharmainitiative"); + int systemCount = m_dbm->getInterfaces(filter, DatabaseManager::SystemScope).count(); + QVERIFY(m_dbm->getInterfaces(filter, DatabaseManager::SystemScope).count() > 0); + QVERIFY(m_dbm->getInterfaces(filter, DatabaseManager::UserScope).count() > 0); + m_dbm->unregisterService("dharmainitiative", DatabaseManager::UserScope); + QVERIFY(m_dbm->getInterfaces(filter, DatabaseManager::SystemScope).count() > 0); + QCOMPARE(m_dbm->getInterfaces(filter, DatabaseManager::UserScope).count(), systemCount); + + //re-add the service to the user database for the next test + ServiceMetaData parser(""); + parser.setDevice(new QFile(m_testdir.absoluteFilePath("ServiceDharma_Swan.xml"))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + + //try to remove a service from the system database that also exist in the user database + filter.setServiceName("dharmainitiative"); + int userCount = m_dbm->getInterfaces(filter, DatabaseManager::UserScope).count() + - m_dbm->getInterfaces(filter, DatabaseManager::SystemScope).count(); + QVERIFY(userCount > 0); + QVERIFY(m_dbm->getInterfaces(filter, DatabaseManager::SystemScope).count() > 0); + QVERIFY(m_dbm->getInterfaces(filter, DatabaseManager::UserScope).count() > 0); + m_dbm->unregisterService("dharmainitiative", DatabaseManager::SystemScope); + QCOMPARE(m_dbm->getInterfaces(filter, DatabaseManager::SystemScope).count(), 0); + QCOMPARE(m_dbm->getInterfaces(filter, DatabaseManager::UserScope).count(), userCount); + + //try and drop a table in the database by SQL injection + QVERIFY(!m_dbm->unregisterService("; drop table Interface;", DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NotFound); + + clean(); +} + +bool tst_DatabaseManager::compareDescriptor(QServiceInterfaceDescriptor interface, + QString interfaceName, QString serviceName, int majorVersion, int minorVersion) +{ + if (interface.d == NULL ) + return false; + interface.d->attributes[QServiceInterfaceDescriptor::Capabilities] = QStringList(); + + return compareDescriptor(interface, interfaceName, serviceName, majorVersion, minorVersion, + QStringList()); +} + +bool tst_DatabaseManager::compareDescriptor(QServiceInterfaceDescriptor interface, + QString interfaceName, QString serviceName, int majorVersion, int minorVersion, + QStringList capabilities, QString filePath, QString serviceDescription, + QString interfaceDescription) +{ + + if(interface.interfaceName().compare(interfaceName, Qt::CaseInsensitive) !=0) { + qWarning() << "Interface name mismatch: expected =" << interfaceName + << " actual =" << interface.interfaceName(); + return false; + } + + if (interface.serviceName().compare(serviceName, Qt::CaseInsensitive) != 0) { + qWarning() << "Service name mismatch: expected =" << serviceName + << " actual =" << interface.serviceName(); + return false; + } + + if (interface.majorVersion() != majorVersion) { + qWarning() << "Major version mismatch: expected =" << majorVersion + << " actual =" << interface.majorVersion(); + return false; + } + + if (interface.minorVersion() != minorVersion) { + qWarning() << "Minor version mismatch: expected =" << minorVersion + << " actual =" << interface.minorVersion(); + return false; + } + + if (capabilities.count() != 0 || interface.attribute(QServiceInterfaceDescriptor::Capabilities).toStringList().count() != 0 ) { + QStringList securityCapabilities; + securityCapabilities = interface.attribute(QServiceInterfaceDescriptor::Capabilities).toStringList(); + + if(securityCapabilities.count() != capabilities.count()) { + qWarning() << "Capabilities count mismatch: expected =" << capabilities.count() + << " actual="<< securityCapabilities.count() + << "\texpected capabilities =" << capabilities + << "actual capabilities =" << securityCapabilities; + return false; + } + + for (int i = 0; i < securityCapabilities.count(); ++i) { + if (securityCapabilities[i] != capabilities[i]) { + qWarning() << "Capability mismatch: expected =" << capabilities[i] + << " actual =" << securityCapabilities[i]; + return false; + } + } + } + + if (!filePath.isEmpty()) { + if (interface.attribute(QServiceInterfaceDescriptor::Location).toString() != filePath) { + qWarning() << "File path mismatch: expected =" << filePath + << " actual =" << interface.attribute(QServiceInterfaceDescriptor::Location).toString(); + return false; + } + } + if (!serviceDescription.isEmpty()) { + if (interface.attribute(QServiceInterfaceDescriptor::ServiceDescription).toString() != serviceDescription) { + qWarning() << "Service Description mismatch: expected =" << serviceDescription + << " actual=" << interface.attribute(QServiceInterfaceDescriptor::ServiceDescription).toString(); + return false; + } + } + if (!interfaceDescription.isEmpty()) { + if (interface.attribute(QServiceInterfaceDescriptor::InterfaceDescription).toString() != interfaceDescription) { + qWarning() << "Interface Description mismatch: expected =" << interfaceDescription + << " actual =" << interface.attribute(QServiceInterfaceDescriptor::InterfaceDescription).toString(); + return false; + } + + } + return true; +} +#ifdef Q_OS_UNIX +void tst_DatabaseManager::permissions() +{ + ServiceMetaDataResults results; + //try create a user scope database with no permissions + //to create the directory needed for the user db + QString userDir = QSfwTestUtil::userDirectory(); + QString systemDir = QSfwTestUtil::systemDirectory(); + + QDir::root().mkpath(userDir); + QDir::root().mkpath(systemDir); + + QFile::Permissions userPermsSet = QFile::permissions(userDir); + modifyPermissionSet(userPermsSet, ~QFile::ExeOwner); + QVERIFY(QFile::setPermissions(userDir, userPermsSet)); + + m_testdir = QDir(TESTDATA_DIR "/testdata"); + ServiceMetaData parser(""); + parser.setDevice(new QFile(m_testdir.absoluteFilePath("ServiceAcme.xml"))); + QVERIFY(parser.extractMetadata()); + m_dbm = new DatabaseManager; + results = parser.parseResults(); + QVERIFY(!m_dbm->registerService(results, DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::CannotOpenServiceDb); + + //try to create a system scope database with no permission to + //create the directory needed for the system db + QFile::Permissions systemPermsSet = QFile::permissions(systemDir); + modifyPermissionSet(systemPermsSet, ~QFile::ExeOwner); + QVERIFY(QFile::setPermissions(systemDir, systemPermsSet)); + + QVERIFY(!m_dbm->registerService(results, DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::CannotOpenServiceDb); + + //restore directory permissions + modifyPermissionSet(userPermsSet, QFile::ExeOwner); + QVERIFY(QFile::setPermissions(userDir, userPermsSet)); + modifyPermissionSet(systemPermsSet, QFile::ExeOwner); + QVERIFY(QFile::setPermissions(systemDir, systemPermsSet)); + + //try to create a user scope database without sufficient permissions + //for creation of the database file + QDir::root().mkpath(userDir + "/Nokia/"); + userPermsSet = QFile::permissions(userDir + "/Nokia/"); + modifyPermissionSet(userPermsSet, ~QFile::WriteOwner); + QVERIFY(QFile::setPermissions(userDir + "/Nokia/", userPermsSet)); + QVERIFY(!m_dbm->registerService(results, DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::CannotOpenServiceDb); + + //restore user directory permissions and create and populate a user database + modifyPermissionSet(userPermsSet, QFile::WriteOwner); + QVERIFY(QFile::setPermissions(userDir + "/Nokia", userPermsSet)); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + QString userDbFilePath = m_dbm->m_userDb->databasePath(); + + //try to access database without read permissions + userPermsSet = QFile::permissions(userDbFilePath); + modifyPermissionSet(userPermsSet, ~QFile::ReadOwner); + + QVERIFY(QFile::setPermissions(userDbFilePath, userPermsSet)); + delete m_dbm; + QServiceFilter filter; + m_dbm = new DatabaseManager; + QList descriptors; + descriptors= m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QVERIFY(!m_dbm->m_userDb->isOpen()); + QVERIFY(!m_dbm->m_systemDb->isOpen()); + QCOMPARE(m_dbm->lastError().code(), DBError::CannotOpenServiceDb); + + //restore permissions + modifyPermissionSet(userPermsSet, QFile::ReadOwner); + QVERIFY(QFile::setPermissions(userDbFilePath, userPermsSet)); + + //try to access an artificially corrupted user database + QFile userDbFile(userDbFilePath); + QFile acmeFile(m_testdir.absoluteFilePath("ServiceAcme.xml")); + QVERIFY(acmeFile.open(QIODevice::ReadWrite)); + QVERIFY(userDbFile.open(QIODevice::ReadWrite)); + userDbFile.resize(50); + userDbFile.seek(100); + QVERIFY(userDbFile.write(acmeFile.readAll()) != -1); + userDbFile.close(); + acmeFile.close(); + descriptors= m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QVERIFY(!m_dbm->m_userDb->isOpen()); + QVERIFY(!m_dbm->m_systemDb->isOpen()); + QCOMPARE(m_dbm->lastError().code(), DBError::InvalidDatabaseFile); + + //recreate a valid user database + userDbFile.remove(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + filter.setServiceName(""); + filter.setInterface(""); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 5); + + //try to register a service in the user db without write permissions + delete m_dbm; + userPermsSet = QFile::permissions(userDbFilePath); + modifyPermissionSet(userPermsSet, ~QFile::WriteOwner); + QVERIFY(QFile::setPermissions(userDbFilePath, userPermsSet)); + m_dbm = new DatabaseManager; + parser.setDevice(new QFile(m_testdir.absoluteFilePath("ServiceLuthorCorp.xml"))); + QVERIFY(parser.extractMetadata()); + results = parser.parseResults(); + QVERIFY(!m_dbm->registerService(results, DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoWritePermissions); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 5); + + modifyPermissionSet(userPermsSet, QFile::WriteOwner); + QVERIFY(QFile::setPermissions(userDbFilePath, userPermsSet)); + clean(); +} + +void tst_DatabaseManager::onlyUserDbAvailable() +{ + QString userNokiaDir = QSfwTestUtil::userDirectory() + "/Nokia/"; + QString systemNokiaDir = QSfwTestUtil::systemDirectory() + "/Nokia/"; + + QDir::root().mkpath(userNokiaDir); + QDir::root().mkpath(systemNokiaDir); + QFile::Permissions systemPermsSet = QFile::permissions(systemNokiaDir); + modifyPermissionSet(systemPermsSet, ~QFile::WriteOwner); + QFile::setPermissions(systemNokiaDir, systemPermsSet); + + m_dbm = new DatabaseManager; + + //check that we can register services with the user database + ServiceMetaData parser(""); + + QStringList userServiceFiles; + userServiceFiles << "ServiceAcme.xml" << "ServiceLuthorCorp.xml" + << "ServicePrimatech.xml"; + foreach (const QString &serviceFile, userServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + } + + QVERIFY(m_dbm->m_userDb->isOpen()); + QVERIFY(!m_dbm->m_systemDb->isOpen()); + + parser.setDevice(new QFile(m_testdir.absoluteFilePath("ServiceOmni.xml"))); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(!m_dbm->registerService(results, DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::CannotOpenServiceDb); + + QServiceFilter filter; + filter.setServiceName(""); + filter.setInterface(""); + QList descriptors; + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 8); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + + //Use getInterfaces where the database has not already been opened + //( via a previous call to register service) + delete m_dbm; + m_dbm = new DatabaseManager; + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 8); + QVERIFY(m_dbm->m_userDb->isOpen()); + QVERIFY(!m_dbm->m_systemDb->isOpen()); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + + //Use getServiceNames where the database has not already been opened + delete m_dbm; + m_dbm = new DatabaseManager; + QStringList serviceNames; + serviceNames = m_dbm->getServiceNames("", DatabaseManager::UserScope); + QCOMPARE(serviceNames.count(), 3); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + + //Use defaultService where database has not already been opened + delete m_dbm; + m_dbm = new DatabaseManager; + QServiceInterfaceDescriptor descriptor; + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "LuthorCorp", 1, 2)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + QVERIFY(m_dbm->m_userDb->isOpen()); + QVERIFY(!m_dbm->m_systemDb->isOpen()); + + //Use setInterfaceDefault(servicename, interfacename, scope) + delete m_dbm; + m_dbm = new DatabaseManager; + QVERIFY(m_dbm->setInterfaceDefault("Primatech", "com.omni.device.accelerometer", + DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "Primatech", 1, 4)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + + QVERIFY(!m_dbm->setInterfaceDefault("Primatech", "com.omni.device.accelerometer", + DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::CannotOpenServiceDb); + + //Use setInterfaceDefault(descriptor, scope) + filter.setServiceName("Primatech"); + filter.setInterface("com.omni.device.accelerometer", "1.2", + QServiceFilter::ExactVersionMatch); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 1); + QVERIFY(compareDescriptor(descriptors[0], "com.omni.device.accelerometer", + "Primatech", 1,2)); + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], + DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "Primatech", 1,2)); + QVERIFY(!m_dbm->setInterfaceDefault(descriptor, DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::InvalidDescriptorScope); + + //Use unregisterService() + delete m_dbm; + m_dbm = new DatabaseManager; + QVERIFY(m_dbm->unregisterService("primatech", DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + filter.setServiceName("Primatech"); + filter.setInterface(""); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + QCOMPARE(descriptors.count(),0); + + QVERIFY(!m_dbm->unregisterService("primatech", DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::CannotOpenServiceDb); + + //restore permissions so we can clean up the test directories + modifyPermissionSet(systemPermsSet, QFile::WriteOwner); + QFile::setPermissions(systemNokiaDir, systemPermsSet); + clean(); +} + +void tst_DatabaseManager::defaultServiceCornerCases() +{ + m_dbm = new DatabaseManager; + ServiceMetaData parser(""); + + QStringList userServiceFiles; + userServiceFiles << "ServiceAcme.xml" << "ServiceLuthorCorp.xml" + << "ServicePrimatech.xml" + << "ServiceDharma_Swan.xml" + << "ServiceDharma_Pearl.xml" + << "ServiceDharma_Flame.xml" + << "ServiceDecepticon.xml"; + + foreach (const QString &serviceFile, userServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + } + + QStringList systemServiceFiles; + systemServiceFiles << "ServiceOmni.xml" << "ServiceWayneEnt.xml" + << "ServiceDharma_Hydra.xml" + << "ServiceDharma_Orchid.xml" + << "ServiceAutobot.xml"; + foreach (const QString &serviceFile, systemServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::SystemScope)); + } + + // == set a system service interface implementation as a default at user scope then + // delete the system service and observe whether a new default + // has been chosen == + m_dbm->setInterfaceDefault("DharmaInitiative", "com.dharma.electro.discharge", + DatabaseManager::UserScope); + QServiceInterfaceDescriptor descriptor = + m_dbm->interfaceDefault("com.dharma.electro.discharge", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 42, 0)); + QVERIFY(descriptor.scope() == QService::SystemScope); + QVERIFY(m_dbm->unregisterService("DharmaInitiative", DatabaseManager::SystemScope)); + descriptor = m_dbm->interfaceDefault("com.dharma.electro.discharge", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 16, 0)); + // check again because there was a bug where the default service + // was correctly returned the first time but not the second + descriptor = m_dbm->interfaceDefault("com.dharma.electro.discharge", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 16, 0)); + + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + + // == set a system service interface as a default at user scope, + // remove availability to system db and confirm default cannot be found + // for that interface. Then restore the system db and confirm + // that a default can indeed be found. == + QVERIFY(m_dbm->setInterfaceDefault("WayneEnt", "com.omni.device.accelerometer", + DatabaseManager::UserScope)); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "WayneEnt", 2, 0)); + QString systemDbFilePath = m_dbm->m_systemDb->databasePath(); + QFile::Permissions systemPermsSet = QFile::permissions(systemDbFilePath); + modifyPermissionSet(systemPermsSet, ~QFile::ReadOwner); + QFile::setPermissions(systemDbFilePath, systemPermsSet); + + delete m_dbm; + m_dbm = new DatabaseManager; + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(m_dbm->m_userDb->isOpen()); + QVERIFY(!m_dbm->m_systemDb->isOpen()); + QVERIFY(!descriptor.isValid()); + QCOMPARE(m_dbm->lastError().code(), DBError::NotFound); + + modifyPermissionSet(systemPermsSet, QFile::ReadOwner); + QFile::setPermissions(systemDbFilePath, systemPermsSet); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(m_dbm->m_systemDb->isOpen()); + QVERIFY(descriptor.isValid()); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "WayneEnt", 2, 0)); + + //== set a system service interface as a user scope default, + // delete the service from the system scope database, + // ensure that when the default interface is queried + // it no longer exists == + m_dbm->setInterfaceDefault("omni", "com.omni.device.lights", //(will set an entry in the + DatabaseManager::UserScope); //defaults table of the user db database) + descriptor = m_dbm->interfaceDefault("com.omni.device.lights", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.lights", + "omni", 9, 0)); + QVERIFY(m_dbm->unregisterService("omni", DatabaseManager::SystemScope)); + descriptor = m_dbm->interfaceDefault("com.omni.device.lights", + DatabaseManager::UserScope); + QVERIFY(!descriptor.isValid()); + QCOMPARE(m_dbm->lastError().code(), DBError::NotFound); + clean(); + //Reinitialise the database + m_dbm = new DatabaseManager; + + userServiceFiles.clear(); + userServiceFiles << "ServiceAcme.xml" << "ServiceLuthorCorp.xml" + << "ServicePrimatech.xml" + << "ServiceDharma_Swan.xml" + << "ServiceDecepticon.xml"; + + foreach (const QString &serviceFile, userServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + } + systemServiceFiles.clear(); + systemServiceFiles << "ServiceOmni.xml" << "ServiceWayneEnt.xml" + << "ServiceDharma_Hydra.xml" + << "ServiceDharma_Orchid.xml" + << "ServiceAutobot.xml"; + foreach (const QString &serviceFile, systemServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::SystemScope)); + } + + //== Set a couple of external defaults in the user scope database, + // -remove the service that provides these defaults at the system scope. + // this will leave "hanging" default links in the user scope database + // -also set one default which will not be a hanging link + // -recreate the database manager and run getServiceNames so it will + // connect to both system and user scope databases. + // -verify that the hanging defaults links have been appropriately removed + // or reset to a new default interface implementation + // -also verify that the non-hanging link still exists == + QServiceFilter filter; + filter.setServiceName("DharmaInitiative"); + filter.setInterface("com.dharma.electro.discharge"); + QList descriptors; + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::SystemScope); + QVERIFY(descriptors.count() > 0); + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::UserScope)); + + filter.setServiceName("DharmaInitiative"); + filter.setInterface("com.dharma.wheel"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::SystemScope); + QVERIFY(descriptors.count() > 0); + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::UserScope)); + + filter.setServiceName("WayneEnt"); + filter.setInterface("com.omni.device.accelerometer"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::SystemScope); + QCOMPARE(descriptors.count(), 1); + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::UserScope)); + + QVERIFY(m_dbm->unregisterService("DharmaInitiative", DatabaseManager::SystemScope)); + QList > externalDefaultsInfo = m_dbm->m_userDb->externalDefaultsInfo(); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + QCOMPARE(externalDefaultsInfo.length(), 3); + + delete m_dbm; + + m_dbm = new DatabaseManager; + m_dbm->getServiceNames("", DatabaseManager::UserScope); + QCOMPARE(m_dbm->m_userDb->externalDefaultsInfo().count(), 1); + descriptor = m_dbm->interfaceDefault("com.dharma.electro.discharge", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor,"com.dharma.electro.discharge", + "DharmaInitiative", 4,0)); + descriptor = m_dbm->interfaceDefault("com.dharma.wheel", + DatabaseManager::UserScope); + QVERIFY(!descriptor.isValid()); + QCOMPARE(m_dbm->lastError().code(), DBError::NotFound); + + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "WayneEnt", 2,0)); + + // == set a system service interface as a default at user scope + // -remove the availability of the system db and confirm the default + // cannot be found + // -set a new default + // -restore availability of the system db and confirm the default + // is still the new default + filter.setServiceName("omni"); + filter.setInterface("com.omni.device.accelerometer"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 1); + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::UserScope)); + delete m_dbm; + + systemPermsSet = QFile::permissions(systemDbFilePath); + modifyPermissionSet(systemPermsSet, ~QFile::ReadOwner); + QFile::setPermissions(systemDbFilePath, systemPermsSet); + + m_dbm = new DatabaseManager; + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(!descriptor.isValid()); + QCOMPARE(m_dbm->lastError().code(), DBError::NotFound); + + filter.setServiceName("LuthorCorp"); + filter.setInterface("com.omni.device.accelerometer"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 1); + QVERIFY(m_dbm->m_userDb->isOpen()); + QVERIFY(!m_dbm->m_systemDb->isOpen()); + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::UserScope)); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "LuthorCorp", 1,2)); + modifyPermissionSet(systemPermsSet, QFile::ReadOwner); + QFile::setPermissions(systemDbFilePath, systemPermsSet); + m_dbm->getServiceNames("", DatabaseManager::UserScope);//this call is just to open the system db + QVERIFY(m_dbm->m_systemDb->isOpen()); + + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(descriptor.isValid()); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "LuthorCorp", 1,2)); + + // == Try set a descriptor as a default but the descriptor is invalid + // because the service it belongs to has been removed == + descriptor = m_dbm->interfaceDefault("com.cybertron.transform", + DatabaseManager::SystemScope); + QVERIFY(compareDescriptor(descriptor, "com.cybertron.transform", + "Autobot", 2, 7)); + QVERIFY(m_dbm->unregisterService("Autobot", + DatabaseManager::SystemScope)); + QVERIFY(!m_dbm->setInterfaceDefault(descriptor, DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NotFound); + + QVERIFY(!m_dbm->setInterfaceDefault(descriptor, DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NotFound); + + clean(); +} +#endif + +void tst_DatabaseManager::nonWritableSystemDb() +{ + m_dbm = new DatabaseManager; + ServiceMetaData parser(""); + + // Setup Initial user and system databases + QStringList userServiceFiles; + userServiceFiles << "ServiceAcme.xml" << "ServiceLuthorCorp.xml" + << "ServicePrimatech.xml"; + foreach (const QString &serviceFile, userServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + } + + QStringList systemServiceFiles; + systemServiceFiles << "ServiceOmni.xml" << "ServiceWayneEnt.xml" + << "ServiceDharma_Orchid.xml" + << "ServiceDharma_Hydra.xml"; + foreach (const QString &serviceFile, systemServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::SystemScope)); + } + + //make system database non-writable + QString systemDbFilePath = m_dbm->m_systemDb->databasePath(); + QFile::Permissions systemPermsSet = QFile::permissions(systemDbFilePath); + modifyPermissionSet(systemPermsSet, ~QFile::WriteOwner); + QFile::setPermissions(systemDbFilePath, systemPermsSet); + + //== test registration() == + delete m_dbm; + m_dbm = new DatabaseManager; + parser.setDevice(new QFile(m_testdir.absoluteFilePath("ServiceDharma_Swan.xml"))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + + parser.setDevice(new QFile(m_testdir.absoluteFilePath("ServiceAutobot.xml"))); + QVERIFY(parser.extractMetadata()); + results = parser.parseResults(); + QVERIFY(!m_dbm->registerService(results, DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoWritePermissions); + + //== test getInterfaces() == + delete m_dbm; + m_dbm = new DatabaseManager; + QList descriptors; + QServiceFilter filter; + filter.setServiceName(""); + filter.setInterface(""); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 18); + + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::SystemScope); + QCOMPARE(descriptors.count(), 9); + + // try a more restrictive filter with getInterfaces + filter.setServiceName(""); + filter.setInterface("com.dharma.electro.discharge", "4.0"); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 4); + + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::SystemScope); + QCOMPARE(descriptors.count(), 3); + + // ==test getServiceName() == + delete m_dbm; + m_dbm = new DatabaseManager; + QStringList expectedNames; + expectedNames << "LuthorCorp" << "Primatech" << "WayneEnt" << "omni"; + QStringList serviceNames = m_dbm->getServiceNames("com.omni.device.accelerometer", + DatabaseManager::UserScope); + foreach(const QString expectedName, expectedNames) + QVERIFY(serviceNames.contains(expectedName, Qt::CaseInsensitive)); + QCOMPARE(serviceNames.count(), expectedNames.count()); + + expectedNames.clear(); + expectedNames << "WayneEnt" << "omni"; + serviceNames = m_dbm->getServiceNames("com.omni.device.accelerometer", + DatabaseManager::SystemScope); + foreach(const QString expectedName, expectedNames) + QVERIFY(serviceNames.contains(expectedName, Qt::CaseInsensitive)); + QCOMPARE(serviceNames.count(), expectedNames.count()); + + //== test interfaceDefault() == + delete m_dbm; + m_dbm = new DatabaseManager; + QServiceInterfaceDescriptor descriptor; + descriptor = m_dbm->interfaceDefault("com.dharma.electro.discharge", + DatabaseManager::UserScope); + QStringList capabilities; + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 4, 0, capabilities, "C:/island/swan.dll")); + + descriptor = m_dbm->interfaceDefault("com.dharma.electro.discharge", + DatabaseManager::SystemScope); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 4, 0, capabilities, "C:/island/orchid.dll")); + //test setInterfaceDefault(service, interface, scope) + delete m_dbm; + m_dbm = new DatabaseManager; + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "LuthorCorp", 1,2)); + QVERIFY(m_dbm->setInterfaceDefault("Primatech", "com.omni.device.accelerometer", + DatabaseManager::UserScope)); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + + // try setting descriptor that originates from the system db + descriptor = m_dbm->interfaceDefault("com.dharma.electro.discharge", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 4, 0)); + QVERIFY(m_dbm->setInterfaceDefault("DharmaInitiative", "com.dhARMa.electro.discharge", + DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + descriptor = m_dbm->interfaceDefault("com.dharma.electro.discharge", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 42, 0)); + + // try setting a default at systems scope (this should fail) + descriptor = m_dbm->interfaceDefault("com.dharma.electro.Discharge", + DatabaseManager::SystemScope); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 4, 0)); + QVERIFY(!m_dbm->setInterfaceDefault("DharmaInitiative", "com.dharma.electro.discharge", + DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoWritePermissions); + descriptor = m_dbm->interfaceDefault("com.dharma.electro.Discharge", + DatabaseManager::SystemScope); + QVERIFY(compareDescriptor(descriptor, "com.dharma.electro.discharge", + "DharmaInitiative", 4, 0)); + + //== test setInterfaceDefault(descriptor,scope) == + delete m_dbm; + m_dbm = new DatabaseManager; + filter.setServiceName("primatech"); + filter.setInterface("com.omni.device.accelerometer", "1.2", + QServiceFilter::ExactVersionMatch); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "Primatech", 1, 4)); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 1); + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "Primatech", 1, 2)); + + // try setting a descriptor that originates from the system db + delete m_dbm; + m_dbm = new DatabaseManager; + filter.setServiceName("WayneEnt"); + filter.setInterface("com.omni.device.accelerometer", "2.0", + QServiceFilter::ExactVersionMatch); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(descriptors.count(), 1); + QCOMPARE(descriptors[0].scope(), QService::SystemScope); + QVERIFY(m_dbm->setInterfaceDefault(descriptors[0], + DatabaseManager::UserScope)); + descriptor = m_dbm->interfaceDefault("com.omni.device.accelerometer", + DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptor, "com.omni.device.accelerometer", + "WayneEnt", 2, 0)); + + // try setting a descriptor at system scope + QVERIFY(!m_dbm->setInterfaceDefault(descriptor, + DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoWritePermissions); + + //==test unregisterService()== + delete m_dbm; + m_dbm = new DatabaseManager; + QVERIFY(m_dbm->unregisterService("primatech", DatabaseManager::UserScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + filter.setServiceName("Primatech"); + filter.setInterface(""); + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QCOMPARE(m_dbm->lastError().code(), DBError::NoError); + QCOMPARE(descriptors.count(), 0); + + QVERIFY(!m_dbm->unregisterService("DharmaInitiative", + DatabaseManager::SystemScope)); + QCOMPARE(m_dbm->lastError().code(), DBError::NoWritePermissions); + + //make system database writable again + modifyPermissionSet(systemPermsSet, QFile::WriteOwner); + QFile::setPermissions(systemDbFilePath, systemPermsSet); + + clean(); +} + +void tst_DatabaseManager::CWRTXmlCompatability() +{ + m_dbm = new DatabaseManager; + ServiceMetaData parser(""); + + QStringList userServiceFiles; + userServiceFiles << "ServiceTest.xml" << "ServiceTest1.xml"; + foreach (const QString &serviceFile, userServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + QVERIFY(parser.extractMetadata()); + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::UserScope)); + } + + QString test("Test"); + for(int i = 0; i <= 10; ++i) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(test + QString::number(i) + QLatin1String(".xml")))); + if (i == 6) + QVERIFY(parser.extractMetadata()); + else + QVERIFY(!parser.extractMetadata()); + } + + QStringList systemServiceFiles; + systemServiceFiles << "ServiceTest2.xml" << "ServiceTest3.xml"; + foreach (const QString &serviceFile, systemServiceFiles) { + parser.setDevice(new QFile(m_testdir.absoluteFilePath(serviceFile))); + if (serviceFile == "ServiceTest3.xml") { + QVERIFY(!parser.extractMetadata());//versions less than 1.0 are not allowed + continue; + } else { + QVERIFY(parser.extractMetadata()); + } + ServiceMetaDataResults results = parser.parseResults(); + QVERIFY(m_dbm->registerService(results, DatabaseManager::SystemScope)); + } + + QServiceFilter filter; + filter.setInterface("com.nokia.ILocation"); + QList descriptors; + descriptors = m_dbm->getInterfaces(filter, DatabaseManager::UserScope); + QVERIFY(compareDescriptor(descriptors[0], "com.nokia.ILocation", "TestService", 1,0)); + QVERIFY(compareDescriptor(descriptors[1], "com.nokia.ILocation", "TestService1", 1,1)); + QVERIFY(compareDescriptor(descriptors[2], "com.nokia.ILocation", "TestService2", 1,2)); +} + +void tst_DatabaseManager::modifyPermissionSet(QFile::Permissions &permsSet, + int perm) +{ + switch(perm) { + case(QFile::ReadOwner): + permsSet |= QFile::ReadOwner; + permsSet |= QFile::ReadUser; + permsSet |= QFile::ReadGroup; + permsSet |= QFile::ReadOther; + break; + case(~QFile::ReadOwner): + permsSet &= ~QFile::ReadOwner; + permsSet &= ~QFile::ReadUser; + permsSet &= ~QFile::ReadGroup; + permsSet &= ~QFile::ReadOther; + break; + case(QFile::WriteOwner): + permsSet |= QFile::WriteOwner; + permsSet |= QFile::WriteUser; + permsSet |= QFile::WriteGroup; + permsSet |= QFile::WriteOther; + break; + case(~QFile::WriteOwner): + permsSet &= ~QFile::WriteOwner; + permsSet &= ~QFile::WriteUser; + permsSet &= ~QFile::WriteGroup; + permsSet &= ~QFile::WriteOther; + break; + case(QFile::ExeOwner): + permsSet |= QFile::ExeOwner; + permsSet |= QFile::ExeUser; + permsSet |= QFile::ExeGroup; + permsSet |= QFile::ExeOther; + break; + case(~QFile::ExeOwner): + permsSet &= ~QFile::ExeOwner; + permsSet &= ~QFile::ExeUser; + permsSet &= ~QFile::ExeGroup; + permsSet &= ~QFile::ExeOther; + break; + default: + break; + } +} + +void tst_DatabaseManager::clean() +{ + if (m_dbm != 0 ) { + delete m_dbm; + } + m_dbm = 0; + + QSfwTestUtil::removeDirectory(QSfwTestUtil::tempSettingsPath()); +} + +void tst_DatabaseManager::cleanupTestCase() +{ + clean(); +} + +QTEST_MAIN(tst_DatabaseManager) + +#include "tst_databasemanager.moc" +