--- a/qtmobility/plugins/contacts/symbian/tsrc/tst_qcontactmanagersymbian/tst_qcontactmanagersymbian.cpp Fri Apr 16 15:51:22 2010 +0300
+++ b/qtmobility/plugins/contacts/symbian/tsrc/tst_qcontactmanagersymbian/tst_qcontactmanagersymbian.cpp Mon May 03 13:18:40 2010 +0300
@@ -48,6 +48,32 @@
QTM_USE_NAMESPACE
+#ifndef QTRY_COMPARE
+#define QTRY_COMPARE(__expr, __expected) \
+ do { \
+ const int __step = 50; \
+ const int __timeout = 5000; \
+ QTest::qWait(__step); \
+ for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \
+ QTest::qWait(__step); \
+ } \
+ QCOMPARE(__expr, __expected); \
+ } while(0)
+#endif
+
+// A macro to help verifications done in signalEmission test case
+#define QTRY_COMPARE_SIGNAL_COUNTS() \
+ QTRY_COMPARE(spyContactsAdded.count(), contactsAdded); \
+ QTRY_COMPARE(spyContactsChanged.count(), contactsChanged); \
+ QTRY_COMPARE(spyContactsRemoved.count(), contactsRemoved); \
+ QTRY_COMPARE(spyRelationshipsAdded.count(), relationshipsAdded); \
+ QTRY_COMPARE(spyRelationshipsRemoved.count(), relationshipsRemoved); \
+ QTRY_COMPARE(spyContactsAdded2.count(), contactsAdded); \
+ QTRY_COMPARE(spyContactsChanged2.count(), contactsChanged); \
+ QTRY_COMPARE(spyContactsRemoved2.count(), contactsRemoved); \
+ QTRY_COMPARE(spyRelationshipsAdded2.count(), relationshipsAdded); \
+ QTRY_COMPARE(spyRelationshipsRemoved2.count(), relationshipsRemoved);
+
//TESTED_CLASS=
//TESTED_FILES=
@@ -68,22 +94,23 @@
virtual ~tst_QContactManagerSymbian();
public slots:
- //void initTestCase();
- //void cleanupTestCase();
void init();
void cleanup();
private slots:
- void avatarSubTypes();
- void avatarSubTypes_data();
- void avatarPixmap();
- void avatarPixmap_data();
- void avatarPathAndPixmap();
+ void signalEmission();
+ void filtering();
+ void avatarImage();
+ void avatarImage_data();
+ void thumbnail_data();
+ void thumbnail();
+ void ringTone();
void displayLabel_data();
void displayLabel();
void invalidContactItems();
private:
+ QContact createContact(QString type, QString firstName, QString lastName);
void addContactItemWithInvalidFieldsL(TContactItemId& itemId);
CContactDatabase* m_contactDatabase;
@@ -111,71 +138,188 @@
name.setFirstName("James");
name.setLastName("Hunt");
contact.saveDetail(&name);
+ QContactPhoneNumber number;
+ number.setNumber("+44752222222");
+ contact.saveDetail(&number);
QVERIFY(m_cm->saveContact(&contact));
m_contactId = contact.id();
}
void tst_QContactManagerSymbian::cleanup()
{
- // Commented out => leave generated contacts into database
+ // If the following is commented out => the generated contacts are left into
+ // the database
QVERIFY(m_cm->removeContact(m_contactId.localId()));
}
-void tst_QContactManagerSymbian::avatarSubTypes_data()
+void tst_QContactManagerSymbian::signalEmission()
{
- QTest::addColumn<QString>("fileName");
- QTest::addColumn<QString>("subType");
+ QScopedPointer<QContactManager> cm2(QContactManager::fromUri("qtcontacts:symbian"));
+
+ // Wait a moment to make sure there are no pending database observer events
+ QTest::qWait(500);
- QString emptyString;
+ // counters to keep track of the expected signal counts
+ int contactsAdded(0);
+ int contactsChanged(0);
+ int contactsRemoved(0);
+ int relationshipsAdded(0);
+ int relationshipsRemoved(0);
+
+ // Signal spys for verifying signal emissions
+ qRegisterMetaType<QContactLocalId>("QContactLocalId");
+ qRegisterMetaType<QList<QContactLocalId> >("QList<QContactLocalId>");
+ QSignalSpy spyContactsAdded(m_cm, SIGNAL(contactsAdded(QList<QContactLocalId>)));
+ QSignalSpy spyContactsChanged(m_cm, SIGNAL(contactsChanged(QList<QContactLocalId>)));
+ QSignalSpy spyContactsRemoved(m_cm, SIGNAL(contactsRemoved(QList<QContactLocalId>)));
+ QSignalSpy spyRelationshipsAdded(m_cm, SIGNAL(relationshipsAdded(QList<QContactLocalId>)));
+ QSignalSpy spyRelationshipsRemoved(m_cm, SIGNAL(relationshipsRemoved(QList<QContactLocalId>)));
+ QSignalSpy spyContactsAdded2(cm2.data(), SIGNAL(contactsAdded(QList<QContactLocalId>)));
+ QSignalSpy spyContactsChanged2(cm2.data(), SIGNAL(contactsChanged(QList<QContactLocalId>)));
+ QSignalSpy spyContactsRemoved2(cm2.data(), SIGNAL(contactsRemoved(QList<QContactLocalId>)));
+ QSignalSpy spyRelationshipsAdded2(cm2.data(), SIGNAL(relationshipsAdded(QList<QContactLocalId>)));
+ QSignalSpy spyRelationshipsRemoved2(cm2.data(), SIGNAL(relationshipsRemoved(QList<QContactLocalId>)));
+
+ // create a group
+ QContact group = createContact(QContactType::TypeGroup, "Hesketh", "");
+ QVERIFY(m_cm->saveContact(&group));
+ contactsAdded++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+
+ // change the group
+ QContactName name = group.detail(QContactName::DefinitionName);
+ name.setCustomLabel("McLaren");
+ group.saveDetail(&name);
+ QVERIFY(m_cm->saveContact(&group));
+ contactsChanged++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+
+ // remove the group
+ QVERIFY(m_cm->removeContact(group.localId()));
+ contactsRemoved++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
- // TODO: file names
- QTest::newRow("Sub type image") << "C:\\Data\\Images\\avatar_sharks_s.jpg" << "Image";
- //QTest::newRow("Sub type video") << "C:\\Data\\Videos\\video.mpg" << "Video";
- //QTest::newRow("Sub type textured mesh") << "C:\\Data\\" << "TexturedMesh";
- QTest::newRow("Sub type audio ringtone") << "C:\\Data\\Sounds\\avatar_sound.aac" << "AudioRingtone";
- QTest::newRow("Sub type video ringtone") << "C:\\Data\\Videos\\avatar_video.3gp" << "VideoRingtone"; // TODO
- QTest::newRow("No sub type") << "C:\\Data\\Images\\avatar_sharks_s.jpg" << emptyString;
+ // Add two contacts
+ QContact contact1 = createContact(QContactType::TypeContact, "James", "Hunt");
+ QVERIFY(m_cm->saveContact(&contact1));
+ contactsAdded++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+ QContact contact2 = createContact(QContactType::TypeContact, "Jochen", "Mass");
+ QVERIFY(m_cm->saveContact(&contact2));
+ contactsAdded++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+
+ // Add group 2
+ QContact group2 = createContact(QContactType::TypeGroup, "McLaren", "");
+ QVERIFY(m_cm->saveContact(&group2));
+ contactsAdded++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+
+ // Add a relationship
+ QContactRelationship r;
+ r.setFirst(group2.id());
+ r.setSecond(contact1.id());
+ r.setRelationshipType(QContactRelationship::HasMember);
+ QVERIFY(m_cm->saveRelationship(&r));
+ relationshipsAdded++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+
+ // Create one more contact manager instance
+ QScopedPointer<QContactManager> cm3(QContactManager::fromUri("qtcontacts:symbian"));
+ QSignalSpy spyRelationshipsAdded3(cm3.data(), SIGNAL(relationshipsAdded(QList<QContactLocalId>)));
+ QSignalSpy spyRelationshipsRemoved3(cm3.data(), SIGNAL(relationshipsRemoved(QList<QContactLocalId>)));
+
+ // Add a relationship
+ QContactRelationship r2;
+ r2.setFirst(group2.id());
+ r2.setSecond(contact2.id());
+ r2.setRelationshipType(QContactRelationship::HasMember);
+ QVERIFY(m_cm->saveRelationship(&r2));
+ relationshipsAdded++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+
+ // Remove relationship 1
+ QVERIFY(m_cm->removeRelationship(r));
+ relationshipsRemoved++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+ QTRY_COMPARE(spyRelationshipsAdded3.count(), 1);
+ QTRY_COMPARE(spyRelationshipsRemoved3.count(), 1);
+
+ // Remove relationship 2
+ QVERIFY(m_cm->removeRelationship(r2));
+ relationshipsRemoved++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+ QTRY_COMPARE(spyRelationshipsAdded3.count(), 1);
+ QTRY_COMPARE(spyRelationshipsRemoved3.count(), 2);
+
+ // Remove contacts
+ QVERIFY(m_cm->removeContact(contact1.localId()));
+ contactsRemoved++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+ QVERIFY(m_cm->removeContact(contact2.localId()));
+ contactsRemoved++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
+ QVERIFY(m_cm->removeContact(group2.localId()));
+ contactsRemoved++;
+ QTRY_COMPARE_SIGNAL_COUNTS();
}
-void tst_QContactManagerSymbian::avatarSubTypes()
+/*
+ * Special filtering cases that cannot be covered in QtMobility system level
+ * test cases.
+ */
+void tst_QContactManagerSymbian::filtering()
{
- QFETCH(QString, fileName);
- QFETCH(QString, subType);
- QContact testContact = m_cm->contact(m_contactId.localId());
+ QContactDetailFilter df;
+ df.setDetailDefinitionName(QContactPhoneNumber::DefinitionName, QContactPhoneNumber::FieldNumber);
+ df.setValue("222");
+
+ // Ends with
+ df.setMatchFlags(QContactFilter::MatchEndsWith);
- // Add avatar with sub type
- QContactAvatar avatar;
- avatar.setAvatar(fileName);
+ QList<QContactLocalId> ids = m_cm->contactIds(df);
+ QCOMPARE(m_cm->error(), QContactManager::NoError);
+ QCOMPARE(ids.count(), 1);
- if(!subType.isEmpty()) {
- avatar.setSubType(subType);
- }
- QVERIFY(testContact.saveDetail(&avatar));
- QVERIFY(m_cm->saveContact(&testContact));
+ df.setValue("333");
+ ids = m_cm->contactIds(df);
+ QCOMPARE(m_cm->error(), QContactManager::NoError);
+ QCOMPARE(ids.count(), 0);
+
+ df.setValue("222222");
+ ids = m_cm->contactIds(df);
+ QCOMPARE(m_cm->error(), QContactManager::NoError);
+ QCOMPARE(ids.count(), 1);
- // Get avatar
- testContact = m_cm->contact(m_contactId.localId());
- QCOMPARE(testContact.details(QContactAvatar::DefinitionName).count(), 1);
- QContactAvatar retrievedAvatar = testContact.detail(QContactAvatar::DefinitionName);
- QVERIFY(!retrievedAvatar.isEmpty());
- QCOMPARE(retrievedAvatar.avatar(), fileName);
- if(subType.isEmpty()) {
- // Known issue: If the sub type of a QContactAvatar is left empty, sub type
- // image is used by default. A side effect is that after loading this kind
- // of an avatar, the sub type has been set to sub type image.
- // -> clear sub type to make the following compare pass
- QVERIFY(retrievedAvatar.removeValue(QContactAvatar::FieldSubType));
- }
- QCOMPARE(retrievedAvatar, avatar);
+ df.setValue("2222222");
+ ids = m_cm->contactIds(df);
+ QCOMPARE(m_cm->error(), QContactManager::NoError);
+ QCOMPARE(ids.count(), 1);
+
+ // Match phone number
+ df.setMatchFlags(QContactFilter::MatchPhoneNumber);
+
+ df.setValue("2222222");
+ ids = m_cm->contactIds(df);
+ QCOMPARE(m_cm->error(), QContactManager::NoError);
+ QCOMPARE(ids.count(), 1);
- // Remove avatar
- retrievedAvatar = testContact.detail(QContactAvatar::DefinitionName);
- QVERIFY(testContact.removeDetail(&retrievedAvatar));
- QVERIFY(m_cm->saveContact(&testContact));
- QCOMPARE(testContact.details(QContactAvatar::DefinitionName).count(), 0);
+ df.setValue("2222");
+ ids = m_cm->contactIds(df);
+ // Should fail with not supported error because symbian's phone number
+ // match algorithm cannot be applied with less than 7 digit search strings
+ QCOMPARE(m_cm->error(), QContactManager::NotSupportedError);
+ QCOMPARE(ids.count(), 0);
+
+ df.setValue("3333");
+ ids = m_cm->contactIds(df);
+ // Should fail with not supported error because symbian's phone number
+ // match algorithm cannot be applied with less than 7 digit search strings
+ QCOMPARE(m_cm->error(), QContactManager::NotSupportedError);
+ QCOMPARE(ids.count(), 0);
}
-void tst_QContactManagerSymbian::avatarPixmap_data()
+void tst_QContactManagerSymbian::avatarImage_data()
{
QTest::addColumn<QString>("fileName");
@@ -185,54 +329,121 @@
QTest::newRow("XXLarge JPEG") << "C:\\Data\\Images\\avatar_sharks_xxl.jpg";
}
-void tst_QContactManagerSymbian::avatarPixmap()
+/*
+ * Special avatar cases that cannot be covered in QtMobility system level
+ * test cases.
+ */
+void tst_QContactManagerSymbian::avatarImage()
+{
+ QFETCH(QString, fileName);
+
+ QContact testContact = m_cm->contact(m_contactId.localId());
+
+ // Verify the image exists
+ QImage image(fileName);
+ QVERIFY(!image.isNull());
+
+ // Set image
+ QContactAvatar avatar;
+ QUrl url(fileName);
+ QVERIFY(url.isValid());
+ avatar.setImageUrl(url);
+ QVERIFY(testContact.saveDetail(&avatar));
+ QVERIFY(m_cm->saveContact(&testContact));
+
+ // Get image
+ testContact = m_cm->contact(m_contactId.localId());
+ avatar = testContact.detail(QContactAvatar::DefinitionName);
+ QVERIFY(!avatar.isEmpty());
+ url = avatar.imageUrl();
+ QVERIFY(url.isValid());
+ image = QImage(url.toString());
+ QVERIFY(!image.isNull());
+}
+
+void tst_QContactManagerSymbian::thumbnail_data()
+{
+ QTest::addColumn<QString>("fileName");
+
+ QTest::newRow("ExtraSmall JPEG") << "C:\\Data\\Images\\avatar_sharks_xs.jpg";
+ QTest::newRow("Small JPEG") << "C:\\Data\\Images\\avatar_sharks_s.jpg";
+ QTest::newRow("Medium JPEG") << "C:\\Data\\Images\\avatar_sharks_m.jpg";
+ QTest::newRow("XXLarge JPEG") << "C:\\Data\\Images\\avatar_sharks_xxl.jpg";
+}
+
+/*
+ * Special thumbnail cases that cannot be covered in QtMobility system level
+ * test cases.
+ */
+void tst_QContactManagerSymbian::thumbnail()
{
QFETCH(QString, fileName);
QContact testContact = m_cm->contact(m_contactId.localId());
- // Set pixmap
- QContactAvatar avatar;
- QPixmap pixmap(fileName);
- QVERIFY(!pixmap.isNull());
- QVERIFY(avatar.setPixmap(pixmap));
- QVERIFY(testContact.saveDetail(&avatar));
+ // Set
+ QContactThumbnail thumb = testContact.detail(QContactThumbnail::DefinitionName);
+ QImage image(fileName);
+ QVERIFY(!image.isNull());
+ thumb.setThumbnail(image);
+ QVERIFY(testContact.saveDetail(&thumb));
QVERIFY(m_cm->saveContact(&testContact));
// Get pixmap
testContact = m_cm->contact(m_contactId.localId());
- avatar = testContact.detail(QContactAvatar::DefinitionName);
- QVERIFY(!avatar.isEmpty());
- pixmap = avatar.pixmap();
- QVERIFY(!pixmap.isNull());
+ thumb = testContact.detail(QContactThumbnail::DefinitionName);
+ QVERIFY(!thumb.isEmpty());
+ QVERIFY(!thumb.thumbnail().isNull());
}
-void tst_QContactManagerSymbian::avatarPathAndPixmap()
+/*
+ * Special ringing tone cases that cannot be covered in QtMobility system level
+ * test cases.
+ */
+void tst_QContactManagerSymbian::ringTone()
{
- QString fileName("C:\\Data\\Images\\avatar_sharks_s.jpg");
QContact testContact = m_cm->contact(m_contactId.localId());
- // Set
- QContactAvatar avatar;
- avatar.setAvatar(fileName);
- QVERIFY(avatar.setPixmap(QPixmap(fileName)));
- QVERIFY(testContact.saveDetail(&avatar));
+ // these files are not actually included to the test data
+ QString audio("C:\\Data\\Sounds\\tone.wav");
+ QString video("C:\\Data\\Videos\\video.3gp");
+
+ // Set audio ringtone
+ QContactRingtone tone = testContact.detail(QContactRingtone::DefinitionName);
+ QUrl audioRingtone(audio);
+ tone.setAudioRingtoneUrl(audioRingtone);
+ QVERIFY(testContact.saveDetail(&tone));
QVERIFY(m_cm->saveContact(&testContact));
- // Get pixmap
+ // Get and verify ringtone
testContact = m_cm->contact(m_contactId.localId());
- avatar = testContact.detail(QContactAvatar::DefinitionName);
- QVERIFY(!avatar.isEmpty());
- QCOMPARE(avatar.avatar(), fileName);
- QPixmap pixmap = avatar.pixmap();
- QVERIFY(!pixmap.isNull());
+ tone = testContact.detail(QContactRingtone::DefinitionName);
+ QVERIFY(!tone.isEmpty());
+ QCOMPARE(tone.audioRingtoneUrl(), audioRingtone);
+ QCOMPARE(tone.videoRingtoneUrl(), QUrl());
+ QCOMPARE(tone.vibrationRingtoneUrl(), QUrl());
+
+ // Set video ringtone
+ QUrl videoRingtone(video);
+ tone.setVideoRingtoneUrl(videoRingtone);
+ QVERIFY(testContact.saveDetail(&tone));
+ QVERIFY(m_cm->saveContact(&testContact));
+
+ // Get and verify ringtone
+ testContact = m_cm->contact(m_contactId.localId());
+ tone = testContact.detail(QContactRingtone::DefinitionName);
+ QVERIFY(!tone.isEmpty());
+ QCOMPARE(tone.audioRingtoneUrl(), audioRingtone);
+ QCOMPARE(tone.videoRingtoneUrl(), videoRingtone);
+ QCOMPARE(tone.vibrationRingtoneUrl(), QUrl());
}
void tst_QContactManagerSymbian::displayLabel_data()
{
+ // Expected display label
+ QTest::addColumn<QString>("displayLabel");
// A string list containing the detail fields in format <detail definition name>:<field name>:<value>
// For example first name: Name:First:James
- QTest::addColumn<QString>("displayLabel");
// Note: With the current implementation the value must not contain a ':' character
QTest::addColumn<QStringList>("details");
@@ -292,6 +503,10 @@
<< "Organization:Name:McLaren");
}
+/*
+ * Special display label test cases for testing symbian backend specific
+ * display label generation.
+ */
void tst_QContactManagerSymbian::displayLabel()
{
qDebug() << QTest::currentDataTag();
@@ -300,7 +515,7 @@
// Parse details and add them to the contact
QContact contact;
- foreach(QString detail, details) {
+ foreach(const QString& detail, details) {
// the expected format is <detail definition name>:<field name>:<value>
QStringList detailParts = detail.split(QChar(':'), QString::KeepEmptyParts, Qt::CaseSensitive);
QVERIFY(detailParts.count() == 3);
@@ -327,12 +542,16 @@
QVERIFY(m_cm->removeContact(contact.localId()));
}
+/*
+ * Special contact handling test cases that cannot be covered in QtMobility
+ * system level test cases.
+ */
void tst_QContactManagerSymbian::invalidContactItems()
{
// 1. Empty contact
QContact empty;
QVERIFY(m_cm->saveContact(&empty));
- empty = m_cm->contact(empty.localId(), QStringList());
+ empty = m_cm->contact(empty.localId());
QVERIFY(m_cm->error() == QContactManager::NoError);
QVERIFY(empty.id() != QContactId());
QVERIFY(m_cm->removeContact(empty.localId()));
@@ -348,6 +567,21 @@
QVERIFY(m_cm->removeContact(invalidContact.localId()));
}
+QContact tst_QContactManagerSymbian::createContact(QString type, QString firstName, QString lastName)
+{
+ QContact contact;
+ contact.setType(type);
+ QContactName name;
+ if(type == QContactType::TypeContact) {
+ name.setFirstName(firstName);
+ name.setLastName(lastName);
+ } else {
+ name.setCustomLabel(firstName);
+ }
+ contact.saveDetail(&name);
+ return contact;
+}
+
void tst_QContactManagerSymbian::addContactItemWithInvalidFieldsL(TContactItemId& itemId)
{
// Create a contact with invalid item fields to the database