/****************************************************************************
**
** 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 <qservicemanager.h>
#include <qservicecontext.h>
#include <qabstractsecuritysession.h>
#include <qserviceinterfacedescriptor_p.h>
#include "../../sampleserviceplugin/sampleserviceplugin.h"
#include "../qsfwtestutil.h"
#include <QtTest/QtTest>
#include <QtCore>
#include <QSettings>
#include <QFileInfo>
#include <QDir>
#include <QPair>
#define QTRY_COMPARE(a,e) \
for (int _i = 0; _i < 5000; _i += 100) { \
if ((a) == (e)) break; \
QTest::qWait(100); \
} \
QCOMPARE(a, e)
#define QTRY_VERIFY(a) \
for (int _i = 0; _i < 5000; _i += 100) { \
if (a) break; \
QTest::qWait(100); \
} \
QVERIFY(a)
#define PRINT_ERR(a) qPrintable(QString("error = %1").arg(a.error()))
typedef QList<QtMobility::QServiceInterfaceDescriptor> ServiceInterfaceDescriptorList;
Q_DECLARE_METATYPE(QtMobility::QServiceFilter)
Q_DECLARE_METATYPE(QtMobility::QServiceInterfaceDescriptor)
Q_DECLARE_METATYPE(ServiceInterfaceDescriptorList)
Q_DECLARE_METATYPE(QSet<QString>)
Q_DECLARE_METATYPE(QList<QByteArray>)
Q_DECLARE_METATYPE(QtMobility::QService::Scope)
QTM_BEGIN_NAMESPACE
typedef QHash<QtMobility::QServiceInterfaceDescriptor::Attribute, QVariant> DescriptorAttributes;
inline uint qHash(const QtMobility::QServiceInterfaceDescriptor &desc)
{
return qHash(desc.serviceName()) + qHash(desc.interfaceName()) + desc.majorVersion() * 7 + desc.minorVersion() * 7;
}
QTM_END_NAMESPACE
QTM_USE_NAMESPACE
static DescriptorAttributes defaultDescriptorAttributes()
{
DescriptorAttributes props;
//props[QServiceInterfaceDescriptor::Capabilities] = QStringList();
props[QServiceInterfaceDescriptor::Location] = "";
props[QServiceInterfaceDescriptor::ServiceDescription] = "";
props[QServiceInterfaceDescriptor::InterfaceDescription] = "";
return props;
}
static const DescriptorAttributes DEFAULT_DESCRIPTOR_PROPERTIES = defaultDescriptorAttributes();
static QStringList validPluginFiles()
{
// these are the plugins under tests/ which point to real service plugins
// that can be used for testing (i.e. plugins that can be loaded, invoked)
QStringList files;
files << "plugins/tst_sfw_sampleserviceplugin" << "plugins/tst_sfw_sampleserviceplugin2";
return files;
}
static const QStringList VALID_PLUGIN_FILES = validPluginFiles();
// Helper function for debugging. Useful e.g. for checking what is difference between
// two descriptors (in addition to attributes printed below, the \
// QServiceInterfaceDescriptor::== operator also compares
// attributes.
static void printDescriptor (QServiceInterfaceDescriptor &desc) {
qDebug("***QServiceInterfaceDescriptor printed:");
qDebug() << "***majorVersion:" << desc.majorVersion();
qDebug() << "***minorVersion:" << desc.minorVersion();
qDebug() << "***interfaceName:" << desc.interfaceName();
qDebug() << "***serviceName:" << desc.serviceName();
qDebug() << "***customAttributes:" << desc.customAttributes();
qDebug() << "***isValid(): " << desc.isValid();
qDebug() << "***scope (user:0, system:1): " << desc.scope();
}
class MySecuritySession : public QAbstractSecuritySession
{
public:
MySecuritySession() {}
virtual ~MySecuritySession() {}
virtual bool isAllowed(const QStringList&) { return true; }
};
class MyServiceContext : public QServiceContext
{
public:
MyServiceContext() {}
~MyServiceContext() {}
virtual void notify(ContextType, const QVariant&) {}
};
class ServicesListener : public QObject
{
Q_OBJECT
public slots:
void serviceAdded(const QString &name , QService::Scope scope) {
params.append(qMakePair(name, scope));
}
void serviceRemoved(const QString &name, QService::Scope scope) {
params.append(qMakePair(name, scope));
}
public:
QList<QPair<QString, QService::Scope> > params;
};
class tst_QServiceManager: public QObject
{
Q_OBJECT
private:
QString xmlTestDataPath(const QString &xmlFileName)
{
// On Symbian applicationDirPath returns application's private directory
return QCoreApplication::applicationDirPath() + "/plugins/xmldata/" + xmlFileName;
}
QByteArray createServiceXml(const QString &serviceName, const QByteArray &interfaceXml, const QString &path, const QString &description = QString()) const
{
QString xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
xml += "<service>\n";
xml += "<name>" + serviceName + "</name>\n";
xml += "<filepath>" + path + "</filepath>\n";
xml += "<description>" + description + "</description>\n";
xml += interfaceXml;
xml += "</service>\n";
return xml.toLatin1();
}
QByteArray createServiceXml(const QString &serviceName, const QList<QServiceInterfaceDescriptor> &descriptors) const
{
Q_ASSERT(descriptors.count() > 0);
return createServiceXml(serviceName, createInterfaceXml(descriptors),
descriptors[0].attribute(QServiceInterfaceDescriptor::Location).toString(),
descriptors[0].attribute(QServiceInterfaceDescriptor::ServiceDescription).toString());
}
QByteArray createInterfaceXml(const QList<QServiceInterfaceDescriptor> &descriptors) const
{
QByteArray interfacesXml;
foreach (const QServiceInterfaceDescriptor &desc, descriptors) {
QString version = QString("%1.%2").arg(desc.majorVersion()).arg(desc.minorVersion());
interfacesXml += createInterfaceXml(desc.interfaceName(), version,
desc.attribute(QServiceInterfaceDescriptor::InterfaceDescription).toString());
}
return interfacesXml;
}
QByteArray createInterfaceXml(const QString &name, const QString &version = "1.0", const QString &description = QString()) const
{
QString xml = "<interface>\n";
xml += "<name>" + name + "</name>\n";
xml += "<version>" + version + "</version>\n";
xml += " <description>" + description + "</description>\n";
xml += "</interface>\n";
return xml.toLatin1();
}
QServiceInterfaceDescriptor createDescriptor(const QString &interfaceName, int major, int minor, const QString &serviceName, const DescriptorAttributes &attributes = DescriptorAttributes(), QService::Scope scope = QService::UserScope) const
{
QString version = QString("%1.%2").arg(major).arg(minor);
QServiceInterfaceDescriptorPrivate *priv = new QServiceInterfaceDescriptorPrivate;
priv->serviceName = serviceName;
priv->interfaceName = interfaceName;
priv->major = major;
priv->minor = minor;
priv->scope = scope;
priv->attributes = attributes;
foreach (QServiceInterfaceDescriptor::Attribute key, DEFAULT_DESCRIPTOR_PROPERTIES.keys()) {
if (!priv->attributes.contains(key))
priv->attributes[key] = DEFAULT_DESCRIPTOR_PROPERTIES[key];
}
QServiceInterfaceDescriptor desc;
QServiceInterfaceDescriptorPrivate::setPrivate(&desc, priv);
return desc;
}
void deleteTestDatabasesAndWaitUntilDone()
{
QSfwTestUtil::removeTempUserDb();
QSfwTestUtil::removeTempSystemDb();
QTRY_VERIFY(!QFile::exists(QSfwTestUtil::tempUserDbDir()));
QTRY_VERIFY(!QFile::exists(QSfwTestUtil::tempSystemDbDir()));
}
private slots:
void initTestCase();
void cleanupTestCase();
void init();
void constructor();
void constructor_scope();
void constructor_scope_data();
void findServices();
void findServices_data();
void findServices_scope();
void findServices_scope_data();
void findInterfaces_filter();
void findInterfaces_filter_data();
void findInterfaces_scope();
void findInterfaces_scope_data();
void loadInterface_string();
void loadInterface_descriptor();
void loadInterface_descriptor_data();
void loadInterface_testLoadedObjectAttributes();
void loadLocalTypedInterface();
void addService();
void addService_data();
void addService_testInvalidServiceXml();
void addService_testPluginLoading();
void addService_testPluginLoading_data();
void addService_testInstallService();
void removeService();
void setInterfaceDefault_strings();
void setInterfaceDefault_strings_multipleInterfaces();
void setInterfaceDefault_descriptor();
void setInterfaceDefault_descriptor_data();
void interfaceDefault();
void serviceAdded();
void serviceAdded_data();
void serviceRemoved();
void serviceRemoved_data();
};
void tst_QServiceManager::initTestCase()
{
qRegisterMetaType<QService::Scope>("QService::Scope");
QSfwTestUtil::setupTempUserDb();
QSfwTestUtil::setupTempSystemDb();
#if defined(Q_OS_SYMBIAN)
QSfwTestUtil::removeDatabases_symbian();
#endif
}
void tst_QServiceManager::init()
{
#if defined(Q_OS_SYMBIAN)
// Wait a millisecond so that QServiceManagers are destroyed and release
// the database file (otherwise QFile::remove will get a permission denied -->
// in next case, the isEmpty() check fails).
QTest::qWait(1);
#endif
QSfwTestUtil::removeTempUserDb();
QSfwTestUtil::removeTempSystemDb();
#if defined(Q_OS_SYMBIAN)
QSfwTestUtil::removeDatabases_symbian();
#endif
QSettings settings("com.nokia.qt.serviceframework.tests", "SampleServicePlugin");
settings.setValue("installed", false);
}
void tst_QServiceManager::cleanupTestCase()
{
QSfwTestUtil::removeTempUserDb();
QSfwTestUtil::removeTempSystemDb();
#if defined(Q_OS_SYMBIAN)
QSfwTestUtil::removeDatabases_symbian();
#endif
//use QEventLopp::DeferredDeletion
//QServiceManager::loadInterface makes use of deleteLater() when
//cleaning up service objects and their respective QPluginLoader
//we want to force the testcase to run the cleanup code
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
}
void tst_QServiceManager::constructor()
{
QObject o;
QServiceManager mgr(&o);
QCOMPARE(mgr.scope(), QService::UserScope);
QCOMPARE(mgr.parent(), &o);
}
void tst_QServiceManager::constructor_scope()
{
QFETCH(QService::Scope, scope);
QObject o;
QServiceManager mgr(scope, &o);
QCOMPARE(mgr.scope(), scope);
QCOMPARE(mgr.parent(), &o);
}
void tst_QServiceManager::constructor_scope_data()
{
QTest::addColumn<QService::Scope>("scope");
QTest::newRow("user") << QService::UserScope;
QTest::newRow("system") << QService::SystemScope;
}
void tst_QServiceManager::findServices()
{
QFETCH(QList<QByteArray>, xmlBlocks);
QFETCH(QStringList, interfaceNames);
QFETCH(QSet<QString>, searchByInterfaceResult);
QFETCH(QSet<QString>, searchAllResult);
QServiceManager mgr;
QServiceFilter wildcardFilter;
// Check that nothing is found neither with default search or interface-search
QVERIFY(mgr.findServices().isEmpty());
foreach (const QString &interface, interfaceNames)
QVERIFY(mgr.findServices(interface).isEmpty());
QCOMPARE(mgr.findInterfaces(wildcardFilter).count(), 0);
// Add all services from the xmlBlocks list
foreach (const QByteArray &xml, xmlBlocks) {
QBuffer buffer;
buffer.setData(xml);
QVERIFY2(mgr.addService(&buffer), PRINT_ERR(mgr));
}
// Check that all services are found with default search
QCOMPARE(mgr.findServices().toSet(), searchAllResult);
// Check that all services are found based on interface search
foreach (const QString &interface, interfaceNames)
QCOMPARE(mgr.findServices(interface).toSet(), searchByInterfaceResult);
// Check that nothing is found with empty interface
QCOMPARE(mgr.findServices("com.invalid.interface") , QStringList());
}
void tst_QServiceManager::findServices_data()
{
QTest::addColumn< QList<QByteArray> >("xmlBlocks");
QTest::addColumn<QStringList>("interfaceNames");
QTest::addColumn< QSet<QString> >("searchByInterfaceResult");
QTest::addColumn< QSet<QString> >("searchAllResult");
QStringList interfaces;
interfaces << "com.nokia.qt.TestInterfaceA";
interfaces << "com.nokia.qt.TestInterfaceB";
QByteArray interfacesXml;
for (int i=0; i<interfaces.count(); i++)
interfacesXml += "\n" + createInterfaceXml(interfaces[i]);
QTest::newRow("one service")
<< (QList<QByteArray>() << createServiceXml("SomeTestService", interfacesXml, VALID_PLUGIN_FILES.first()))
<< interfaces
<< (QSet<QString>() << "SomeTestService")
<< (QSet<QString>() << "SomeTestService");
QTest::newRow("multiple services with same interfaces")
<< (QList<QByteArray>() << createServiceXml("SomeTestService", interfacesXml, VALID_PLUGIN_FILES[0])
<< createServiceXml("SomeSimilarTestService", interfacesXml, VALID_PLUGIN_FILES[1]))
<< interfaces
<< (QSet<QString>() << "SomeTestService" << "SomeSimilarTestService")
<< (QSet<QString>() << "SomeTestService" << "SomeSimilarTestService");
QStringList interfaces2;
interfaces2 << "com.nokia.qt.TestInterfaceY";
interfaces2 << "com.nokia.qt.TestInterfaceZ";
QByteArray interfacesXml2;
for (int i=0; i<interfaces2.count(); i++)
interfacesXml2 += "\n" + createInterfaceXml(interfaces2[i]);
QTest::newRow("multiple services with different interfaces")
<< (QList<QByteArray>() << createServiceXml("SomeTestService", interfacesXml, VALID_PLUGIN_FILES[0])
<< createServiceXml("TestServiceWithOtherInterfaces", interfacesXml2, VALID_PLUGIN_FILES[1]))
<< interfaces2
<< (QSet<QString>() << "TestServiceWithOtherInterfaces")
<< (QSet<QString>() << "SomeTestService" << "TestServiceWithOtherInterfaces");
}
void tst_QServiceManager::findServices_scope()
{
#if defined(Q_OS_SYMBIAN)
QSKIP("There is no difference between user and system scope in symbian", SkipAll);
#endif
QFETCH(QService::Scope, scope_add);
QFETCH(QService::Scope, scope_find);
QFETCH(bool, expectFound);
QByteArray xml = createServiceXml("SomeTestService",
createInterfaceXml("com.nokia.qt.TestInterface"), VALID_PLUGIN_FILES[0]);
QBuffer buffer(&xml);
QServiceManager mgrUser(QService::UserScope);
QServiceManager mgrSystem(QService::SystemScope);
QServiceManager &mgrAdd = scope_add == QService::UserScope ? mgrUser : mgrSystem;
QServiceManager &mgrFind = scope_find == QService::UserScope ? mgrUser : mgrSystem;
QVERIFY2(mgrAdd.addService(&buffer), PRINT_ERR(mgrAdd));
QStringList result = mgrFind.findServices();
QCOMPARE(!result.isEmpty(), expectFound);
}
void tst_QServiceManager::findServices_scope_data()
{
QTest::addColumn<QService::Scope>("scope_add");
QTest::addColumn<QService::Scope>("scope_find");
QTest::addColumn<bool>("expectFound");
QTest::newRow("user scope")
<< QService::UserScope << QService::UserScope << true;
QTest::newRow("system scope")
<< QService::SystemScope << QService::SystemScope << true;
QTest::newRow("user scope - add, system scope - find")
<< QService::UserScope << QService::SystemScope << false;
QTest::newRow("system scope - add, user scope - find")
<< QService::SystemScope << QService::UserScope << true;
}
void tst_QServiceManager::findInterfaces_filter()
{
QFETCH(QByteArray, xml);
QFETCH(QServiceFilter, filter);
QFETCH(QList<QServiceInterfaceDescriptor>, expectedInterfaces);
QServiceManager mgr;
QBuffer buffer(&xml);
QVERIFY2(mgr.addService(&buffer), PRINT_ERR(mgr));
QList<QServiceInterfaceDescriptor> result = mgr.findInterfaces(filter);
QCOMPARE(result.toSet(), expectedInterfaces.toSet());
}
void tst_QServiceManager::findInterfaces_filter_data()
{
QTest::addColumn<QByteArray>("xml");
QTest::addColumn<QServiceFilter>("filter");
QTest::addColumn<ServiceInterfaceDescriptorList>("expectedInterfaces");
QString serviceName = "SomeTestService";
DescriptorAttributes attributes;
attributes[QServiceInterfaceDescriptor::Location] = VALID_PLUGIN_FILES.first();
QList<QServiceInterfaceDescriptor> descriptors;
descriptors << createDescriptor("com.nokia.qt.TestInterfaceA", 1, 0, serviceName, attributes);
descriptors << createDescriptor("com.nokia.qt.TestInterfaceB", 1, 0, serviceName, attributes);
descriptors << createDescriptor("com.nokia.qt.TestInterfaceB", 2, 0, serviceName, attributes);
descriptors << createDescriptor("com.nokia.qt.TestInterfaceB", 2, 3, serviceName, attributes);
QByteArray serviceXml = createServiceXml(serviceName, descriptors);
QServiceFilter filter;
QTest::newRow("empty/wildcard filter")
<< serviceXml
<< QServiceFilter()
<< descriptors;
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceA");
QTest::newRow("by interface name (A)")
<< serviceXml
<< filter
<< descriptors.mid(0, 1);
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB");
QTest::newRow("by interface name (B)")
<< serviceXml
<< filter
<< descriptors.mid(1);
filter = QServiceFilter();
filter.setServiceName(serviceName);
QTest::newRow("by service name, should find all")
<< serviceXml
<< filter
<< descriptors;
filter = QServiceFilter();
filter.setInterface("com.invalid.interface");
QTest::newRow("by non-existing interface name")
<< serviceXml
<< filter
<< ServiceInterfaceDescriptorList();
filter = QServiceFilter();
filter.setServiceName("InvalidServiceName");
QTest::newRow("by non-existing service name")
<< serviceXml
<< filter
<< ServiceInterfaceDescriptorList();
//version lookup testing for existing interface
//valid from first version onwards
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "1.0");
QTest::newRow("by version name 1.0 DefaultMatch, should find all B interfaces")
<< serviceXml
<< filter
<< descriptors.mid(1);
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "1.0", QServiceFilter::MinimumVersionMatch);
QTest::newRow("by version name 1.0 MinimumMatch, should find all B interfaces")
<< serviceXml
<< filter
<< descriptors.mid(1);
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "1.0", QServiceFilter::ExactVersionMatch);
QTest::newRow("by version name 1.0 ExactMatch, find B 1.0 only")
<< serviceXml
<< filter
<< descriptors.mid(1, 1);
//valid with exact version match
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "2.0");
QTest::newRow("by version name 2.0 DefaultMatch, find B 2.0+")
<< serviceXml
<< filter
<< descriptors.mid(2);
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "2.0", QServiceFilter::MinimumVersionMatch);
QTest::newRow("by version name 2.0 MinimumMatch, find B 2.0+")
<< serviceXml
<< filter
<< descriptors.mid(2);
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "2.0", QServiceFilter::ExactVersionMatch);
QTest::newRow("by version name 2.0 ExactMatch, find B 2.0")
<< serviceXml
<< filter
<< descriptors.mid(2, 1);
//valid but not exact version match
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "1.9");
QTest::newRow("by version name 1.9 DefaultMatch, find B 1.9+")
<< serviceXml
<< filter
<< descriptors.mid(2);
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "1.9", QServiceFilter::MinimumVersionMatch);
QTest::newRow("by version name 1.9 MinimumMatch, find B 1.9+")
<< serviceXml
<< filter
<< descriptors.mid(2);
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "1.9", QServiceFilter::ExactVersionMatch);
QTest::newRow("by version name 1.9 ExactMatch")
<< serviceXml
<< filter
<< ServiceInterfaceDescriptorList();
//version doesn't exist yet
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "3.9");
QTest::newRow("by version name 3.9 DefaultMatch")
<< serviceXml
<< filter
<< ServiceInterfaceDescriptorList();
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "3.9", QServiceFilter::MinimumVersionMatch);
QTest::newRow("by version name 3.9 MinimumMatch")
<< serviceXml
<< filter
<< ServiceInterfaceDescriptorList();
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "3.9", QServiceFilter::ExactVersionMatch);
QTest::newRow("by version name 3.9 ExactMatch")
<< serviceXml
<< filter
<< ServiceInterfaceDescriptorList();
//invalid version tag 1 -> match anything
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "x3.9");
QTest::newRow("by version name x3.9 DefaultMatch")
<< serviceXml<< filter
<< descriptors;
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "x3.9", QServiceFilter::MinimumVersionMatch);
QTest::newRow("by version name x3.9 MinimumMatch")
<< serviceXml
<< filter
<< descriptors;
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "x3.9", QServiceFilter::ExactVersionMatch);
QTest::newRow("by version name x3.9 ExactMatch")
<< serviceXml
<< filter
<< descriptors;
//envalid/empty version tag
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "");
QTest::newRow("by empty version string DefaultMatch")
<< serviceXml
<< filter
<< descriptors.mid(1);
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "", QServiceFilter::MinimumVersionMatch);
QTest::newRow("by empty version string MinimumMatch")
<< serviceXml
<< filter
<< descriptors.mid(1);
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "", QServiceFilter::ExactVersionMatch); //what's the result of this?
QTest::newRow("by empty version string ExactMatch")
<< serviceXml
<< filter
<< descriptors.mid(1);
//invalid version tag 2
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "abc");
QTest::newRow("by version name abc DefaultMatch")
<< serviceXml<< filter
<< descriptors;
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "abc", QServiceFilter::MinimumVersionMatch);
QTest::newRow("by version name abc MinimumMatch")
<< serviceXml<< filter
<< descriptors;
filter = QServiceFilter();
filter.setInterface("com.nokia.qt.TestInterfaceB", "abc", QServiceFilter::ExactVersionMatch);
QTest::newRow("by version name abc ExactMatch")
<< serviceXml
<< filter
<< descriptors;
}
void tst_QServiceManager::findInterfaces_scope()
{
#if defined(Q_OS_SYMBIAN)
QSKIP("There is no difference between user and system scope in symbian", SkipAll);
#endif
QFETCH(QService::Scope, scope_add);
QFETCH(QService::Scope, scope_find);
QFETCH(bool, expectFound);
QByteArray xml = createServiceXml("SomeTestService",
createInterfaceXml("com.nokia.qt.TestInterface"), VALID_PLUGIN_FILES[0]);
QBuffer buffer(&xml);
QServiceManager mgrUser(QService::UserScope);
QServiceManager mgrSystem(QService::SystemScope);
QServiceManager &mgrAdd = scope_add == QService::UserScope ? mgrUser : mgrSystem;
QServiceManager &mgrFind = scope_find == QService::UserScope ? mgrUser : mgrSystem;
QList<QServiceInterfaceDescriptor> result = mgrFind.findInterfaces(QString());
QVERIFY(result.isEmpty());
QVERIFY2(mgrAdd.addService(&buffer), PRINT_ERR(mgrAdd));
result = mgrFind.findInterfaces("SomeTestService");
QCOMPARE(!result.isEmpty(), expectFound);
result = mgrFind.findInterfaces(QString());
if (expectFound)
QVERIFY(result.count() == 1);
else
QVERIFY(result.isEmpty());
result = mgrFind.findInterfaces("NonExistingService");
QVERIFY(result.isEmpty());
}
void tst_QServiceManager::findInterfaces_scope_data()
{
findServices_scope_data();
}
void tst_QServiceManager::loadInterface_string()
{
// The sampleservice.xml and sampleservice2.xml services in
// tests/sampleserviceplugin and tests/sampleserviceplugin2 implement a
// common interface, "com.nokia.qt.TestInterfaceA". If both are
// registered, loadInterface(QString) should return the correct one
// depending on which is set as the default.
// Real servicenames and classnames
QString serviceA = "SampleService";
QString serviceAClassName = "SampleServicePluginClass";
QString serviceB = "SampleService2";
QString serviceBClassName = "SampleServicePluginClass2";
QObject *obj = 0;
QServiceManager mgr;
QString commonInterface = "com.nokia.qt.TestInterfaceA";
// Add first service. Adds the service described in
// c/Private/<uid3 of this executable>/plugins/xmldata/sampleservice.xml
QVERIFY2(mgr.addService(xmlTestDataPath("sampleservice.xml")), PRINT_ERR(mgr));
obj = mgr.loadInterface(commonInterface, 0, 0);
QVERIFY(obj != 0);
QCOMPARE(QString(obj->metaObject()->className()), serviceAClassName);
delete obj;
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
// Add first service. Adds the service described in
// c/Private/<uid3 of this executable>/plugins/xmldata/sampleservice2.xml
QVERIFY2(mgr.addService(xmlTestDataPath("sampleservice2.xml")), PRINT_ERR(mgr));
// if first service is set as default, it should be returned
QVERIFY(mgr.setInterfaceDefault(serviceA, commonInterface));
obj = mgr.loadInterface(commonInterface, 0, 0);
QVERIFY(obj != 0);
QCOMPARE(QString(obj->metaObject()->className()), serviceAClassName);
delete obj;
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
// if second service is set as default, it should be returned
QVERIFY(mgr.setInterfaceDefault(serviceB, commonInterface));
obj = mgr.loadInterface(commonInterface, 0, 0);
QVERIFY(obj != 0);
QCOMPARE(QString(obj->metaObject()->className()), serviceBClassName);
delete obj;
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
}
void tst_QServiceManager::loadInterface_descriptor()
{
QFETCH(QServiceInterfaceDescriptor, descriptor);
QFETCH(QString, className);
QObject* obj;
{
QServiceManager mgr;
MySecuritySession session;
MyServiceContext context;
obj = mgr.loadInterface(descriptor, &context, &session);
QVERIFY(obj != 0);
QCOMPARE(className, QString(obj->metaObject()->className()));
}
QVERIFY(obj != 0);
delete obj;
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
}
void tst_QServiceManager::loadInterface_descriptor_data()
{
QTest::addColumn<QServiceInterfaceDescriptor>("descriptor");
QTest::addColumn<QString>("className");
QLibrary lib;
QServiceInterfaceDescriptor descriptor;
QServiceInterfaceDescriptorPrivate *priv = new QServiceInterfaceDescriptorPrivate;
priv->interfaceName = "com.nokia.qt.TestInterfaceA"; // needed by service plugin implementation
lib.setFileName(QCoreApplication::applicationDirPath() + "/plugins/tst_sfw_sampleserviceplugin");
QVERIFY(lib.load());
QVERIFY(lib.unload());
#if defined (Q_OS_SYMBIAN)
priv->attributes[QServiceInterfaceDescriptor::Location] = "plugins/" + lib.fileName();
#else
priv->attributes[QServiceInterfaceDescriptor::Location] = lib.fileName();
#endif
QServiceInterfaceDescriptorPrivate::setPrivate(&descriptor, priv);
QTest::newRow("tst_sfw_sampleserviceplugin")
<< descriptor
<< "SampleServicePluginClass";
lib.setFileName(QCoreApplication::applicationDirPath() + "/plugins/tst_sfw_testservice2plugin");
QVERIFY(lib.load());
QVERIFY(lib.unload());
#if defined(Q_OS_SYMBIAN)
priv->attributes[QServiceInterfaceDescriptor::Location] = "plugins/" + lib.fileName();
#else
priv->attributes[QServiceInterfaceDescriptor::Location] = lib.fileName();
#endif
QServiceInterfaceDescriptorPrivate::setPrivate(&descriptor, priv);
QTest::newRow("tst_sfw_sampleserviceplugin2")
<< descriptor
<< "TestService";
}
void tst_QServiceManager::loadInterface_testLoadedObjectAttributes()
{
QLibrary lib(QCoreApplication::applicationDirPath() + "/plugins/tst_sfw_testservice2plugin");
QVERIFY(lib.load());
QVERIFY(lib.unload());
QServiceInterfaceDescriptor descriptor;
QServiceInterfaceDescriptorPrivate *priv = new QServiceInterfaceDescriptorPrivate;
priv->interfaceName = "com.nokia.qt.TestInterfaceA"; // needed by service plugin implementation
#if defined(Q_OS_SYMBIAN)
priv->attributes[QServiceInterfaceDescriptor::Location] = "plugins/" + lib.fileName();
#else
priv->attributes[QServiceInterfaceDescriptor::Location] = lib.fileName();
#endif
QServiceInterfaceDescriptorPrivate::setPrivate(&descriptor, priv);
QServiceManager mgr;
MySecuritySession session;
MyServiceContext context;
QObject *obj = mgr.loadInterface(descriptor, &context, &session);
QVERIFY(obj != 0);
bool invokeOk = false;
QString name;
// check attributes
QMetaProperty nameProperty = obj->metaObject()->property(obj->metaObject()->indexOfProperty("name"));
QVERIFY(nameProperty.isValid());
QVERIFY(nameProperty.write(obj, "A service name"));
QCOMPARE(nameProperty.read(obj), QVariant("A service name"));
// check signals
QVERIFY(obj->metaObject()->indexOfSignal("someSignal()") >= 0);
QSignalSpy spy(obj, SIGNAL(someSignal()));
invokeOk = QMetaObject::invokeMethod(obj, "someSignal");
QVERIFY(invokeOk);
QVERIFY(spy.count() == 1);
// check slots
invokeOk = QMetaObject::invokeMethod(obj, "callSlot");
QVERIFY(invokeOk);
invokeOk = QMetaObject::invokeMethod(obj, "callSlotAndSetName", Q_ARG(QString, "test string"));
QVERIFY(invokeOk);
invokeOk = QMetaObject::invokeMethod(obj, "callSlotAndReturnName", Q_RETURN_ARG(QString, name));
QVERIFY(invokeOk);
QCOMPARE(name, QString("test string"));
// check invokables
invokeOk = QMetaObject::invokeMethod(obj, "callInvokable");
QVERIFY(invokeOk);
// call method on a returned object
QObject *embeddedObj = 0;
int value = 0;
invokeOk = QMetaObject::invokeMethod(obj, "embeddedTestService", Q_RETURN_ARG(QObject*, embeddedObj));
QVERIFY(invokeOk);
invokeOk = QMetaObject::invokeMethod(embeddedObj, "callWithInt", Q_RETURN_ARG(int, value), Q_ARG(int, 10));
QVERIFY(invokeOk);
QCOMPARE(value, 10);
// call a method that is not invokable via meta system
invokeOk = QMetaObject::invokeMethod(embeddedObj, "callNormalMethod");
QVERIFY(!invokeOk);
delete obj;
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
}
void tst_QServiceManager::loadLocalTypedInterface()
{
//ensure the plugin exists
QLibrary lib(QCoreApplication::applicationDirPath() + "/plugins/tst_sfw_sampleserviceplugin");
QCOMPARE(lib.load(), true);
lib.unload();
QServiceManager mgr;
MySecuritySession session;
MyServiceContext context;
QServiceInterfaceDescriptor descriptor;
QServiceInterfaceDescriptorPrivate *priv = new QServiceInterfaceDescriptorPrivate;
priv->interfaceName = "com.nokia.qt.TestInterfaceA"; // needed by service plugin implementation
#if defined(Q_OS_SYMBIAN)
priv->attributes[QServiceInterfaceDescriptor::Location] = "plugins/" + lib.fileName();
#else
priv->attributes[QServiceInterfaceDescriptor::Location] = lib.fileName();
#endif
QServiceInterfaceDescriptorPrivate::setPrivate(&descriptor, priv);
//use manual descriptor -> avoid database involvement
SampleServicePluginClass *plugin = 0;
plugin = mgr.loadLocalTypedInterface<SampleServicePluginClass>(descriptor, &context, &session);
QVERIFY(plugin != 0);
QCOMPARE(plugin->context(), (QServiceContext *)&context);
QCOMPARE(plugin->securitySession(), (QAbstractSecuritySession *)&session);
delete plugin;
plugin = 0;
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
//use database descriptor
QFile file1(xmlTestDataPath("sampleservice.xml"));
QVERIFY(file1.exists());
QVERIFY2(mgr.addService(&file1), PRINT_ERR(mgr));
QCOMPARE(mgr.findServices("com.nokia.qt.TestInterfaceA"), QStringList("SampleService"));
QCOMPARE(mgr.findServices("com.nokia.qt.TestInterfaceB"), QStringList("SampleService"));
QCOMPARE(mgr.findServices("com.nokia.qt.TestInterfaceC"), QStringList("SampleService"));
QList<QServiceInterfaceDescriptor> ifaces = mgr.findInterfaces("SampleService");
QList<SampleServicePluginClass*> serviceObjects;
QVERIFY(ifaces.count() == 3);
for (int i = 0; i<ifaces.count(); i++) {
plugin = mgr.loadLocalTypedInterface<SampleServicePluginClass>(ifaces.at(i), &context, &session);
if (ifaces.at(i).interfaceName() == "com.nokia.qt.TestInterfaceC") {
QVERIFY(plugin == 0);
} else {
QVERIFY(plugin != 0);
QCOMPARE(plugin->context(), (QServiceContext *)&context);
QCOMPARE(plugin->securitySession(), (QAbstractSecuritySession *)&session);
plugin->testSlotOne();
serviceObjects.append(plugin);
}
}
//test for a bug where two service instances from same plugin
//caused a crash when the first instance was deleted and
//the second instance called
QVERIFY(serviceObjects.count() == 2);
delete serviceObjects.takeFirst();
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
plugin = serviceObjects.takeFirst();
plugin->testSlotOne();
delete plugin;
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
//use default lookup
plugin = mgr.loadLocalTypedInterface<SampleServicePluginClass>("com.nokia.qt.TestInterfaceA", &context, &session);
QVERIFY(plugin != 0);
QCOMPARE(plugin->context(), (QServiceContext *)&context);
QCOMPARE(plugin->securitySession(), (QAbstractSecuritySession *)&session);
delete plugin;
QCoreApplication::processEvents(QEventLoop::AllEvents|QEventLoop::DeferredDeletion);
plugin = 0;
//use totally wrong but QObject based template class type
QFile *w = mgr.loadLocalTypedInterface<QFile>("com.nokia.qt.TestInterfaceA", &context, &session);
QVERIFY(!w);
//use non QObject based template class type
//doesn't compile and should never compile
//QString* s = mgr.loadLocalTypedInterface<QString>("com.nokia.qt.TestInterfaceA", &context, &session);
//QVERIFY(!s);
}
#define TST_QSERVICEMANAGER_ADD_SERVICE(paramType, file) { \
if (paramType == "QString") \
QVERIFY2(mgr.addService(file->fileName()), PRINT_ERR(mgr)); \
else if (paramType == "QIODevice") \
QVERIFY2(mgr.addService(file), PRINT_ERR(mgr)); \
else \
QFAIL("tst_QServiceManager::addService(): Bad test parameter"); \
}
void tst_QServiceManager::addService()
{
QFETCH(QString, paramType);
QServiceManager mgr;
QString commonInterface = "com.qt.serviceframework.tests.CommonInterface";
QByteArray xmlA = createServiceXml("ServiceA", createInterfaceXml(commonInterface), VALID_PLUGIN_FILES[0]);
QByteArray xmlB = createServiceXml("ServiceB", createInterfaceXml(commonInterface), VALID_PLUGIN_FILES[1]);
QTemporaryFile *tempFileA = new QTemporaryFile(this);
QVERIFY2(tempFileA->open(), "Can't open temp file A");
tempFileA->write(xmlA);
tempFileA->seek(0);
QTemporaryFile *tempFileB = new QTemporaryFile(this);
QVERIFY2(tempFileB->open(), "Can't open temp file B");
tempFileB->write(xmlB);
tempFileB->seek(0);
TST_QSERVICEMANAGER_ADD_SERVICE(paramType, tempFileA);
QCOMPARE(mgr.findServices(), QStringList("ServiceA"));
// the service should be automatically set as the default for its
// implemented interfaces since it was the first service added for them
QCOMPARE(mgr.interfaceDefault(commonInterface).serviceName(), QString("ServiceA"));
QCOMPARE(mgr.interfaceDefault(commonInterface).serviceName(), QString("ServiceA"));
// add second service
TST_QSERVICEMANAGER_ADD_SERVICE(paramType, tempFileB);
QStringList result = mgr.findServices();
QCOMPARE(result.count(), 2);
QVERIFY(result.contains("ServiceA"));
QVERIFY(result.contains("ServiceB"));
// the default does not change once ServiceB is added
QCOMPARE(mgr.interfaceDefault(commonInterface).serviceName(), QString("ServiceA"));
QCOMPARE(mgr.interfaceDefault(commonInterface).serviceName(), QString("ServiceA"));
delete tempFileA;
delete tempFileB;
}
void tst_QServiceManager::addService_data()
{
QTest::addColumn<QString>("paramType");
QTest::newRow("string") << "QString";
QTest::newRow("iodevice") << "QIODevice";
}
void tst_QServiceManager::addService_testInvalidServiceXml()
{
QBuffer buffer;
QServiceManager mgr;
QVERIFY2(!mgr.addService(&buffer), PRINT_ERR(mgr));
// a service with no interfaces
QString xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
xml += "<service><name>SomeService</name><filepath>" + VALID_PLUGIN_FILES.first() + "</filepath>\n";
xml += "</service>\n";
buffer.close();
buffer.setData(xml.toLatin1());
QVERIFY(!mgr.addService(&buffer));
QVERIFY2(mgr.findServices().isEmpty(), PRINT_ERR(mgr));
}
void tst_QServiceManager::addService_testPluginLoading()
{
QFETCH(QString, pluginPath);
QFETCH(bool, isAdded);
QServiceManager mgr;
QByteArray xml = createServiceXml("SomeService", createInterfaceXml("com.qt.serviceframework.Interface"), pluginPath);
QBuffer buffer(&xml);
QVERIFY2(mgr.addService(&buffer) == isAdded, PRINT_ERR(mgr));
// the service should not be added if the service plugin cannot be loaded
if (!isAdded)
QVERIFY(mgr.findServices().isEmpty());
}
void tst_QServiceManager::addService_testPluginLoading_data()
{
QTest::addColumn<QString>("pluginPath");
QTest::addColumn<bool>("isAdded");
QTest::newRow("valid path") << VALID_PLUGIN_FILES.first() << true;
QTest::newRow("invalid path") << "no_such_plugin" << false;
}
void tst_QServiceManager::addService_testInstallService()
{
QSettings settings("com.nokia.qt.serviceframework.tests", "SampleServicePlugin");
QCOMPARE(settings.value("installed").toBool(), false);
QServiceManager mgr;
QVERIFY2(mgr.addService(xmlTestDataPath("sampleservice.xml")), PRINT_ERR(mgr));
QCOMPARE(mgr.findServices(), QStringList("SampleService"));
// test installService() was called on the plugin
QCOMPARE(settings.value("installed").toBool(), true);
}
void tst_QServiceManager::removeService()
{
QServiceManager mgr;
QVERIFY(!mgr.removeService("NonExistentService"));
QSettings settings("com.nokia.qt.serviceframework.tests", "SampleServicePlugin");
QCOMPARE(settings.value("installed").toBool(), false);
QVERIFY2(mgr.addService(xmlTestDataPath("sampleservice.xml")), PRINT_ERR(mgr));
QCOMPARE(mgr.findServices("com.nokia.qt.TestInterfaceA"), QStringList("SampleService"));
QCOMPARE(settings.value("installed").toBool(), true);
QVERIFY(mgr.removeService("SampleService"));
QVERIFY(mgr.findServices().isEmpty());
QCOMPARE(mgr.findServices("com.nokia.qt.TestInterfaceA"), QStringList());
QCOMPARE(settings.value("installed").toBool(), false);
// add it again, should still work
QVERIFY2(mgr.addService(xmlTestDataPath("sampleservice.xml")), PRINT_ERR(mgr));
QCOMPARE(mgr.findServices("com.nokia.qt.TestInterfaceA"), QStringList("SampleService"));
QCOMPARE(settings.value("installed").toBool(), true);
}
void tst_QServiceManager::setInterfaceDefault_strings()
{
QServiceManager mgr;
QString interfaceName = "com.nokia.qt.serviceframework.tests.AnInterface";
DescriptorAttributes attributes;
QServiceInterfaceDescriptor descriptor;
QByteArray xml;
attributes[QServiceInterfaceDescriptor::Location] = VALID_PLUGIN_FILES[0];
descriptor = createDescriptor(interfaceName, 1, 0, "ServiceA", attributes);
xml = createServiceXml("ServiceA",
createInterfaceXml(QList<QServiceInterfaceDescriptor>() << descriptor),
attributes[QServiceInterfaceDescriptor::Location].toString());
QBuffer buffer(&xml);
// fails if the specified interface hasn't been registered
QCOMPARE(mgr.setInterfaceDefault("ServiceA", interfaceName), false);
// now it works
QVERIFY2(mgr.addService(&buffer), PRINT_ERR(mgr));
QCOMPARE(mgr.setInterfaceDefault("ServiceA", interfaceName), true);
QCOMPARE(mgr.interfaceDefault(interfaceName), descriptor);
// replace the default with another service
attributes[QServiceInterfaceDescriptor::Location] = VALID_PLUGIN_FILES[1];
descriptor = createDescriptor(interfaceName, 1, 0, "ServiceB", attributes);
xml = createServiceXml("ServiceB",
createInterfaceXml(QList<QServiceInterfaceDescriptor>() << descriptor),
attributes[QServiceInterfaceDescriptor::Location].toString());
buffer.close();
buffer.setData(xml);
QVERIFY2(mgr.addService(&buffer), PRINT_ERR(mgr));
QCOMPARE(mgr.setInterfaceDefault("ServiceB", interfaceName), true);
QCOMPARE(mgr.interfaceDefault(interfaceName), descriptor);
// bad arguments
QCOMPARE(mgr.setInterfaceDefault("", ""), false);
QCOMPARE(mgr.setInterfaceDefault("blah", "blah"), false);
QCOMPARE(mgr.setInterfaceDefault("SampleService", ""), false);
}
void tst_QServiceManager::setInterfaceDefault_strings_multipleInterfaces()
{
QServiceManager mgr;
QString interfaceName = "com.nokia.qt.serviceframework.tests.AnInterface";
DescriptorAttributes attributes;
QServiceInterfaceDescriptor descriptor;
QByteArray xml;
// if there are multiple interfaces, the default should be the latest version
attributes[QServiceInterfaceDescriptor::Location] = VALID_PLUGIN_FILES[0];
QList<QServiceInterfaceDescriptor> descriptorList;
descriptorList << createDescriptor(interfaceName, 1, 0, "ServiceC", attributes)
<< createDescriptor(interfaceName, 1, 8, "ServiceC", attributes)
<< createDescriptor(interfaceName, 1, 3, "ServiceC", attributes);
xml = createServiceXml("ServiceC", createInterfaceXml(descriptorList),
attributes[QServiceInterfaceDescriptor::Location].toString());
QBuffer buffer(&xml);
QVERIFY2(mgr.addService(&buffer), PRINT_ERR(mgr));
QCOMPARE(mgr.setInterfaceDefault("ServiceC", interfaceName), true);
QCOMPARE(mgr.interfaceDefault(interfaceName), descriptorList[1]);
}
void tst_QServiceManager::setInterfaceDefault_descriptor()
{
QFETCH(QService::Scope, scope_add);
QFETCH(QService::Scope, scope_find);
QFETCH(bool, expectFound);
QServiceManager mgr(scope_add);
QServiceInterfaceDescriptor desc;
QString interfaceName = "com.nokia.qt.serviceframework.TestInterface";
DescriptorAttributes attributes;
attributes[QServiceInterfaceDescriptor::Location] = VALID_PLUGIN_FILES.first();
QCOMPARE(mgr.setInterfaceDefault(desc), false);
desc = createDescriptor(interfaceName, 1, 0, "SomeService", attributes,
scope_add);
// fails if the specified interface hasn't been registered
QCOMPARE(mgr.setInterfaceDefault(desc), false);
// now it works
QByteArray xml = createServiceXml("SomeService",
createInterfaceXml(QList<QServiceInterfaceDescriptor>() << desc), VALID_PLUGIN_FILES.first());
QBuffer buffer(&xml);
QVERIFY2(mgr.addService(&buffer), PRINT_ERR(mgr));
QCOMPARE(mgr.setInterfaceDefault(desc), true);
QCOMPARE(mgr.interfaceDefault(interfaceName), desc);
#if defined(Q_OS_SYMBIAN)
QCOMPARE(mgr.interfaceDefault(interfaceName).isValid(), expectFound);
#else
QServiceManager mgrWithOtherScope(scope_find);
QCOMPARE(mgrWithOtherScope.interfaceDefault(interfaceName).isValid(), expectFound);
#endif
}
void tst_QServiceManager::setInterfaceDefault_descriptor_data()
{
QTest::addColumn<QService::Scope>("scope_add");
QTest::addColumn<QService::Scope>("scope_find");
QTest::addColumn<bool>("expectFound");
#if defined(Q_OS_SYMBIAN)
// Symbian implementation hard-codes user-scope for everything, do not test any system scope-stuff
// because returned service interface descriptor is always in user-scope
QTest::newRow("user scope")
<< QService::UserScope << QService::UserScope << true;
#else
QTest::newRow("user scope")
<< QService::UserScope << QService::UserScope << true;
QTest::newRow("system scope")
<< QService::SystemScope << QService::SystemScope << true;
QTest::newRow("user scope - add, system scope - find")
<< QService::UserScope << QService::SystemScope << false;
QTest::newRow("system scope - add, user scope - find")
<< QService::SystemScope << QService::UserScope << true;
#endif /* Q_OS_SYMBIAN */
}
void tst_QServiceManager::interfaceDefault()
{
QServiceManager mgr;
QVERIFY(!mgr.interfaceDefault("").isValid());
}
void tst_QServiceManager::serviceAdded()
{
QFETCH(QByteArray, xml);
QFETCH(QString, serviceName);
QFETCH(QService::Scope, scope_modify);
QFETCH(QService::Scope, scope_listen);
QFETCH(bool, expectSignal);
QBuffer buffer;
buffer.setData(xml);
QServiceManager mgr_modify(scope_modify);
QServiceManager mgr_listen(scope_listen);
// ensure mgr.connectNotify() is called
ServicesListener *listener = new ServicesListener;
connect(&mgr_listen, SIGNAL(serviceAdded(QString,QService::Scope)),
listener, SLOT(serviceAdded(QString,QService::Scope)));
QSignalSpy spyAdd(&mgr_listen, SIGNAL(serviceAdded(QString,QService::Scope)));
QVERIFY2(mgr_modify.addService(&buffer), PRINT_ERR(mgr_modify));
if (!expectSignal) {
QTest::qWait(2000);
QCOMPARE(spyAdd.count(), 0);
} else {
QTRY_COMPARE(spyAdd.count(), 1);
}
if (expectSignal) {
QCOMPARE(spyAdd.at(0).at(0).toString(), serviceName);
QCOMPARE( listener->params.at(0).second , scope_modify);
}
listener->params.clear();
// Pause between file changes so they are detected separately
QTest::qWait(2000);
QSignalSpy spyRemove(&mgr_listen, SIGNAL(serviceRemoved(QString,QService::Scope)));
QVERIFY(mgr_modify.removeService(serviceName));
if (!expectSignal) {
QTest::qWait(2000);
QCOMPARE(spyRemove.count(), 0);
} else {
QTRY_COMPARE(spyRemove.count(), 1);
}
#if !defined (Q_OS_WIN) && !defined (Q_OS_SYMBIAN)
// on win and symbian, cannot delete the database while it is in use
// try it again after deleting the database
deleteTestDatabasesAndWaitUntilDone();
#else
// Pause between file changes so they are detected separately
QTest::qWait(2000);
#endif
spyAdd.clear();
buffer.seek(0);
QVERIFY2(mgr_modify.addService(&buffer), PRINT_ERR(mgr_modify));
if (!expectSignal) {
QTest::qWait(2000);
QCOMPARE(spyAdd.count(), 0);
} else {
QTRY_COMPARE(spyAdd.count(), 1);
}
if (expectSignal) {
QCOMPARE(spyAdd.at(0).at(0).toString(), serviceName);
QCOMPARE(listener->params.at(0).second, scope_modify);
}
// ensure mgr.disconnectNotify() is called
disconnect(&mgr_listen, SIGNAL(serviceRemoved(QString,QService::Scope)),
listener, SLOT(serviceRemoved(QString,QService::Scope)));
delete listener;
}
void tst_QServiceManager::serviceAdded_data()
{
QTest::addColumn<QByteArray>("xml");
QTest::addColumn<QString>("serviceName");
QTest::addColumn<QService::Scope>("scope_modify");
QTest::addColumn<QService::Scope>("scope_listen");
QTest::addColumn<bool>("expectSignal");
QFile file1(xmlTestDataPath("sampleservice.xml"));
QVERIFY(file1.open(QIODevice::ReadOnly));
QFile file2(xmlTestDataPath("testserviceplugin.xml"));
QVERIFY(file2.open(QIODevice::ReadOnly));
QByteArray file1Data = file1.readAll();
#if defined (Q_OS_SYMBIAN)
// Symbian implementation hard-codes (ignores) scopes for everything, do not test mixed-scope stuff
QTest::newRow("SampleService, user scope") << file1Data << "SampleService"
<< QService::SystemScope << QService::SystemScope << true;
QTest::newRow("TestService, user scope") << file2.readAll() << "TestService"
<< QService::SystemScope << QService::SystemScope << true;
#else
QTest::newRow("SampleService, user scope") << file1Data << "SampleService"
<< QService::UserScope << QService::UserScope << true;
QTest::newRow("TestService, user scope") << file2.readAll() << "TestService"
<< QService::UserScope << QService::UserScope << true;
QTest::newRow("system scope") << file1Data << "SampleService"
<< QService::SystemScope << QService::SystemScope << true;
QTest::newRow("modify as user, listen in system") << file1Data << "SampleService"
<< QService::UserScope << QService::SystemScope << false;
QTest::newRow("modify as system, listen in user") << file1Data << "SampleService"
<< QService::SystemScope << QService::UserScope << true;
#endif /* Q_OS_SYMBIAN */
}
void tst_QServiceManager::serviceRemoved()
{
QFETCH(QByteArray, xml);
QFETCH(QString, serviceName);
QFETCH(QService::Scope, scope_modify);
QFETCH(QService::Scope, scope_listen);
QFETCH(bool, expectSignal);
QBuffer buffer;
buffer.setData(xml);
QServiceManager mgr_modify(scope_modify);
QServiceManager mgr_listen(scope_listen);
// ensure mgr.connectNotify() is called
ServicesListener *listener = new ServicesListener;
connect(&mgr_listen, SIGNAL(serviceRemoved(QString,QService::Scope)),
listener, SLOT(serviceRemoved(QString,QService::Scope)));
QSignalSpy spyAdd(&mgr_listen, SIGNAL(serviceAdded(QString,QService::Scope)));
QVERIFY2(mgr_modify.addService(&buffer), PRINT_ERR(mgr_modify));
if (!expectSignal) {
QTest::qWait(2000);
QCOMPARE(spyAdd.count(), 0);
} else {
QTRY_COMPARE(spyAdd.count(), 1);
}
// Pause between file changes so they are detected separately
QTest::qWait(2000);
QSignalSpy spyRemove(&mgr_listen, SIGNAL(serviceRemoved(QString,QService::Scope)));
QVERIFY(mgr_modify.removeService(serviceName));
if (!expectSignal) {
QTest::qWait(2000);
QCOMPARE(spyRemove.count(), 0);
} else {
QTRY_COMPARE(spyRemove.count(), 1);
}
if (expectSignal) {
QCOMPARE(spyRemove.at(0).at(0).toString(), serviceName);
QCOMPARE(listener->params.at(0).second , scope_modify);
}
listener->params.clear();
#if !defined (Q_OS_WIN) && !defined (Q_OS_SYMBIAN)
// on win and symbian, cannot delete the database while it is in use
// try it again after deleting the database
deleteTestDatabasesAndWaitUntilDone();
#else
// Pause between file changes so they are detected separately
QTest::qWait(2000);
#endif
spyAdd.clear();
buffer.seek(0);
QVERIFY2(mgr_modify.addService(&buffer), PRINT_ERR(mgr_modify));
if (!expectSignal) {
QTest::qWait(2000);
QCOMPARE(spyAdd.count(), 0);
} else {
QTRY_COMPARE(spyAdd.count(), 1);
}
spyRemove.clear();
// Pause between file changes so they are detected separately
QTest::qWait(2000);
QVERIFY(mgr_modify.removeService(serviceName));
if (!expectSignal) {
QTest::qWait(2000);
QCOMPARE(spyRemove.count(), 0);
} else {
QTRY_COMPARE(spyRemove.count(), 1);
}
if (expectSignal) {
QCOMPARE(spyRemove.at(0).at(0).toString(), serviceName);
QCOMPARE(listener->params.at(0).second , scope_modify);
}
// ensure mgr.disconnectNotify() is called
disconnect(&mgr_listen, SIGNAL(serviceRemoved(QString,QService::Scope)),
listener, SLOT(serviceRemoved(QString,QService::Scope)));
delete listener;
}
void tst_QServiceManager::serviceRemoved_data()
{
serviceAdded_data();
}
QTEST_MAIN(tst_QServiceManager)
#include "tst_qservicemanager.moc"