qtmobility/plugins/contacts/qtcontacts-tracker/tests/ut_qtcontacts_trackerplugin_definitions/ut_qtcontacts_trackerplugin_definitions.cpp
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the 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 "ut_qtcontacts_trackerplugin_definitions.h"
#include <QContactInvalidFilter>
typedef QSet<QString> QStringSet;
void ut_qtcontacts_trackerplugin_definitions::checkAllDefitionsTested()
{
const QStringSet testSlots(testSlotNames());
foreach(const QContactDetailDefinition d, mContactManager->detailDefinitions()) {
const QString saveAndFetchOne(QLatin1String("saveAndFetchOne") + d.name());
QVERIFY2(testSlots.contains(saveAndFetchOne), qPrintable(d.name()));
const QString saveAndFetchMany(QLatin1String("saveAndFetchMany") + d.name());
QVERIFY2(testSlots.contains(saveAndFetchMany), qPrintable(d.name()));
const QString saveAndFetchAll(QLatin1String("saveAndFetchAll") + d.name());
QVERIFY2(testSlots.contains(saveAndFetchAll), qPrintable(d.name()));
}
}
class SampleGenerator
{
public:
SampleGenerator(QVariant::Type type, const QVariantList &allowedValues) :
mType(type), mComplete(false), mIndex(0)
{
if (allowedValues.isEmpty()) {
QVariant sample;
switch(type) {
case QVariant::Date:
sample.setValue(QDate::currentDate());
break;
case QVariant::DateTime:
sample.setValue(QDateTime::currentDateTime());
break;
case QVariant::Double:
sample.setValue(double(qrand()) / RAND_MAX);
break;
case QVariant::Pixmap:
sample.setValue(QPixmap(2, 2));
break;
case QVariant::String:
sample.setValue(QUuid::createUuid().toString());
break;
case QVariant::StringList:
sample.setValue(QStringList(QUuid::createUuid().toString()) <<
QLatin1String("1") << QLatin1String("2") <<
QLatin1String("3"));
break;
default:
QFAIL(qPrintable(QString("unsupported variant type: %1").
arg(QVariant::typeToName(type))));
}
mValues.append(sample);
} else {
mValues.append(allowedValues);
switch(type) {
case QVariant::StringList:
for(int i = 2; i <= allowedValues.count(); ++i) {
QStringList stringList;
for(int j = 0; j < i; ++j)
stringList.append(allowedValues[j].toString());
mValues.append(QVariant(stringList));
}
break;
default:
break;
}
}
}
void nextSample(QVariant &result)
{
currentSample(result);
if (++mIndex == mValues.count()) {
mComplete = true;
mIndex = 0;
}
}
void currentSample(QVariant &result)
{
result.setValue(mValues[mIndex]);
if (result.isValid()) {
QVERIFY2(result.convert(mType), QVariant::typeToName(mType));
}
}
bool isComplete() const
{
return mComplete;
}
private:
QVariant::Type mType;
QVariantList mValues;
bool mComplete;
int mIndex;
};
void ut_qtcontacts_trackerplugin_definitions::createTestContacts(const QString &definitionName, QList<QContact> &result)
{
const QContactDetailDefinition &definition
(mContactManager->detailDefinition(definitionName));
typedef QMap<QString, QContactDetailFieldDefinition> FieldMap;
const FieldMap fields(definition.fields());
typedef QHash<QString, SampleGenerator> GeneratorMap;
GeneratorMap generators;
for(FieldMap::const_iterator i(fields.begin()), e(fields.end()); i != e; ++i) {
const QContactDetailFieldDefinition &field(i.value());
generators.insert(i.key(), SampleGenerator(field.dataType(), field.allowableValues()));
CHECK_CURRENT_TEST_FAILED;
}
QList<QContactDetail> detailList;
for(GeneratorMap::iterator i(generators.begin()), e(generators.end()); i != e; ++i) {
QVariant sample;
SampleGenerator &generator(i.value());
generator.currentSample(sample);
CHECK_CURRENT_TEST_FAILED;
QContactDetail detail(definition.name());
detail.setValue(i.key(), sample);
detailList.append(detail);
}
forever {
QContactDetail detail(definition.name());
bool samplesComplete = true;
for(GeneratorMap::iterator i(generators.begin()), e(generators.end()); i != e; ++i) {
QVariant sample;
SampleGenerator &generator(i.value());
generator.nextSample(sample);
CHECK_CURRENT_TEST_FAILED;
if (not generator.isComplete())
samplesComplete = false;
if (sample.isValid())
detail.setValue(i.key(), sample);
}
detailList.append(detail);
if (samplesComplete)
break;
}
foreach(QContactDetail detail, detailList) {
QContact contact;
QVERIFY(contact.saveDetail(&detail));
result.append(contact);
}
}
static bool localIdOrder(const QContact &a, const QContact &b)
{
return a.localId() < b.localId();
}
static bool isEmpty(const QVariant &value)
{
const QVariant empty(value.type());
return value == empty;
}
static const QStringSet newBrokenDetails()
{
return (QStringSet() <<
QLatin1String("Anniversary") << // FIXME: doesn't load at all
QLatin1String("Avatar") << // FIXME: doesn't load at all
QLatin1String("Birthday") << // FIXME: doesn't load at all
QLatin1String("EmailAddress") << // FIXME: doesn't load for work context
QLatin1String("Gender") << // FIXME: doesn't load at all
QLatin1String("GeoLocation") << // FIXME: doesn't load at all
QLatin1String("Guid") << // FIXME: doesn't load at all
QLatin1String("Note") << // FIXME: doesn't load at all
QLatin1String("OnlineAccount") << // FIXME: doesn't load at all
QLatin1String("Organization") << // FIXME: doesn't load at all
QLatin1String("StreetAddress") << // FIXME: doesn't load at all
QLatin1String("SyncTarget") << // FIXME: doesn't load at all
QLatin1String("Timestamp") << // FIXME: doesn't load at all
QLatin1String("Url")); // FIXME: doesn't load at all
}
static const QHash<QString, QStringSet> newBrokenFields()
{
QHash<QString, QStringSet> brokenFields;
brokenFields.insert(QLatin1String("EmailAddress"),
QStringSet() << QLatin1String("Context"));
brokenFields.insert(QLatin1String("Name"),
QStringSet() << QLatin1String("Context") // FIXME: meaning of this field?
<< QLatin1String("CustomLabel") // FIXME: meaning of this field?
<< QLatin1String("Suffix"));
brokenFields.insert(QLatin1String("Nickname"),
QStringSet() << QLatin1String("Context")); // FIXME: meaning of this field?
brokenFields.insert(QLatin1String("PhoneNumber"),
QStringSet() << QLatin1String("Context")
<< QLatin1String("PhoneNumber")
<< QLatin1String("SubTypes"));
return brokenFields;
}
static const QStringSet newSynthesizedDetails()
{
return (QStringSet() <<
QLatin1String("DisplayLabel") <<
QLatin1String("Type"));
}
static const QStringSet brokenDetails(newBrokenDetails());
static const QHash<QString, QStringSet> brokenFields(newBrokenFields());
static const QStringSet synthesizedDetails(newSynthesizedDetails());
void ut_qtcontacts_trackerplugin_definitions::verifyContacts(const QString &definitionName,
QList<QContact> &savedContacts,
QList<QContact> &fetchedContacts)
{
qSort(savedContacts.begin(), savedContacts.end(), localIdOrder);
qSort(fetchedContacts.begin(), fetchedContacts.end(), localIdOrder);
QCOMPARE(fetchedContacts.count(), savedContacts.count());
for(int i = 0, l = savedContacts.count(); i < l; ++i) {
const QList<QContactDetail> &savedDetails(savedContacts[i].details(definitionName));
const QList<QContactDetail> &fetchedDetails(fetchedContacts[i].details(definitionName));
QCOMPARE(savedDetails.count(), 1);
QCOMPARE(fetchedDetails.count(), 1);
QVariantMap savedValues(savedDetails[0].variantValues());
QVariantMap fetchedValues(fetchedDetails[0].variantValues());
QStringSet fieldNames(savedValues.keys().toSet());
fieldNames.unite(fetchedValues.keys().toSet());
foreach(const QString &key, fieldNames) {
if (brokenFields[definitionName].contains(key)) {
const QString msg(QString::fromLatin1("ignoring broken %1 field").arg(key));
QEXPECT_FAIL("", qPrintable(msg), Continue);
}
if (not savedValues.contains(key)) {
QVERIFY(isEmpty(fetchedValues[key]));
} else if (not fetchedValues.contains(key)) {
QVERIFY(isEmpty(savedValues[key]));
} else {
QCOMPARE(savedValues[key], fetchedValues[key]);
}
}
}
}
void ut_qtcontacts_trackerplugin_definitions::saveAndFetchOne(const QString &definitionName)
{
qDebug() << "===============================================================================";
qDebug() << qPrintable(definitionName);
qDebug() << "===============================================================================";
if (brokenDetails.contains(definitionName)) {
QSKIP("support for this detail is broken right now", SkipAll);
}
if (synthesizedDetails.contains(definitionName)) {
QSKIP("synthesized details are out of scope for now", SkipAll);
}
QList<QContact> savedContacts;
QList<QContactLocalId> savedContactIds;
createTestContacts(definitionName, savedContacts);
CHECK_CURRENT_TEST_FAILED;
saveContacts(savedContacts);
CHECK_CURRENT_TEST_FAILED;
foreach(const QContact &contact, savedContacts) {
savedContactIds.append(contact.localId());
}
QCOMPARE(savedContactIds.toSet().count(), savedContacts.count());
QList<QContact> fetchedContacts;
foreach(const QContactLocalId &id, savedContactIds) {
QContact contact;
fetchContact(id, contact);
CHECK_CURRENT_TEST_FAILED;
fetchedContacts.append(contact);
}
verifyContacts(definitionName, savedContacts, fetchedContacts);
}
void ut_qtcontacts_trackerplugin_definitions::saveAndFetchMany(const QString &definitionName)
{
qDebug() << "===============================================================================";
qDebug() << qPrintable(definitionName);
qDebug() << "===============================================================================";
if (brokenDetails.contains(definitionName)) {
QSKIP("support for this detail is broken right now", SkipAll);
}
if (synthesizedDetails.contains(definitionName)) {
QSKIP("synthesized details are out of scope for now", SkipAll);
}
QList<QContact> savedContacts;
QList<QContactLocalId> savedContactIds;
createTestContacts(definitionName, savedContacts);
CHECK_CURRENT_TEST_FAILED;
saveContacts(savedContacts);
CHECK_CURRENT_TEST_FAILED;
foreach(const QContact &contact, savedContacts) {
savedContactIds.append(contact.localId());
}
QCOMPARE(savedContactIds.toSet().count(), savedContacts.count());
QList<QContact> fetchedContacts;
fetchContacts(savedContactIds, fetchedContacts);
CHECK_CURRENT_TEST_FAILED;
verifyContacts(definitionName, savedContacts, fetchedContacts);
}
void ut_qtcontacts_trackerplugin_definitions::saveAndFetchAll(const QString &definitionName)
{
qDebug() << "===============================================================================";
qDebug() << qPrintable(definitionName);
qDebug() << "===============================================================================";
if (brokenDetails.contains(definitionName)) {
QSKIP("support for this detail is broken right now", SkipAll);
}
if (synthesizedDetails.contains(definitionName)) {
QSKIP("synthesized details are out of scope for now", SkipAll);
}
QList<QContact> savedContacts;
QSet<QContactLocalId> savedContactIds;
createTestContacts(definitionName, savedContacts);
CHECK_CURRENT_TEST_FAILED;
saveContacts(savedContacts);
CHECK_CURRENT_TEST_FAILED;
foreach(const QContact &contact, savedContacts) {
savedContactIds.insert(contact.localId());
}
QCOMPARE(savedContactIds.count(), savedContacts.count());
QList<QContact> fetchedContacts;
fetchContacts(QContactInvalidFilter(), fetchedContacts);
CHECK_CURRENT_TEST_FAILED;
QList<QContact>::iterator i = fetchedContacts.begin();
while (i != fetchedContacts.end()) {
if (not savedContactIds.contains(i->localId())) {
i = fetchedContacts.erase(i);
} else {
++i;
}
}
verifyContacts(definitionName, savedContacts, fetchedContacts);
}
#define IMPLEMENT_SAVE_AND_FETCH(DefinitionName) \
\
void ut_qtcontacts_trackerplugin_definitions::saveAndFetchOne##DefinitionName() \
{ \
saveAndFetchOne(QString::fromLatin1(#DefinitionName)); \
CHECK_CURRENT_TEST_FAILED; \
} \
\
void ut_qtcontacts_trackerplugin_definitions::saveAndFetchMany##DefinitionName() \
{ \
saveAndFetchMany(QString::fromLatin1(#DefinitionName)); \
CHECK_CURRENT_TEST_FAILED; \
} \
\
void ut_qtcontacts_trackerplugin_definitions::saveAndFetchAll##DefinitionName() \
{ \
saveAndFetchAll(QString::fromLatin1(#DefinitionName)); \
CHECK_CURRENT_TEST_FAILED; \
}
IMPLEMENT_SAVE_AND_FETCH(Anniversary)
IMPLEMENT_SAVE_AND_FETCH(Avatar)
IMPLEMENT_SAVE_AND_FETCH(Birthday)
IMPLEMENT_SAVE_AND_FETCH(DisplayLabel)
IMPLEMENT_SAVE_AND_FETCH(EmailAddress)
IMPLEMENT_SAVE_AND_FETCH(Gender)
IMPLEMENT_SAVE_AND_FETCH(GeoLocation)
IMPLEMENT_SAVE_AND_FETCH(Guid)
IMPLEMENT_SAVE_AND_FETCH(Name)
IMPLEMENT_SAVE_AND_FETCH(Nickname)
IMPLEMENT_SAVE_AND_FETCH(Note)
IMPLEMENT_SAVE_AND_FETCH(OnlineAccount)
IMPLEMENT_SAVE_AND_FETCH(Organization)
IMPLEMENT_SAVE_AND_FETCH(PhoneNumber)
IMPLEMENT_SAVE_AND_FETCH(StreetAddress)
IMPLEMENT_SAVE_AND_FETCH(SyncTarget)
IMPLEMENT_SAVE_AND_FETCH(Timestamp)
IMPLEMENT_SAVE_AND_FETCH(Type)
IMPLEMENT_SAVE_AND_FETCH(Url)
QTEST_MAIN(ut_qtcontacts_trackerplugin_definitions)