qtmobility/tests/auto/qcontactasync/unittest/tst_qcontactasync.cpp
changeset 4 90517678cc4f
parent 1 2b40d63a9c3d
child 5 453da2cfceef
equal deleted inserted replaced
1:2b40d63a9c3d 4:90517678cc4f
   214 
   214 
   215     void testQuickDestruction();
   215     void testQuickDestruction();
   216     void testQuickDestruction_data() { addManagers(); }
   216     void testQuickDestruction_data() { addManagers(); }
   217 
   217 
   218     void threadDelivery();
   218     void threadDelivery();
   219     void progressReceived(QContactFetchRequest* request, bool appendOnly);
       
   220     void threadDelivery_data() { addManagers(); }
   219     void threadDelivery_data() { addManagers(); }
       
   220 protected slots:
       
   221     void resultsAvailableReceived();
   221 
   222 
   222 private:
   223 private:
       
   224     bool compareContactLists(QList<QContact> lista, QList<QContact> listb);
       
   225     bool compareContacts(QContact ca, QContact cb);
   223     bool containsIgnoringTimestamps(const QList<QContact>& list, const QContact& c);
   226     bool containsIgnoringTimestamps(const QList<QContact>& list, const QContact& c);
   224     bool compareIgnoringTimestamps(const QContact& ca, const QContact& cb);
   227     bool compareIgnoringTimestamps(const QContact& ca, const QContact& cb);
   225     QContactManager* prepareModel(const QString& uri);
   228     QContactManager* prepareModel(const QString& uri);
   226 
   229 
   227     Qt::HANDLE m_mainThreadId;
   230     Qt::HANDLE m_mainThreadId;
   228     Qt::HANDLE m_progressSlotThreadId;
   231     Qt::HANDLE m_resultsAvailableSlotThreadId;
   229     QContactManagerDataHolder managerDataHolder;
   232     QContactManagerDataHolder managerDataHolder;
   230 };
   233 };
   231 
   234 
   232 tst_QContactAsync::tst_QContactAsync()
   235 tst_QContactAsync::tst_QContactAsync()
   233 {
   236 {
   249 {
   252 {
   250 }
   253 }
   251 
   254 
   252 void tst_QContactAsync::cleanup()
   255 void tst_QContactAsync::cleanup()
   253 {
   256 {
       
   257 }
       
   258 
       
   259 bool tst_QContactAsync::compareContactLists(QList<QContact> lista, QList<QContact> listb)
       
   260 {
       
   261     // NOTE: This compare is contact order insensitive.  
       
   262     
       
   263     // Remove matching contacts
       
   264     foreach (QContact a, lista) {
       
   265         foreach (QContact b, listb) {
       
   266             if (compareContacts(a, b)) {
       
   267                 lista.removeOne(a);
       
   268                 listb.removeOne(b);
       
   269                 break;
       
   270             }
       
   271         }
       
   272     }    
       
   273     return (lista.count() == 0 && listb.count() == 0);
       
   274 }
       
   275 
       
   276 bool tst_QContactAsync::compareContacts(QContact ca, QContact cb)
       
   277 {
       
   278     // NOTE: This compare is contact detail order insensitive.
       
   279     
       
   280     if (ca.localId() != cb.localId())
       
   281         return false;
       
   282     
       
   283     QList<QContactDetail> aDetails = ca.details();
       
   284     QList<QContactDetail> bDetails = cb.details();
       
   285 
       
   286     // Remove matching details
       
   287     foreach (QContactDetail ad, aDetails) {
       
   288         foreach (QContactDetail bd, bDetails) {
       
   289             if (ad == bd) {
       
   290                 ca.removeDetail(&ad);
       
   291                 cb.removeDetail(&bd);
       
   292                 break;
       
   293             }
       
   294             
       
   295             // Special handling for timestamp
       
   296             if (ad.definitionName() == QContactTimestamp::DefinitionName &&
       
   297                 bd.definitionName() == QContactTimestamp::DefinitionName) {
       
   298                 QContactTimestamp at = static_cast<QContactTimestamp>(ad);
       
   299                 QContactTimestamp bt = static_cast<QContactTimestamp>(bd);
       
   300                 if (at.created().toString() == bt.created().toString() &&
       
   301                     at.lastModified().toString() == bt.lastModified().toString()) {
       
   302                     ca.removeDetail(&ad);
       
   303                     cb.removeDetail(&bd);
       
   304                     break;
       
   305                 }
       
   306                     
       
   307             }            
       
   308         }
       
   309     }
       
   310     return (ca == cb);
   254 }
   311 }
   255 
   312 
   256 bool tst_QContactAsync::containsIgnoringTimestamps(const QList<QContact>& list, const QContact& c)
   313 bool tst_QContactAsync::containsIgnoringTimestamps(const QList<QContact>& list, const QContact& c)
   257 {
   314 {
   258     QList<QContact> cl = list;
   315     QList<QContact> cl = list;
   416 
   473 
   417     // restrictions
   474     // restrictions
   418     sorting.clear();
   475     sorting.clear();
   419     cfr.setFilter(fil);
   476     cfr.setFilter(fil);
   420     cfr.setSorting(sorting);
   477     cfr.setSorting(sorting);
   421     cfr.setDefinitionRestrictions(QStringList(QContactName::DefinitionName));
   478     QContactFetchHint fetchHint;
   422     QCOMPARE(cfr.definitionRestrictions(), QStringList(QContactName::DefinitionName));
   479     fetchHint.setDetailDefinitionsHint(QStringList(QContactName::DefinitionName));
       
   480     cfr.setFetchHint(fetchHint);
       
   481     QCOMPARE(cfr.fetchHint().detailDefinitionsHint(), QStringList(QContactName::DefinitionName));
   423     QVERIFY(!cfr.cancel()); // not started
   482     QVERIFY(!cfr.cancel()); // not started
   424     QVERIFY(cfr.start());
   483     QVERIFY(cfr.start());
   425     QVERIFY((cfr.isActive() && cfr.state() == QContactAbstractRequest::ActiveState) || cfr.isFinished());
   484     QVERIFY((cfr.isActive() && cfr.state() == QContactAbstractRequest::ActiveState) || cfr.isFinished());
   426     //QVERIFY(cfr.isFinished() || !cfr.start());  // already started. // thread scheduling means this is untestable
   485     //QVERIFY(cfr.isFinished() || !cfr.start());  // already started. // thread scheduling means this is untestable
   427     QVERIFY(cfr.waitForFinished());
   486     QVERIFY(cfr.waitForFinished());
   476 
   535 
   477     // cancelling
   536     // cancelling
   478     sorting.clear();
   537     sorting.clear();
   479     cfr.setFilter(fil);
   538     cfr.setFilter(fil);
   480     cfr.setSorting(sorting);
   539     cfr.setSorting(sorting);
   481     cfr.setDefinitionRestrictions(QStringList());
   540     cfr.setFetchHint(QContactFetchHint());
   482 
   541 
   483     int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times.  If it doesn't work due to threading, bail out.
   542     int bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT; // attempt to cancel 40 times.  If it doesn't work due to threading, bail out.
   484     while (true) {
   543     while (true) {
   485         QVERIFY(!cfr.cancel()); // not started
   544         QVERIFY(!cfr.cancel()); // not started
   486         FILL_QUEUE_WITH_FETCH_REQUESTS();
   545         FILL_QUEUE_WITH_FETCH_REQUESTS();
   491             spy.clear();
   550             spy.clear();
   492             cfr.waitForFinished();
   551             cfr.waitForFinished();
   493             sorting.clear();
   552             sorting.clear();
   494             cfr.setFilter(fil);
   553             cfr.setFilter(fil);
   495             cfr.setSorting(sorting);
   554             cfr.setSorting(sorting);
   496             cfr.setDefinitionRestrictions(QStringList());
   555             cfr.setFetchHint(QContactFetchHint());
       
   556             cfr.setFetchHint(QContactFetchHint());
   497             bailoutCount -= 1;
   557             bailoutCount -= 1;
   498             if (!bailoutCount) {
   558             if (!bailoutCount) {
   499                 qWarning("Unable to test cancelling due to thread scheduling!");
   559                 qWarning("Unable to test cancelling due to thread scheduling!");
   500                 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
   560                 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
   501                 break;
   561                 break;
   522             // after the request has already finished.. so loop and try again.
   582             // after the request has already finished.. so loop and try again.
   523             cfr.waitForFinished();
   583             cfr.waitForFinished();
   524             sorting.clear();
   584             sorting.clear();
   525             cfr.setFilter(fil);
   585             cfr.setFilter(fil);
   526             cfr.setSorting(sorting);
   586             cfr.setSorting(sorting);
   527             cfr.setDefinitionRestrictions(QStringList());
   587             cfr.setFetchHint(QContactFetchHint());
   528             bailoutCount -= 1;
   588             bailoutCount -= 1;
   529             spy.clear();
   589             spy.clear();
   530             if (!bailoutCount) {
   590             if (!bailoutCount) {
   531                 qWarning("Unable to test cancelling due to thread scheduling!");
   591                 qWarning("Unable to test cancelling due to thread scheduling!");
   532                 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
   592                 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
   899     spy.clear();
   959     spy.clear();
   900 
   960 
   901     expected.clear();
   961     expected.clear();
   902     expected << cm->contact(cm->contactIds().last());
   962     expected << cm->contact(cm->contactIds().last());
   903     result = csr.contacts();
   963     result = csr.contacts();
   904     QCOMPARE(expected, result);
   964     QVERIFY(compareContactLists(expected, result));
   905 
   965 
   906     //here we can't compare the whole contact details, testContact would be updated by async call because we just use QThreadSignalSpy to receive signals.
   966     //here we can't compare the whole contact details, testContact would be updated by async call because we just use QThreadSignalSpy to receive signals.
   907     //QVERIFY(containsIgnoringTimestamps(expected, testContact));
   967     //QVERIFY(containsIgnoringTimestamps(expected, testContact));
   908     QVERIFY(expected.at(0).detail<QContactPhoneNumber>().number() == phn.number());
   968     QVERIFY(expected.at(0).detail<QContactPhoneNumber>().number() == phn.number());
   909     
   969     
  1126 {
  1186 {
  1127     QFETCH(QString, uri);
  1187     QFETCH(QString, uri);
  1128 
  1188 
  1129     QScopedPointer<QContactManager> cm(prepareModel(uri));
  1189     QScopedPointer<QContactManager> cm(prepareModel(uri));
  1130     if (!cm->hasFeature(QContactManager::MutableDefinitions)) {
  1190     if (!cm->hasFeature(QContactManager::MutableDefinitions)) {
  1131        QSKIP("This contact manager doest not support mutable definitions, can't remove a definition!", SkipSingle);
  1191        QSKIP("This contact manager does not support mutable definitions, can't remove a definition!", SkipSingle);
  1132     }
  1192     }
  1133     QContactDetailDefinitionRemoveRequest drr;
  1193     QContactDetailDefinitionRemoveRequest drr;
  1134     QVERIFY(drr.type() == QContactAbstractRequest::DetailDefinitionRemoveRequest);
  1194     QVERIFY(drr.type() == QContactAbstractRequest::DetailDefinitionRemoveRequest);
  1135     drr.setDefinitionNames(QContactType::TypeContact, QStringList());
  1195     drr.setDefinitionNames(QContactType::TypeContact, QStringList());
  1136     QVERIFY(drr.contactType() == QString(QLatin1String(QContactType::TypeContact)));
  1196     QVERIFY(drr.contactType() == QString(QLatin1String(QContactType::TypeContact)));
  1234             // due to thread scheduling, async cancel might be attempted
  1294             // due to thread scheduling, async cancel might be attempted
  1235             // after the request has already finished.. so loop and try again.
  1295             // after the request has already finished.. so loop and try again.
  1236             drr.waitForFinished();
  1296             drr.waitForFinished();
  1237             drr.setDefinitionNames(QContactType::TypeContact, removeIds);
  1297             drr.setDefinitionNames(QContactType::TypeContact, removeIds);
  1238 
  1298 
  1239             QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 2); // hasn't changed
  1299             QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 3); // finished
  1240             bailoutCount -= 1;
  1300             bailoutCount -= 1;
  1241             if (!bailoutCount) {
  1301             if (!bailoutCount) {
  1242                 qWarning("Unable to test cancelling due to thread scheduling!");
  1302                 qWarning("Unable to test cancelling due to thread scheduling!");
  1243                 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
  1303                 bailoutCount = MAX_OPTIMISTIC_SCHEDULING_LIMIT;
  1244                 break;
  1304                 break;
  1245             }
  1305             }
  1246             spy.clear();
  1306             spy.clear();
       
  1307             // XXX should be readded
  1247             continue;
  1308             continue;
  1248         }
  1309         }
  1249 
  1310 
  1250         // if we get here, then we are cancelling the request.
  1311         // if we get here, then we are cancelling the request.
  1251         QVERIFY(drr.waitForFinished());
  1312         QVERIFY(drr.waitForFinished());
  1279         drr.waitForFinished();
  1340         drr.waitForFinished();
  1280         QVERIFY(drr.isCanceled());
  1341         QVERIFY(drr.isCanceled());
  1281         QVERIFY(spy.count() >= 1); // active + cancelled progress signals
  1342         QVERIFY(spy.count() >= 1); // active + cancelled progress signals
  1282         spy.clear();
  1343         spy.clear();
  1283 
  1344 
  1284         QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 2); // hasn't changed
  1345         QCOMPARE(cm->detailDefinitions().keys().size(), originalCount - 3); // hasn't changed
  1285         break;
  1346         break;
  1286     }
  1347     }
  1287 
  1348 
  1288 }
  1349 }
  1289 
  1350 
  1293 
  1354 
  1294     QScopedPointer<QContactManager> cm(prepareModel(uri));
  1355     QScopedPointer<QContactManager> cm(prepareModel(uri));
  1295 
  1356 
  1296     if (!cm->hasFeature(QContactManager::MutableDefinitions)) {
  1357     if (!cm->hasFeature(QContactManager::MutableDefinitions)) {
  1297 
  1358 
  1298        QSKIP("This contact manager doest not support mutable definitions, can't save a definition!", SkipSingle);
  1359        QSKIP("This contact manager does not support mutable definitions, can't save a definition!", SkipSingle);
  1299     }
  1360     }
  1300     
  1361     
  1301     QContactDetailDefinitionSaveRequest dsr;
  1362     QContactDetailDefinitionSaveRequest dsr;
  1302     QVERIFY(dsr.type() == QContactAbstractRequest::DetailDefinitionSaveRequest);
  1363     QVERIFY(dsr.type() == QContactAbstractRequest::DetailDefinitionSaveRequest);
  1303     dsr.setContactType(QContactType::TypeContact);
  1364     dsr.setContactType(QContactType::TypeContact);
  1455 
  1516 
  1456 void tst_QContactAsync::relationshipFetch()
  1517 void tst_QContactAsync::relationshipFetch()
  1457 {
  1518 {
  1458     QFETCH(QString, uri);
  1519     QFETCH(QString, uri);
  1459     QScopedPointer<QContactManager> cm(prepareModel(uri));
  1520     QScopedPointer<QContactManager> cm(prepareModel(uri));
       
  1521 
       
  1522     if (!cm->hasFeature(QContactManager::Relationships)) {
       
  1523        QSKIP("This contact manager does not support relationships!", SkipSingle);
       
  1524     }
       
  1525     
       
  1526     if (cm->managerName() == "symbian") {
       
  1527         QSKIP("This contact manager does not support the required relationship types for this test to pass!", SkipSingle);
       
  1528     }
       
  1529     
  1460     QContactRelationshipFetchRequest rfr;
  1530     QContactRelationshipFetchRequest rfr;
  1461     QVERIFY(rfr.type() == QContactAbstractRequest::RelationshipFetchRequest);
  1531     QVERIFY(rfr.type() == QContactAbstractRequest::RelationshipFetchRequest);
  1462 
  1532 
  1463     // initial state - not started, no manager.
  1533     // initial state - not started, no manager.
  1464     QVERIFY(!rfr.isActive());
  1534     QVERIFY(!rfr.isActive());
  1527     QVERIFY(rfr.waitForFinished());
  1597     QVERIFY(rfr.waitForFinished());
  1528     QVERIFY(rfr.isFinished());
  1598     QVERIFY(rfr.isFinished());
  1529     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1599     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1530     spy.clear();
  1600     spy.clear();
  1531 
  1601 
  1532     rels = cm->relationships(aId, QContactRelationshipFilter::First);
  1602     rels = cm->relationships(aId, QContactRelationship::First);
  1533     result = rfr.relationships();
  1603     result = rfr.relationships();
  1534     QCOMPARE(rels, result);
  1604     QCOMPARE(rels, result);
  1535 
  1605 
  1536     // specific participant retrieval #1 - destination participant
  1606     // specific participant retrieval #1 - destination participant
  1537     rfr.setFirst(QContactId());
  1607     rfr.setFirst(QContactId());
  1555     QVERIFY(rfr.isFinished());
  1625     QVERIFY(rfr.isFinished());
  1556     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1626     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1557     spy.clear();
  1627     spy.clear();
  1558 
  1628 
  1559     // retrieve rels where second = id of B, and ensure that we get the same results
  1629     // retrieve rels where second = id of B, and ensure that we get the same results
  1560     rels = cm->relationships(bId, QContactRelationshipFilter::Second);
  1630     rels = cm->relationships(bId, QContactRelationship::Second);
  1561     result = rfr.relationships();
  1631     result = rfr.relationships();
  1562     QCOMPARE(rels, result);
  1632     QCOMPARE(rels, result);
  1563 
  1633 
  1564     // specific participant retrieval #2 - source participant
  1634     // specific participant retrieval #2 - source participant
  1565     rfr.setFirst(QContactId());
  1635     rfr.setFirst(QContactId());
  1588     rfr.setFirst(cId);
  1658     rfr.setFirst(cId);
  1589     rfr.setSecond(QContactId());
  1659     rfr.setSecond(QContactId());
  1590     QVERIFY(rfr.start());
  1660     QVERIFY(rfr.start());
  1591     QVERIFY(rfr.waitForFinished());
  1661     QVERIFY(rfr.waitForFinished());
  1592     result = rfr.relationships();
  1662     result = rfr.relationships();
  1593     rels = cm->relationships(cId, QContactRelationshipFilter::First);
  1663     rels = cm->relationships(cId, QContactRelationship::First);
  1594     QCOMPARE(rels, result);
  1664     QCOMPARE(rels, result);
  1595 
  1665 
  1596     // cancelling
  1666     // cancelling
  1597     rfr.setRelationshipType(QString());
  1667     rfr.setRelationshipType(QString());
  1598 
  1668 
  1653 
  1723 
  1654 void tst_QContactAsync::relationshipRemove()
  1724 void tst_QContactAsync::relationshipRemove()
  1655 {
  1725 {
  1656     QFETCH(QString, uri);
  1726     QFETCH(QString, uri);
  1657     QScopedPointer<QContactManager> cm(prepareModel(uri));
  1727     QScopedPointer<QContactManager> cm(prepareModel(uri));
       
  1728     
       
  1729     if (!cm->hasFeature(QContactManager::Relationships)) {
       
  1730        QSKIP("This contact manager does not support relationships!", SkipSingle);
       
  1731     }
       
  1732     
       
  1733     if (cm->managerName() == "symbian") {
       
  1734         QSKIP("This contact manager does not support the required relationship types for this test to pass!", SkipSingle);
       
  1735     }
       
  1736     
  1658     QContactRelationshipRemoveRequest rrr;
  1737     QContactRelationshipRemoveRequest rrr;
  1659     QVERIFY(rrr.type() == QContactAbstractRequest::RelationshipRemoveRequest);
  1738     QVERIFY(rrr.type() == QContactAbstractRequest::RelationshipRemoveRequest);
  1660 
  1739 
  1661     // initial state - not started, no manager.
  1740     // initial state - not started, no manager.
  1662     QVERIFY(!rrr.isActive());
  1741     QVERIFY(!rrr.isActive());
  1708     //QVERIFY(rrr.isFinished() || !rrr.start());  // already started. // thread scheduling means this is untestable
  1787     //QVERIFY(rrr.isFinished() || !rrr.start());  // already started. // thread scheduling means this is untestable
  1709     QVERIFY(rrr.waitForFinished());
  1788     QVERIFY(rrr.waitForFinished());
  1710     QVERIFY(rrr.isFinished());
  1789     QVERIFY(rrr.isFinished());
  1711     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1790     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1712     spy.clear();
  1791     spy.clear();
  1713     QCOMPARE(cm->relationships(QContactRelationship::HasAssistant, cId, QContactRelationshipFilter::Second).size(), 1);
  1792     QCOMPARE(cm->relationships(QContactRelationship::HasAssistant, cId, QContactRelationship::Second).size(), 1);
  1714 
  1793 
  1715     // remove (asynchronously) a nonexistent relationship - should fail.
  1794     // remove (asynchronously) a nonexistent relationship - should fail.
  1716     r.setFirst(cId);
  1795     r.setFirst(cId);
  1717     r.setSecond(aId);
  1796     r.setSecond(aId);
  1718     r.setRelationshipType(QContactRelationship::HasManager);
  1797     r.setRelationshipType(QContactRelationship::HasManager);
  1728     QVERIFY(rrr.waitForFinished());
  1807     QVERIFY(rrr.waitForFinished());
  1729     QVERIFY(rrr.isFinished());
  1808     QVERIFY(rrr.isFinished());
  1730     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1809     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1731     spy.clear();
  1810     spy.clear();
  1732 
  1811 
  1733     QCOMPARE(cm->relationships(QContactRelationship::HasManager, cId, QContactRelationshipFilter::First).size(), 0);
  1812     QCOMPARE(cm->relationships(QContactRelationship::HasManager, cId, QContactRelationship::First).size(), 0);
  1734 //    QCOMPARE(rrr.error(), QContactManager::DoesNotExistError);
  1813 //    QCOMPARE(rrr.error(), QContactManager::DoesNotExistError);
  1735 
  1814 
  1736     // cancelling
  1815     // cancelling
  1737     r.setFirst(cId);
  1816     r.setFirst(cId);
  1738     r.setSecond(QContactId());
  1817     r.setSecond(QContactId());
  1801 
  1880 
  1802 void tst_QContactAsync::relationshipSave()
  1881 void tst_QContactAsync::relationshipSave()
  1803 {
  1882 {
  1804     QFETCH(QString, uri);
  1883     QFETCH(QString, uri);
  1805     QScopedPointer<QContactManager> cm(prepareModel(uri));
  1884     QScopedPointer<QContactManager> cm(prepareModel(uri));
       
  1885     
       
  1886     if (!cm->hasFeature(QContactManager::Relationships)) {
       
  1887        QSKIP("This contact manager does not support relationships!", SkipSingle);
       
  1888     }
       
  1889     
       
  1890     if (cm->managerName() == "symbian") {
       
  1891         QSKIP("This contact manager does not support the required relationship types for this test to pass!", SkipSingle);
       
  1892     }    
       
  1893     
  1806     QContactRelationshipSaveRequest rsr;
  1894     QContactRelationshipSaveRequest rsr;
  1807     QVERIFY(rsr.type() == QContactAbstractRequest::RelationshipSaveRequest);
  1895     QVERIFY(rsr.type() == QContactAbstractRequest::RelationshipSaveRequest);
  1808 
  1896 
  1809     // initial state - not started, no manager.
  1897     // initial state - not started, no manager.
  1810     QVERIFY(!rsr.isActive());
  1898     QVERIFY(!rsr.isActive());
  1852     QVERIFY(rsr.waitForFinished());
  1940     QVERIFY(rsr.waitForFinished());
  1853     QVERIFY(rsr.isFinished());
  1941     QVERIFY(rsr.isFinished());
  1854     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1942     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1855     spy.clear();
  1943     spy.clear();
  1856 
  1944 
  1857     QList<QContactRelationship> expected = cm->relationships(QContactRelationship::HasSpouse, aId, QContactRelationshipFilter::First);
  1945     QList<QContactRelationship> expected = cm->relationships(QContactRelationship::HasSpouse, aId, QContactRelationship::First);
  1858     QList<QContactRelationship> result = rsr.relationships();
  1946     QList<QContactRelationship> result = rsr.relationships();
  1859     QCOMPARE(expected, result);
  1947     QCOMPARE(expected, result);
  1860     QVERIFY(result.contains(testRel));
  1948     QVERIFY(result.contains(testRel));
  1861     QCOMPARE(cm->relationships(aId).size(), originalCount + 1); // should be one extra
  1949     QCOMPARE(cm->relationships(aId).size(), originalCount + 1); // should be one extra
  1862 
  1950 
  1875     QVERIFY(rsr.isFinished());
  1963     QVERIFY(rsr.isFinished());
  1876     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1964     QVERIFY(spy.count() >= 1); // active + finished progress signals
  1877     spy.clear();
  1965     spy.clear();
  1878 
  1966 
  1879     expected.clear();
  1967     expected.clear();
  1880     expected = cm->relationships(QContactRelationship::HasSpouse, aId, QContactRelationshipFilter::First);
  1968     expected = cm->relationships(QContactRelationship::HasSpouse, aId, QContactRelationship::First);
  1881     result = rsr.relationships();
  1969     result = rsr.relationships();
  1882     QCOMPARE(result, QList<QContactRelationship>() << testRel);
  1970     QCOMPARE(result, QList<QContactRelationship>() << testRel);
  1883     QVERIFY(expected.contains(testRel));
  1971     QVERIFY(expected.contains(testRel));
  1884     QCOMPARE(cm->relationships(aId).size(), originalCount + 2); // should now be two extra
  1972     QCOMPARE(cm->relationships(aId).size(), originalCount + 2); // should now be two extra
  1885 
  1973 
  1916         QVERIFY(rsr.isCanceled());
  2004         QVERIFY(rsr.isCanceled());
  1917         QVERIFY(spy.count() >= 1); // active + cancelled progress signals
  2005         QVERIFY(spy.count() >= 1); // active + cancelled progress signals
  1918         spy.clear();
  2006         spy.clear();
  1919 
  2007 
  1920         // verify that the changes were not saved
  2008         // verify that the changes were not saved
  1921         QList<QContactRelationship> aRels = cm->relationships(aId, QContactRelationshipFilter::First);
  2009         QList<QContactRelationship> aRels = cm->relationships(aId, QContactRelationship::First);
  1922         QVERIFY(!aRels.contains(testRel));
  2010         QVERIFY(!aRels.contains(testRel));
  1923         QCOMPARE(cm->relationships(aId).size(), originalCount + 2); // should still only be two extra
  2011         QCOMPARE(cm->relationships(aId).size(), originalCount + 2); // should still only be two extra
  1924 
  2012 
  1925         break;
  2013         break;
  1926     }
  2014     }
  1951         QVERIFY(rsr.isCanceled());
  2039         QVERIFY(rsr.isCanceled());
  1952         QVERIFY(spy.count() >= 1); // active + cancelled progress signals
  2040         QVERIFY(spy.count() >= 1); // active + cancelled progress signals
  1953         spy.clear();
  2041         spy.clear();
  1954 
  2042 
  1955         // verify that the changes were not saved
  2043         // verify that the changes were not saved
  1956         QList<QContactRelationship> aRels = cm->relationships(aId, QContactRelationshipFilter::First);
  2044         QList<QContactRelationship> aRels = cm->relationships(aId, QContactRelationship::First);
  1957         QVERIFY(!aRels.contains(testRel));
  2045         QVERIFY(!aRels.contains(testRel));
  1958         QCOMPARE(cm->relationships(aId).size(), originalCount + 2); // should still only be two extra
  2046         QCOMPARE(cm->relationships(aId).size(), originalCount + 2); // should still only be two extra
  1959 
  2047 
  1960         break;
  2048         break;
  1961     }
  2049     }
  2108 void tst_QContactAsync::threadDelivery()
  2196 void tst_QContactAsync::threadDelivery()
  2109 {
  2197 {
  2110     QFETCH(QString, uri);
  2198     QFETCH(QString, uri);
  2111     QScopedPointer<QContactManager> cm(prepareModel(uri));
  2199     QScopedPointer<QContactManager> cm(prepareModel(uri));
  2112     m_mainThreadId = cm->thread()->currentThreadId();
  2200     m_mainThreadId = cm->thread()->currentThreadId();
  2113     m_progressSlotThreadId = m_mainThreadId;
  2201     m_resultsAvailableSlotThreadId = m_mainThreadId;
  2114 
  2202 
  2115     // now perform a fetch request and check that the progress is delivered to the correct thread.
  2203     // now perform a fetch request and check that the progress is delivered to the correct thread.
  2116     QContactFetchRequest *req = new QContactFetchRequest;
  2204     QContactFetchRequest *req = new QContactFetchRequest;
  2117     req->setManager(cm.data());
  2205     req->setManager(cm.data());
  2118     connect(req, SIGNAL(progress(QContactFetchRequest*,bool)), this, SLOT(progressReceived(QContactFetchRequest*, bool)));
  2206     connect(req, SIGNAL(resultsAvailable()), this, SLOT(resultsAvailableReceived()));
  2119     req->start();
  2207     req->start();
  2120 
  2208 
  2121     int totalWaitTime = 0;
  2209     int totalWaitTime = 0;
       
  2210     QTest::qWait(1); // force it to process events at least once.
  2122     while (req->state() != QContactAbstractRequest::FinishedState) {
  2211     while (req->state() != QContactAbstractRequest::FinishedState) {
  2123         // ensure that the progress signal was delivered to the main thread.
  2212         // ensure that the progress signal was delivered to the main thread.
  2124         QCOMPARE(m_mainThreadId, m_progressSlotThreadId);
  2213         QCOMPARE(m_mainThreadId, m_resultsAvailableSlotThreadId);
  2125 
  2214 
  2126         QTest::qWait(5); // spin until done
  2215         QTest::qWait(5); // spin until done
  2127         totalWaitTime += 5;
  2216         totalWaitTime += 5;
  2128 
  2217 
  2129         // break after 30 seconds.
  2218         // break after 30 seconds.
  2132             QSKIP("Asynchronous request not complete after 30 seconds!", SkipSingle);
  2221             QSKIP("Asynchronous request not complete after 30 seconds!", SkipSingle);
  2133         }
  2222         }
  2134     }
  2223     }
  2135 
  2224 
  2136     // ensure that the progress signal was delivered to the main thread.
  2225     // ensure that the progress signal was delivered to the main thread.
  2137     QCOMPARE(m_mainThreadId, m_progressSlotThreadId);
  2226     QCOMPARE(m_mainThreadId, m_resultsAvailableSlotThreadId);
  2138     delete req;
  2227     delete req;
  2139 }
  2228 }
  2140 
  2229 
  2141 void tst_QContactAsync::progressReceived(QContactFetchRequest* request, bool appendOnly)
  2230 void tst_QContactAsync::resultsAvailableReceived()
  2142 {
  2231 {
  2143     Q_UNUSED(appendOnly);
  2232     QContactFetchRequest *req = qobject_cast<QContactFetchRequest *>(QObject::sender());
  2144     m_progressSlotThreadId = request->thread()->currentThreadId();
  2233     if (req)
       
  2234         m_resultsAvailableSlotThreadId = req->thread()->currentThreadId();
       
  2235     else
       
  2236         qDebug() << "resultsAvailableReceived() : request deleted; unable to set thread id!";
  2145 }
  2237 }
  2146 
  2238 
  2147 void tst_QContactAsync::addManagers()
  2239 void tst_QContactAsync::addManagers()
  2148 {
  2240 {
  2149     QTest::addColumn<QString>("uri");
  2241     QTest::addColumn<QString>("uri");
  2153 
  2245 
  2154     // remove ones that we know will not pass
  2246     // remove ones that we know will not pass
  2155     managers.removeAll("invalid");
  2247     managers.removeAll("invalid");
  2156     managers.removeAll("maliciousplugin");
  2248     managers.removeAll("maliciousplugin");
  2157     managers.removeAll("testdummy");
  2249     managers.removeAll("testdummy");
       
  2250     managers.removeAll("symbiansim"); // SIM backend does not support all the required details for tests to pass.
  2158 
  2251 
  2159     foreach(QString mgr, managers) {
  2252     foreach(QString mgr, managers) {
  2160         QMap<QString, QString> params;
  2253         QMap<QString, QString> params;
  2161         QTest::newRow(QString("mgr='%1'").arg(mgr).toLatin1().constData()) << QContactManager::buildUri(mgr, params);
  2254         QTest::newRow(QString("mgr='%1'").arg(mgr).toLatin1().constData()) << QContactManager::buildUri(mgr, params);
  2162         if (mgr == "memory") {
  2255         if (mgr == "memory") {
  2203     a.saveDetail(&url);
  2296     a.saveDetail(&url);
  2204 
  2297 
  2205     cm->saveContact(&a);
  2298     cm->saveContact(&a);
  2206     cm->saveContact(&b);
  2299     cm->saveContact(&b);
  2207     cm->saveContact(&c);
  2300     cm->saveContact(&c);
       
  2301     
       
  2302     if (!cm->hasFeature(QContactManager::Relationships)) {
       
  2303         return cm;
       
  2304     }
       
  2305     
       
  2306     if (cm->managerName() == "symbian") {
       
  2307         // Symbian backend does not support other relationships than HasMember (which is same as groups)
       
  2308         return cm;
       
  2309     }
  2208 
  2310 
  2209     QContactRelationship arb;
  2311     QContactRelationship arb;
  2210     arb.setFirst(a.id());
  2312     arb.setFirst(a.id());
  2211     arb.setSecond(b.id());
  2313     arb.setSecond(b.id());
  2212     arb.setRelationshipType(QContactRelationship::HasManager);
  2314     arb.setRelationshipType(QContactRelationship::HasManager);