qtcontactsmobility/tests/auto/qcontactasync/unittest/tst_qcontactasync.cpp
changeset 24 0ba2181d7c28
child 25 76a2435edfd4
equal deleted inserted replaced
0:e686773b3f54 24:0ba2181d7c28
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 <QtTest/QtTest>
       
    43 
       
    44 #include <QCoreApplication>
       
    45 #include "qtcontacts.h"
       
    46 #include "qcontactmanagerdataholder.h" //QContactManagerDataHolder
       
    47 
       
    48 QTM_USE_NAMESPACE
       
    49 
       
    50 class tst_QContactAsync : public QObject
       
    51 {
       
    52     Q_OBJECT
       
    53 
       
    54 public:
       
    55     tst_QContactAsync();
       
    56     virtual ~tst_QContactAsync();
       
    57 
       
    58 public slots:
       
    59     void init();
       
    60     void cleanup();
       
    61 
       
    62 private:
       
    63     void addManagers(); // add standard managers to the data
       
    64 
       
    65 private slots:
       
    66     void testDestructor();
       
    67     void testDestructor_data() { addManagers(); }
       
    68 
       
    69     void contactFetch();
       
    70     void contactFetch_data() { addManagers(); }
       
    71     void contactIdFetch();
       
    72     void contactIdFetch_data() { addManagers(); }
       
    73     void contactRemove();
       
    74     void contactRemove_data() { addManagers(); }
       
    75     void contactSave();
       
    76     void contactSave_data() { addManagers(); }
       
    77 
       
    78     void definitionFetch();
       
    79     void definitionFetch_data() { addManagers(); }
       
    80     void definitionRemove();
       
    81     void definitionRemove_data() { addManagers(); }
       
    82     void definitionSave();
       
    83     void definitionSave_data() { addManagers(); }
       
    84 
       
    85     void relationshipFetch();
       
    86     void relationshipFetch_data() { addManagers(); }
       
    87     void relationshipRemove();
       
    88     void relationshipRemove_data() { addManagers(); }
       
    89     void relationshipSave();
       
    90     void relationshipSave_data() { addManagers(); }
       
    91 
       
    92     void maliciousManager(); // uses it's own custom data (manager)
       
    93 
       
    94     void threadDelivery();
       
    95     void progressReceived(QContactFetchRequest* request, bool appendOnly);
       
    96     void threadDelivery_data() { addManagers(); }
       
    97 
       
    98 private:
       
    99     bool containsIgnoringTimestamps(const QList<QContact>& list, const QContact& c);
       
   100     bool compareIgnoringTimestamps(const QContact& ca, const QContact& cb);
       
   101     bool prepareModel(const QString &uri, QContactManager *&cm);
       
   102     bool prepareModel(const QString &uri, QContactManager *&cm, QList<QContact> &contacts, QList<QContactRelationship> &relationships);
       
   103 
       
   104     Qt::HANDLE m_mainThreadId;
       
   105     Qt::HANDLE m_progressSlotThreadId;
       
   106     QContactManagerDataHolder managerDataHolder;
       
   107 };
       
   108 
       
   109 typedef QList<QContactLocalId> QContactLocalIdList;
       
   110 Q_DECLARE_METATYPE(QContactLocalIdList);
       
   111 
       
   112 tst_QContactAsync::tst_QContactAsync()
       
   113 {
       
   114     // ensure we can load all of the plugins we need to.
       
   115     QString path = QApplication::applicationDirPath() + "/dummyplugin/plugins";
       
   116     QApplication::addLibraryPath(path);
       
   117 
       
   118     qRegisterMetaType<QContactLocalIdList>("QList<QContactLocalId>");
       
   119 }
       
   120 
       
   121 tst_QContactAsync::~tst_QContactAsync()
       
   122 {
       
   123     QString path = QApplication::applicationDirPath() + "/dummyplugin/plugins";
       
   124     QApplication::removeLibraryPath(path);
       
   125 }
       
   126 
       
   127 void tst_QContactAsync::init()
       
   128 {
       
   129 }
       
   130 
       
   131 void tst_QContactAsync::cleanup()
       
   132 {
       
   133 }
       
   134 
       
   135 bool tst_QContactAsync::containsIgnoringTimestamps(const QList<QContact>& list, const QContact& c)
       
   136 {
       
   137     QList<QContact> cl = list;
       
   138     QContact a(c);
       
   139     for (int i = 0; i < cl.size(); i++) {
       
   140         QContact b(cl.at(i));
       
   141         if (compareIgnoringTimestamps(a, b))
       
   142             return true;
       
   143     }
       
   144 
       
   145     return false;
       
   146 }
       
   147 
       
   148 bool tst_QContactAsync::compareIgnoringTimestamps(const QContact& ca, const QContact& cb)
       
   149 {
       
   150     // Compares two contacts, ignoring any timestamp details
       
   151     QContact a(ca);
       
   152     QContact b(cb);
       
   153     QList<QContactDetail> aDetails = a.details();
       
   154     QList<QContactDetail> bDetails = b.details();
       
   155 
       
   156     // They can be in any order, so loop
       
   157     // First remove any matches, and any timestamps
       
   158     foreach (QContactDetail d, aDetails) {
       
   159         foreach (QContactDetail d2, bDetails) {
       
   160             if (d == d2) {
       
   161                 a.removeDetail(&d);
       
   162                 b.removeDetail(&d2);
       
   163                 break;
       
   164             }
       
   165 
       
   166             if (d.definitionName() == QContactTimestamp::DefinitionName) {
       
   167                 a.removeDetail(&d);
       
   168             }
       
   169 
       
   170             if (d2.definitionName() == QContactTimestamp::DefinitionName) {
       
   171                 b.removeDetail(&d2);
       
   172             }
       
   173         }
       
   174     }
       
   175 
       
   176     if (a == b)
       
   177         return true;
       
   178     return false;
       
   179 }
       
   180 
       
   181 void tst_QContactAsync::testDestructor()
       
   182 {
       
   183     QFETCH(QString, uri);
       
   184     QContactManager* cm(0);
       
   185     QVERIFY(prepareModel(uri, cm));
       
   186     QContactFetchRequest* req = new QContactFetchRequest;
       
   187     req->setManager(cm);
       
   188 
       
   189     QContactManager* cm2(0);
       
   190     QVERIFY(prepareModel(uri, cm2));
       
   191     QContactFetchRequest* req2 = new QContactFetchRequest;
       
   192     req2->setManager(cm2);
       
   193 
       
   194     // first, delete manager then request
       
   195     delete cm;
       
   196     delete req;
       
   197 
       
   198     // second, delete request then manager
       
   199     delete req2;
       
   200     delete cm2;
       
   201 }
       
   202 
       
   203 void tst_QContactAsync::contactFetch()
       
   204 {
       
   205     QFETCH(QString, uri);
       
   206     QContactManager* cm(0);
       
   207     QVERIFY(prepareModel(uri, cm));
       
   208     QContactFetchRequest cfr;
       
   209     QVERIFY(cfr.type() == QContactAbstractRequest::ContactFetchRequest);
       
   210 
       
   211     // initial state - not started, no manager.
       
   212     QVERIFY(!cfr.isActive());
       
   213     QVERIFY(!cfr.isFinished());
       
   214     QVERIFY(!cfr.start());
       
   215     QVERIFY(!cfr.cancel());
       
   216     QVERIFY(!cfr.waitForFinished());
       
   217     QVERIFY(!cfr.waitForProgress());
       
   218 
       
   219     // "all contacts" retrieval
       
   220     QContactFilter fil;
       
   221     cfr.setManager(cm);
       
   222     QCOMPARE(cfr.manager(), cm);
       
   223     QVERIFY(!cfr.isActive());
       
   224     QVERIFY(!cfr.isFinished());
       
   225     QVERIFY(!cfr.cancel());
       
   226     QVERIFY(!cfr.waitForFinished());
       
   227     QVERIFY(!cfr.waitForProgress());
       
   228     qRegisterMetaType<QContactFetchRequest*>("QContactFetchRequest*");
       
   229     QSignalSpy spy(&cfr, SIGNAL(progress(QContactFetchRequest*, bool)));
       
   230     cfr.setFilter(fil);
       
   231     QCOMPARE(cfr.filter(), fil);
       
   232     QVERIFY(!cfr.cancel()); // not started
       
   233     QVERIFY(cfr.start());
       
   234     QVERIFY(cfr.isActive());
       
   235     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   236     QVERIFY(!cfr.isFinished());
       
   237     QVERIFY(!cfr.start());  // already started.
       
   238     QVERIFY(cfr.waitForFinished());
       
   239     int expectedCount = 2;
       
   240     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   241     QVERIFY(cfr.isFinished());
       
   242     QVERIFY(!cfr.isActive());
       
   243 
       
   244     QList<QContactLocalId> contactIds = cm->contacts();
       
   245     QList<QContact> contacts = cfr.contacts();
       
   246     QCOMPARE(contactIds.size(), contacts.size());
       
   247     for (int i = 0; i < contactIds.size(); i++) {
       
   248         QContact curr = cm->contact(contactIds.at(i));
       
   249         QVERIFY(contacts.at(i) == curr);
       
   250     }
       
   251 
       
   252     // asynchronous detail filtering
       
   253     QContactDetailFilter dfil;
       
   254     dfil.setDetailDefinitionName(QContactUrl::DefinitionName, QContactUrl::FieldUrl);
       
   255     cfr.setFilter(dfil);
       
   256     QVERIFY(cfr.filter() == dfil);
       
   257     QVERIFY(!cfr.cancel()); // not started
       
   258     QVERIFY(cfr.start());
       
   259     QVERIFY(cfr.isActive());
       
   260     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   261     QVERIFY(!cfr.isFinished());
       
   262     QVERIFY(!cfr.start());  // already started.
       
   263     QVERIFY(cfr.waitForFinished());
       
   264     expectedCount += 2;
       
   265     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   266     QVERIFY(cfr.isFinished());
       
   267     QVERIFY(!cfr.isActive());
       
   268 
       
   269     contactIds = cm->contacts(dfil);
       
   270     contacts = cfr.contacts();
       
   271     QCOMPARE(contactIds.size(), contacts.size());
       
   272     for (int i = 0; i < contactIds.size(); i++) {
       
   273         QContact curr = cm->contact(contactIds.at(i));
       
   274         QVERIFY(contacts.at(i) == curr);
       
   275     }
       
   276 
       
   277     // sort order
       
   278     QContactSortOrder sortOrder;
       
   279     sortOrder.setDetailDefinitionName(QContactPhoneNumber::DefinitionName, QContactPhoneNumber::FieldNumber);
       
   280     QList<QContactSortOrder> sorting;
       
   281     sorting.append(sortOrder);
       
   282     cfr.setFilter(fil);
       
   283     cfr.setSorting(sorting);
       
   284     QCOMPARE(cfr.sorting(), sorting);
       
   285     QVERIFY(!cfr.cancel()); // not started
       
   286     QVERIFY(cfr.start());
       
   287     QVERIFY(cfr.isActive());
       
   288     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   289     QVERIFY(!cfr.isFinished());
       
   290     QVERIFY(!cfr.start());  // already started.
       
   291     QVERIFY(cfr.waitForFinished());
       
   292     expectedCount += 2;
       
   293     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   294     QVERIFY(cfr.isFinished());
       
   295     QVERIFY(!cfr.isActive());
       
   296 
       
   297     contactIds = cm->contacts(sorting);
       
   298     contacts = cfr.contacts();
       
   299     QCOMPARE(contactIds.size(), contacts.size());
       
   300     for (int i = 0; i < contactIds.size(); i++) {
       
   301         QContact curr = cm->contact(contactIds.at(i));
       
   302         QVERIFY(contacts.at(i) == curr);
       
   303     }
       
   304 
       
   305     // restrictions
       
   306     sorting.clear();
       
   307     cfr.setFilter(fil);
       
   308     cfr.setSorting(sorting);
       
   309     cfr.setDefinitionRestrictions(QStringList(QContactName::DefinitionName));
       
   310     QCOMPARE(cfr.definitionRestrictions(), QStringList(QContactName::DefinitionName));
       
   311     QVERIFY(!cfr.cancel()); // not started
       
   312     QVERIFY(cfr.start());
       
   313     QVERIFY(cfr.isActive());
       
   314     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   315     QVERIFY(!cfr.isFinished());
       
   316     QVERIFY(!cfr.start());  // already started.
       
   317     QVERIFY(cfr.waitForFinished());
       
   318     expectedCount += 2;
       
   319     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   320     QVERIFY(cfr.isFinished());
       
   321     QVERIFY(!cfr.isActive());
       
   322 
       
   323     contactIds = cm->contacts(sorting);
       
   324     contacts = cfr.contacts();
       
   325     QCOMPARE(contactIds.size(), contacts.size());
       
   326     for (int i = 0; i < contactIds.size(); i++) {
       
   327         // create a contact from the restricted data only (id + display label)
       
   328         QContact currFull = cm->contact(contactIds.at(i));
       
   329         QContact currRestricted;
       
   330         currRestricted.setId(currFull.id());
       
   331         QList<QContactName> names = currFull.details<QContactName>();
       
   332         foreach (const QContactName& name, names) {
       
   333             QContactName fullName = name;
       
   334             if (!fullName.isEmpty()) {
       
   335                 currRestricted.saveDetail(&fullName);
       
   336             }
       
   337         }
       
   338 
       
   339         // now find the contact in the retrieved list which our restricted contact mimics
       
   340         QContact retrievedRestricted;
       
   341         bool found = false;
       
   342         foreach (const QContact& retrieved, contacts) {
       
   343             if (retrieved.id() == currRestricted.id()) {
       
   344                 retrievedRestricted = retrieved;
       
   345                 found = true;
       
   346             }
       
   347         }
       
   348 
       
   349         QVERIFY(found); // must exist or fail.
       
   350 
       
   351         // ensure that the contact is the same (except synth fields)
       
   352         QList<QContactDetail> fdets = retrievedRestricted.details();
       
   353         QList<QContactDetail> rdets = currRestricted.details();
       
   354         foreach (const QContactDetail& det, fdets) {
       
   355             // ignore backend synthesised details
       
   356             // again, this requires a "default contact details" function to work properly.
       
   357             if (det.definitionName() == QContactDisplayLabel::DefinitionName
       
   358                 || det.definitionName() == QContactTimestamp::DefinitionName) {
       
   359                 continue;
       
   360             }
       
   361 
       
   362             // everything else must exist in both.
       
   363             if(!rdets.contains(det)) {
       
   364                 qWarning("A detail exists in retrieved contact which doesn't exist in restricted contact!  This could be due to backend synthesization, or represent a bug!  (Definition name: %s)", det.definitionName().toAscii().constData());
       
   365             }
       
   366         }
       
   367     }
       
   368 
       
   369     // cancelling
       
   370     sorting.clear();
       
   371     cfr.setFilter(fil);
       
   372     cfr.setSorting(sorting);
       
   373     cfr.setDefinitionRestrictions(QStringList());
       
   374     QVERIFY(!cfr.cancel()); // not started
       
   375     QVERIFY(cfr.start());
       
   376     QVERIFY(cfr.isActive());
       
   377     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   378     QVERIFY(!cfr.isFinished());
       
   379     QVERIFY(cfr.cancel());
       
   380     QVERIFY(cfr.status() == QContactAbstractRequest::Cancelling);
       
   381     QVERIFY(cfr.isActive());    // still cancelling
       
   382     QVERIFY(!cfr.isFinished()); // not finished cancelling
       
   383     QVERIFY(!cfr.start());      // already started.
       
   384     QVERIFY(cfr.waitForFinished());
       
   385     expectedCount += 3;
       
   386     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   387     QVERIFY(cfr.isFinished());
       
   388     QVERIFY(!cfr.isActive());
       
   389     QVERIFY(cfr.status() == QContactAbstractRequest::Cancelled);
       
   390 
       
   391     // restart, and wait for progress after cancel.
       
   392     QVERIFY(!cfr.cancel()); // not started
       
   393     QVERIFY(cfr.start());
       
   394     QVERIFY(cfr.isActive());
       
   395     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   396     QVERIFY(!cfr.isFinished());
       
   397     QVERIFY(cfr.cancel());
       
   398     QVERIFY(cfr.status() == QContactAbstractRequest::Cancelling);
       
   399     QVERIFY(cfr.isActive());    // still cancelling
       
   400     QVERIFY(!cfr.isFinished()); // not finished cancelling
       
   401     QVERIFY(!cfr.start());      // already started.
       
   402     QVERIFY(cfr.waitForProgress());
       
   403     expectedCount += 3;
       
   404     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   405     QVERIFY(cfr.isFinished());
       
   406     QVERIFY(!cfr.isActive());
       
   407     QVERIFY(cfr.status() == QContactAbstractRequest::Cancelled);
       
   408 
       
   409     delete cm;
       
   410 }
       
   411 
       
   412 void tst_QContactAsync::contactIdFetch()
       
   413 {
       
   414     QFETCH(QString, uri);
       
   415     QContactManager* cm(0);
       
   416     QVERIFY(prepareModel(uri, cm));
       
   417     QContactLocalIdFetchRequest cfr;
       
   418     QVERIFY(cfr.type() == QContactAbstractRequest::ContactLocalIdFetchRequest);
       
   419 
       
   420     // initial state - not started, no manager.
       
   421     QVERIFY(!cfr.isActive());
       
   422     QVERIFY(!cfr.isFinished());
       
   423     QVERIFY(!cfr.start());
       
   424     QVERIFY(!cfr.cancel());
       
   425     QVERIFY(!cfr.waitForFinished());
       
   426     QVERIFY(!cfr.waitForProgress());
       
   427 
       
   428     // "all contacts" retrieval
       
   429     QContactFilter fil;
       
   430     cfr.setManager(cm);
       
   431     QCOMPARE(cfr.manager(), cm);
       
   432     QVERIFY(!cfr.isActive());
       
   433     QVERIFY(!cfr.isFinished());
       
   434     QVERIFY(!cfr.cancel());
       
   435     QVERIFY(!cfr.waitForFinished());
       
   436     QVERIFY(!cfr.waitForProgress());
       
   437     qRegisterMetaType<QContactLocalIdFetchRequest*>("QContactLocalIdFetchRequest*");
       
   438     QSignalSpy spy(&cfr, SIGNAL(progress(QContactLocalIdFetchRequest*, bool)));
       
   439     cfr.setFilter(fil);
       
   440     QCOMPARE(cfr.filter(), fil);
       
   441     QVERIFY(!cfr.cancel()); // not started
       
   442     QVERIFY(cfr.start());
       
   443     QVERIFY(cfr.isActive());
       
   444     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   445     QVERIFY(!cfr.isFinished());
       
   446     QVERIFY(!cfr.start());  // already started.
       
   447     QVERIFY(cfr.waitForFinished());
       
   448     int expectedCount = 2;
       
   449     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   450     QVERIFY(cfr.isFinished());
       
   451     QVERIFY(!cfr.isActive());
       
   452 
       
   453     QList<QContactLocalId> contactIds = cm->contacts();
       
   454     QList<QContactLocalId> result = cfr.ids();
       
   455     QCOMPARE(contactIds, result);
       
   456 
       
   457     // asynchronous detail filtering
       
   458     QContactDetailFilter dfil;
       
   459     dfil.setDetailDefinitionName(QContactUrl::DefinitionName, QContactUrl::FieldUrl);
       
   460     cfr.setFilter(dfil);
       
   461     QVERIFY(cfr.filter() == dfil);
       
   462     QVERIFY(!cfr.cancel()); // not started
       
   463     QVERIFY(cfr.start());
       
   464     QVERIFY(cfr.isActive());
       
   465     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   466     QVERIFY(!cfr.isFinished());
       
   467     QVERIFY(!cfr.start());  // already started.
       
   468     QVERIFY(cfr.waitForFinished());
       
   469     expectedCount += 2;
       
   470     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   471     QVERIFY(cfr.isFinished());
       
   472     QVERIFY(!cfr.isActive());
       
   473 
       
   474     contactIds = cm->contacts(dfil);
       
   475     result = cfr.ids();
       
   476     QCOMPARE(contactIds, result);
       
   477 
       
   478     // sort order
       
   479     QContactSortOrder sortOrder;
       
   480     sortOrder.setDetailDefinitionName(QContactPhoneNumber::DefinitionName, QContactPhoneNumber::FieldNumber);
       
   481     QList<QContactSortOrder> sorting;
       
   482     sorting.append(sortOrder);
       
   483     cfr.setFilter(fil);
       
   484     cfr.setSorting(sorting);
       
   485     QCOMPARE(cfr.sorting(), sorting);
       
   486     QVERIFY(!cfr.cancel()); // not started
       
   487     QVERIFY(cfr.start());
       
   488     QVERIFY(cfr.isActive());
       
   489     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   490     QVERIFY(!cfr.isFinished());
       
   491     QVERIFY(!cfr.start());  // already started.
       
   492     QVERIFY(cfr.waitForFinished());
       
   493     expectedCount += 2;
       
   494     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   495     QVERIFY(cfr.isFinished());
       
   496     QVERIFY(!cfr.isActive());
       
   497 
       
   498     contactIds = cm->contacts(sorting);
       
   499     result = cfr.ids();
       
   500     QCOMPARE(contactIds, result);
       
   501 
       
   502     // cancelling
       
   503     sorting.clear();
       
   504     cfr.setFilter(fil);
       
   505     cfr.setSorting(sorting);
       
   506     QVERIFY(!cfr.cancel()); // not started
       
   507     QVERIFY(cfr.start());
       
   508     QVERIFY(cfr.isActive());
       
   509     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   510     QVERIFY(!cfr.isFinished());
       
   511     QVERIFY(cfr.cancel());
       
   512     QVERIFY(cfr.status() == QContactAbstractRequest::Cancelling);
       
   513     QVERIFY(cfr.isActive());    // still cancelling
       
   514     QVERIFY(!cfr.isFinished()); // not finished cancelling
       
   515     QVERIFY(!cfr.start());      // already started.
       
   516     QVERIFY(cfr.waitForFinished());
       
   517     expectedCount += 3;
       
   518     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   519     QVERIFY(cfr.isFinished());
       
   520     QVERIFY(!cfr.isActive());
       
   521     QVERIFY(cfr.status() == QContactAbstractRequest::Cancelled);
       
   522 
       
   523     // restart, and wait for progress after cancel.
       
   524     QVERIFY(!cfr.cancel()); // not started
       
   525     QVERIFY(cfr.start());
       
   526     QVERIFY(cfr.isActive());
       
   527     QVERIFY(cfr.status() == QContactAbstractRequest::Active);
       
   528     QVERIFY(!cfr.isFinished());
       
   529     QVERIFY(cfr.cancel());
       
   530     QVERIFY(cfr.status() == QContactAbstractRequest::Cancelling);
       
   531     QVERIFY(cfr.isActive());    // still cancelling
       
   532     QVERIFY(!cfr.isFinished()); // not finished cancelling
       
   533     QVERIFY(!cfr.start());      // already started.
       
   534     QVERIFY(cfr.waitForProgress());
       
   535     expectedCount += 3;
       
   536     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   537     QVERIFY(cfr.isFinished());
       
   538     QVERIFY(!cfr.isActive());
       
   539     QVERIFY(cfr.status() == QContactAbstractRequest::Cancelled);
       
   540 
       
   541     delete cm;
       
   542 }
       
   543 
       
   544 void tst_QContactAsync::contactRemove()
       
   545 {
       
   546     QFETCH(QString, uri);
       
   547     QContactManager* cm(0);
       
   548     QVERIFY(prepareModel(uri, cm));
       
   549     QContactRemoveRequest crr;
       
   550     QVERIFY(crr.type() == QContactAbstractRequest::ContactRemoveRequest);
       
   551 
       
   552     // initial state - not started, no manager.
       
   553     QVERIFY(!crr.isActive());
       
   554     QVERIFY(!crr.isFinished());
       
   555     QVERIFY(!crr.start());
       
   556     QVERIFY(!crr.cancel());
       
   557     QVERIFY(!crr.waitForFinished());
       
   558     QVERIFY(!crr.waitForProgress());
       
   559 
       
   560     // specific contact removal
       
   561     int originalCount = cm->contacts().size();
       
   562     QContactDetailFilter dfil;
       
   563     dfil.setDetailDefinitionName(QContactUrl::DefinitionName, QContactUrl::FieldUrl);
       
   564     crr.setFilter(dfil);
       
   565     crr.setManager(cm);
       
   566     QCOMPARE(crr.manager(), cm);
       
   567     QVERIFY(!crr.isActive());
       
   568     QVERIFY(!crr.isFinished());
       
   569     QVERIFY(!crr.cancel());
       
   570     QVERIFY(!crr.waitForFinished());
       
   571     QVERIFY(!crr.waitForProgress());
       
   572     qRegisterMetaType<QContactRemoveRequest*>("QContactRemoveRequest*");
       
   573     QSignalSpy spy(&crr, SIGNAL(progress(QContactRemoveRequest*)));
       
   574     QVERIFY(crr.filter() == dfil);
       
   575     QVERIFY(!crr.cancel()); // not started
       
   576     QVERIFY(crr.start());
       
   577     QVERIFY(crr.isActive());
       
   578     QVERIFY(crr.status() == QContactAbstractRequest::Active);
       
   579     QVERIFY(!crr.isFinished());
       
   580     QVERIFY(!crr.start());  // already started.
       
   581     QVERIFY(crr.waitForFinished());
       
   582     int expectedCount = 2;
       
   583     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   584     QVERIFY(crr.isFinished());
       
   585     QVERIFY(!crr.isActive());
       
   586 
       
   587     QCOMPARE(cm->contacts().size(), originalCount - 1);
       
   588     QVERIFY(cm->contacts(dfil).isEmpty());
       
   589 
       
   590     // remove all contacts
       
   591     dfil.setDetailDefinitionName(QContactDisplayLabel::DefinitionName); // delete everything.
       
   592     crr.setFilter(dfil);
       
   593     QVERIFY(crr.filter() == dfil);
       
   594     QVERIFY(!crr.cancel()); // not started
       
   595     QVERIFY(crr.start());
       
   596     QVERIFY(crr.isActive());
       
   597     QVERIFY(crr.status() == QContactAbstractRequest::Active);
       
   598     QVERIFY(!crr.isFinished());
       
   599     QVERIFY(!crr.start());  // already started.
       
   600     QVERIFY(crr.waitForFinished());
       
   601     expectedCount += 2;
       
   602     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   603     QVERIFY(crr.isFinished());
       
   604     QVERIFY(!crr.isActive());
       
   605 
       
   606     QCOMPARE(cm->contacts().size(), 0); // no contacts should be left.
       
   607 
       
   608     // cancelling
       
   609     QContact temp;
       
   610     QContactName nameDetail;
       
   611     nameDetail.setFirst("Should not be removed");
       
   612     temp.saveDetail(&nameDetail);
       
   613     cm->saveContact(&temp);
       
   614     crr.setFilter(dfil);
       
   615     QVERIFY(!crr.cancel()); // not started
       
   616     QVERIFY(crr.start());
       
   617     QVERIFY(crr.isActive());
       
   618     QVERIFY(crr.status() == QContactAbstractRequest::Active);
       
   619     QVERIFY(!crr.isFinished());
       
   620     QVERIFY(crr.cancel());
       
   621     QVERIFY(crr.status() == QContactAbstractRequest::Cancelling);
       
   622     QVERIFY(crr.isActive());    // still cancelling
       
   623     QVERIFY(!crr.isFinished()); // not finished cancelling
       
   624     QVERIFY(!crr.start());      // already started.
       
   625     QVERIFY(crr.waitForFinished());
       
   626     expectedCount += 3;
       
   627     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   628     QVERIFY(crr.isFinished());
       
   629     QVERIFY(!crr.isActive());
       
   630     QVERIFY(crr.status() == QContactAbstractRequest::Cancelled);
       
   631 
       
   632     QCOMPARE(cm->contacts().size(), 1);
       
   633     QCOMPARE(cm->contact(cm->contacts().first()), temp);
       
   634 
       
   635     // restart, and wait for progress after cancel.
       
   636     QVERIFY(!crr.cancel()); // not started
       
   637     QVERIFY(crr.start());
       
   638     QVERIFY(crr.isActive());
       
   639     QVERIFY(crr.status() == QContactAbstractRequest::Active);
       
   640     QVERIFY(!crr.isFinished());
       
   641     QVERIFY(crr.cancel());
       
   642     QVERIFY(crr.status() == QContactAbstractRequest::Cancelling);
       
   643     QVERIFY(crr.isActive());    // still cancelling
       
   644     QVERIFY(!crr.isFinished()); // not finished cancelling
       
   645     QVERIFY(!crr.start());      // already started.
       
   646     QVERIFY(crr.waitForProgress());
       
   647     expectedCount += 3;
       
   648     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   649     QVERIFY(crr.isFinished());
       
   650     QVERIFY(!crr.isActive());
       
   651     QVERIFY(crr.status() == QContactAbstractRequest::Cancelled);
       
   652 
       
   653     QCOMPARE(cm->contacts().size(), 1);
       
   654     QCOMPARE(cm->contact(cm->contacts().first()), temp);
       
   655     cm->removeContact(temp.localId()); // clean up
       
   656 
       
   657     delete cm;
       
   658 }
       
   659 
       
   660 void tst_QContactAsync::contactSave()
       
   661 {
       
   662     QFETCH(QString, uri);
       
   663     QContactManager* cm(0);
       
   664     QVERIFY(prepareModel(uri, cm));
       
   665     QContactSaveRequest csr;
       
   666     QVERIFY(csr.type() == QContactAbstractRequest::ContactSaveRequest);
       
   667 
       
   668     // initial state - not started, no manager.
       
   669     QVERIFY(!csr.isActive());
       
   670     QVERIFY(!csr.isFinished());
       
   671     QVERIFY(!csr.start());
       
   672     QVERIFY(!csr.cancel());
       
   673     QVERIFY(!csr.waitForFinished());
       
   674     QVERIFY(!csr.waitForProgress());
       
   675 
       
   676     // save a new contact
       
   677     int originalCount = cm->contacts().size();
       
   678     QContact testContact;
       
   679     QContactName nameDetail;
       
   680     nameDetail.setFirst("Test Contact");
       
   681     testContact.saveDetail(&nameDetail);
       
   682     QList<QContact> saveList;
       
   683     saveList << testContact;
       
   684     csr.setManager(cm);
       
   685     QCOMPARE(csr.manager(), cm);
       
   686     QVERIFY(!csr.isActive());
       
   687     QVERIFY(!csr.isFinished());
       
   688     QVERIFY(!csr.cancel());
       
   689     QVERIFY(!csr.waitForFinished());
       
   690     QVERIFY(!csr.waitForProgress());
       
   691     qRegisterMetaType<QContactSaveRequest*>("QContactSaveRequest*");
       
   692     QSignalSpy spy(&csr, SIGNAL(progress(QContactSaveRequest*)));
       
   693     csr.setContacts(saveList);
       
   694     QCOMPARE(csr.contacts(), saveList);
       
   695     QVERIFY(!csr.cancel()); // not started
       
   696     QVERIFY(csr.start());
       
   697     QVERIFY(csr.isActive());
       
   698     QVERIFY(csr.status() == QContactAbstractRequest::Active);
       
   699     QVERIFY(!csr.isFinished());
       
   700     QVERIFY(!csr.start());  // already started.
       
   701     QVERIFY(csr.waitForFinished());
       
   702     int expectedCount = 2;
       
   703     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   704     QVERIFY(csr.isFinished());
       
   705     QVERIFY(!csr.isActive());
       
   706 
       
   707     QList<QContact> expected;
       
   708     expected << cm->contact(cm->contacts().last());
       
   709     QList<QContact> result = csr.contacts();
       
   710     QCOMPARE(expected, result);
       
   711     QCOMPARE(cm->contacts().size(), originalCount + 1);
       
   712 
       
   713     // update a previously saved contact
       
   714     QContactPhoneNumber phn;
       
   715     phn.setNumber("12345678");
       
   716     testContact = expected.first();
       
   717     testContact.saveDetail(&phn);
       
   718     saveList.clear();
       
   719     saveList << testContact;
       
   720     csr.setContacts(saveList);
       
   721     QCOMPARE(csr.contacts(), saveList);
       
   722     QVERIFY(!csr.cancel()); // not started
       
   723     QVERIFY(csr.start());
       
   724     QVERIFY(csr.isActive());
       
   725     QVERIFY(csr.status() == QContactAbstractRequest::Active);
       
   726     QVERIFY(!csr.isFinished());
       
   727     QVERIFY(!csr.start());  // already started.
       
   728     QVERIFY(csr.waitForFinished());
       
   729     expectedCount += 2;
       
   730     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   731     QVERIFY(csr.isFinished());
       
   732     QVERIFY(!csr.isActive());
       
   733 
       
   734     expected.clear();
       
   735     expected << cm->contact(cm->contacts().last());
       
   736     result = csr.contacts();
       
   737     QCOMPARE(expected, result);
       
   738 
       
   739     //here we can't compare the whole contact details, testContact would be updated by async call because we just use QSignalSpy to receive signals.
       
   740     //QVERIFY(containsIgnoringTimestamps(expected, testContact));
       
   741     QVERIFY(expected.at(0).detail<QContactPhoneNumber>().number() == phn.number());
       
   742     
       
   743     QCOMPARE(cm->contacts().size(), originalCount + 1);
       
   744 
       
   745     // cancelling
       
   746     QContact temp = testContact;
       
   747     QContactUrl url;
       
   748     url.setUrl("should not get saved");
       
   749     temp.saveDetail(&url);
       
   750     saveList.clear();
       
   751     saveList << temp;
       
   752     csr.setContacts(saveList);
       
   753     QVERIFY(!csr.cancel()); // not started
       
   754     QVERIFY(csr.start());
       
   755     QVERIFY(csr.isActive());
       
   756     QVERIFY(csr.status() == QContactAbstractRequest::Active);
       
   757     QVERIFY(!csr.isFinished());
       
   758     QVERIFY(csr.cancel());
       
   759     QVERIFY(csr.status() == QContactAbstractRequest::Cancelling);
       
   760     QVERIFY(csr.isActive());    // still cancelling
       
   761     QVERIFY(!csr.isFinished()); // not finished cancelling
       
   762     QVERIFY(!csr.start());      // already started.
       
   763     QVERIFY(csr.waitForFinished());
       
   764     expectedCount += 3;
       
   765     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   766     QVERIFY(csr.isFinished());
       
   767     QVERIFY(!csr.isActive());
       
   768     QVERIFY(csr.status() == QContactAbstractRequest::Cancelled);
       
   769 
       
   770     // verify that the changes were not saved
       
   771     expected.clear();
       
   772     QList<QContactLocalId> allContacts = cm->contacts();
       
   773     for (int i = 0; i < allContacts.size(); i++) {
       
   774         expected.append(cm->contact(allContacts.at(i)));
       
   775     }
       
   776     QVERIFY(!expected.contains(temp));
       
   777     QCOMPARE(cm->contacts().size(), originalCount + 1);
       
   778 
       
   779     // restart, and wait for progress after cancel.
       
   780     QVERIFY(!csr.cancel()); // not started
       
   781     QVERIFY(csr.start());
       
   782     QVERIFY(csr.isActive());
       
   783     QVERIFY(csr.status() == QContactAbstractRequest::Active);
       
   784     QVERIFY(!csr.isFinished());
       
   785     QVERIFY(csr.cancel());
       
   786     QVERIFY(csr.status() == QContactAbstractRequest::Cancelling);
       
   787     QVERIFY(csr.isActive());    // still cancelling
       
   788     QVERIFY(!csr.isFinished()); // not finished cancelling
       
   789     QVERIFY(!csr.start());      // already started.
       
   790     QVERIFY(csr.waitForProgress());
       
   791     expectedCount += 3;
       
   792     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   793     QVERIFY(csr.isFinished());
       
   794     QVERIFY(!csr.isActive());
       
   795     QVERIFY(csr.status() == QContactAbstractRequest::Cancelled);
       
   796 
       
   797     // verify that the changes were not saved
       
   798     expected.clear();
       
   799     allContacts = cm->contacts();
       
   800     for (int i = 0; i < allContacts.size(); i++) {
       
   801         expected.append(cm->contact(allContacts.at(i)));
       
   802     }
       
   803     QVERIFY(!expected.contains(temp));
       
   804     QCOMPARE(cm->contacts().size(), originalCount + 1);
       
   805 
       
   806     delete cm;
       
   807 }
       
   808 
       
   809 void tst_QContactAsync::definitionFetch()
       
   810 {
       
   811     QFETCH(QString, uri);
       
   812     QContactManager* cm(0);
       
   813     QVERIFY(prepareModel(uri, cm));
       
   814     QContactDetailDefinitionFetchRequest dfr;
       
   815     QVERIFY(dfr.type() == QContactAbstractRequest::DetailDefinitionFetchRequest);
       
   816     dfr.setContactType(QContactType::TypeContact);
       
   817     QVERIFY(dfr.contactType() == QString(QLatin1String(QContactType::TypeContact)));
       
   818 
       
   819     // initial state - not started, no manager.
       
   820     QVERIFY(!dfr.isActive());
       
   821     QVERIFY(!dfr.isFinished());
       
   822     QVERIFY(!dfr.start());
       
   823     QVERIFY(!dfr.cancel());
       
   824     QVERIFY(!dfr.waitForFinished());
       
   825     QVERIFY(!dfr.waitForProgress());
       
   826 
       
   827     // "all definitions" retrieval
       
   828     dfr.setManager(cm);
       
   829     QCOMPARE(dfr.manager(), cm);
       
   830     QVERIFY(!dfr.isActive());
       
   831     QVERIFY(!dfr.isFinished());
       
   832     QVERIFY(!dfr.cancel());
       
   833     QVERIFY(!dfr.waitForFinished());
       
   834     QVERIFY(!dfr.waitForProgress());
       
   835     qRegisterMetaType<QContactDetailDefinitionFetchRequest*>("QContactDetailDefinitionFetchRequest*");
       
   836     QSignalSpy spy(&dfr, SIGNAL(progress(QContactDetailDefinitionFetchRequest*, bool)));
       
   837     dfr.setNames(QStringList());
       
   838     QVERIFY(!dfr.cancel()); // not started
       
   839     QVERIFY(dfr.start());
       
   840     QVERIFY(dfr.isActive());
       
   841     QVERIFY(dfr.status() == QContactAbstractRequest::Active);
       
   842     QVERIFY(!dfr.isFinished());
       
   843     QVERIFY(!dfr.start());  // already started.
       
   844     QVERIFY(dfr.waitForFinished());
       
   845     int expectedCount = 2;
       
   846     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   847     QVERIFY(dfr.isFinished());
       
   848     QVERIFY(!dfr.isActive());
       
   849 
       
   850     QMap<QString, QContactDetailDefinition> defs = cm->detailDefinitions();
       
   851     QMap<QString, QContactDetailDefinition> result = dfr.definitions();
       
   852     QCOMPARE(defs, result);
       
   853 
       
   854     // specific definition retrieval
       
   855     QStringList specific;
       
   856     specific << QContactUrl::DefinitionName;
       
   857     dfr.setNames(specific);
       
   858     QVERIFY(!dfr.cancel()); // not started
       
   859     QVERIFY(dfr.start());
       
   860     QVERIFY(dfr.isActive());
       
   861     QVERIFY(dfr.status() == QContactAbstractRequest::Active);
       
   862     QVERIFY(!dfr.isFinished());
       
   863     QVERIFY(!dfr.start());  // already started.
       
   864     QVERIFY(dfr.waitForFinished());
       
   865     expectedCount += 2;
       
   866     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   867     QVERIFY(dfr.isFinished());
       
   868     QVERIFY(!dfr.isActive());
       
   869 
       
   870     defs.clear();
       
   871     defs.insert(QContactUrl::DefinitionName, cm->detailDefinition(QContactUrl::DefinitionName));
       
   872     result = dfr.definitions();
       
   873     QCOMPARE(defs, result);
       
   874 
       
   875     // cancelling
       
   876     dfr.setNames(QStringList());
       
   877     QVERIFY(!dfr.cancel()); // not started
       
   878     QVERIFY(dfr.start());
       
   879     QVERIFY(dfr.isActive());
       
   880     QVERIFY(dfr.status() == QContactAbstractRequest::Active);
       
   881     QVERIFY(!dfr.isFinished());
       
   882     QVERIFY(dfr.cancel());
       
   883     QVERIFY(dfr.status() == QContactAbstractRequest::Cancelling);
       
   884     QVERIFY(dfr.isActive());    // still cancelling
       
   885     QVERIFY(!dfr.isFinished()); // not finished cancelling
       
   886     QVERIFY(!dfr.start());      // already started.
       
   887     QVERIFY(dfr.waitForFinished());
       
   888     expectedCount += 3;
       
   889     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   890     QVERIFY(dfr.isFinished());
       
   891     QVERIFY(!dfr.isActive());
       
   892     QVERIFY(dfr.status() == QContactAbstractRequest::Cancelled);
       
   893 
       
   894     // restart, and wait for progress after cancel.
       
   895     QVERIFY(!dfr.cancel()); // not started
       
   896     QVERIFY(dfr.start());
       
   897     QVERIFY(dfr.isActive());
       
   898     QVERIFY(dfr.status() == QContactAbstractRequest::Active);
       
   899     QVERIFY(!dfr.isFinished());
       
   900     QVERIFY(dfr.cancel());
       
   901     QVERIFY(dfr.status() == QContactAbstractRequest::Cancelling);
       
   902     QVERIFY(dfr.isActive());    // still cancelling
       
   903     QVERIFY(!dfr.isFinished()); // not finished cancelling
       
   904     QVERIFY(!dfr.start());      // already started.
       
   905     QVERIFY(dfr.waitForProgress());
       
   906     expectedCount += 3;
       
   907     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
   908     QVERIFY(dfr.isFinished());
       
   909     QVERIFY(!dfr.isActive());
       
   910     QVERIFY(dfr.status() == QContactAbstractRequest::Cancelled);
       
   911 
       
   912     delete cm;
       
   913 }
       
   914 
       
   915 void tst_QContactAsync::definitionRemove()
       
   916 {
       
   917     QFETCH(QString, uri);
       
   918     QContactManager* cm(0);
       
   919     QVERIFY(prepareModel(uri, cm));
       
   920     if (!cm->hasFeature(QContactManager::MutableDefinitions, QContactType::TypeContact)) {
       
   921        QSKIP("This contact manager doest not support mutable definitions, can't remove a definition!", SkipSingle);
       
   922     }
       
   923     QContactDetailDefinitionRemoveRequest drr;
       
   924     QVERIFY(drr.type() == QContactAbstractRequest::DetailDefinitionRemoveRequest);
       
   925     drr.setContactType(QContactType::TypeContact);
       
   926     QVERIFY(drr.contactType() == QString(QLatin1String(QContactType::TypeContact)));
       
   927 
       
   928     // initial state - not started, no manager.
       
   929     QVERIFY(!drr.isActive());
       
   930     QVERIFY(!drr.isFinished());
       
   931     QVERIFY(!drr.start());
       
   932     QVERIFY(!drr.cancel());
       
   933     QVERIFY(!drr.waitForFinished());
       
   934     QVERIFY(!drr.waitForProgress());
       
   935 
       
   936     // specific group removal
       
   937     int originalCount = cm->detailDefinitions().keys().size();
       
   938     QStringList removeIds;
       
   939     removeIds << cm->detailDefinitions().keys().first();
       
   940     drr.setNames(removeIds);
       
   941     drr.setManager(cm);
       
   942     QCOMPARE(drr.manager(), cm);
       
   943     QVERIFY(!drr.isActive());
       
   944     QVERIFY(!drr.isFinished());
       
   945     QVERIFY(!drr.cancel());
       
   946     QVERIFY(!drr.waitForFinished());
       
   947     QVERIFY(!drr.waitForProgress());
       
   948     qRegisterMetaType<QContactDetailDefinitionRemoveRequest*>("QContactDetailDefinitionRemoveRequest*");
       
   949     QSignalSpy spy(&drr, SIGNAL(progress(QContactDetailDefinitionRemoveRequest*)));
       
   950     QVERIFY(drr.names() == removeIds);
       
   951     QVERIFY(!drr.cancel()); // not started
       
   952     QVERIFY(drr.start());
       
   953     QVERIFY(drr.isActive());
       
   954     QVERIFY(drr.status() == QContactAbstractRequest::Active);
       
   955     QVERIFY(!drr.isFinished());
       
   956     QVERIFY(!drr.start());  // already started.
       
   957     QVERIFY(drr.waitForFinished());
       
   958     int expectedCount = 2;
       
   959     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   960     QVERIFY(drr.isFinished());
       
   961     QVERIFY(!drr.isActive());
       
   962 
       
   963     QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 1);
       
   964     cm->detailDefinition(removeIds.first()); // check that it has already been removed.
       
   965     QCOMPARE(cm->error(), QContactManager::DoesNotExistError);
       
   966 
       
   967     // remove (asynchronously) a nonexistent group - should fail.
       
   968     drr.setNames(removeIds);
       
   969     QVERIFY(!drr.cancel()); // not started
       
   970     QVERIFY(drr.start());
       
   971     QVERIFY(drr.isActive());
       
   972     QVERIFY(drr.status() == QContactAbstractRequest::Active);
       
   973     QVERIFY(!drr.isFinished());
       
   974     QVERIFY(!drr.start());  // already started.
       
   975     QVERIFY(drr.waitForFinished());
       
   976     expectedCount += 2;
       
   977     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   978     QVERIFY(drr.isFinished());
       
   979     QVERIFY(!drr.isActive());
       
   980 
       
   981     QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 1); // hasn't changed
       
   982     QCOMPARE(drr.error(), QContactManager::DoesNotExistError);
       
   983 
       
   984     // remove with list containing one valid and one invalid id.
       
   985     removeIds << cm->detailDefinitions().keys().first();
       
   986     drr.setNames(removeIds);
       
   987     QVERIFY(!drr.cancel()); // not started
       
   988     QVERIFY(drr.start());
       
   989     QVERIFY(drr.isActive());
       
   990     QVERIFY(drr.status() == QContactAbstractRequest::Active);
       
   991     QVERIFY(!drr.isFinished());
       
   992     QVERIFY(!drr.start());  // already started.
       
   993     QVERIFY(drr.waitForFinished());
       
   994     expectedCount += 2;
       
   995     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
   996     QVERIFY(drr.isFinished());
       
   997     QVERIFY(!drr.isActive());
       
   998 
       
   999     QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 2); // only one more has been removed
       
  1000     QCOMPARE(drr.errors().first(), QContactManager::DoesNotExistError);
       
  1001     QCOMPARE(drr.errors().at(1), QContactManager::NoError);
       
  1002 
       
  1003     // remove with empty list - nothing should happen.
       
  1004     removeIds.clear();
       
  1005     drr.setNames(removeIds);
       
  1006     QVERIFY(!drr.cancel()); // not started
       
  1007     QVERIFY(drr.start());
       
  1008     QVERIFY(drr.isActive());
       
  1009     QVERIFY(drr.status() == QContactAbstractRequest::Active);
       
  1010     QVERIFY(!drr.isFinished());
       
  1011     QVERIFY(!drr.start());  // already started.
       
  1012     QVERIFY(drr.waitForFinished());
       
  1013     expectedCount += 2;
       
  1014     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1015     QVERIFY(drr.isFinished());
       
  1016     QVERIFY(!drr.isActive());
       
  1017 
       
  1018     QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 2); // hasn't changed
       
  1019     QCOMPARE(drr.error(), QContactManager::NoError);  // no error but no effect.
       
  1020 
       
  1021     // cancelling
       
  1022     removeIds.clear();
       
  1023     removeIds << cm->detailDefinitions().keys().first();
       
  1024     drr.setNames(removeIds);
       
  1025     QVERIFY(!drr.cancel()); // not started
       
  1026     QVERIFY(drr.start());
       
  1027     QVERIFY(drr.isActive());
       
  1028     QVERIFY(drr.status() == QContactAbstractRequest::Active);
       
  1029     QVERIFY(!drr.isFinished());
       
  1030     QVERIFY(drr.cancel());
       
  1031     QVERIFY(drr.status() == QContactAbstractRequest::Cancelling);
       
  1032     QVERIFY(drr.isActive());    // still cancelling
       
  1033     QVERIFY(!drr.isFinished()); // not finished cancelling
       
  1034     QVERIFY(!drr.start());      // already started.
       
  1035     QVERIFY(drr.waitForFinished());
       
  1036     expectedCount += 3;
       
  1037     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1038     QVERIFY(drr.isFinished());
       
  1039     QVERIFY(!drr.isActive());
       
  1040     QVERIFY(drr.status() == QContactAbstractRequest::Cancelled);
       
  1041 
       
  1042     QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 2); // hasn't changed
       
  1043 
       
  1044     // restart, and wait for progress after cancel.
       
  1045     QVERIFY(!drr.cancel()); // not started
       
  1046     QVERIFY(drr.start());
       
  1047     QVERIFY(drr.isActive());
       
  1048     QVERIFY(drr.status() == QContactAbstractRequest::Active);
       
  1049     QVERIFY(!drr.isFinished());
       
  1050     QVERIFY(drr.cancel());
       
  1051     QVERIFY(drr.status() == QContactAbstractRequest::Cancelling);
       
  1052     QVERIFY(drr.isActive());    // still cancelling
       
  1053     QVERIFY(!drr.isFinished()); // not finished cancelling
       
  1054     QVERIFY(!drr.start());      // already started.
       
  1055     QVERIFY(drr.waitForProgress());
       
  1056     expectedCount += 3;
       
  1057     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1058     QVERIFY(drr.isFinished());
       
  1059     QVERIFY(!drr.isActive());
       
  1060     QVERIFY(drr.status() == QContactAbstractRequest::Cancelled);
       
  1061 
       
  1062     QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 2); // hasn't changed
       
  1063 
       
  1064     delete cm;
       
  1065 }
       
  1066 
       
  1067 void tst_QContactAsync::definitionSave()
       
  1068 {
       
  1069     QFETCH(QString, uri);
       
  1070     QContactManager* cm(0);
       
  1071     QVERIFY(prepareModel(uri, cm));
       
  1072     
       
  1073     if (!cm->hasFeature(QContactManager::MutableDefinitions, QContactType::TypeContact)) {
       
  1074        QSKIP("This contact manager doest not support mutable definitions, can't save a definition!", SkipSingle);
       
  1075     }
       
  1076     
       
  1077     QContactDetailDefinitionSaveRequest dsr;
       
  1078     QVERIFY(dsr.type() == QContactAbstractRequest::DetailDefinitionSaveRequest);
       
  1079     dsr.setContactType(QContactType::TypeContact);
       
  1080     QVERIFY(dsr.contactType() == QString(QLatin1String(QContactType::TypeContact)));
       
  1081 
       
  1082     // initial state - not started, no manager.
       
  1083     QVERIFY(!dsr.isActive());
       
  1084     QVERIFY(!dsr.isFinished());
       
  1085     QVERIFY(!dsr.start());
       
  1086     QVERIFY(!dsr.cancel());
       
  1087     QVERIFY(!dsr.waitForFinished());
       
  1088     QVERIFY(!dsr.waitForProgress());
       
  1089 
       
  1090     // save a new detail definition
       
  1091     int originalCount = cm->detailDefinitions().keys().size();
       
  1092     QContactDetailDefinition testDef;
       
  1093     testDef.setName("TestDefinitionId");
       
  1094     QMap<QString, QContactDetailDefinitionField> fields;
       
  1095     QContactDetailDefinitionField f;
       
  1096     f.setDataType(QVariant::String);
       
  1097     fields.insert("TestDefinitionField", f);
       
  1098     testDef.setFields(fields);
       
  1099     QList<QContactDetailDefinition> saveList;
       
  1100     saveList << testDef;
       
  1101     dsr.setManager(cm);
       
  1102     QCOMPARE(dsr.manager(), cm);
       
  1103     QVERIFY(!dsr.isActive());
       
  1104     QVERIFY(!dsr.isFinished());
       
  1105     QVERIFY(!dsr.cancel());
       
  1106     QVERIFY(!dsr.waitForFinished());
       
  1107     QVERIFY(!dsr.waitForProgress());
       
  1108     qRegisterMetaType<QContactDetailDefinitionSaveRequest*>("QContactDetailDefinitionSaveRequest*");
       
  1109     QSignalSpy spy(&dsr, SIGNAL(progress(QContactDetailDefinitionSaveRequest*)));
       
  1110     dsr.setDefinitions(saveList);
       
  1111     QCOMPARE(dsr.definitions(), saveList);
       
  1112     QVERIFY(!dsr.cancel()); // not started
       
  1113     QVERIFY(dsr.start());
       
  1114     QVERIFY(dsr.isActive());
       
  1115     QVERIFY(dsr.status() == QContactAbstractRequest::Active);
       
  1116     QVERIFY(!dsr.isFinished());
       
  1117     QVERIFY(!dsr.start());  // already started.
       
  1118     QVERIFY(dsr.waitForFinished());
       
  1119     int expectedCount = 2;
       
  1120     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1121     QVERIFY(dsr.isFinished());
       
  1122     QVERIFY(!dsr.isActive());
       
  1123 
       
  1124     QList<QContactDetailDefinition> expected;
       
  1125     expected << cm->detailDefinition("TestDefinitionId");
       
  1126     QList<QContactDetailDefinition> result = dsr.definitions();
       
  1127     QCOMPARE(expected, result);
       
  1128     QVERIFY(expected.contains(testDef));
       
  1129     QCOMPARE(cm->detailDefinitions().values().size(), originalCount + 1);
       
  1130 
       
  1131     // update a previously saved group
       
  1132     fields.insert("TestDefinitionFieldTwo", f);
       
  1133     testDef.setFields(fields);
       
  1134     saveList.clear();
       
  1135     saveList << testDef;
       
  1136     dsr.setDefinitions(saveList);
       
  1137     QCOMPARE(dsr.definitions(), saveList);
       
  1138     QVERIFY(!dsr.cancel()); // not started
       
  1139     QVERIFY(dsr.start());
       
  1140     QVERIFY(dsr.isActive());
       
  1141     QVERIFY(dsr.status() == QContactAbstractRequest::Active);
       
  1142     QVERIFY(!dsr.isFinished());
       
  1143     QVERIFY(!dsr.start());  // already started.
       
  1144     QVERIFY(dsr.waitForFinished());
       
  1145     expectedCount += 2;
       
  1146     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1147     QVERIFY(dsr.isFinished());
       
  1148     QVERIFY(!dsr.isActive());
       
  1149 
       
  1150     expected.clear();
       
  1151     expected << cm->detailDefinition("TestDefinitionId");
       
  1152     result = dsr.definitions();
       
  1153     QCOMPARE(expected, result);
       
  1154     QVERIFY(expected.contains(testDef));
       
  1155     QCOMPARE(cm->detailDefinitions().values().size(), originalCount + 1);
       
  1156 
       
  1157     // cancelling
       
  1158     fields.insert("TestDefinitionFieldThree - shouldn't get saved", f);
       
  1159     testDef.setFields(fields);
       
  1160     saveList.clear();
       
  1161     saveList << testDef;
       
  1162     dsr.setDefinitions(saveList);
       
  1163     QCOMPARE(dsr.definitions(), saveList);
       
  1164     QVERIFY(!dsr.cancel()); // not started
       
  1165     QVERIFY(dsr.start());
       
  1166     QVERIFY(dsr.isActive());
       
  1167     QVERIFY(dsr.status() == QContactAbstractRequest::Active);
       
  1168     QVERIFY(!dsr.isFinished());
       
  1169     QVERIFY(dsr.cancel());
       
  1170     QVERIFY(dsr.status() == QContactAbstractRequest::Cancelling);
       
  1171     QVERIFY(dsr.isActive());    // still cancelling
       
  1172     QVERIFY(!dsr.isFinished()); // not finished cancelling
       
  1173     QVERIFY(!dsr.start());      // already started.
       
  1174     QVERIFY(dsr.waitForFinished());
       
  1175     expectedCount += 3;
       
  1176     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1177     QVERIFY(dsr.isFinished());
       
  1178     QVERIFY(!dsr.isActive());
       
  1179     QVERIFY(dsr.status() == QContactAbstractRequest::Cancelled);
       
  1180 
       
  1181     // verify that the changes were not saved
       
  1182     QList<QContactDetailDefinition> allDefs = cm->detailDefinitions().values();
       
  1183     QVERIFY(!allDefs.contains(testDef));
       
  1184     QCOMPARE(cm->detailDefinitions().values().size(), originalCount + 1);
       
  1185 
       
  1186     // restart, and wait for progress after cancel.
       
  1187     QVERIFY(!dsr.cancel()); // not started
       
  1188     QVERIFY(dsr.start());
       
  1189     QVERIFY(dsr.isActive());
       
  1190     QVERIFY(dsr.status() == QContactAbstractRequest::Active);
       
  1191     QVERIFY(!dsr.isFinished());
       
  1192     QVERIFY(dsr.cancel());
       
  1193     QVERIFY(dsr.status() == QContactAbstractRequest::Cancelling);
       
  1194     QVERIFY(dsr.isActive());    // still cancelling
       
  1195     QVERIFY(!dsr.isFinished()); // not finished cancelling
       
  1196     QVERIFY(!dsr.start());      // already started.
       
  1197     QVERIFY(dsr.waitForProgress());
       
  1198     expectedCount += 3;
       
  1199     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1200     QVERIFY(dsr.isFinished());
       
  1201     QVERIFY(!dsr.isActive());
       
  1202     QVERIFY(dsr.status() == QContactAbstractRequest::Cancelled);
       
  1203 
       
  1204     // verify that the changes were not saved
       
  1205     allDefs = cm->detailDefinitions().values();
       
  1206     QVERIFY(!allDefs.contains(testDef));
       
  1207     QCOMPARE(cm->detailDefinitions().values().size(), originalCount + 1);
       
  1208 
       
  1209     delete cm;
       
  1210 }
       
  1211 
       
  1212 void tst_QContactAsync::relationshipFetch()
       
  1213 {
       
  1214     QFETCH(QString, uri);
       
  1215     QContactManager* cm(0);
       
  1216     QList<QContact> contacts;
       
  1217     QList<QContactRelationship> relationships;
       
  1218     QVERIFY(prepareModel(uri, cm, contacts, relationships));
       
  1219     QContactRelationshipFetchRequest rfr;
       
  1220     QVERIFY(rfr.type() == QContactAbstractRequest::RelationshipFetchRequest);
       
  1221     
       
  1222     // initial state - not started, no manager.
       
  1223     QVERIFY(!rfr.isActive());
       
  1224     QVERIFY(!rfr.isFinished());
       
  1225     QVERIFY(!rfr.start());
       
  1226     QVERIFY(!rfr.cancel());
       
  1227     QVERIFY(!rfr.waitForFinished());
       
  1228     QVERIFY(!rfr.waitForProgress());    
       
  1229     
       
  1230     if (!cm->hasFeature(QContactManager::Relationships))
       
  1231     {
       
  1232         // ensure manager returs errors
       
  1233         rfr.setManager(cm);
       
  1234         QCOMPARE(rfr.manager(), cm);
       
  1235         QVERIFY(!rfr.isActive());
       
  1236         QVERIFY(!rfr.isFinished());
       
  1237         QVERIFY(!rfr.cancel());
       
  1238         QVERIFY(!rfr.waitForFinished());
       
  1239         QVERIFY(!rfr.waitForProgress());
       
  1240         QVERIFY(!rfr.cancel()); // not started
       
  1241         QVERIFY(rfr.start());
       
  1242         QVERIFY(rfr.isActive());
       
  1243         QVERIFY(rfr.status() == QContactAbstractRequest::Active);
       
  1244         QVERIFY(!rfr.isFinished());
       
  1245         QVERIFY(!rfr.start());  // already started.
       
  1246         QVERIFY(rfr.waitForFinished());
       
  1247         QVERIFY(rfr.error() == QContactManager::NotSupportedError);
       
  1248         QVERIFY(rfr.isFinished());
       
  1249         QVERIFY(!rfr.isActive());
       
  1250         return;
       
  1251     }
       
  1252     
       
  1253     // use variables to make code more readable
       
  1254     QContactId aId = contacts.at(0).id();
       
  1255     QContactId bId = contacts.at(1).id();
       
  1256     QContactId cId = contacts.at(2).id();
       
  1257     QContactId dId = contacts.at(3).id();
       
  1258     QContactId eId = contacts.at(4).id();
       
  1259     QContactId fId = contacts.at(5).id();    
       
  1260     QContactRelationship adRel = relationships.at(0);
       
  1261     QContactRelationship aeRel = relationships.at(1);
       
  1262     QContactRelationship beRel = relationships.at(2);
       
  1263     QContactRelationship ceRel = relationships.at(3);
       
  1264     QContactRelationship cfRel = relationships.at(4);
       
  1265     QString relType = adRel.relationshipType();
       
  1266 
       
  1267     // "all relationships" retrieval
       
  1268     rfr.setManager(cm);
       
  1269     QCOMPARE(rfr.manager(), cm);
       
  1270     QVERIFY(!rfr.isActive());
       
  1271     QVERIFY(!rfr.isFinished());
       
  1272     QVERIFY(!rfr.cancel());
       
  1273     QVERIFY(!rfr.waitForFinished());
       
  1274     QVERIFY(!rfr.waitForProgress());
       
  1275     qRegisterMetaType<QContactRelationshipFetchRequest*>("QContactRelationshipFetchRequest*");
       
  1276     QSignalSpy spy(&rfr, SIGNAL(progress(QContactRelationshipFetchRequest*, bool)));
       
  1277     QVERIFY(!rfr.cancel()); // not started
       
  1278     QVERIFY(rfr.start());
       
  1279     QVERIFY(rfr.isActive());
       
  1280     QVERIFY(rfr.status() == QContactAbstractRequest::Active);
       
  1281     QVERIFY(!rfr.isFinished());
       
  1282     QVERIFY(!rfr.start());  // already started.
       
  1283     QVERIFY(rfr.waitForFinished());
       
  1284     QVERIFY(rfr.error() == QContactManager::NoError);
       
  1285     int expectedCount = 2;
       
  1286     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1287     QVERIFY(rfr.isFinished());
       
  1288     QVERIFY(!rfr.isActive());
       
  1289     QList<QContactRelationship> rels = cm->relationships();
       
  1290     QList<QContactRelationship> result = rfr.relationships();
       
  1291     QCOMPARE(rels, result);
       
  1292     
       
  1293     // specific relationship type retrieval
       
  1294     rfr.setRelationshipType(relType);
       
  1295     QVERIFY(!rfr.cancel()); // not started
       
  1296     QVERIFY(rfr.start());
       
  1297     QVERIFY(rfr.isActive());
       
  1298     QVERIFY(rfr.status() == QContactAbstractRequest::Active);
       
  1299     QVERIFY(!rfr.isFinished());
       
  1300     QVERIFY(!rfr.start());  // already started.
       
  1301     QVERIFY(rfr.waitForFinished());
       
  1302     QVERIFY(rfr.error() == QContactManager::NoError);
       
  1303     expectedCount += 2;
       
  1304     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1305     QVERIFY(rfr.isFinished());
       
  1306     QVERIFY(!rfr.isActive());
       
  1307     rels = cm->relationships(relType);
       
  1308     result = rfr.relationships();
       
  1309     QCOMPARE(rels, result);
       
  1310 
       
  1311     // specific source contact retrieval
       
  1312     rfr.setFirst(aId);
       
  1313     rfr.setRelationshipType(QString());
       
  1314     QVERIFY(!rfr.cancel()); // not started
       
  1315     QVERIFY(rfr.start());
       
  1316     QVERIFY(rfr.isActive());
       
  1317     QVERIFY(rfr.status() == QContactAbstractRequest::Active);
       
  1318     QVERIFY(!rfr.isFinished());
       
  1319     QVERIFY(!rfr.start());  // already started.
       
  1320     QVERIFY(rfr.waitForFinished());
       
  1321     QVERIFY(rfr.error() == QContactManager::NoError);
       
  1322     expectedCount += 2;
       
  1323     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1324     QVERIFY(rfr.isFinished());
       
  1325     QVERIFY(!rfr.isActive());
       
  1326     rels = cm->relationships(aId, QContactRelationshipFilter::First);
       
  1327     result = rfr.relationships();
       
  1328     QCOMPARE(rels, result);
       
  1329 
       
  1330     // specific participant retrieval #1 - destination participant
       
  1331     rfr.setFirst(QContactId());
       
  1332     rfr.setParticipant(eId, QContactRelationshipFilter::Second);
       
  1333     QVERIFY(rfr.participantRole() == QContactRelationshipFilter::Second);
       
  1334     QVERIFY(!rfr.cancel()); // not started
       
  1335     QVERIFY(rfr.start());
       
  1336     QVERIFY(rfr.isActive());
       
  1337     QVERIFY(rfr.status() == QContactAbstractRequest::Active);
       
  1338     QVERIFY(!rfr.isFinished());
       
  1339     QVERIFY(!rfr.start());  // already started.
       
  1340     QVERIFY(rfr.waitForFinished());
       
  1341     QVERIFY(rfr.error() == QContactManager::NoError);
       
  1342     expectedCount += 2;
       
  1343     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1344     QVERIFY(rfr.isFinished());
       
  1345     QVERIFY(!rfr.isActive());
       
  1346     rels = cm->relationships(eId, QContactRelationshipFilter::Second);
       
  1347     result = rfr.relationships();
       
  1348     QCOMPARE(rels, result);
       
  1349 
       
  1350     // specific participant retrieval #2 - source participant
       
  1351     rfr.setFirst(QContactId());
       
  1352     rfr.setParticipant(cId, QContactRelationshipFilter::First);
       
  1353     QVERIFY(rfr.participantRole() == QContactRelationshipFilter::First);
       
  1354     QVERIFY(!rfr.cancel()); // not started
       
  1355     QVERIFY(rfr.start());
       
  1356     QVERIFY(rfr.isActive());
       
  1357     QVERIFY(rfr.status() == QContactAbstractRequest::Active);
       
  1358     QVERIFY(!rfr.isFinished());
       
  1359     QVERIFY(!rfr.start());  // already started.
       
  1360     QVERIFY(rfr.waitForFinished());
       
  1361     QVERIFY(rfr.error() == QContactManager::NoError);
       
  1362     expectedCount += 2;
       
  1363     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1364     QVERIFY(rfr.isFinished());
       
  1365     QVERIFY(!rfr.isActive());
       
  1366     rels = cm->relationships(cId, QContactRelationshipFilter::First);
       
  1367     result = rfr.relationships();
       
  1368     QCOMPARE(rels, result);
       
  1369     
       
  1370     if (relationships.count() > 4)
       
  1371     {
       
  1372         // specific participant retrieval #3 - either participant
       
  1373         rfr.setFirst(QContactId());
       
  1374         rfr.setParticipant(aId, QContactRelationshipFilter::Either);
       
  1375         QVERIFY(rfr.participantRole() == QContactRelationshipFilter::Either);
       
  1376         QVERIFY(!rfr.cancel()); // not started
       
  1377         QVERIFY(rfr.start());
       
  1378         QVERIFY(rfr.isActive());
       
  1379         QVERIFY(rfr.status() == QContactAbstractRequest::Active);
       
  1380         QVERIFY(!rfr.isFinished());
       
  1381         QVERIFY(!rfr.start());  // already started.
       
  1382         QVERIFY(rfr.waitForFinished());
       
  1383         QVERIFY(rfr.error() == QContactManager::NoError);
       
  1384         expectedCount += 2;
       
  1385         QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1386         QVERIFY(rfr.isFinished());
       
  1387         QVERIFY(!rfr.isActive());
       
  1388         rels = cm->relationships(aId); // either role.
       
  1389         result = rfr.relationships();
       
  1390         QCOMPARE(rels, result);
       
  1391     }    
       
  1392 
       
  1393     // cancelling
       
  1394     rfr.setRelationshipType(QString());
       
  1395     QVERIFY(!rfr.cancel()); // not started
       
  1396     QVERIFY(rfr.start());
       
  1397     QVERIFY(rfr.isActive());
       
  1398     QVERIFY(rfr.status() == QContactAbstractRequest::Active);
       
  1399     QVERIFY(!rfr.isFinished());
       
  1400     QVERIFY(rfr.cancel());
       
  1401     QVERIFY(rfr.status() == QContactAbstractRequest::Cancelling);
       
  1402     QVERIFY(rfr.isActive());    // still cancelling
       
  1403     QVERIFY(!rfr.isFinished()); // not finished cancelling
       
  1404     QVERIFY(!rfr.start());      // already started.
       
  1405     QVERIFY(rfr.waitForFinished());
       
  1406     QVERIFY(rfr.error() == QContactManager::NoError);
       
  1407     expectedCount += 3;
       
  1408     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1409     QVERIFY(rfr.isFinished());
       
  1410     QVERIFY(!rfr.isActive());
       
  1411     QVERIFY(rfr.status() == QContactAbstractRequest::Cancelled);
       
  1412 
       
  1413     // restart, and wait for progress after cancel.
       
  1414     QVERIFY(!rfr.cancel()); // not started
       
  1415     QVERIFY(rfr.start());
       
  1416     QVERIFY(rfr.isActive());
       
  1417     QVERIFY(rfr.status() == QContactAbstractRequest::Active);
       
  1418     QVERIFY(!rfr.isFinished());
       
  1419     QVERIFY(rfr.cancel());
       
  1420     QVERIFY(rfr.status() == QContactAbstractRequest::Cancelling);
       
  1421     QVERIFY(rfr.isActive());    // still cancelling
       
  1422     QVERIFY(!rfr.isFinished()); // not finished cancelling
       
  1423     QVERIFY(!rfr.start());      // already started.
       
  1424     QVERIFY(rfr.waitForProgress());
       
  1425     expectedCount += 3;
       
  1426     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1427     QVERIFY(rfr.isFinished());
       
  1428     QVERIFY(!rfr.isActive());
       
  1429     QVERIFY(rfr.status() == QContactAbstractRequest::Cancelled);
       
  1430     
       
  1431     delete cm;
       
  1432 }
       
  1433 
       
  1434 void tst_QContactAsync::relationshipRemove()
       
  1435 {
       
  1436     QFETCH(QString, uri);
       
  1437     QContactManager* cm(0);
       
  1438     QList<QContact> contacts;
       
  1439     QList<QContactRelationship> relationships;
       
  1440     QVERIFY(prepareModel(uri, cm, contacts, relationships));
       
  1441     QContactRelationshipRemoveRequest rrr;
       
  1442     QVERIFY(rrr.type() == QContactAbstractRequest::RelationshipRemoveRequest);
       
  1443         
       
  1444     if (!cm->hasFeature(QContactManager::Relationships))
       
  1445     {
       
  1446         // ensure manager returns error
       
  1447         rrr.setFirst(contacts.at(0).id());
       
  1448         rrr.setManager(cm);
       
  1449         QCOMPARE(rrr.manager(), cm);
       
  1450         QVERIFY(!rrr.isActive());
       
  1451         QVERIFY(!rrr.isFinished());
       
  1452         QVERIFY(!rrr.cancel());
       
  1453         QVERIFY(!rrr.waitForFinished());
       
  1454         QVERIFY(!rrr.waitForProgress());
       
  1455         QVERIFY(!rrr.cancel()); // not started
       
  1456         QVERIFY(rrr.start());
       
  1457         QVERIFY(rrr.isActive());
       
  1458         QVERIFY(rrr.status() == QContactAbstractRequest::Active);
       
  1459         QVERIFY(!rrr.isFinished());
       
  1460         QVERIFY(!rrr.start());  // already started.
       
  1461         QVERIFY(rrr.waitForFinished());
       
  1462         QVERIFY(rrr.error() == QContactManager::NotSupportedError);
       
  1463         QVERIFY(rrr.isFinished());
       
  1464         QVERIFY(!rrr.isActive());
       
  1465         return;
       
  1466     }
       
  1467 
       
  1468     // use variables to make code more readable
       
  1469     QContactId aId = contacts.at(0).id();
       
  1470     QContactId bId = contacts.at(1).id();
       
  1471     QContactId cId = contacts.at(2).id();
       
  1472     QContactId dId = contacts.at(3).id();
       
  1473     QContactId eId = contacts.at(4).id();
       
  1474     QContactId fId = contacts.at(5).id();    
       
  1475     QContactRelationship adRel = relationships.at(0);
       
  1476     QContactRelationship aeRel = relationships.at(1);
       
  1477     QContactRelationship beRel = relationships.at(2);
       
  1478     QContactRelationship ceRel = relationships.at(3);
       
  1479     QContactRelationship cfRel = relationships.at(4);
       
  1480     QString relType = adRel.relationshipType();
       
  1481     
       
  1482     // initial state - not started, no manager.
       
  1483     QVERIFY(!rrr.isActive());
       
  1484     QVERIFY(!rrr.isFinished());
       
  1485     QVERIFY(!rrr.start());
       
  1486     QVERIFY(!rrr.cancel());
       
  1487     QVERIFY(!rrr.waitForFinished());
       
  1488     QVERIFY(!rrr.waitForProgress());
       
  1489 
       
  1490     // specific source, destination and type removal
       
  1491     int relationshipCount = cm->relationships().count();
       
  1492     rrr.setFirst(adRel.first());
       
  1493     rrr.setSecond(adRel.second());
       
  1494     rrr.setRelationshipType(adRel.relationshipType());
       
  1495     rrr.setManager(cm);
       
  1496     qRegisterMetaType<QContactRelationshipRemoveRequest*>("QContactRelationshipRemoveRequest*");
       
  1497     QSignalSpy spy(&rrr, SIGNAL(progress(QContactRelationshipRemoveRequest*)));
       
  1498     QCOMPARE(rrr.manager(), cm);
       
  1499     QVERIFY(!rrr.isActive());
       
  1500     QVERIFY(!rrr.isFinished());
       
  1501     QVERIFY(!rrr.cancel());
       
  1502     QVERIFY(!rrr.waitForFinished());
       
  1503     QVERIFY(!rrr.waitForProgress());
       
  1504     QVERIFY(rrr.relationshipType() == adRel.relationshipType());
       
  1505     QVERIFY(!rrr.cancel()); // not started
       
  1506     QVERIFY(rrr.start());
       
  1507     QVERIFY(rrr.isActive());
       
  1508     QVERIFY(rrr.status() == QContactAbstractRequest::Active);
       
  1509     QVERIFY(!rrr.isFinished());
       
  1510     QVERIFY(!rrr.start());  // already started.
       
  1511     QVERIFY(rrr.waitForFinished());
       
  1512     QVERIFY(rrr.error() == QContactManager::NoError);
       
  1513     int expectedCount = 2;
       
  1514     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1515     QVERIFY(rrr.isFinished());
       
  1516     QVERIFY(!rrr.isActive());
       
  1517     QCOMPARE(cm->relationships().count(), relationshipCount-1);
       
  1518     
       
  1519     // remove (asynchronously) a nonexistent relationship - should fail.
       
  1520     relationshipCount = cm->relationships().count();
       
  1521     rrr.setFirst(bId);
       
  1522     rrr.setSecond(aId);
       
  1523     rrr.setRelationshipType(relType);
       
  1524     rrr.setManager(cm);
       
  1525     QVERIFY(!rrr.cancel()); // not started
       
  1526     QVERIFY(rrr.start());
       
  1527     QVERIFY(rrr.isActive());
       
  1528     QVERIFY(rrr.status() == QContactAbstractRequest::Active);
       
  1529     QVERIFY(!rrr.isFinished());
       
  1530     QVERIFY(!rrr.start());  // already started.
       
  1531     QVERIFY(rrr.waitForFinished());
       
  1532     QCOMPARE(rrr.error(), QContactManager::DoesNotExistError);
       
  1533     expectedCount += 2;
       
  1534     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1535     QVERIFY(rrr.isFinished());
       
  1536     QVERIFY(!rrr.isActive());
       
  1537     QCOMPARE(cm->relationships().count(), relationshipCount);
       
  1538     
       
  1539     // specific relationship type plus source removal
       
  1540     rrr.setFirst(cId);
       
  1541     rrr.setSecond(QContactId());
       
  1542     rrr.setRelationshipType(relType);
       
  1543     rrr.setManager(cm);
       
  1544     QCOMPARE(rrr.manager(), cm);
       
  1545     QVERIFY(!rrr.isActive());
       
  1546     QVERIFY(!rrr.cancel());
       
  1547     QVERIFY(!rrr.waitForFinished());
       
  1548     QVERIFY(!rrr.waitForProgress());
       
  1549     QVERIFY(rrr.relationshipType() == relType);
       
  1550     QVERIFY(!rrr.cancel()); // not started
       
  1551     QVERIFY(rrr.start());
       
  1552     QVERIFY(rrr.isActive());
       
  1553     QVERIFY(rrr.status() == QContactAbstractRequest::Active);
       
  1554     QVERIFY(!rrr.isFinished());
       
  1555     QVERIFY(!rrr.start());  // already started.
       
  1556     QVERIFY(rrr.waitForFinished());
       
  1557     QVERIFY(rrr.error() == QContactManager::NoError);
       
  1558     expectedCount += 2;
       
  1559     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1560     QVERIFY(rrr.isFinished());
       
  1561     QVERIFY(!rrr.isActive());
       
  1562     QCOMPARE(cm->relationships(relType, cId, QContactRelationshipFilter::First).size(), 0);
       
  1563     QCOMPARE(cm->error(), QContactManager::DoesNotExistError);
       
  1564     
       
  1565     // specific source removal
       
  1566     rrr.setFirst(aId);
       
  1567     rrr.setSecond(QContactId());
       
  1568     rrr.setRelationshipType(QString());
       
  1569     rrr.setManager(cm);
       
  1570     QCOMPARE(rrr.manager(), cm);
       
  1571     QVERIFY(!rrr.isActive());
       
  1572     QVERIFY(!rrr.cancel());
       
  1573     QVERIFY(!rrr.waitForFinished());
       
  1574     QVERIFY(!rrr.waitForProgress());
       
  1575     QVERIFY(rrr.relationshipType() == QString());
       
  1576     QVERIFY(!rrr.cancel()); // not started
       
  1577     QVERIFY(rrr.start());
       
  1578     QVERIFY(rrr.isActive());
       
  1579     QVERIFY(rrr.status() == QContactAbstractRequest::Active);
       
  1580     QVERIFY(!rrr.isFinished());
       
  1581     QVERIFY(!rrr.start());  // already started.
       
  1582     QVERIFY(rrr.waitForFinished());
       
  1583     QVERIFY(rrr.error() == QContactManager::NoError);
       
  1584     expectedCount += 2;
       
  1585     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1586     QVERIFY(rrr.isFinished());
       
  1587     QVERIFY(!rrr.isActive());
       
  1588     QCOMPARE(cm->relationships(aId, QContactRelationshipFilter::First).size(), 0);
       
  1589     QCOMPARE(cm->error(), QContactManager::DoesNotExistError);
       
  1590     
       
  1591     // cancelling
       
  1592     rrr.setFirst(bId);
       
  1593     rrr.setSecond(QContactId());
       
  1594     rrr.setRelationshipType(QString());
       
  1595     QVERIFY(!rrr.cancel()); // not started
       
  1596     QVERIFY(rrr.start());
       
  1597     QVERIFY(rrr.isActive());
       
  1598     QVERIFY(rrr.status() == QContactAbstractRequest::Active);
       
  1599     QVERIFY(!rrr.isFinished());
       
  1600     QVERIFY(rrr.cancel());
       
  1601     QVERIFY(rrr.status() == QContactAbstractRequest::Cancelling);
       
  1602     QVERIFY(rrr.isActive());    // still cancelling
       
  1603     QVERIFY(!rrr.isFinished()); // not finished cancelling
       
  1604     QVERIFY(!rrr.start());      // already started.
       
  1605     QVERIFY(rrr.waitForFinished());
       
  1606     QVERIFY(rrr.error() == QContactManager::NoError);
       
  1607     expectedCount += 3;
       
  1608     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1609     QVERIFY(rrr.isFinished());
       
  1610     QVERIFY(!rrr.isActive());
       
  1611     QVERIFY(rrr.status() == QContactAbstractRequest::Cancelled);
       
  1612     QVERIFY(cm->relationships(bId).size() != 0); // didn't remove them.
       
  1613     
       
  1614     // restart, and wait for progress after cancel.
       
  1615     QVERIFY(!rrr.cancel()); // not started
       
  1616     QVERIFY(rrr.start());
       
  1617     QVERIFY(rrr.isActive());
       
  1618     QVERIFY(rrr.status() == QContactAbstractRequest::Active);
       
  1619     QVERIFY(!rrr.isFinished());
       
  1620     QVERIFY(rrr.cancel());
       
  1621     QVERIFY(rrr.status() == QContactAbstractRequest::Cancelling);
       
  1622     QVERIFY(rrr.isActive());    // still cancelling
       
  1623     QVERIFY(!rrr.isFinished()); // not finished cancelling
       
  1624     QVERIFY(!rrr.start());      // already started.
       
  1625     QVERIFY(rrr.waitForProgress());
       
  1626     expectedCount += 3;
       
  1627     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1628     QVERIFY(rrr.isFinished());
       
  1629     QVERIFY(!rrr.isActive());
       
  1630     QVERIFY(rrr.status() == QContactAbstractRequest::Cancelled);
       
  1631     QVERIFY(cm->relationships(bId).size() != 0); // didn't remove them.
       
  1632     
       
  1633     // specific relationship type removal
       
  1634     rrr.setFirst(QContactId());
       
  1635     rrr.setSecond(QContactId());
       
  1636     rrr.setRelationshipType(relType);
       
  1637     rrr.setManager(cm);
       
  1638     QCOMPARE(rrr.manager(), cm);
       
  1639     QVERIFY(!rrr.isActive());
       
  1640     QVERIFY(!rrr.cancel());
       
  1641     QVERIFY(!rrr.waitForFinished());
       
  1642     QVERIFY(!rrr.waitForProgress());
       
  1643     QVERIFY(rrr.relationshipType() == relType);
       
  1644     QVERIFY(!rrr.cancel()); // not started
       
  1645     QVERIFY(rrr.start());
       
  1646     QVERIFY(rrr.isActive());
       
  1647     QVERIFY(rrr.status() == QContactAbstractRequest::Active);
       
  1648     QVERIFY(!rrr.isFinished());
       
  1649     QVERIFY(!rrr.start());  // already started.
       
  1650     QVERIFY(rrr.waitForFinished());
       
  1651     QVERIFY(rrr.error() == QContactManager::NoError);
       
  1652     expectedCount += 2;
       
  1653     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1654     QVERIFY(rrr.isFinished());
       
  1655     QVERIFY(!rrr.isActive());
       
  1656     
       
  1657     QCOMPARE(cm->relationships(relType).size(), 0);
       
  1658     cm->relationships(relType); // check that it has already been removed.
       
  1659     QCOMPARE(cm->error(), QContactManager::DoesNotExistError);
       
  1660 
       
  1661     delete cm;
       
  1662 }
       
  1663 
       
  1664 void tst_QContactAsync::relationshipSave()
       
  1665 {
       
  1666     QFETCH(QString, uri);
       
  1667     QContactManager* cm(0);
       
  1668     QList<QContact> contacts;
       
  1669     QList<QContactRelationship> relationships;
       
  1670     QVERIFY(prepareModel(uri, cm, contacts, relationships));
       
  1671     QContactRelationshipSaveRequest rsr;
       
  1672     QVERIFY(rsr.type() == QContactAbstractRequest::RelationshipSaveRequest);
       
  1673     
       
  1674     if (!cm->hasFeature(QContactManager::Relationships))
       
  1675     {
       
  1676         // ensure saving returns errors
       
  1677         QContactRelationship rel;
       
  1678         rel.setFirst(contacts.at(0).id());
       
  1679         rel.setSecond(contacts.at(1).id());
       
  1680         rel.setRelationshipType(QContactRelationship::HasManager);
       
  1681         QList<QContactRelationship> list;
       
  1682         list << rel;
       
  1683         rsr.setManager(cm);
       
  1684         QCOMPARE(rsr.manager(), cm);
       
  1685         QVERIFY(!rsr.isActive());
       
  1686         QVERIFY(!rsr.isFinished());
       
  1687         QVERIFY(!rsr.cancel());
       
  1688         QVERIFY(!rsr.waitForFinished());
       
  1689         QVERIFY(!rsr.waitForProgress());
       
  1690         rsr.setRelationships(list);
       
  1691         QCOMPARE(rsr.relationships(), list);
       
  1692         QVERIFY(!rsr.cancel()); // not started
       
  1693         QVERIFY(rsr.start());
       
  1694         QVERIFY(rsr.isActive());
       
  1695         QVERIFY(rsr.status() == QContactAbstractRequest::Active);
       
  1696         QVERIFY(!rsr.isFinished());
       
  1697         QVERIFY(!rsr.start());  // already started.
       
  1698         QVERIFY(rsr.waitForFinished());
       
  1699         QVERIFY(rsr.error() == QContactManager::NotSupportedError);
       
  1700         QVERIFY(rsr.isFinished());
       
  1701         QVERIFY(!rsr.isActive());
       
  1702         return;
       
  1703     }
       
  1704     
       
  1705     // use variables to make code more readable
       
  1706     QContactId aId = contacts.at(0).id();
       
  1707     QContactId bId = contacts.at(1).id();
       
  1708     QContactId cId = contacts.at(2).id();
       
  1709     QContactId dId = contacts.at(3).id();
       
  1710     QContactId eId = contacts.at(4).id();
       
  1711     QContactId fId = contacts.at(5).id();    
       
  1712     QContactRelationship adRel = relationships.at(0);
       
  1713     QContactRelationship aeRel = relationships.at(1);
       
  1714     QContactRelationship beRel = relationships.at(2);
       
  1715     QContactRelationship ceRel = relationships.at(3);
       
  1716     QContactRelationship cfRel = relationships.at(4);
       
  1717     QString relType = adRel.relationshipType();
       
  1718 
       
  1719     // initial state - not started, no manager.
       
  1720     QVERIFY(!rsr.isActive());
       
  1721     QVERIFY(!rsr.isFinished());
       
  1722     QVERIFY(!rsr.start());
       
  1723     QVERIFY(!rsr.cancel());
       
  1724     QVERIFY(!rsr.waitForFinished());
       
  1725     QVERIFY(!rsr.waitForProgress());
       
  1726 
       
  1727     // save a new relationship
       
  1728     int originalCount = cm->relationships(bId).size();
       
  1729     QContactRelationship testRel;
       
  1730     testRel.setFirst(bId);
       
  1731     testRel.setSecond(dId);
       
  1732     testRel.setRelationshipType(relType);
       
  1733     QList<QContactRelationship> saveList;
       
  1734     saveList << testRel;
       
  1735     rsr.setManager(cm);
       
  1736     QCOMPARE(rsr.manager(), cm);
       
  1737     QVERIFY(!rsr.isActive());
       
  1738     QVERIFY(!rsr.isFinished());
       
  1739     QVERIFY(!rsr.cancel());
       
  1740     QVERIFY(!rsr.waitForFinished());
       
  1741     QVERIFY(!rsr.waitForProgress());
       
  1742     qRegisterMetaType<QContactRelationshipSaveRequest*>("QContactRelationshipSaveRequest*");
       
  1743     QSignalSpy spy(&rsr, SIGNAL(progress(QContactRelationshipSaveRequest*)));
       
  1744     rsr.setRelationships(saveList);
       
  1745     QCOMPARE(rsr.relationships(), saveList);
       
  1746     QVERIFY(!rsr.cancel()); // not started
       
  1747     QVERIFY(rsr.start());
       
  1748     QVERIFY(rsr.isActive());
       
  1749     QVERIFY(rsr.status() == QContactAbstractRequest::Active);
       
  1750     QVERIFY(!rsr.isFinished());
       
  1751     QVERIFY(!rsr.start());  // already started.
       
  1752     QVERIFY(rsr.waitForFinished());
       
  1753     int expectedCount = 2;
       
  1754     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1755     QVERIFY(rsr.isFinished());
       
  1756     QVERIFY(!rsr.isActive());
       
  1757     QList<QContactRelationship> result = rsr.relationships();
       
  1758     QVERIFY(result.contains(testRel));
       
  1759     QList<QContactRelationship> bRelationships = cm->relationships(relType, bId, QContactRelationshipFilter::First);
       
  1760     QVERIFY(bRelationships.contains(testRel));
       
  1761     QCOMPARE(cm->relationships(bId).size(), originalCount + 1); // should be one extra
       
  1762 
       
  1763     // save a new relationship
       
  1764     testRel.setSecond(fId);
       
  1765     saveList.clear();
       
  1766     saveList << testRel;
       
  1767     rsr.setRelationships(saveList);
       
  1768     QCOMPARE(rsr.relationships(), saveList);
       
  1769     QVERIFY(!rsr.cancel()); // not started
       
  1770     QVERIFY(rsr.start());
       
  1771     QVERIFY(rsr.isActive());
       
  1772     QVERIFY(rsr.status() == QContactAbstractRequest::Active);
       
  1773     QVERIFY(!rsr.isFinished());
       
  1774     QVERIFY(!rsr.start());  // already started.
       
  1775     QVERIFY(rsr.waitForFinished());
       
  1776     expectedCount += 2;
       
  1777     QCOMPARE(spy.count(), expectedCount); // active + finished progress signals.
       
  1778     QVERIFY(rsr.isFinished());
       
  1779     QVERIFY(!rsr.isActive());
       
  1780     bRelationships.clear();
       
  1781     bRelationships = cm->relationships(relType, bId, QContactRelationshipFilter::First);
       
  1782     result = rsr.relationships();
       
  1783     QCOMPARE(result, QList<QContactRelationship>() << testRel);
       
  1784     QVERIFY(bRelationships.contains(testRel));
       
  1785     QCOMPARE(cm->relationships(bId).size(), originalCount + 2); // should now be two extra
       
  1786 
       
  1787     // cancelling
       
  1788     testRel.setSecond(bId); // shouldn't get saved (circular anyway)
       
  1789     saveList.clear();
       
  1790     saveList << testRel;
       
  1791     rsr.setRelationships(saveList);
       
  1792     QCOMPARE(rsr.relationships(), saveList);
       
  1793     QVERIFY(!rsr.cancel()); // not started
       
  1794     QVERIFY(rsr.start());
       
  1795     QVERIFY(rsr.isActive());
       
  1796     QVERIFY(rsr.status() == QContactAbstractRequest::Active);
       
  1797     QVERIFY(!rsr.isFinished());
       
  1798     QVERIFY(rsr.cancel());
       
  1799     QVERIFY(rsr.status() == QContactAbstractRequest::Cancelling);
       
  1800     QVERIFY(rsr.isActive());    // still cancelling
       
  1801     QVERIFY(!rsr.isFinished()); // not finished cancelling
       
  1802     QVERIFY(!rsr.start());      // already started.
       
  1803     QVERIFY(rsr.waitForFinished());
       
  1804     expectedCount += 3;
       
  1805     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1806     QVERIFY(rsr.isFinished());
       
  1807     QVERIFY(!rsr.isActive());
       
  1808     QVERIFY(rsr.status() == QContactAbstractRequest::Cancelled);
       
  1809 
       
  1810     // verify that the changes were not saved
       
  1811     QList<QContactRelationship> aRels = cm->relationships(bId, QContactRelationshipFilter::First);
       
  1812     QVERIFY(!aRels.contains(testRel));
       
  1813     QCOMPARE(cm->relationships(bId).size(), originalCount + 2); // should still only be two extra
       
  1814 
       
  1815     // restart, and wait for progress after cancel.
       
  1816     QVERIFY(!rsr.cancel()); // not started
       
  1817     QVERIFY(rsr.start());
       
  1818     QVERIFY(rsr.isActive());
       
  1819     QVERIFY(rsr.status() == QContactAbstractRequest::Active);
       
  1820     QVERIFY(!rsr.isFinished());
       
  1821     QVERIFY(rsr.cancel());
       
  1822     QVERIFY(rsr.status() == QContactAbstractRequest::Cancelling);
       
  1823     QVERIFY(rsr.isActive());    // still cancelling
       
  1824     QVERIFY(!rsr.isFinished()); // not finished cancelling
       
  1825     QVERIFY(!rsr.start());      // already started.
       
  1826     QVERIFY(rsr.waitForProgress());
       
  1827     expectedCount += 3;
       
  1828     QCOMPARE(spy.count(), expectedCount); // active + cancelling + cancelled progress signals.
       
  1829     QVERIFY(rsr.isFinished());
       
  1830     QVERIFY(!rsr.isActive());
       
  1831     QVERIFY(rsr.status() == QContactAbstractRequest::Cancelled);
       
  1832 
       
  1833     // verify that the changes were not saved
       
  1834     aRels = cm->relationships(bId);
       
  1835     QVERIFY(!aRels.contains(testRel));
       
  1836     QCOMPARE(cm->relationships(bId).size(), originalCount + 2); // should still only be two extra
       
  1837 
       
  1838     delete cm;
       
  1839 }
       
  1840 
       
  1841 void tst_QContactAsync::maliciousManager()
       
  1842 {
       
  1843     // use the invalid manager: passes all requests through to base class
       
  1844     QContactManager cm("invalid");
       
  1845     QContactFilter fil; // matches everything
       
  1846     QContactFetchRequest cfr;
       
  1847     cfr.setFilter(fil);
       
  1848     cfr.setManager(&cm);
       
  1849     QVERIFY(!cfr.start());
       
  1850     QVERIFY(!cfr.cancel());
       
  1851     QVERIFY(!cfr.waitForFinished());
       
  1852     QVERIFY(!cfr.start());
       
  1853     QVERIFY(!cfr.waitForProgress());
       
  1854 
       
  1855     // ensure that the base class implementation of requestDestroyed() is called
       
  1856     QContactFetchRequest *destroyedRequest = new QContactFetchRequest;
       
  1857     destroyedRequest->setManager(&cm);
       
  1858     destroyedRequest->setFilter(fil);
       
  1859     QVERIFY(!destroyedRequest->start());
       
  1860     delete destroyedRequest;
       
  1861 
       
  1862     // now use a malicious manager that deliberately calls
       
  1863     // incorrect "updateRequest" functions in base class:
       
  1864     QContactManager mcm("maliciousplugin");
       
  1865     QCOMPARE(mcm.managerName(), QString("maliciousplugin"));
       
  1866     QList<QContact> emptyCList;
       
  1867     QList<QContactLocalId> emptyIList;
       
  1868     QList<QContactDetailDefinition> emptyDList;
       
  1869     QStringList emptyDNList;
       
  1870     QMap<QString, QContactDetailDefinition> emptyDMap;
       
  1871     cfr.setFilter(fil);
       
  1872     cfr.setManager(&mcm);
       
  1873     QVERIFY(cfr.start());
       
  1874     QVERIFY(cfr.cancel());
       
  1875     QVERIFY(!cfr.waitForProgress(100));
       
  1876     QVERIFY(!cfr.waitForFinished(100));
       
  1877     QVERIFY(cfr.start());
       
  1878     QVERIFY(!cfr.waitForProgress(100));
       
  1879     QVERIFY(!cfr.waitForFinished(100));
       
  1880     QVERIFY(cfr.cancel());
       
  1881 
       
  1882     QContactLocalIdFetchRequest cifr;
       
  1883     cifr.setFilter(fil);
       
  1884     cifr.setManager(&mcm);
       
  1885     QVERIFY(cifr.start());
       
  1886     QVERIFY(cifr.cancel());
       
  1887     QVERIFY(!cifr.waitForProgress(100));
       
  1888     QVERIFY(!cifr.waitForFinished(100));
       
  1889     QVERIFY(cifr.start());
       
  1890     QVERIFY(!cifr.waitForProgress(100));
       
  1891     QVERIFY(!cifr.waitForFinished(100));
       
  1892     QVERIFY(cifr.cancel());
       
  1893 
       
  1894     QContactRemoveRequest crr;
       
  1895     crr.setFilter(fil);
       
  1896     crr.setManager(&mcm);
       
  1897     QVERIFY(crr.start());
       
  1898     QVERIFY(crr.cancel());
       
  1899     QVERIFY(!crr.waitForProgress(100));
       
  1900     QVERIFY(!crr.waitForFinished(100));
       
  1901     QVERIFY(crr.start());
       
  1902     QVERIFY(!crr.waitForProgress(100));
       
  1903     QVERIFY(!crr.waitForFinished(100));
       
  1904     QVERIFY(crr.cancel());
       
  1905 
       
  1906     QContactSaveRequest csr;
       
  1907     csr.setContacts(emptyCList);
       
  1908     csr.setManager(&mcm);
       
  1909     QVERIFY(csr.start());
       
  1910     QVERIFY(csr.cancel());
       
  1911     QVERIFY(!csr.waitForProgress(100));
       
  1912     QVERIFY(!csr.waitForFinished(100));
       
  1913     QVERIFY(csr.start());
       
  1914     QVERIFY(!csr.waitForProgress(100));
       
  1915     QVERIFY(!csr.waitForFinished(100));
       
  1916     QVERIFY(csr.cancel());
       
  1917 
       
  1918     QContactDetailDefinitionFetchRequest dfr;
       
  1919     dfr.setNames(emptyDNList);
       
  1920     dfr.setManager(&mcm);
       
  1921     QVERIFY(dfr.start());
       
  1922     QVERIFY(dfr.cancel());
       
  1923     QVERIFY(!dfr.waitForProgress(100));
       
  1924     QVERIFY(!dfr.waitForFinished(100));
       
  1925     QVERIFY(dfr.start());
       
  1926     QVERIFY(!dfr.waitForProgress(100));
       
  1927     QVERIFY(!dfr.waitForFinished(100));
       
  1928     QVERIFY(dfr.cancel());
       
  1929 
       
  1930     QContactDetailDefinitionSaveRequest dsr;
       
  1931     dsr.setDefinitions(emptyDList);
       
  1932     dsr.setManager(&mcm);
       
  1933     QVERIFY(dsr.start());
       
  1934     QVERIFY(dsr.cancel());
       
  1935     QVERIFY(!dsr.waitForProgress(100));
       
  1936     QVERIFY(!dsr.waitForFinished(100));
       
  1937     QVERIFY(dsr.start());
       
  1938     QVERIFY(!dsr.waitForProgress(100));
       
  1939     QVERIFY(!dsr.waitForFinished(100));
       
  1940     QVERIFY(dsr.cancel());
       
  1941 
       
  1942     QContactDetailDefinitionRemoveRequest drr;
       
  1943     drr.setNames(emptyDNList);
       
  1944     drr.setManager(&mcm);
       
  1945     QVERIFY(drr.start());
       
  1946     QVERIFY(drr.cancel());
       
  1947     QVERIFY(!drr.waitForProgress(100));
       
  1948     QVERIFY(!drr.waitForFinished(100));
       
  1949     QVERIFY(drr.start());
       
  1950     QVERIFY(!drr.waitForProgress(100));
       
  1951     QVERIFY(!drr.waitForFinished(100));
       
  1952     QVERIFY(drr.cancel());
       
  1953 }
       
  1954 
       
  1955 void tst_QContactAsync::threadDelivery()
       
  1956 {
       
  1957     QFETCH(QString, uri);
       
  1958     QContactManager *cm(0);
       
  1959     QVERIFY(prepareModel(uri, cm));
       
  1960     m_mainThreadId = cm->thread()->currentThreadId();
       
  1961     m_progressSlotThreadId = m_mainThreadId;
       
  1962 
       
  1963     // now perform a fetch request and check that the progress is delivered to the correct thread.
       
  1964     QContactFetchRequest *req = new QContactFetchRequest;
       
  1965     req->setManager(cm);
       
  1966     connect(req, SIGNAL(progress(QContactFetchRequest*,bool)), this, SLOT(progressReceived(QContactFetchRequest*, bool)));
       
  1967     req->start();
       
  1968 
       
  1969     int totalWaitTime = 0;
       
  1970     while (req->status() != QContactAbstractRequest::Finished) {
       
  1971         // ensure that the progress signal was delivered to the main thread.
       
  1972         QCOMPARE(m_mainThreadId, m_progressSlotThreadId);
       
  1973 
       
  1974         QTest::qWait(5); // spin until done
       
  1975         totalWaitTime += 5;
       
  1976 
       
  1977         // break after 30 seconds.
       
  1978         if (totalWaitTime > 30000) {
       
  1979             delete req;
       
  1980             delete cm;
       
  1981             QSKIP("Asynchronous request not complete after 30 seconds!", SkipSingle);
       
  1982         }
       
  1983     }
       
  1984 
       
  1985     // ensure that the progress signal was delivered to the main thread.
       
  1986     QCOMPARE(m_mainThreadId, m_progressSlotThreadId);
       
  1987     delete req;
       
  1988     delete cm;
       
  1989 }
       
  1990 
       
  1991 void tst_QContactAsync::progressReceived(QContactFetchRequest* request, bool appendOnly)
       
  1992 {
       
  1993     Q_UNUSED(appendOnly);
       
  1994     m_progressSlotThreadId = request->thread()->currentThreadId();
       
  1995 }
       
  1996 
       
  1997 void tst_QContactAsync::addManagers()
       
  1998 {
       
  1999     QTest::addColumn<QString>("uri");
       
  2000 
       
  2001     // retrieve the list of available managers
       
  2002     QStringList managers = QContactManager::availableManagers();
       
  2003 
       
  2004     // remove ones that we know will not pass
       
  2005     managers.removeAll("invalid");
       
  2006     managers.removeAll("maliciousplugin");
       
  2007     managers.removeAll("testdummy");
       
  2008 
       
  2009     foreach(QString mgr, managers) {
       
  2010         QMap<QString, QString> params;
       
  2011         QTest::newRow(QString("mgr='%1'").arg(mgr).toLatin1().constData()) << QContactManager::buildUri(mgr, params);
       
  2012         if (mgr == "memory") {
       
  2013             params.insert("id", "tst_QContactManager");
       
  2014             QTest::newRow(QString("mgr='%1', params").arg(mgr).toLatin1().constData()) << QContactManager::buildUri(mgr, params);
       
  2015         }
       
  2016     }
       
  2017 }
       
  2018 
       
  2019 bool tst_QContactAsync::prepareModel(const QString &managerUri, QContactManager *&cm)
       
  2020 {
       
  2021     QList<QContact> contacts;
       
  2022     QList<QContactRelationship> relationships;
       
  2023     return prepareModel(managerUri, cm, contacts, relationships);
       
  2024 }
       
  2025 
       
  2026 bool tst_QContactAsync::prepareModel(const QString &managerUri, QContactManager *&cm, QList<QContact> &contacts, QList<QContactRelationship> &relationships)
       
  2027 {
       
  2028     cm = QContactManager::fromUri(managerUri);
       
  2029 
       
  2030     // XXX TODO: ensure that this is the case:
       
  2031     // there should be no contacts in the database.
       
  2032     QList<QContactLocalId> toRemove = cm->contacts();
       
  2033     foreach (const QContactLocalId& removeId, toRemove) {
       
  2034         if (!cm->removeContact(removeId))
       
  2035             return false;
       
  2036     }
       
  2037 
       
  2038     QContact a, b, c, d, e, f;
       
  2039     QContactPhoneNumber n;
       
  2040     n.setNumber("1");
       
  2041     a.saveDetail(&n);
       
  2042     n.setNumber("2");
       
  2043     b.saveDetail(&n);
       
  2044     n.setNumber("3");
       
  2045     c.saveDetail(&n);
       
  2046     n.setNumber("4");
       
  2047     d.saveDetail(&n);
       
  2048     n.setNumber("5");
       
  2049     e.saveDetail(&n);
       
  2050     n.setNumber("6");
       
  2051     f.saveDetail(&n);    
       
  2052 
       
  2053     QContactUrl url;
       
  2054     url.setUrl("http://test.nokia.com");
       
  2055     a.saveDetail(&url);
       
  2056     
       
  2057     a.setType(QContactType::TypeGroup);
       
  2058     b.setType(QContactType::TypeGroup);
       
  2059     c.setType(QContactType::TypeGroup);
       
  2060 
       
  2061     if (!cm->saveContact(&a)) 
       
  2062         return false;
       
  2063     if (!cm->saveContact(&b)) 
       
  2064         return false;
       
  2065     if (!cm->saveContact(&c)) 
       
  2066         return false;
       
  2067     if (!cm->saveContact(&d)) 
       
  2068         return false;
       
  2069     if (!cm->saveContact(&e)) 
       
  2070         return false;
       
  2071     if (!cm->saveContact(&f)) 
       
  2072         return false;
       
  2073     
       
  2074     contacts.append(a);
       
  2075     contacts.append(b);
       
  2076     contacts.append(c);
       
  2077     contacts.append(d);
       
  2078     contacts.append(e);
       
  2079     contacts.append(f);
       
  2080     
       
  2081     if (cm->hasFeature(QContactManager::Relationships))
       
  2082     {
       
  2083         QStringList supportedRelationshipTypes = cm->supportedRelationshipTypes();
       
  2084 
       
  2085         if (cm->hasFeature(QContactManager::ArbitraryRelationshipTypes)) {
       
  2086             supportedRelationshipTypes.insert(0, "some-arbitrary-relationship");
       
  2087             if (!supportedRelationshipTypes.contains(QContactRelationship::HasManager))
       
  2088                 supportedRelationshipTypes.append(QContactRelationship::HasManager);
       
  2089             if (!supportedRelationshipTypes.contains(QContactRelationship::HasAssistant))
       
  2090                 supportedRelationshipTypes.append(QContactRelationship::HasAssistant);
       
  2091             if (!supportedRelationshipTypes.contains(QContactRelationship::HasSpouse))
       
  2092                 supportedRelationshipTypes.append(QContactRelationship::HasSpouse);
       
  2093         }
       
  2094                     
       
  2095         if (supportedRelationshipTypes.count() == 0)
       
  2096             return false; // should not happen
       
  2097                 
       
  2098         QContactRelationship adRel;
       
  2099         adRel.setFirst(a.id());
       
  2100         adRel.setSecond(d.id());
       
  2101         adRel.setRelationshipType(supportedRelationshipTypes.at(0));
       
  2102         if (!cm->saveRelationship(&adRel))
       
  2103             return false;
       
  2104         relationships.append(adRel);
       
  2105         
       
  2106         QContactRelationship aeRel;
       
  2107         aeRel.setFirst(a.id());
       
  2108         aeRel.setSecond(e.id());
       
  2109         aeRel.setRelationshipType(supportedRelationshipTypes.at(0));
       
  2110         if (!cm->saveRelationship(&aeRel))
       
  2111             return false;
       
  2112         relationships.append(aeRel);
       
  2113         
       
  2114         QContactRelationship beRel;
       
  2115         beRel.setFirst(b.id());
       
  2116         beRel.setSecond(e.id());
       
  2117         beRel.setRelationshipType(supportedRelationshipTypes.at(0));
       
  2118         if (!cm->saveRelationship(&beRel))
       
  2119             return false; 
       
  2120         relationships.append(beRel);
       
  2121         
       
  2122         QContactRelationship ceRel;
       
  2123         ceRel.setFirst(c.id());
       
  2124         ceRel.setSecond(e.id());
       
  2125         ceRel.setRelationshipType(supportedRelationshipTypes.at(0));
       
  2126         if (!cm->saveRelationship(&ceRel))
       
  2127             return false;
       
  2128         relationships.append(ceRel);
       
  2129        
       
  2130         QContactRelationship cfRel;
       
  2131         cfRel.setFirst(c.id());
       
  2132         cfRel.setSecond(f.id());
       
  2133         cfRel.setRelationshipType(supportedRelationshipTypes.at(0));
       
  2134         if (!cm->saveRelationship(&cfRel))
       
  2135             return false;
       
  2136         relationships.append(cfRel);
       
  2137         
       
  2138         if (supportedRelationshipTypes.count() > 1)
       
  2139         {
       
  2140             QContactRelationship daRel;
       
  2141             daRel.setFirst(d.id());
       
  2142             daRel.setSecond(a.id());
       
  2143             daRel.setRelationshipType(supportedRelationshipTypes.at(1));
       
  2144             if (!cm->saveRelationship(&daRel)) 
       
  2145                 return false;
       
  2146             relationships.append(daRel);
       
  2147         }
       
  2148         
       
  2149         if (supportedRelationshipTypes.count() > 2)
       
  2150         {
       
  2151             QContactRelationship adRel2;
       
  2152             adRel2.setFirst(a.id());
       
  2153             adRel2.setSecond(d.id());
       
  2154             adRel2.setRelationshipType(supportedRelationshipTypes.at(2));
       
  2155             if (!cm->saveRelationship(&adRel2)) 
       
  2156                 return false;
       
  2157             relationships.append(adRel2);
       
  2158         }
       
  2159     }
       
  2160 
       
  2161     return true;
       
  2162 
       
  2163     // TODO: cleanup once test is complete
       
  2164 }
       
  2165 
       
  2166 QTEST_MAIN(tst_QContactAsync)
       
  2167 #include "tst_qcontactasync.moc"