qtmobility/plugins/contacts/symbian/tsrc/tst_performance/tst_performance.cpp
changeset 14 6fbed849b4f4
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
       
     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 <QObject>
       
    43 #include <qmobilityglobal.h>
       
    44 #include <qtcontacts.h>
       
    45 #include <QtTest/QtTest>
       
    46 #include <QDebug>
       
    47 #include <QFile>
       
    48 #include <qversitreader.h>
       
    49 #include <qversitcontactimporter.h>
       
    50 
       
    51 QTM_USE_NAMESPACE
       
    52 
       
    53 const QString testDataPath("c:/data/others");
       
    54 const QString resultFileName("c:/data/results/tst_performance_results.csv");
       
    55 
       
    56 class tst_Performance : public QObject
       
    57 {
       
    58     Q_OBJECT
       
    59 
       
    60 private slots:  // Init & cleanup
       
    61     void init();
       
    62     void cleanup();
       
    63 
       
    64 private slots:  // Test cases
       
    65     void validate_data();
       
    66     void validate();
       
    67     void fetch_data();
       
    68     void fetch();
       
    69 
       
    70 private:
       
    71     void addTestRows(QString fileNameFilter);
       
    72     bool importContacts(QString vcardFileName, int &count);
       
    73     bool detailsExist(QList<QContact> contacts, QStringList definitionNames);
       
    74     void startBenchmark(QString benchmarkName);
       
    75     bool endBenchmark(const int target);
       
    76 
       
    77     QContactManager *m_cm;
       
    78     QTime m_timer;
       
    79     QString m_benchmarkName;
       
    80 };
       
    81 
       
    82 
       
    83 void tst_Performance::init()
       
    84 {
       
    85     m_cm = new QContactManager("symbian");
       
    86     m_cm->removeContacts(m_cm->contactIds(), 0);
       
    87 }
       
    88 
       
    89 void tst_Performance::cleanup()
       
    90 {
       
    91     m_cm->removeContacts(m_cm->contactIds(), 0);
       
    92     delete m_cm;
       
    93 }
       
    94 
       
    95 void tst_Performance::validate_data()
       
    96 {
       
    97     // Path to a file containing vcards, constructed dynamically
       
    98     QTest::addColumn<QString>("vcardFileName");
       
    99 
       
   100    // Add new test row for each vcf file
       
   101    addTestRows(QString("tst_performance_validate*.vcf"));
       
   102 }
       
   103 
       
   104 void tst_Performance::validate()
       
   105 {
       
   106     QFETCH(QString, vcardFileName);
       
   107 
       
   108     // Import contacts from the file into contacts database
       
   109     int count(0);
       
   110     QVERIFY(importContacts(vcardFileName, count));
       
   111 
       
   112     // QContactName
       
   113     QContactFetchHint nameHint;
       
   114     nameHint.setDetailDefinitionsHint(QStringList() << QContactName::DefinitionName);
       
   115     QList<QContact> contacts = m_cm->contacts(QList<QContactSortOrder>(), nameHint);
       
   116     QCOMPARE(contacts.count(), count);
       
   117     QVERIFY(detailsExist(contacts, QStringList() << QContactName::DefinitionName));
       
   118 
       
   119     // QContactPhoneNumber
       
   120     QContactFetchHint numberHint;
       
   121     numberHint.setDetailDefinitionsHint(QStringList() << QContactPhoneNumber::DefinitionName);
       
   122     contacts = m_cm->contacts(QList<QContactSortOrder>(), numberHint);
       
   123     QCOMPARE(contacts.count(), count);
       
   124     QVERIFY(detailsExist(contacts, QStringList() << QContactPhoneNumber::DefinitionName));
       
   125 
       
   126     // QContactAddress
       
   127     QContactFetchHint addressHint;
       
   128     addressHint.setDetailDefinitionsHint(QStringList() << QContactAddress::DefinitionName);
       
   129     contacts = m_cm->contacts(QList<QContactSortOrder>(), addressHint);
       
   130     QCOMPARE(contacts.count(), count);
       
   131     QVERIFY(detailsExist(contacts, QStringList() << QContactAddress::DefinitionName));
       
   132 }
       
   133 
       
   134 void tst_Performance::fetch_data()
       
   135 {
       
   136     // Path to a file containing vcards, constructed dynamically
       
   137     QTest::addColumn<QString>("vcardFileName");
       
   138 
       
   139     // Add new test row for each vcf file
       
   140     addTestRows(QString("tst_performance_fetch*.vcf"));
       
   141 }
       
   142 
       
   143 void tst_Performance::fetch()
       
   144 {
       
   145     QFETCH(QString, vcardFileName);
       
   146 
       
   147     // Import contacts from the file into contacts database
       
   148     int count(0);
       
   149     QVERIFY(importContacts(vcardFileName, count));
       
   150 
       
   151     // The actual benchmark measurements begin... We cannot use QBENCHMARK
       
   152     // since it does not give separate results for each operation, but shows
       
   153     // only the latest result in the log. Also, it does not support writing the
       
   154     // result into an external CSV file.
       
   155 
       
   156     {
       
   157         // measure contact id fetch
       
   158         QList<QContactLocalId> ids;
       
   159         startBenchmark(vcardFileName + QString(" / QContactManager::contactIds"));
       
   160         ids = m_cm->contactIds();
       
   161         QVERIFY(endBenchmark(0));
       
   162         QCOMPARE(ids.count(), count);
       
   163     }
       
   164 
       
   165     {
       
   166         // measure contact fetch
       
   167         QList<QContact> contacts;
       
   168         startBenchmark(vcardFileName + QString(" / QContactManager::contacts"));
       
   169         contacts = m_cm->contacts();
       
   170         QVERIFY(endBenchmark(0));
       
   171         QCOMPARE(contacts.count(), count);
       
   172     }
       
   173 
       
   174     {
       
   175         // measure contact fetch with fetch hint (only name)
       
   176         QContactFetchHint hint;
       
   177         hint.setDetailDefinitionsHint(QStringList() << QContactName::DefinitionName);
       
   178         startBenchmark(vcardFileName + QString(" / QContactManager::contacts w/ detail definitions hint"));
       
   179         QList<QContact> contacts = m_cm->contacts(QList<QContactSortOrder>(), hint);
       
   180         QVERIFY(endBenchmark(0));
       
   181         QCOMPARE(contacts.count(), count);
       
   182     }
       
   183 
       
   184     {
       
   185         // measure contact fetch without relationships and binary blobs
       
   186         QContactFetchHint hint;
       
   187         hint.setOptimizationHints(QContactFetchHint::NoRelationships | QContactFetchHint::NoBinaryBlobs);
       
   188         startBenchmark(vcardFileName + QString(" / QContactManager::contacts w/ optimization hints"));
       
   189         QList<QContact> contacts = m_cm->contacts(QList<QContactSortOrder>(), hint);
       
   190         QVERIFY(endBenchmark(0));
       
   191         QCOMPARE(contacts.count(), count);
       
   192     }
       
   193 
       
   194     // TODO: measure sort
       
   195     // TODO: measure filter etc...
       
   196 }
       
   197 
       
   198 void tst_Performance::addTestRows(QString fileNameFilter)
       
   199 {
       
   200     // add new test row for each vcard file
       
   201     QDir vcfDir(testDataPath);
       
   202     QStringList tst_dataFiles = vcfDir.entryList(QStringList() << fileNameFilter);
       
   203     foreach (QString tst_dataFile, tst_dataFiles) {
       
   204         qDebug() << "Found new vcard file: " << tst_dataFile;
       
   205         QTest::newRow(tst_dataFile.toAscii()) << tst_dataFile;
       
   206     }
       
   207 }
       
   208 
       
   209 bool tst_Performance::importContacts(QString vcardFileName, int &contactCount)
       
   210 {
       
   211     contactCount = 0;
       
   212 
       
   213     QFile vcardFile(testDataPath + "/" + vcardFileName);
       
   214     if (!vcardFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
       
   215         return false;
       
   216     }
       
   217 
       
   218     // Read contacts from vcard file
       
   219     while (!vcardFile.atEnd()) {
       
   220         QBuffer vcard;
       
   221         QByteArray line = vcardFile.readLine();
       
   222         if (line.startsWith(QByteArray("BEGIN:VCARD"))) {
       
   223             vcard.open(QBuffer::ReadWrite);
       
   224             vcard.write(line);
       
   225             bool complete(false);
       
   226             while (!complete && !vcardFile.atEnd()) {
       
   227                 line = vcardFile.readLine();
       
   228                 vcard.write(line);
       
   229                 if (line.contains(QByteArray("END:VCARD"))) {
       
   230                     complete = true;
       
   231                 }
       
   232             }
       
   233 
       
   234             // Parse the input into QVersitDocuments
       
   235             // Note: we could also use the more convenient QVersitReader(QByteArray) constructor.
       
   236             QVersitReader reader(vcard.buffer());
       
   237             if (!reader.startReading()) {return false;}
       
   238             if (!reader.waitForFinished()) {return false;}
       
   239 
       
   240             // Convert the QVersitDocuments to QContacts
       
   241             QList<QVersitDocument> inputDocuments = reader.results();
       
   242             QVersitContactImporter importer;
       
   243             if (!importer.importDocuments(inputDocuments)) {
       
   244                 return false;
       
   245             }
       
   246 
       
   247             QList<QContact> contacts = importer.contacts();
       
   248             if (!m_cm->saveContacts(&contacts, 0)) {
       
   249                 return false;
       
   250             }
       
   251             contactCount++;
       
   252         }
       
   253     }
       
   254     //qDebug() << contactCount << "contacts added in total";
       
   255     return true;
       
   256 }
       
   257 
       
   258 bool tst_Performance::detailsExist(QList<QContact> contacts, QStringList definitionNames)
       
   259 {
       
   260     foreach(QContact contact, contacts) {
       
   261         foreach (QString definitionName, definitionNames) {
       
   262             QList<QContactDetail> details = contact.details(definitionName);
       
   263             if (!details.count()) {
       
   264                 qDebug() << "Detail not found:" << definitionName;
       
   265                 return false;
       
   266             }
       
   267             foreach (QContactDetail detail, details) {
       
   268                 contact.removeDetail(&detail);
       
   269             }
       
   270         }
       
   271 
       
   272         // Verify that there were no extra details (this is important from
       
   273         // performance point of view; we don't want to waste time by giving
       
   274         // details that the client does not need.
       
   275         foreach (QContactDetail detail, contact.details()) {
       
   276             // Skip "always on" details
       
   277             if (detail.definitionName() != QContactDisplayLabel::DefinitionName
       
   278                 && detail.definitionName() != QContactType::DefinitionName
       
   279                 && detail.definitionName() != QContactGuid::DefinitionName
       
   280                 && detail.definitionName() != QContactTimestamp::DefinitionName) {
       
   281                 qDebug() << "Extra detail: " << detail.definitionName();
       
   282                 // displaylabel, type, guid, timestamp
       
   283                 return false;
       
   284             }
       
   285         }
       
   286     }
       
   287     return true;
       
   288 }
       
   289 
       
   290 void tst_Performance::startBenchmark(QString benchmarkName)
       
   291 {
       
   292     qDebug() << "Starting benchmark" << benchmarkName;
       
   293     m_benchmarkName = benchmarkName;
       
   294     m_timer.start();
       
   295 }
       
   296 
       
   297 bool tst_Performance::endBenchmark(const int target)
       
   298 {
       
   299     Q_ASSERT(!m_benchmarkName.isEmpty());
       
   300     int result = m_timer.elapsed();
       
   301     qDebug() << "The result for benchmark" << m_benchmarkName << "is [" << result << "]ms";
       
   302     QFile resultFile(resultFileName);
       
   303     if (resultFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
       
   304         QTextStream out(&resultFile);
       
   305         out << m_benchmarkName + QString(";") + QString::number(result) + "\r\n";
       
   306         resultFile.close();
       
   307     }
       
   308 
       
   309     if (target == 0 || result <= target) {
       
   310         return true;
       
   311     }
       
   312     qDebug() << "Target not reached!";
       
   313     return false;
       
   314 }
       
   315 
       
   316 QTEST_MAIN(tst_Performance);
       
   317 #include "tst_performance.moc"