tests/auto/qversit/tst_qversit.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qversitdefs_p.h"
       
    43 #include "tst_qversit.h"
       
    44 #include "qversitreader.h"
       
    45 #include "qversitreader_p.h"
       
    46 #include "qversitcontactexporter.h"
       
    47 #include "qversitcontactimporter.h"
       
    48 #include "qcontact.h"
       
    49 #include "qcontactmanager.h"
       
    50 #include "qcontactmanagerengine.h"
       
    51 
       
    52 #include <QtTest/QtTest>
       
    53 #include <QDebug>
       
    54 #include <QDir>
       
    55 #include <QList>
       
    56 
       
    57 QTM_BEGIN_NAMESPACE
       
    58 class MyQVersitResourceHandler : public QVersitResourceHandler
       
    59 {
       
    60 public:
       
    61     MyQVersitResourceHandler() : mIndex(0)
       
    62     {
       
    63     }
       
    64 
       
    65     bool saveResource(const QByteArray& contents, const QVersitProperty& property,
       
    66                       QString* location)
       
    67     {
       
    68         Q_UNUSED(property)
       
    69         *location = QString::number(mIndex++);
       
    70         mObjects.insert(*location, contents);
       
    71         return true;
       
    72     }
       
    73 
       
    74     bool loadResource(const QString &location, QByteArray *contents, QString *mimeType)
       
    75     {
       
    76         Q_UNUSED(location)
       
    77         Q_UNUSED(contents)
       
    78         Q_UNUSED(mimeType)
       
    79         return false;
       
    80     }
       
    81 
       
    82     int mIndex;
       
    83     QMap<QString, QByteArray> mObjects;
       
    84 };
       
    85 
       
    86 
       
    87 class MyDetailHandler : public QVersitContactExporterDetailHandler {
       
    88 public:
       
    89     MyDetailHandler() : detailNumber(0) {}
       
    90     bool preProcessDetail(const QContact& contact, const QContactDetail& detail,
       
    91                           QVersitDocument* document) {
       
    92         Q_UNUSED(contact) Q_UNUSED(detail) Q_UNUSED(document)
       
    93         return false;
       
    94     }
       
    95     /* eg. a detail with definition name "Detail" and fields "Field1"="Value1" and
       
    96      * "Field2"="Value2" will be exported to the vCard properties:
       
    97      * G0.DETAIL-FIELD1:Value1
       
    98      * G0.DETAIL-FIELD2:Value2
       
    99      * And the next detail (say, "Detail" with a field "Field1"="Value3" will generate:
       
   100      * G1.DETAIL-FIELD1:Value3
       
   101      * ie. Different details will have different vCard groups.
       
   102      */
       
   103     bool postProcessDetail(const QContact& contact, const QContactDetail& detail,
       
   104                            bool alreadyProcessed, QVersitDocument* document) {
       
   105         Q_UNUSED(contact)
       
   106         // beware: if the base implementation exports some but not all fields, alreadyProcessed
       
   107         // will be true and the unprocessed fields won't be exported
       
   108         if (alreadyProcessed)
       
   109             return false;
       
   110         if (detail.definitionName() == QContactType::DefinitionName)
       
   111             return false; // special case of an unhandled detail that we don't export
       
   112         QVersitProperty property;
       
   113         QVariantMap fields = detail.variantValues();
       
   114         // fields from the same detail have the same group so the importer can collate them
       
   115         QString detailGroup = QLatin1String("G") + QString::number(detailNumber++);
       
   116         for (QVariantMap::const_iterator it = fields.constBegin();
       
   117                 it != fields.constEnd();
       
   118                 it++) {
       
   119             property.setGroups(QStringList(detailGroup));
       
   120             // beware: detail.definitionName and the field name will be made uppercase on export
       
   121             property.setName(QLatin1String("X-QCONTACTDETAIL-")
       
   122                              + detail.definitionName()
       
   123                              + QLatin1String("-")
       
   124                              + it.key());
       
   125             // beware: this might not handle nonstring values properly:
       
   126             property.setValue(it.value());
       
   127             document->addProperty(property);
       
   128         }
       
   129         return true;
       
   130     }
       
   131 private:
       
   132     int detailNumber;
       
   133 };
       
   134 
       
   135 class MyPropertyHandler : public QVersitContactImporterPropertyHandler {
       
   136 public:
       
   137     bool preProcessProperty(const QVersitDocument& document, const QVersitProperty& property,
       
   138                             int contactIndex, QContact* contact) {
       
   139         Q_UNUSED(document) Q_UNUSED(property) Q_UNUSED(contactIndex) Q_UNUSED(contact)
       
   140         return false;
       
   141     }
       
   142     /* eg. if the document has the properties:
       
   143      * G0.DETAIL-FIELD1:Value1
       
   144      * G0.DETAIL-FIELD2:Value2
       
   145      * G1.DETAIL-FIELD1:Value3
       
   146      * This will generate two details - the first with fields "FIELD1"="Value1" and
       
   147      * "FIELD2"="Value2" and the second with "FIELD1"="Value3"
       
   148      * ie. the vCard groups determine which properties form a single detail.
       
   149      */
       
   150     bool postProcessProperty(const QVersitDocument& document, const QVersitProperty& property,
       
   151                              bool alreadyProcessed, int contactIndex, QContact* contact) {
       
   152         Q_UNUSED(document) Q_UNUSED(contactIndex)
       
   153         const QString prefix = QLatin1String("X-QCONTACTDETAIL-");
       
   154         if (alreadyProcessed)
       
   155             return false;
       
   156         if (!property.name().startsWith(prefix))
       
   157             return false;
       
   158         QString detailAndField = property.name().mid(prefix.size());
       
   159         QStringList detailAndFieldParts = detailAndField.split(QLatin1Char('-'),
       
   160                                                                QString::SkipEmptyParts);
       
   161         if (detailAndFieldParts.size() != 2)
       
   162             return false;
       
   163         QString definitionName = detailAndFieldParts.at(0);
       
   164         QString fieldName = detailAndFieldParts.at(1);
       
   165         if (property.groups().size() != 1)
       
   166             return false;
       
   167         QString group = property.groups().first();
       
   168         // find a detail generated from the a property with the same group
       
   169         QContactDetail detail = handledDetails.value(group);
       
   170         // make sure the the existing detail has the same definition name
       
   171         if (detail.definitionName() != definitionName)
       
   172             detail = QContactDetail(definitionName);
       
   173         detail.setValue(fieldName, property.value());
       
   174         contact->saveDetail(&detail);
       
   175         handledDetails.insert(group, detail);
       
   176         return false;
       
   177     }
       
   178     QMap<QString, QContactDetail> handledDetails; // map from group name to detail
       
   179 };
       
   180 
       
   181 QTM_END_NAMESPACE
       
   182 
       
   183 QTM_USE_NAMESPACE
       
   184 
       
   185 #ifndef TESTDATA_DIR
       
   186 #define TESTDATA_DIR "./"
       
   187 #endif
       
   188 
       
   189 Q_DECLARE_METATYPE(QList<QContact>)
       
   190 Q_DECLARE_METATYPE(QContact)
       
   191 
       
   192 void tst_QVersit::testImportFiles()
       
   193 {
       
   194     QFETCH(QString, filename);
       
   195     QFETCH(QByteArray, charset);
       
   196     QFETCH(QList<QContact>, expectedContacts);
       
   197 
       
   198     QVersitReader reader;
       
   199     QFile file(filename);
       
   200     QVERIFY2(file.open(QIODevice::ReadOnly), filename.toAscii());
       
   201     reader.setDevice(&file);
       
   202     if (charset != "") {
       
   203         reader.setDefaultCodec(QTextCodec::codecForName(charset));
       
   204     }
       
   205     QVERIFY(reader.startReading());
       
   206     QVERIFY(reader.waitForFinished());
       
   207     QList<QVersitDocument> documents = reader.results();
       
   208     QCOMPARE(reader.error(), QVersitReader::NoError);
       
   209     QVersitContactImporter importer;
       
   210     MyQVersitResourceHandler resourceHandler;
       
   211     importer.setResourceHandler(&resourceHandler);
       
   212     MyPropertyHandler propertyHandler;
       
   213     importer.setPropertyHandler(&propertyHandler);
       
   214     QVERIFY(importer.importDocuments(documents));
       
   215     QList<QContact> contacts = importer.contacts();
       
   216 
       
   217     if (expectedContacts.size() > 0) {
       
   218         QCOMPARE(contacts.size(), expectedContacts.size());
       
   219         QListIterator<QContact> i(expectedContacts);
       
   220         foreach (QContact parsed, contacts) {
       
   221             QContact expected = i.next();
       
   222             QList<QContactDetail> expectedDetails = expected.details();
       
   223             foreach(QContactDetail expectedDetail, expectedDetails) {
       
   224                 QString name = expectedDetail.definitionName();
       
   225                 QContactDetail parsedDetail = parsed.detail(name);
       
   226                 if (parsedDetail != expectedDetail) {
       
   227                     qDebug() << "Detail: " << name.toAscii();
       
   228                     qDebug() << "Actual:" << parsedDetail.variantValues();
       
   229                     qDebug() << "Expected:" << expectedDetail.variantValues();
       
   230                     QCOMPARE(parsedDetail, expectedDetail);
       
   231                 }
       
   232             }
       
   233         }
       
   234     }
       
   235 }
       
   236 
       
   237 #define QTEST_NEW_ROW(filename,charset,contact) \
       
   238         QTest::newRow(filename) \
       
   239         << QString::fromAscii(TESTDATA_DIR "testdata/") + QString::fromAscii(filename) \
       
   240         << QByteArray(charset) \
       
   241         << (contact)
       
   242 
       
   243 void tst_QVersit::testImportFiles_data()
       
   244 {
       
   245     QTest::addColumn<QString>("filename");
       
   246     QTest::addColumn<QByteArray>("charset");
       
   247     QTest::addColumn<QList<QContact> >("expectedContacts");
       
   248 
       
   249     QTEST_NEW_ROW("AAB4-MultipleAll.vcf", "UTF-16BE", QList<QContact>());
       
   250     QTEST_NEW_ROW("AAB4-MultipleAscii.vcf", "", QList<QContact>());
       
   251     QTEST_NEW_ROW("AAB4-SingleCompany.vcf", "", QList<QContact>());
       
   252     QTEST_NEW_ROW("AAB4-SingleExtensive.vcf", "", QList<QContact>());
       
   253     QTEST_NEW_ROW("AAB4-SingleNonAscii.vcf", "UTF-16BE", QList<QContact>());
       
   254     QTEST_NEW_ROW("AAB4-SingleNonAsciiWithPhoto.vcf", "UTF-16BE", QList<QContact>());
       
   255     QTEST_NEW_ROW("AAB5-SingleNonAscii.vcf", "UTF-8", QList<QContact>());
       
   256 
       
   257     {
       
   258         QList<QContact> list;
       
   259         QContact contact;
       
   260         QContactName name;
       
   261         name.setCustomLabel(QLatin1String("Firstname Lastname"));
       
   262         name.setFirstName(QLatin1String("Firstname"));
       
   263         name.setLastName(QLatin1String("Lastname"));
       
   264         name.setPrefix(QLatin1String("Title"));
       
   265         name.setSuffix(QLatin1String("Suffix"));
       
   266         contact.saveDetail(&name);
       
   267         QContactOrganization org;
       
   268         org.setName(QLatin1String("Company Name"));
       
   269         org.setDepartment(QStringList(QLatin1String("Department Name")));
       
   270         org.setTitle(QLatin1String("Job title"));
       
   271         contact.saveDetail(&org);
       
   272         QContactNote note;
       
   273         note.setNote(QLatin1String("This is a note field.  Pretty boring."));
       
   274         contact.saveDetail(&note);
       
   275         QContactManagerEngine::setContactDisplayLabel(&contact, QLatin1String("Firstname Lastname"));
       
   276         list.append(contact);
       
   277         QContactUrl homeUrl;
       
   278         homeUrl.setUrl(QLatin1String("http://mywebpage.com"));
       
   279         homeUrl.setContexts(QContactDetail::ContextHome);
       
   280         contact.saveDetail(&homeUrl);
       
   281         QContactUrl workUrl;
       
   282         workUrl.setUrl(QLatin1String("http://workwebpage"));
       
   283         workUrl.setContexts(QContactDetail::ContextWork);
       
   284         contact.saveDetail(&workUrl);
       
   285         QTEST_NEW_ROW("Entourage11-basic.vcf", "UTF-16BE", list);
       
   286     }
       
   287 
       
   288     QTEST_NEW_ROW("Entourage11-image.vcf", "UTF-16BE", QList<QContact>());
       
   289 
       
   290     QTEST_NEW_ROW("Entourage11-nonascii.vcf", "UTF-16BE", QList<QContact>());
       
   291 
       
   292     {
       
   293         QList<QContact> list;
       
   294         QContact contact;
       
   295         QContactName name;
       
   296         name.setCustomLabel(QLatin1String("first last"));
       
   297         name.setFirstName(QLatin1String("first"));
       
   298         name.setLastName(QLatin1String("last"));
       
   299         contact.saveDetail(&name);
       
   300         QContactOrganization org;
       
   301         org.setName(QLatin1String("Nokia"));
       
   302         org.setDepartment(QStringList(QLatin1String("Qt DF")));
       
   303         contact.saveDetail(&org);
       
   304         QContactManagerEngine::setContactDisplayLabel(&contact, QLatin1String("first last"));
       
   305         list.append(contact);
       
   306         QTEST_NEW_ROW("Entourage12-basic.vcf", "", list);
       
   307     }
       
   308 
       
   309     QTEST_NEW_ROW("Entourage12-kevin.vcf", "UTF-8", QList<QContact>());
       
   310     QTEST_NEW_ROW("Entourage12-nonascii.vcf", "UTF-8", QList<QContact>());
       
   311     QTEST_NEW_ROW("gmail.vcf", "UTF-8", QList<QContact>());
       
   312 
       
   313     {
       
   314         QContact contact;
       
   315         QContactName name;
       
   316         name.setFirstName(QLatin1String("name"));
       
   317         contact.saveDetail(&name);
       
   318         QContactFamily family;
       
   319         family.setChildren(QStringList(QLatin1String("Child1")));
       
   320         contact.saveDetail(&family);
       
   321         family.setChildren(QStringList(QLatin1String("Child2")) << QLatin1String("Child3"));
       
   322         contact.saveDetail(&family);
       
   323         QContactNickname nickname;
       
   324         nickname.setNickname(QLatin1String("Nick6"));
       
   325         contact.saveDetail(&nickname);
       
   326         nickname.setNickname(QLatin1String("Nick5"));
       
   327         contact.saveDetail(&nickname);
       
   328         nickname.setNickname(QLatin1String("Nick4"));
       
   329         contact.saveDetail(&nickname);
       
   330         nickname.setNickname(QLatin1String("Nick3"));
       
   331         contact.saveDetail(&nickname);
       
   332         nickname.setNickname(QLatin1String("Nick2"));
       
   333         contact.saveDetail(&nickname);
       
   334         nickname.setNickname(QLatin1String("Nick1"));
       
   335         contact.saveDetail(&nickname);
       
   336         QContactPhoneNumber assistantphone;
       
   337         assistantphone.setNumber(QLatin1String("1234"));
       
   338         assistantphone.setSubTypes(QContactPhoneNumber::SubTypeAssistant);
       
   339         contact.saveDetail(&assistantphone);
       
   340         QContactManagerEngine::setContactDisplayLabel(&contact, QLatin1String("name"));
       
   341         QTEST_NEW_ROW("test1.vcf", "UTF-8", QList<QContact>() << contact);
       
   342     }
       
   343 }
       
   344 
       
   345 void tst_QVersit::testExportImport()
       
   346 {
       
   347     // Test that a contact, when exported, then imported again, is unaltered
       
   348     QFETCH(QContact, contact);
       
   349 
       
   350     QVersitContactExporter exporter;
       
   351     MyDetailHandler detailHandler;
       
   352     exporter.setDetailHandler(&detailHandler);
       
   353     QVERIFY(exporter.exportContacts(QList<QContact>() << contact, QVersitDocument::VCard30Type));
       
   354     QList<QVersitDocument> documents = exporter.documents();
       
   355     QCOMPARE(documents.size(), 1);
       
   356 
       
   357     QVersitContactImporter importer;
       
   358     MyPropertyHandler propertyHandler;
       
   359     importer.setPropertyHandler(&propertyHandler);
       
   360     QVERIFY(importer.importDocuments(documents));
       
   361     QList<QContact> contacts = importer.contacts();
       
   362     QCOMPARE(contacts.size(), 1);
       
   363     // We can't do a deep compare because detail ids are different
       
   364     QCOMPARE(contacts.first().details().count(), contact.details().count());
       
   365 }
       
   366 
       
   367 void tst_QVersit::testExportImport_data()
       
   368 {
       
   369     QTest::addColumn<QContact>("contact");
       
   370 
       
   371     QContact contact;
       
   372     QContactName name;
       
   373     name.setFirstName(QLatin1String("first"));
       
   374     name.setLastName(QLatin1String("last"));
       
   375     name.setCustomLabel(QLatin1String("custom"));
       
   376     contact.saveDetail(&name);
       
   377     // detail definition/field names are encoded as vCard property names, which must be uppercase,
       
   378     // so only uppercase definition/field names work.
       
   379     QContactDetail customDetail1("CUSTOMDETAIL");
       
   380     customDetail1.setValue(QLatin1String("CUSTOMFIELD11"), QLatin1String("Value11"));
       
   381     customDetail1.setValue(QLatin1String("CUSTOMFIELD12"), QLatin1String("Value12"));
       
   382     contact.saveDetail(&customDetail1);
       
   383     QContactDetail customDetail2("CUSTOMDETAIL");
       
   384     customDetail2.setValue(QLatin1String("CUSTOMFIELD21"), QLatin1String("Value21"));
       
   385     customDetail2.setValue(QLatin1String("CUSTOMFIELD22"), QLatin1String("Value22"));
       
   386     contact.saveDetail(&customDetail2);
       
   387     contact.setType(QContactType::TypeContact);
       
   388 
       
   389     QTest::newRow("custom detail") << contact;
       
   390 }
       
   391 
       
   392 QTEST_MAIN(tst_QVersit)