diff -r 90517678cc4f -r 453da2cfceef qtmobility/tests/auto/qcontactmanager/tst_qcontactmanager.cpp --- a/qtmobility/tests/auto/qcontactmanager/tst_qcontactmanager.cpp Mon May 03 13:18:40 2010 +0300 +++ b/qtmobility/tests/auto/qcontactmanager/tst_qcontactmanager.cpp Fri May 14 16:41:33 2010 +0300 @@ -108,6 +108,8 @@ int foo; }; Q_DECLARE_METATYPE(UnsupportedMetatype) +Q_DECLARE_METATYPE(QContact) +Q_DECLARE_METATYPE(QContactManager::Error) class tst_QContactManager : public QObject { @@ -127,11 +129,11 @@ QContact createContact(QContactDetailDefinition nameDef, QString firstName, QString lastName, QString phoneNumber); void saveContactName(QContact *contact, QContactDetailDefinition nameDef, QContactName *contactName, const QString &name) const; - QContactManagerDataHolder managerDataHolder; + QScopedPointer managerDataHolder; public slots: - void init(); - void cleanup(); + void initTestCase(); + void cleanupTestCase(); private slots: void doDump(); @@ -143,6 +145,7 @@ /* Special test with special data */ void uriParsing(); void nameSynthesis(); + void compatibleContact(); /* Tests that are run on all managers */ void metadata(); @@ -167,10 +170,13 @@ void invalidManager(); void memoryManager(); void changeSet(); - - /* data providers (mostly all engines) */ - void uriParsing_data(); // Special data - void nameSynthesis_data(); // Special data + void fetchHint(); + + /* Special test with special data */ + void uriParsing_data(); + void nameSynthesis_data(); + void compatibleContact_data(); + /* Tests that are run on all managers */ void metadata_data() {addManagers();} void nullIdOperations_data() {addManagers();} void add_data() {addManagers();} @@ -195,8 +201,10 @@ { } -void tst_QContactManager::init() +void tst_QContactManager::initTestCase() { + managerDataHolder.reset(new QContactManagerDataHolder()); + /* Make sure these other test plugins are NOT loaded by default */ // These are now removed from the list of managers in addManagers() //QVERIFY(!QContactManager::availableManagers().contains("testdummy")); @@ -204,8 +212,9 @@ //QVERIFY(!QContactManager::availableManagers().contains("maliciousplugin")); } -void tst_QContactManager::cleanup() +void tst_QContactManager::cleanupTestCase() { + managerDataHolder.reset(0); } void tst_QContactManager::dumpContactDifferences(const QContact& ca, const QContact& cb) @@ -293,6 +302,33 @@ } } + // Second remove any superset matches (eg, backend adds a field) + aDetails = a.details(); + bDetails = b.details(); + foreach (QContactDetail d, aDetails) { + foreach (QContactDetail d2, bDetails) { + if (d.definitionName() == d2.definitionName()) { + bool canRemove = true; + QMap d2map = d2.variantValues(); + foreach (QString key, d2map.keys()) { + if (d.value(key) != d2.value(key)) { + // d can have _more_ keys than d2, + // but not _less_; and it cannot + // change the value. + canRemove = false; + } + } + + if (canRemove) { + // if we get to here, we can remove the details. + a.removeDetail(&d); + b.removeDetail(&d2); + break; + } + } + } + } + // check for contact type updates if (!a.type().isEmpty()) if (!b.type().isEmpty()) @@ -311,7 +347,7 @@ void tst_QContactManager::dumpContact(const QContact& contact) { QContactManager m; - qDebug() << "Contact: " << contact.id().localId() << "(" << m.synthesizedDisplayLabel(contact) << ")"; + qDebug() << "Contact: " << contact.id().localId() << "(" << m.synthesizedContactDisplayLabel(contact) << ")"; QList details = contact.details(); foreach(QContactDetail d, details) { qDebug() << " " << d.definitionName() << ":"; @@ -703,11 +739,11 @@ QVERIFY(cm->saveContact(&alice)); QVERIFY(cm->error() == QContactManager::NoError); - QVERIFY(alice.id() != QContactId()); + QVERIFY(!alice.id().managerUri().isEmpty()); + QVERIFY(alice.id().localId() != 0); QCOMPARE(cm->contactIds().count(), currCount+1); QContact added = cm->contact(alice.id().localId()); - QVERIFY(added.id() != QContactId()); QVERIFY(added.id() == alice.id()); if (!isSuperset(added, alice)) { @@ -748,6 +784,18 @@ // continue; //} + if (cm->managerName() == "maemo5") { + // The maemo5 backend only supports reading of Guid and QCOA + if (def.name() == QContactGuid::DefinitionName) + continue; + if (def.name() == QContactOnlineAccount::DefinitionName) + continue; + } + + // This is probably read-only + if (def.name() == QContactTimestamp::DefinitionName) + continue; + // otherwise, create a new detail of the given type and save it to the contact QContactDetail det(def.name()); QMap fieldmap = def.fields(); @@ -756,6 +804,10 @@ // get the field, and check to see that it's not constrained. QContactDetailFieldDefinition currentField = fieldmap.value(fieldKey); + // Don't test detail uris as these are manager specific + if (fieldKey == QContactDetail::FieldDetailUri) + continue; + // Special case: phone number. if (def.name() == QContactPhoneNumber::DefinitionName && fieldKey == QContactPhoneNumber::FieldNumber) { @@ -810,12 +862,13 @@ // if we get here, we don't know what sort of value can be saved... } } - megacontact.saveDetail(&det); + if (!det.isEmpty()) + megacontact.saveDetail(&det); } QVERIFY(cm->saveContact(&megacontact)); // must be able to save since built from definitions. QContact retrievedMegacontact = cm->contact(megacontact.id().localId()); - if (retrievedMegacontact != megacontact) { + if (!isSuperset(retrievedMegacontact, megacontact)) { dumpContactDifferences(megacontact, retrievedMegacontact); QEXPECT_FAIL("mgr='wince'", "Address Display Label mismatch", Continue); QCOMPARE(megacontact, retrievedMegacontact); @@ -845,7 +898,7 @@ // verify save QContact retrievedContactable = cm->contact(veryContactable.id().localId()); - if (retrievedContactable != veryContactable) { + if (!isSuperset(retrievedContactable, veryContactable)) { dumpContactDifferences(veryContactable, retrievedContactable); QEXPECT_FAIL("mgr='wince'", "Number of phones supported mismatch", Continue); QCOMPARE(veryContactable, retrievedContactable); @@ -1146,7 +1199,7 @@ nf.setLastName("Lastname"); foo.saveDetail(&nf); - QVERIFY(manager.synthesizedDisplayLabel(foo).isEmpty()); + QVERIFY(manager.synthesizedContactDisplayLabel(foo).isEmpty()); QVERIFY(manager.error() == QContactManager::NotSupportedError); QVERIFY(manager.saveContact(&foo) == false); @@ -1594,7 +1647,119 @@ c.saveDetail(&org2); // Finally! - QCOMPARE(cm.synthesizedDisplayLabel(c), expected); + QCOMPARE(cm.synthesizedContactDisplayLabel(c), expected); +} + +void tst_QContactManager::compatibleContact_data() +{ + QTest::addColumn("input"); + QTest::addColumn("expected"); + QTest::addColumn("error"); + + QContact baseContact; + QContactName name; + name.setFirstName(QLatin1String("First")); + baseContact.saveDetail(&name); + + { + QTest::newRow("already compatible") << baseContact << baseContact << QContactManager::NoError; + } + + { + QContact contact(baseContact); + QContactDetail detail("UnknownDetail"); + detail.setValue("Key", QLatin1String("Value")); + contact.saveDetail(&detail); + QTest::newRow("unknown detail") << contact << baseContact << QContactManager::NoError; + } + + { + QContact contact(baseContact); + QContactType type1; + type1.setType(QContactType::TypeContact); + contact.saveDetail(&type1); + QContactType type2; + type2.setType(QContactType::TypeGroup); + contact.saveDetail(&type2); + QContact expected(baseContact); + expected.saveDetail(&type2); + QTest::newRow("duplicate unique field") << contact << expected << QContactManager::NoError; + } + + { + QContact contact(baseContact); + QContactPhoneNumber phoneNumber; + phoneNumber.setValue("UnknownKey", "Value"); + contact.saveDetail(&phoneNumber); + QTest::newRow("unknown field") << contact << baseContact << QContactManager::NoError; + } + + { + QContact contact(baseContact); + QContactDisplayLabel displayLabel; + displayLabel.setValue(QContactDisplayLabel::FieldLabel, QStringList("Value")); + contact.saveDetail(&displayLabel); + QTest::newRow("wrong type") << contact << baseContact << QContactManager::NoError; + } + + { + QContact contact(baseContact); + QContactPhoneNumber phoneNumber1; + phoneNumber1.setNumber(QLatin1String("1234")); + phoneNumber1.setSubTypes(QStringList() + << QContactPhoneNumber::SubTypeMobile + << QContactPhoneNumber::SubTypeVoice + << QLatin1String("InvalidSubtype")); + contact.saveDetail(&phoneNumber1); + QContact expected(baseContact); + QContactPhoneNumber phoneNumber2; + phoneNumber2.setNumber(QLatin1String("1234")); + phoneNumber2.setSubTypes(QStringList() + << QContactPhoneNumber::SubTypeMobile + << QContactPhoneNumber::SubTypeVoice); + expected.saveDetail(&phoneNumber2); + QTest::newRow("bad value (list)") << contact << expected << QContactManager::NoError; + } + + { + QContact contact(baseContact); + QContactPhoneNumber phoneNumber1; + phoneNumber1.setNumber(QLatin1String("1234")); + phoneNumber1.setSubTypes(QStringList(QLatin1String("InvalidSubtype"))); + contact.saveDetail(&phoneNumber1); + QContact expected(baseContact); + QContactPhoneNumber phoneNumber2; + phoneNumber2.setNumber(QLatin1String("1234")); + expected.saveDetail(&phoneNumber2); + QTest::newRow("all bad value (list)") << contact << expected << QContactManager::NoError; + } + + { + QContact contact(baseContact); + QContactGender gender; + gender.setGender(QLatin1String("UnknownGender")); + contact.saveDetail(&gender); + QTest::newRow("bad value (string)") << contact << baseContact << QContactManager::NoError; + } + + { + QContact contact; + QContactGender gender; + gender.setGender(QLatin1String("UnknownGender")); + contact.saveDetail(&gender); + QTest::newRow("bad value (string)") << contact << QContact() << QContactManager::DoesNotExistError; + } +} + +void tst_QContactManager::compatibleContact() +{ + QContactManager cm("memory"); + + QFETCH(QContact, input); + QFETCH(QContact, expected); + QFETCH(QContactManager::Error, error); + QCOMPARE(cm.compatibleContact(input), expected); + QCOMPARE(cm.error(), error); } void tst_QContactManager::contactValidation() @@ -1700,12 +1865,9 @@ void tst_QContactManager::signalEmission() { + QTest::qWait(500); // clear the signal queue QFETCH(QString, uri); QScopedPointer m1(QContactManager::fromUri(uri)); - QScopedPointer m2(QContactManager::fromUri(uri)); - - QVERIFY(m1->hasFeature(QContactManager::Anonymous) == - m2->hasFeature(QContactManager::Anonymous)); qRegisterMetaType("QContactLocalId"); qRegisterMetaType >("QList"); @@ -1714,8 +1876,8 @@ QSignalSpy spyCR(m1.data(), SIGNAL(contactsRemoved(QList))); QList args; + QList arg; QContact c; - QContactLocalId temp; QList batchAdd; QList batchRemove; QList sigids; @@ -1729,12 +1891,14 @@ QContactName nc; saveContactName(&c, nameDef, &nc, "John"); QVERIFY(m1->saveContact(&c)); + QContactLocalId cid = c.id().localId(); addSigCount += 1; QTRY_COMPARE(spyCA.count(), addSigCount); args = spyCA.takeFirst(); addSigCount -= 1; - QVERIFY(args.count() == 1); - temp = QContactLocalId(args.at(0).value()); + arg = args.first().value >(); + QVERIFY(arg.count() == 1); + QCOMPARE(QContactLocalId(arg.at(0)), cid); // verify save modified emits signal changed saveContactName(&c, nameDef, &nc, "Citizen"); @@ -1743,8 +1907,9 @@ QTRY_COMPARE(spyCM.count(), modSigCount); args = spyCM.takeFirst(); modSigCount -= 1; - QVERIFY(args.count() == 1); - QCOMPARE(temp, QContactLocalId(args.at(0).value())); + arg = args.first().value >(); + QVERIFY(arg.count() == 1); + QCOMPARE(QContactLocalId(arg.at(0)), cid); // verify remove emits signal removed m1->removeContact(c.id().localId()); @@ -1752,8 +1917,9 @@ QTRY_COMPARE(spyCR.count(), remSigCount); args = spyCR.takeFirst(); remSigCount -= 1; - QVERIFY(args.count() == 1); - QCOMPARE(temp, QContactLocalId(args.at(0).value())); + arg = args.first().value >(); + QVERIFY(arg.count() == 1); + QCOMPARE(QContactLocalId(arg.at(0)), cid); // verify multiple adds works as advertised QContact c2, c3; @@ -1845,6 +2011,11 @@ QTRY_COMPARE(spyCA.count(), 0); QTRY_COMPARE(spyCM.count(), 0); + QScopedPointer m2(QContactManager::fromUri(uri)); + + QVERIFY(m1->hasFeature(QContactManager::Anonymous) == + m2->hasFeature(QContactManager::Anonymous)); + /* Now some cross manager testing */ if (!m1->hasFeature(QContactManager::Anonymous)) { // verify that signals are emitted for modifications made to other managers (same id). @@ -2126,10 +2297,17 @@ QVERIFY(d.displayLabel().isEmpty()); - QString synth = cm->synthesizedDisplayLabel(d); + QString synth = cm->synthesizedContactDisplayLabel(d); + + // Make sure this doesn't crash + cm->synthesizeContactDisplayLabel(0); + + // Make sure this gives the same results + cm->synthesizeContactDisplayLabel(&d); + QCOMPARE(d.displayLabel(), synth); /* - * The display label is not updated until you save the contact. + * The display label is not updated until you save the contact or call synthCDL */ QVERIFY(cm->saveContact(&d)); d = cm->contact(d.id().localId()); @@ -2185,16 +2363,8 @@ c.saveDetail(&p3); c.saveDetail(&u); - // set a preference for dialing a particular saved phonenumber. - c.setPreferredDetail("Dial", p2); - QVERIFY(cm->saveContact(&c)); // save the contact QContact loaded = cm->contact(c.id().localId()); // reload the contact - - // test that the preference was saved correctly. - QContactDetail pref = loaded.preferredDetail("Dial"); - QVERIFY(pref == p2); - cm->removeContact(c.id().localId()); } @@ -2214,12 +2384,19 @@ QVERIFY(changeSet.addedContacts().contains(id)); changeSet.insertChangedContact(id); - changeSet.insertChangedContact(id); + changeSet.insertChangedContacts(QList() << id); QVERIFY(changeSet.changedContacts().size() == 1); // set, should only be added once. QVERIFY(!changeSet.addedContacts().isEmpty()); QVERIFY(!changeSet.changedContacts().isEmpty()); QVERIFY(changeSet.removedContacts().isEmpty()); QVERIFY(changeSet.changedContacts().contains(id)); + changeSet.clearChangedContacts(); + QVERIFY(changeSet.changedContacts().isEmpty()); + + changeSet.insertRemovedContacts(QList() << id); + QVERIFY(changeSet.removedContacts().contains(id)); + changeSet.clearRemovedContacts(); + QVERIFY(changeSet.removedContacts().isEmpty()); QVERIFY(changeSet.dataChanged() == false); QContactChangeSet changeSet2; @@ -2227,6 +2404,11 @@ QVERIFY(changeSet.addedContacts() == changeSet2.addedContacts()); changeSet.emitSignals(0); + changeSet2.clearAddedContacts(); + QVERIFY(changeSet2.addedContacts().isEmpty()); + changeSet2.insertAddedContacts(changeSet.addedContacts().toList()); + QVERIFY(changeSet.addedContacts() == changeSet2.addedContacts()); + changeSet2.clearAll(); QVERIFY(changeSet.addedContacts() != changeSet2.addedContacts()); @@ -2241,6 +2423,14 @@ changeSet.emitSignals(0); changeSet.addedRelationshipsContacts().insert(id); + changeSet.insertAddedRelationshipsContacts(QList() << id); + QVERIFY(changeSet.addedRelationshipsContacts().contains(id)); + changeSet.clearAddedRelationshipsContacts(); + QVERIFY(changeSet.addedRelationshipsContacts().isEmpty()); + changeSet.insertRemovedRelationshipsContacts(QList() << id); + QVERIFY(changeSet.removedRelationshipsContacts().contains(id)); + changeSet.clearRemovedRelationshipsContacts(); + QVERIFY(changeSet.removedRelationshipsContacts().isEmpty()); changeSet.emitSignals(0); changeSet.removedRelationshipsContacts().insert(id); changeSet.emitSignals(0); @@ -2257,6 +2447,17 @@ changeSet.emitSignals(0); } +void tst_QContactManager::fetchHint() +{ + QContactFetchHint hint; + hint.setOptimizationHints(QContactFetchHint::NoBinaryBlobs); + QCOMPARE(hint.optimizationHints(), QContactFetchHint::NoBinaryBlobs); + QStringList rels; + rels << QString(QLatin1String(QContactRelationship::HasMember)); + hint.setRelationshipTypesHint(rels); + QCOMPARE(hint.relationshipTypesHint(), rels); +} + void tst_QContactManager::selfContactId() { QFETCH(QString, uri); @@ -2266,6 +2467,7 @@ QContactLocalId selfContact = cm->selfContactId(); if (!cm->hasFeature(QContactManager::SelfContact)) { // ensure that the error codes / return values are meaningful failures. + QEXPECT_FAIL("mgr='maemo5'", "maemo5 supports getting the self contact but not setting it.", Continue); QVERIFY(cm->error() == QContactManager::DoesNotExistError); QVERIFY(!cm->setSelfContactId(QContactLocalId(123))); QVERIFY(cm->error() == QContactManager::NotSupportedError);