qtmobility/plugins/contacts/symbiansim/tsrc/tst_simcm/tst_simcm.cpp
changeset 14 6fbed849b4f4
parent 11 06b8e2af4411
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
    51 #endif
    51 #endif
    52 #include <mmtsy_names.h>
    52 #include <mmtsy_names.h>
    53 
    53 
    54 QTM_USE_NAMESPACE
    54 QTM_USE_NAMESPACE
    55 
    55 
       
    56 typedef QList<QContactLocalId> QContactIds;
       
    57 Q_DECLARE_METATYPE(QContactIds);
       
    58 
    56 #ifndef QTRY_COMPARE
    59 #ifndef QTRY_COMPARE
    57 #define QTRY_COMPARE(__expr, __expected) \
    60 #define QTRY_COMPARE(__expr, __expected) \
    58     do { \
    61     do { \
    59         const int __step = 50; \
    62         const int __step = 50; \
    60         const int __timeout = 5000; \
    63         const int __timeout = 5000; \
    80 public:
    83 public:
    81     tst_SimCM();
    84     tst_SimCM();
    82     virtual ~tst_SimCM();
    85     virtual ~tst_SimCM();
    83 
    86 
    84 public slots:
    87 public slots:
    85     void init();
       
    86     void cleanup();
       
    87     void initTestCase();
    88     void initTestCase();
    88     void cleanupTestCase();
    89     void cleanupTestCase();
    89 
    90 
    90 private slots:
    91 private slots:
    91     /* Test cases that need data */
    92     /* Test cases that need data */
   103     void fetchContacts();
   104     void fetchContacts();
   104     void updateContactDetail_data();
   105     void updateContactDetail_data();
   105     void updateContactDetail();
   106     void updateContactDetail();
   106     void batchOperations_data();
   107     void batchOperations_data();
   107     void batchOperations();
   108     void batchOperations();
       
   109     void detailFilter_data();
       
   110     void detailFilter();
       
   111     void sortingAdn_data();
       
   112     void sortingAdn();
   108 
   113 
   109     /* Test cases that take no data */
   114     /* Test cases that take no data */
   110     void signalEmission();
   115     void signalEmission();
   111     void sdnContacts();
   116     void sdnContacts();
       
   117     void fillSlots();
   112 
   118 
   113 private:
   119 private:
   114     void initManager(QString simStore);
   120     void initManager(QString simStore);
   115     void getEtelStoreInfoL(const TDesC &phonebook, TDes8 &infoPckg) const;
   121     void getEtelStoreInfoL(const TDesC &phonebook, TDes8 &infoPckg) const;
   116     bool isContactSupported(QContact contact);
   122     bool isContactSupported(QContact contact);
   117     void parseDetails(QContact &contact, QStringList details, QList<QContactDetail> &parsedDetails);
   123     void parseDetails(QContact &contact, QStringList details, QList<QContactDetail> &parsedDetails);
   118     void compareDetails(QContact contact, QList<QContactDetail> expectedDetails);
   124     bool compareDetails(QContact contact, QList<QContactDetail> expectedDetails);
   119     QContact createContact(QString name, QString number);
   125     QContact createContact(QString name, QString number);
       
   126     QContact saveContact(QString name, QString number);
       
   127     void dumpStoreInfo();
       
   128     bool compareContactLists(QList<QContact> lista, QList<QContact> listb);
       
   129     bool compareContacts(QContact ca, QContact cb);
       
   130     
   120 
   131 
   121 private:
   132 private:
   122     QContactManager* m_cm;
   133     QContactManager* m_cm;
   123 #ifdef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
   134 #ifdef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
   124     RMobilePhoneBookStore::TMobilePhoneBookInfoV1 m_etelStoreInfo;
   135     RMobilePhoneBookStore::TMobilePhoneBookInfoV1 m_etelStoreInfo;
   137 
   148 
   138 tst_SimCM::~tst_SimCM()
   149 tst_SimCM::~tst_SimCM()
   139 {
   150 {
   140 }
   151 }
   141 
   152 
   142 void tst_SimCM::init()
       
   143 {
       
   144     // remove all contacts
       
   145     QList<QContactLocalId> ids = m_cm->contactIds();
       
   146     m_cm->removeContacts(ids, 0);   
       
   147 }
       
   148 
       
   149 void tst_SimCM::cleanup()
       
   150 {
       
   151     // remove all contacts
       
   152     QList<QContactLocalId> ids = m_cm->contactIds();
       
   153     m_cm->removeContacts(ids, 0);   
       
   154 }
       
   155 
       
   156 void tst_SimCM::initTestCase()
   153 void tst_SimCM::initTestCase()
   157 {
   154 {
   158     initManager(QString());
   155     initManager(QString());
   159 
   156 
   160     // TODO: how about other stores?
   157     // TODO: how about other stores?
   161     TRAPD(err, getEtelStoreInfoL(KETelIccAdnPhoneBook, m_etelStoreInfoPckg));
   158     TRAPD(err, getEtelStoreInfoL(KETelIccAdnPhoneBook, m_etelStoreInfoPckg));
   162     QCOMPARE(err, KErrNone);
   159     QCOMPARE(err, KErrNone);
       
   160 
       
   161     // remove all contacts
       
   162     m_cm->removeContacts(m_cm->contactIds(), 0);   
   163 }
   163 }
   164 
   164 
   165 void tst_SimCM::cleanupTestCase()
   165 void tst_SimCM::cleanupTestCase()
   166 {
   166 {
       
   167     // remove all contacts
       
   168     m_cm->removeContacts(m_cm->contactIds(), 0);   
   167     delete m_cm;
   169     delete m_cm;
   168     m_cm = 0;
   170     m_cm = 0;
   169 }
   171 }
   170 
   172 
   171 void tst_SimCM::initManager_data()
   173 void tst_SimCM::initManager_data()
   352 {
   354 {
   353     QTest::addColumn<QString>("simStore"); // empty (defaults to ADN), "ADN", "SDN" or "FDN"
   355     QTest::addColumn<QString>("simStore"); // empty (defaults to ADN), "ADN", "SDN" or "FDN"
   354     QTest::addColumn<int>("expectedResult"); // 1 = pass, 0 = fail, -1 = depends on the SIM card
   356     QTest::addColumn<int>("expectedResult"); // 1 = pass, 0 = fail, -1 = depends on the SIM card
   355     QTest::addColumn<QString>("expectedDisplayLabel");
   357     QTest::addColumn<QString>("expectedDisplayLabel");
   356     QTest::addColumn<QStringList>("details"); // format is <detail definition name>:<field name>:<value>
   358     QTest::addColumn<QStringList>("details"); // format is <detail definition name>:<field name>:<value>
   357     QString unnamedLabel("Unnamed");
       
   358     QString es;
   359     QString es;
   359     QString tooLongText("James Hunt the 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890th");
   360     QString tooLongText("James Hunt the 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890th");
   360 
   361 
   361     // TODO: what name field to use for a sim contact name?
   362 #ifdef __WINS__
       
   363     qWarning("Etel test server (emulator) does report an error when saving if contact has too long details!");
       
   364 #endif
       
   365 
   362     // Note: With the current implementation the value must not contain a ':' character
   366     // Note: With the current implementation the value must not contain a ':' character
   363     QTest::newRow("ADN custom label")
   367     QTest::newRow("ADN custom label")
   364         << QString("ADN")
   368         << QString("ADN")
   365         << 1 // expected to pass
   369         << 1 // expected to pass
   366         << "James"
   370         << "James"
   389             << "Name:CustomLabel:James"
   393             << "Name:CustomLabel:James"
   390             << "Name:CustomLabel:James Hunt");
   394             << "Name:CustomLabel:James Hunt");
   391 
   395 
   392     QTest::newRow("ADN too long custom label")
   396     QTest::newRow("ADN too long custom label")
   393         << QString("ADN")
   397         << QString("ADN")
   394         << 1 // expected to pass. Note: too long display label is truncated
   398 #ifdef __WINS__
       
   399         << 1 // Etel test server does not enforce the max lengths
       
   400 #else
       
   401         << 0 // expected to fail
       
   402 #endif
   395         << tooLongText
   403         << tooLongText
   396         << (QStringList()
   404         << (QStringList()
   397             << (QString("Name:CustomLabel:").append(tooLongText)));
   405             << (QString("Name:CustomLabel:").append(tooLongText)));
   398 
   406 
   399     QTest::newRow("ADN custom label and nick name")
   407     QTest::newRow("ADN custom label and nick name")
   404             << "Name:CustomLabel:James Hunt"
   412             << "Name:CustomLabel:James Hunt"
   405             << "Nickname:Nickname:Hunt the Shunt");
   413             << "Nickname:Nickname:Hunt the Shunt");
   406 
   414 
   407     QTest::newRow("ADN custom label and too long nick name")
   415     QTest::newRow("ADN custom label and too long nick name")
   408         << QString("ADN")
   416         << QString("ADN")
   409         << -1 // Depends on SIM card support (some cards support second name)
   417 #ifdef __WINS__
       
   418         << 1 // Etel test server does not enforce the max lengths
       
   419 #else
       
   420         << 0 // expected to fail
       
   421 #endif
   410         << "James Hunt"
   422         << "James Hunt"
   411         << (QStringList()
   423         << (QStringList()
   412             << "Name:CustomLabel:James Hunt"
   424             << "Name:CustomLabel:James Hunt"
   413             << (QString("Nickname:Nickname:").append(tooLongText)));
   425             << (QString("Nickname:Nickname:").append(tooLongText)));
   414 
   426 
   415     QTest::newRow("ADN phone number")
   427     QTest::newRow("ADN phone number")
   416         << QString("ADN")
   428         << QString("ADN")
   417         << 1
   429         << 1
   418         << unnamedLabel
   430         << es
   419         << (QStringList()
   431         << (QStringList()
       
   432             << "PhoneNumber:PhoneNumber:+44752222222");
       
   433 
       
   434     QTest::newRow("ADN empty name and phone number")
       
   435         << QString("ADN")
       
   436         << 1
       
   437         << es
       
   438         << (QStringList()
       
   439             << "Name:CustomLabel:"
   420             << "PhoneNumber:PhoneNumber:+44752222222");
   440             << "PhoneNumber:PhoneNumber:+44752222222");
   421 
   441 
   422     QTest::newRow("ADN custom label and phone number")
   442     QTest::newRow("ADN custom label and phone number")
   423         << QString("ADN")
   443         << QString("ADN")
   424         << 1
   444         << 1
   512             << "EmailAddress:EmailAddress:james@mclaren.com"
   532             << "EmailAddress:EmailAddress:james@mclaren.com"
   513             << "EmailAddress:EmailAddress:james.hunt@bbc.co.uk");
   533             << "EmailAddress:EmailAddress:james.hunt@bbc.co.uk");
   514 
   534 
   515     QTest::newRow("ADN custom label and too long email")
   535     QTest::newRow("ADN custom label and too long email")
   516         << QString("ADN")
   536         << QString("ADN")
       
   537 #ifdef __WINS__
       
   538         << 1 // Etel test server does not enforce the max lengths
       
   539 #else
   517         << 0 // long enough e-mail to fail on any SIM card
   540         << 0 // long enough e-mail to fail on any SIM card
       
   541 #endif
   518         << "James Hunt"
   542         << "James Hunt"
   519         << (QStringList()
   543         << (QStringList()
   520             << "Name:CustomLabel:James Hunt"
   544             << "Name:CustomLabel:James Hunt"
   521             << "EmailAddress:EmailAddress:james.hunt.the12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890th@mclaren.com");
   545             << "EmailAddress:EmailAddress:james.hunt.the12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890th@mclaren.com");
   522 
   546 
   618 
   642 
   619         // verify contact id
   643         // verify contact id
   620         QVERIFY(contact.id() != QContactId());
   644         QVERIFY(contact.id() != QContactId());
   621 
   645 
   622         // verify that the details were saved as expected
   646         // verify that the details were saved as expected
   623         compareDetails(contact, expectedDetails);
   647         QVERIFY(compareDetails(contact, expectedDetails));
   624 
   648 
   625         // verify display label, allow truncating to the max text length
   649         // verify display label
   626         QCOMPARE(contact.displayLabel(), expectedDisplayLabel.left(m_etelStoreInfo.iMaxTextLength));
   650         QCOMPARE(contact.displayLabel(), expectedDisplayLabel);
   627 
   651 
   628         // TODO: verify that no extra details were added?
   652         // TODO: verify that no extra details were added?
   629         //?QCOMPARE(contact.details().count(), detailsUnderTest.count() + 2);
   653         //?QCOMPARE(contact.details().count(), detailsUnderTest.count() + 2);
       
   654 
       
   655         // Read the contact from SIM and re-verify the result
       
   656         contact = m_cm->contact(contact.localId());
       
   657         QVERIFY(compareDetails(contact, expectedDetails));
       
   658         QCOMPARE(contact.displayLabel(), expectedDisplayLabel);
   630 
   659 
   631         // verify contact removal
   660         // verify contact removal
   632         QVERIFY(m_cm->removeContact(contact.localId()));
   661         QVERIFY(m_cm->removeContact(contact.localId()));
   633         QCOMPARE(m_cm->error(), QContactManager::NoError);
   662         QCOMPARE(m_cm->error(), QContactManager::NoError);
   634 
   663 
   657 
   686 
   658     QTest::newRow("SDN")
   687     QTest::newRow("SDN")
   659         << QString("SDN")
   688         << QString("SDN")
   660         << int(0); // You cannot save a contact to SDN
   689         << int(0); // You cannot save a contact to SDN
   661 
   690 
   662     // TODO: How to save to FDN? A dialog for PIN2 should be shown...
   691     // Requires that PIN2 has been given (for example by activating and
       
   692     // de-activating FDN via S60 Phonebook)
   663     QTest::newRow("FDN")
   693     QTest::newRow("FDN")
   664         << QString("FDN")
   694         << QString("FDN")
   665         << int(1);
   695         << int(1);
   666 }
   696 }
   667 
   697 
   846     if (!isContactSupported(contact)) {
   876     if (!isContactSupported(contact)) {
   847         QSKIP("The contact cannot be saved onto the SIM card", SkipSingle);
   877         QSKIP("The contact cannot be saved onto the SIM card", SkipSingle);
   848     }
   878     }
   849     QVERIFY(m_cm->saveContact(&contact));
   879     QVERIFY(m_cm->saveContact(&contact));
   850     QCOMPARE(m_cm->error(), QContactManager::NoError);
   880     QCOMPARE(m_cm->error(), QContactManager::NoError);
   851     compareDetails(contact, parsedDetails);
   881     QVERIFY(compareDetails(contact, parsedDetails));
   852 
   882 
   853     // 3. Update contact detail and verify result
   883     // 3. Update contact detail and verify result
   854     foreach (const QContactDetail& detail, parsedDetails) {
   884     foreach (const QContactDetail& detail, parsedDetails) {
   855         QContactDetail savedDetail = contact.detail(detail.definitionName());
   885         QContactDetail savedDetail = contact.detail(detail.definitionName());
   856         QVERIFY(contact.removeDetail(&savedDetail));
   886         QVERIFY(contact.removeDetail(&savedDetail));
   860         QVERIFY(m_cm->removeContact(contact.localId()));
   890         QVERIFY(m_cm->removeContact(contact.localId()));
   861         QSKIP("The contact cannot be saved onto the SIM card", SkipSingle);
   891         QSKIP("The contact cannot be saved onto the SIM card", SkipSingle);
   862     }
   892     }
   863     QVERIFY(m_cm->saveContact(&contact));
   893     QVERIFY(m_cm->saveContact(&contact));
   864     QCOMPARE(m_cm->error(), QContactManager::NoError);
   894     QCOMPARE(m_cm->error(), QContactManager::NoError);
   865     compareDetails(contact, parsedDetails);
   895     QVERIFY(compareDetails(contact, parsedDetails));
   866 
   896 
   867     // 4. Remove the contact
   897     // 4. Remove the contact
   868     QVERIFY(m_cm->removeContact(contact.localId()));
   898     QVERIFY(m_cm->removeContact(contact.localId()));
   869 }
   899 }
   870 
   900 
   882     QTest::newRow("SDN")
   912     QTest::newRow("SDN")
   883         << QString("SDN")
   913         << QString("SDN")
   884         << 10
   914         << 10
   885         << false; // You cannot save contacts to SDN
   915         << false; // You cannot save contacts to SDN
   886 
   916 
   887     // TODO: How to save to FDN? A dialog for PIN2 should be shown...
   917     // Requires that PIN2 has been given (for example by activating and
       
   918     // de-activating FDN via S60 Phonebook)
   888     QTest::newRow("FDN")
   919     QTest::newRow("FDN")
   889         << QString("FDN")
   920         << QString("FDN")
   890         << 10
   921         << 10
   891         << true;
   922         << true;
   892 }
   923 }
   959         QCOMPARE(m_cm->error(), QContactManager::NoError);
   990         QCOMPARE(m_cm->error(), QContactManager::NoError);
   960         QCOMPARE(errorMap.count(), 0);
   991         QCOMPARE(errorMap.count(), 0);
   961     }
   992     }
   962 }
   993 }
   963 
   994 
       
   995 void tst_SimCM::detailFilter_data()
       
   996 {
       
   997     QTest::addColumn<QString>("detailName");
       
   998     QTest::addColumn<QString>("detailField");
       
   999     QTest::addColumn<QString>("value");
       
  1000     QTest::addColumn<int>("flags");
       
  1001     QTest::addColumn<bool>("filterSupported");
       
  1002     QTest::addColumn<QString>("expected");
       
  1003 
       
  1004     // Phone number
       
  1005     
       
  1006     QString detail = QContactPhoneNumber::DefinitionName;
       
  1007     QString field = QContactPhoneNumber::FieldNumber;
       
  1008     
       
  1009     QTest::newRow("phonenumber=123456789, flags=MatchExactly")
       
  1010         << detail << field << "123456789" << (int) QContactFilter::MatchExactly << false << "a";
       
  1011     
       
  1012     QTest::newRow("phonenumber=123456789, flags=MatchContains")
       
  1013         << detail << field << "123456789" << (int) QContactFilter::MatchContains << false << "abc";
       
  1014     
       
  1015     QTest::newRow("phonenumber=#, flags=MatchContains")
       
  1016         << detail << field << "#" << (int) QContactFilter::MatchContains << false << "f";
       
  1017     
       
  1018     QTest::newRow("phonenumber=p, flags=MatchContains")
       
  1019         << detail << field << "p" << (int) QContactFilter::MatchContains << false << "e";
       
  1020         
       
  1021     QTest::newRow("phonenumber=0, flags=MatchStartsWith")
       
  1022         << detail << field << "0" << (int) QContactFilter::MatchStartsWith << false << "defi";    
       
  1023     
       
  1024     QTest::newRow("phonenumber=012, flags=MatchEndsWith")
       
  1025         << detail << field << "012" << (int) QContactFilter::MatchEndsWith << false << "c";
       
  1026     
       
  1027     QTest::newRow("phonenumber=+358505555555, flags=MatchPhoneNumber")
       
  1028         << detail << field << "+358505555555" << (int) QContactFilter::MatchPhoneNumber << true << "ij";
       
  1029     
       
  1030     QTest::newRow("phonenumber=313, flags=MatchPhoneNumber")
       
  1031         << detail << field << "313" << (int) QContactFilter::MatchPhoneNumber << true << "h";
       
  1032     
       
  1033     // Custom label
       
  1034     detail = (QLatin1String) QContactName::DefinitionName;
       
  1035     field = (QLatin1String) QContactName::FieldCustomLabel;
       
  1036     
       
  1037     QTest::newRow("customlabel=frederik")
       
  1038             << detail << field << "frederik" << 0 << false << "c";
       
  1039     
       
  1040     QTest::newRow("customlabel=Kallasvuo flags=MatchContains")
       
  1041             << detail << field << "Kallasvuo" << (int) (QContactFilter::MatchContains) << false << "d";
       
  1042     
       
  1043     QTest::newRow("customlabel=Matti flags=MatchStartsWith")
       
  1044             << detail << field << "Matti" << (int) (QContactFilter::MatchStartsWith) << false << "b";
       
  1045     
       
  1046     QTest::newRow("customlabel=co flags=MatchEndsWith")
       
  1047             << detail << field << "co" << (int) (QContactFilter::MatchEndsWith) << false << "f";
       
  1048     
       
  1049     // ITU-T standard keypad collation:
       
  1050     // 2 = abc, 3 = def, 4 = ghi, 5 = jkl, 6 = mno, 7 = pqrs, 8 = tuv, 9 = wxyz, 0 = space
       
  1051     
       
  1052     QTest::newRow("customlabel T9 olli, flags=MatchKeypadCollation|MatchExactly")
       
  1053         << detail << field << "6554" << (int) (QContactFilter::MatchKeypadCollation | QContactFilter::MatchExactly) << false << "g";
       
  1054 
       
  1055     QTest::newRow("customlabel T9 olli, flags=MatchKeypadCollation|MatchContains")
       
  1056         << detail << field << "6554" << (int) (QContactFilter::MatchKeypadCollation | QContactFilter::MatchContains) << false << "adg";
       
  1057     
       
  1058     QTest::newRow("customlabel T9 jorma, flags=MatchKeypadCollation|MatchStartsWith")
       
  1059         << detail << field << "56762" << (int) (QContactFilter::MatchKeypadCollation | QContactFilter::MatchStartsWith) << false << "a";
       
  1060 
       
  1061     QTest::newRow("customlabel T9 nen, flags=MatchKeypadCollation|MatchEndsWith")
       
  1062         << detail << field << "636" << (int) (QContactFilter::MatchKeypadCollation | QContactFilter::MatchEndsWith) << false << "b";
       
  1063 }
       
  1064 
       
  1065 void tst_SimCM::detailFilter()
       
  1066 {
       
  1067     QFETCH(QString, detailName);
       
  1068     QFETCH(QString, detailField);
       
  1069     QFETCH(QString, value);
       
  1070     QFETCH(int, flags);
       
  1071     QFETCH(bool, filterSupported);
       
  1072     QFETCH(QString, expected);
       
  1073 
       
  1074     initManager("ADN");
       
  1075     QVERIFY(m_cm->error() == QContactManager::NoError);
       
  1076 
       
  1077     QMap<QContactLocalId, QString> saved;
       
  1078     saved.insert(saveContact("Jorma Ollila", "123456789").localId(), "a");
       
  1079     saved.insert(saveContact("Matti Nykänen", "+123456789").localId(), "b");
       
  1080     saved.insert(saveContact("Frederik", "+123456789012").localId(), "c");
       
  1081     saved.insert(saveContact("Olli-Pekka Kallasvuo", "0718008000").localId(), "d");
       
  1082     saved.insert(saveContact("Foobar", "0987654321p").localId(), "e");
       
  1083     saved.insert(saveContact("Telco", "0718008000#1234#123").localId(), "f");
       
  1084     saved.insert(saveContact("Olli", "543253425").localId(), "g");
       
  1085     saved.insert(saveContact("Donald Duck", "313").localId(), "h");
       
  1086     saved.insert(saveContact("Daisy Duck", "0505555555").localId(), "i");
       
  1087     saved.insert(saveContact("Daisy Duck (int)", "+358505555555").localId(), "j");
       
  1088 
       
  1089     QContactDetailFilter f;
       
  1090     f.setDetailDefinitionName(detailName, detailField);
       
  1091     f.setMatchFlags(QContactFilter::MatchFlags(flags));
       
  1092     f.setValue(value);
       
  1093     
       
  1094     QVERIFY(m_cm->isFilterSupported(f) == filterSupported);
       
  1095 
       
  1096     QList<QContactLocalId> ids = m_cm->contactIds(f);
       
  1097     QVERIFY(m_cm->error() == QContactManager::NoError);
       
  1098 
       
  1099     QString result;
       
  1100     foreach (QContactLocalId id, ids)
       
  1101         result += saved.value(id);
       
  1102 
       
  1103     // Remove all 
       
  1104     m_cm->removeContacts(m_cm->contactIds(), 0);   
       
  1105 
       
  1106     QCOMPARE(result, expected);
       
  1107 }
       
  1108 
       
  1109 
       
  1110 
   964 /*
  1111 /*
   965  * Test if signals contactsAdded, contactsChanged and contactsRemoved are
  1112  * Test if signals contactsAdded, contactsChanged and contactsRemoved are
   966  * emitted correctly.
  1113  * emitted correctly.
   967  */
  1114  */
   968 void tst_SimCM::signalEmission()
  1115 void tst_SimCM::signalEmission()
  1033     QList<QContact> contacts = cm->contacts();
  1180     QList<QContact> contacts = cm->contacts();
  1034     QVERIFY(contacts.count());
  1181     QVERIFY(contacts.count());
  1035     foreach(const QContact& c, contacts) {
  1182     foreach(const QContact& c, contacts) {
  1036         // Assume a valid SDN contact always has a display label and a phone number
  1183         // Assume a valid SDN contact always has a display label and a phone number
  1037         QVERIFY(!c.displayLabel().isEmpty());
  1184         QVERIFY(!c.displayLabel().isEmpty());
  1038         QVERIFY(!c.displayLabel().contains("unnamed", Qt::CaseInsensitive));
       
  1039         QVERIFY(!c.detail(QContactPhoneNumber::DefinitionName).isEmpty());
  1185         QVERIFY(!c.detail(QContactPhoneNumber::DefinitionName).isEmpty());
  1040         foreach(const QContactDetail& d, c.details()) {
  1186         foreach(const QContactDetail& d, c.details()) {
  1041             qDebug() << "Detail: " << d.definitionName();
  1187             qDebug() << "Detail: " << d.definitionName();
  1042             foreach (QVariant varianttt, d.variantValues()) {
  1188             foreach (QVariant varianttt, d.variantValues()) {
  1043                 qDebug() << "Variant value: " << varianttt.toString();
  1189                 qDebug() << "Variant value: " << varianttt.toString();
  1051     // Writing should fail
  1197     // Writing should fail
  1052     QContact c = createContact("foo", "1234567");
  1198     QContact c = createContact("foo", "1234567");
  1053     QVERIFY(!cm->saveContact(&c));
  1199     QVERIFY(!cm->saveContact(&c));
  1054 }
  1200 }
  1055 
  1201 
       
  1202 void tst_SimCM::fillSlots()
       
  1203 {
       
  1204     initManager("ADN");
       
  1205     
       
  1206     // remove all contacts
       
  1207     QList<QContactLocalId> ids = m_cm->contactIds();
       
  1208     m_cm->removeContacts(ids, 0); 
       
  1209         
       
  1210     // Update store info for empty sim card
       
  1211     TRAPD(err, getEtelStoreInfoL(KETelIccAdnPhoneBook, m_etelStoreInfoPckg));
       
  1212     QVERIFY(err == KErrNone);
       
  1213     //dumpStoreInfo();
       
  1214     
       
  1215     // Get detail definitions
       
  1216     QMap<QString, QContactDetailDefinition> defs = m_cm->detailDefinitions();
       
  1217     bool nicknameSupported = defs.contains(QContactNickname::DefinitionName);
       
  1218     bool additionalNumberSupported = !defs.value(QContactPhoneNumber::DefinitionName).isUnique();
       
  1219     bool emailSupported = defs.contains(QContactNickname::DefinitionName);
       
  1220     
       
  1221     // Fill all slots with a name
       
  1222     QList<QContact> savedContacts;
       
  1223     int i;
       
  1224     for (i=0; i<m_etelStoreInfo.iTotalEntries; i++)
       
  1225     {
       
  1226         QContact c;
       
  1227         QString label;
       
  1228         label.fill('x', 10);
       
  1229         QString tmp = QString("%1-").arg(i);
       
  1230         label.replace(0, tmp.size(), tmp);
       
  1231         QContactName name;
       
  1232         name.setCustomLabel(label);
       
  1233         c.saveDetail(&name);
       
  1234         QVERIFY(m_cm->saveContact(&c));
       
  1235         savedContacts << c;        
       
  1236     }
       
  1237     qDebug() << QString("Wrote %1 contacts with a name").arg(i);
       
  1238     
       
  1239     // Sim card should be full now. Try writing one more.
       
  1240     {
       
  1241         QContact c;
       
  1242         QContactName name;
       
  1243         name.setCustomLabel("foobar");
       
  1244         c.saveDetail(&name);
       
  1245         QVERIFY(!m_cm->saveContact(&c));
       
  1246     }
       
  1247          
       
  1248     // Write all slots with a number
       
  1249     for (i=0; i<m_etelStoreInfo.iTotalEntries; i++)
       
  1250     {
       
  1251         QContact &c = savedContacts[i];
       
  1252         QString num;
       
  1253         num.fill('0', 10);
       
  1254         QString tmp = QString("%1#").arg(i);
       
  1255         num.replace(0, tmp.size(), tmp);
       
  1256         QContactPhoneNumber number;
       
  1257         number.setNumber(num);
       
  1258         c.saveDetail(&number);
       
  1259         QVERIFY(m_cm->saveContact(&c));
       
  1260     }
       
  1261     qDebug() << QString("Wrote %1 contacts with a number").arg(i);
       
  1262     
       
  1263     // Write all slots with a nickname
       
  1264     for (i=0; i<m_etelStoreInfo.iTotalEntries && nicknameSupported; i++)
       
  1265     {
       
  1266         QContact c = savedContacts[i];
       
  1267         QContactNickname nickname;
       
  1268         QString nick;
       
  1269         nick.fill('x', 10);
       
  1270         QString tmp = QString("%1-").arg(i);
       
  1271         nick.replace(0, tmp.size(), tmp);
       
  1272         nickname.setNickname(nick);
       
  1273         c.saveDetail(&nickname);
       
  1274         if (!m_cm->saveContact(&c)) {
       
  1275             if (m_cm->error() == QContactManager::LimitReachedError)
       
  1276                 break;
       
  1277             else
       
  1278                 QFAIL("Failed to write nickname");
       
  1279         }
       
  1280         savedContacts[i] = c;
       
  1281     }
       
  1282     qDebug() << QString("Wrote %1 contacts with a nickname").arg(i);
       
  1283     
       
  1284     // Write all slots with a additional number
       
  1285     for (i=0; i<m_etelStoreInfo.iTotalEntries && additionalNumberSupported; i++)
       
  1286     {
       
  1287         QContact c = savedContacts[i];
       
  1288         QString num;
       
  1289         num.fill('0', 10);
       
  1290         QString tmp = QString("%1#1").arg(i);
       
  1291         num.replace(0, tmp.size(), tmp);
       
  1292         QContactPhoneNumber additionalNumber;
       
  1293         additionalNumber.setNumber(num);
       
  1294         c.saveDetail(&additionalNumber);
       
  1295         if (!m_cm->saveContact(&c)) {
       
  1296             if (m_cm->error() == QContactManager::LimitReachedError)
       
  1297                 break;
       
  1298             else
       
  1299                 QFAIL("Failed to write additional number");
       
  1300         }
       
  1301         savedContacts[i] = c;
       
  1302     }
       
  1303     qDebug() << QString("Wrote %1 contacts with additional number").arg(i);
       
  1304     
       
  1305     // Write all slots with a email
       
  1306     for (i=0; i<m_etelStoreInfo.iTotalEntries && emailSupported; i++)
       
  1307     {
       
  1308         QContact c = savedContacts[i];
       
  1309         QContactEmailAddress emailAddress;
       
  1310         QString email;
       
  1311         email.fill('x', 10);
       
  1312         QString tmp = QString("%1@").arg(i);
       
  1313         email.replace(0, tmp.size(), tmp);
       
  1314         emailAddress.setEmailAddress(email);
       
  1315         c.saveDetail(&emailAddress);
       
  1316         if (!m_cm->saveContact(&c)) {
       
  1317             if (m_cm->error() == QContactManager::LimitReachedError)
       
  1318                 break;
       
  1319             else
       
  1320                 QFAIL("Failed to write email");
       
  1321         }
       
  1322         savedContacts[i] = c;
       
  1323     }
       
  1324     qDebug() << QString("Wrote %1 contacts with an email").arg(i);
       
  1325     
       
  1326     TRAP(err, getEtelStoreInfoL(KETelIccAdnPhoneBook, m_etelStoreInfoPckg));
       
  1327     QVERIFY(err == KErrNone);
       
  1328     //dumpStoreInfo();
       
  1329 
       
  1330     QList<QContact> contacts = m_cm->contacts();
       
  1331 #ifdef __WINS__
       
  1332     // Cannot do full compare in emulator because of etel test server bug.
       
  1333     // If saving for example nickname fails with QContactManager::LimitReachedError
       
  1334     // it will still save the contact.
       
  1335     QVERIFY(contacts.count() == savedContacts.count());
       
  1336 #else
       
  1337     QVERIFY(compareContactLists(contacts, savedContacts));
       
  1338 #endif
       
  1339     QVERIFY(m_cm->removeContacts(m_cm->contactIds(), 0));
       
  1340 }
       
  1341 
       
  1342 void tst_SimCM::sortingAdn_data()
       
  1343 {
       
  1344     QTest::addColumn<QString>("definitionName");
       
  1345     QTest::addColumn<QString>("fieldName");
       
  1346     QTest::addColumn<int>("direction");
       
  1347     QTest::addColumn<int>("caseSensitivity");
       
  1348     QTest::addColumn<int>("blankPolicy");
       
  1349     QTest::addColumn<QContactIds>("expectedResult");
       
  1350     QTest::addColumn<QContactIds>("unknownResult");
       
  1351 
       
  1352     initManager("ADN");
       
  1353     QContact blankName = createContact(QString(""), QString("+44752222222"));
       
  1354     QVERIFY(m_cm->saveContact(&blankName));
       
  1355     QContact james = createContact(QString("James Hunt"), QString("+44753333333"));
       
  1356     QVERIFY(m_cm->saveContact(&james));
       
  1357     QContact kimi = createContact(QString("Kimi Räikkönen"), QString("+358441111111"));
       
  1358     QVERIFY(m_cm->saveContact(&kimi));
       
  1359     QContact kimiNoCaps = createContact(QString("kimi räikkönen"), QString("+358442222222"));
       
  1360     QVERIFY(m_cm->saveContact(&kimiNoCaps));
       
  1361     QContact sebastianNoPhone = createContact(QString("Sebastian Vettel"), QString(""));
       
  1362     QVERIFY(m_cm->saveContact(&sebastianNoPhone));
       
  1363 
       
  1364     QString contactNameDef = QContactName::DefinitionName;
       
  1365     QString customLabel = QContactName::FieldCustomLabel;
       
  1366     QString phoneNumberDef = QContactPhoneNumber::DefinitionName;
       
  1367     QString phoneNumber = QContactPhoneNumber::FieldNumber;
       
  1368 
       
  1369     // The relative order of "kimi" and "Kimi" are undefined in this case
       
  1370     QTest::newRow("custom label, ascending, case insensitive, blanks first")
       
  1371         << contactNameDef
       
  1372         << customLabel
       
  1373         << (int) Qt::AscendingOrder
       
  1374         << (int) Qt::CaseInsensitive
       
  1375         << (int) QContactSortOrder::BlanksFirst
       
  1376         << (QContactIds()
       
  1377             << blankName.localId()
       
  1378             << james.localId()
       
  1379             << kimi.localId()
       
  1380             << kimiNoCaps.localId()
       
  1381             << sebastianNoPhone.localId())
       
  1382         << (QContactIds()
       
  1383             << kimi.localId()
       
  1384             << kimiNoCaps.localId());
       
  1385 
       
  1386     QTest::newRow("custom label, ascending, case sensitive, blanks first")
       
  1387         << contactNameDef
       
  1388         << customLabel
       
  1389         << (int) Qt::AscendingOrder
       
  1390         << (int) Qt::CaseSensitive
       
  1391         << (int) QContactSortOrder::BlanksFirst
       
  1392         << (QContactIds()
       
  1393             << blankName.localId()
       
  1394             << james.localId()
       
  1395             << kimiNoCaps.localId()
       
  1396             << kimi.localId()
       
  1397             << sebastianNoPhone.localId())
       
  1398         << QContactIds();
       
  1399 
       
  1400     // The relative order of "kimi" and "Kimi" are undefined in this case
       
  1401     QTest::newRow("custom label, descending, case insensitive, blanks first")
       
  1402         << contactNameDef
       
  1403         << customLabel
       
  1404         << (int) Qt::DescendingOrder
       
  1405         << (int) Qt::CaseInsensitive
       
  1406         << (int) QContactSortOrder::BlanksFirst
       
  1407         << (QContactIds()
       
  1408             << blankName.localId()
       
  1409             << sebastianNoPhone.localId()
       
  1410             << kimi.localId()
       
  1411             << kimiNoCaps.localId()
       
  1412             << james.localId())
       
  1413         << (QContactIds()
       
  1414             << kimi.localId()
       
  1415             << kimiNoCaps.localId());
       
  1416 
       
  1417     QTest::newRow("phone number, ascending, case insensitive, blanks first")
       
  1418         << phoneNumberDef
       
  1419         << phoneNumber
       
  1420         << (int) Qt::AscendingOrder
       
  1421         << (int) Qt::CaseInsensitive
       
  1422         << (int) QContactSortOrder::BlanksFirst
       
  1423         << (QContactIds()
       
  1424             << sebastianNoPhone.localId()
       
  1425             << kimi.localId()
       
  1426             << kimiNoCaps.localId()
       
  1427             << blankName.localId()
       
  1428             << james.localId())
       
  1429         << QContactIds();
       
  1430 
       
  1431     QTest::newRow("phone number, ascending, case sensitive, blanks last")
       
  1432         << phoneNumberDef
       
  1433         << phoneNumber
       
  1434         << (int) Qt::AscendingOrder
       
  1435         << (int) Qt::CaseSensitive
       
  1436         << (int) QContactSortOrder::BlanksLast
       
  1437         << (QContactIds()
       
  1438             << kimi.localId()
       
  1439             << kimiNoCaps.localId()
       
  1440             << blankName.localId()
       
  1441             << james.localId()
       
  1442             << sebastianNoPhone.localId())
       
  1443         << QContactIds();
       
  1444 
       
  1445     QTest::newRow("phone number, descending, case insensitive, blanks first")
       
  1446         << phoneNumberDef
       
  1447         << phoneNumber
       
  1448         << (int) Qt::DescendingOrder
       
  1449         << (int) Qt::CaseInsensitive
       
  1450         << (int) QContactSortOrder::BlanksFirst
       
  1451         << (QContactIds()
       
  1452             << sebastianNoPhone.localId()
       
  1453             << james.localId()
       
  1454             << blankName.localId()
       
  1455             << kimiNoCaps.localId()
       
  1456             << kimi.localId())
       
  1457         << QContactIds();
       
  1458 }
       
  1459 
       
  1460 /*!
       
  1461  * Contact sorting needs to be tested here, because the system tests in
       
  1462  * \tests\auto\qcontactmanagerfiltering\tst_QContactManagerFiltering are not
       
  1463  * compatible with the sim backend.
       
  1464  */
       
  1465 void tst_SimCM::sortingAdn()
       
  1466 {
       
  1467     QFETCH(QString, definitionName);
       
  1468     QFETCH(QString, fieldName);
       
  1469     QFETCH(int, direction);
       
  1470     QFETCH(int, caseSensitivity);
       
  1471     QFETCH(int, blankPolicy);
       
  1472     QFETCH(QContactIds, expectedResult);
       
  1473     QFETCH(QContactIds, unknownResult);
       
  1474 
       
  1475     QContactSortOrder sortOrder;
       
  1476     sortOrder.setDetailDefinitionName(definitionName, fieldName);
       
  1477     sortOrder.setDirection((Qt::SortOrder) direction);
       
  1478     sortOrder.setCaseSensitivity((Qt::CaseSensitivity) caseSensitivity);
       
  1479     sortOrder.setBlankPolicy((QContactSortOrder::BlankPolicy) blankPolicy);
       
  1480     QVERIFY(sortOrder.isValid());
       
  1481 
       
  1482     QList<QContactSortOrder> sortOrders;
       
  1483     sortOrders.append(sortOrder);
       
  1484 
       
  1485     /*
       
  1486     TODO
       
  1487     QList<QContact> contacts(const QList<QContactSortOrder>& sortOrders = QList<QContactSortOrder>(), const QContactFetchHint& fetchHint = QContactFetchHint()) const;
       
  1488     QList<QContact> contacts(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders = QList<QContactSortOrder>(), const QContactFetchHint& fetchHint = QContactFetchHint()) const;
       
  1489     */
       
  1490 
       
  1491     // First variant
       
  1492     QList<QContactLocalId> ids = m_cm->contactIds(sortOrders);
       
  1493     qDebug() << "result: " << ids;
       
  1494     qDebug() << "expected: " << expectedResult;
       
  1495     QCOMPARE(m_cm->error(), QContactManager::NoError);
       
  1496     if (unknownResult.count()) {
       
  1497         // TODO: how to check all possible alternatives?
       
  1498         foreach (QContactLocalId id, unknownResult) {
       
  1499             QVERIFY(expectedResult.removeOne(id));
       
  1500             QVERIFY(ids.removeOne(id));
       
  1501         }
       
  1502     }
       
  1503     QCOMPARE(ids, expectedResult);
       
  1504 
       
  1505     // Second variant with filter
       
  1506     ids = m_cm->contactIds(QContactFilter(), sortOrders);
       
  1507     QCOMPARE(m_cm->error(), QContactManager::NoError);
       
  1508     if (unknownResult.count()) {
       
  1509         // TODO: how to check all possible alternatives?
       
  1510         foreach (QContactLocalId id, unknownResult) {
       
  1511             QVERIFY(ids.removeOne(id));
       
  1512         }
       
  1513     }
       
  1514     QCOMPARE(ids, expectedResult);
       
  1515 }
       
  1516 
  1056 /*!
  1517 /*!
  1057  * Private helper function for checking the data format that the store supports
  1518  * Private helper function for checking the data format that the store supports
  1058  */
  1519  */
  1059 void tst_SimCM::getEtelStoreInfoL(const TDesC &phonebook, TDes8 &infoPckg) const
  1520 void tst_SimCM::getEtelStoreInfoL(const TDesC &phonebook, TDes8 &infoPckg) const
  1060 {
  1521 {
  1156         if (contact.details().contains(QContactDetail(detailParts[0]))
  1617         if (contact.details().contains(QContactDetail(detailParts[0]))
  1157             && contact.detail(detailParts[0]).variantValues().key(detailParts[1]).isNull()) {
  1618             && contact.detail(detailParts[0]).variantValues().key(detailParts[1]).isNull()) {
  1158             contactDetail = contact.detail(detailParts[0]);
  1619             contactDetail = contact.detail(detailParts[0]);
  1159         }
  1620         }
  1160 
  1621 
  1161         // Set the field value only if not empty (do not add empty fields)  
  1622         if (detailParts[2].isNull()) {
  1162         if (!detailParts[2].isEmpty()) {
  1623             QVERIFY(contactDetail.setValue(detailParts[1], QString("")));
       
  1624         } else {
  1163             QVERIFY(contactDetail.setValue(detailParts[1], detailParts[2]));
  1625             QVERIFY(contactDetail.setValue(detailParts[1], detailParts[2]));
  1164         }
  1626         }
  1165 
       
  1166         QVERIFY(contact.saveDetail(&contactDetail));
  1627         QVERIFY(contact.saveDetail(&contactDetail));
  1167         parsedDetails.append(contactDetail);
  1628         parsedDetails.append(contactDetail);
  1168     }
  1629     }
  1169 }
  1630 }
  1170 
  1631 
  1171 /*
  1632 /*
  1172  * Private helper function for comparing QContact details to a well-known set
  1633  * Private helper function for comparing QContact details to a well-known set
  1173  * of QContactDetails.
  1634  * of QContactDetails.
  1174  * \return true if all the expected contact details have a match in the \contact.
       
  1175  */
  1635  */
  1176 void tst_SimCM::compareDetails(QContact contact, QList<QContactDetail> expectedDetails)
  1636 bool tst_SimCM::compareDetails(QContact contact, QList<QContactDetail> expectedDetails)
  1177 {
  1637 {
       
  1638     bool result(true);
       
  1639 
  1178     foreach (QContactDetail expectedDetail, expectedDetails) {
  1640     foreach (QContactDetail expectedDetail, expectedDetails) {
  1179         QContactDetail actualDetail = contact.detail(expectedDetail.definitionName());
  1641         QString detailName = expectedDetail.definitionName();
  1180         QVERIFY(!actualDetail.isEmpty());
  1642         foreach (const QString& key, expectedDetail.variantValues().keys()) {
  1181 
  1643             bool match(false);
  1182         // Allow truncating the custom label to the max text length
  1644             // Go through the actual details to see if the expected detail is included there
  1183         if (expectedDetail.definitionName() == QContactName::DefinitionName) {
  1645             foreach (QContactDetail actualDetail, contact.details(expectedDetail.definitionName())) {
  1184             QContactName nameDetail = static_cast<QContactName>(expectedDetail);
  1646                 QString a = actualDetail.variantValue(key).toString();
  1185             nameDetail.setCustomLabel(nameDetail.customLabel().left(m_etelStoreInfo.iMaxTextLength));
  1647                 QString b = expectedDetail.variantValue(key).toString();
  1186             expectedDetail = static_cast<QContactDetail>(nameDetail);
  1648                 if (!actualDetail.variantValues().contains(key)) {
  1187         // Allow truncating the nick name to the max text length
  1649                     qDebug() << "field does not exist, detail:"
  1188         } else if (expectedDetail.definitionName() == QContactNickname::DefinitionName) {
  1650                         << detailName
  1189                 QContactNickname nick = static_cast<QContactNickname>(expectedDetail);
  1651                         << "key:"
  1190                 nick.setNickname(nick.nickname().left(m_etelStoreInfo.iMaxTextLength));
  1652                         << key
  1191                 expectedDetail = static_cast<QContactDetail>(nick);
  1653                         << " value: "
  1192         }
  1654                         << expectedDetail.variantValue(key);
  1193 
  1655                 } else if (actualDetail.variantValue(key) != expectedDetail.variantValue(key)) {
  1194         if(!contact.details().contains(expectedDetail)) {
  1656                     qDebug() << "Detail found, but value does not match. Detail:"
  1195             // FAIL! Make it easier to debug the output by
  1657                         << detailName
  1196             // comparing the contact detail field contents
  1658                         << "Expected: "
  1197             foreach (const QString& key, expectedDetail.variantValues().keys()) {
  1659                         << expectedDetail.variantValue(key)
  1198                 QVariant value1 = actualDetail.value(key);
  1660                         << " actual: "
  1199                 QVariant value2 = expectedDetail.value(key);
  1661                         << actualDetail.variantValue(key);
  1200                 QCOMPARE(actualDetail.value(key), expectedDetail.value(key));
  1662                 } else {
       
  1663                     match = true;
       
  1664                 }
       
  1665             }
       
  1666 
       
  1667             // Allow empty details, since they are not saved
       
  1668             if (!match && !expectedDetail.variantValue(key).toString().isEmpty()) {
       
  1669                 result = false;
  1201             }
  1670             }
  1202         }
  1671         }
  1203     }
  1672     }
       
  1673     return result;
  1204 }
  1674 }
  1205 
  1675 
  1206 QContact tst_SimCM::createContact(QString name, QString number)
  1676 QContact tst_SimCM::createContact(QString name, QString number)
  1207 {
  1677 {
  1208     QContact c;
  1678     QContact c;
  1216     c.saveDetail(&nb);
  1686     c.saveDetail(&nb);
  1217 
  1687 
  1218     return c;
  1688     return c;
  1219 }
  1689 }
  1220 
  1690 
       
  1691 QContact tst_SimCM::saveContact(QString name, QString number)
       
  1692 {
       
  1693     QContact c;
       
  1694     
       
  1695     QContactName n;
       
  1696     n.setCustomLabel(name);
       
  1697     c.saveDetail(&n);
       
  1698     
       
  1699     QContactPhoneNumber nb;
       
  1700     nb.setNumber(number);
       
  1701     c.saveDetail(&nb);
       
  1702     
       
  1703     if (!m_cm->saveContact(&c)) {
       
  1704         qWarning() << 
       
  1705             QString("Failed to save a contact! (name=%1,number=%2) error:%3")
       
  1706                 .arg(name).arg(number).arg(m_cm->error());
       
  1707     }
       
  1708 
       
  1709     return c;
       
  1710 }
       
  1711 
       
  1712 void tst_SimCM::dumpStoreInfo()
       
  1713 {
       
  1714     TPtrC name = m_etelStoreInfo.iName;
       
  1715     TPtrC8 identity = m_etelStoreInfo.iIdentity;
       
  1716     
       
  1717     qDebug() << "Store info:"
       
  1718         << "\nType                         " << m_etelStoreInfo.iType
       
  1719         << "\nTotalEntries                 " << m_etelStoreInfo.iTotalEntries
       
  1720         << "\nUsedEntries                  " << m_etelStoreInfo.iUsedEntries
       
  1721         << "\nCaps                         " << m_etelStoreInfo.iCaps
       
  1722         << "\nName                         " << QString::fromUtf16(name.Ptr(), name.Length())
       
  1723         << "\nMaxNumLength                 " << m_etelStoreInfo.iMaxNumLength
       
  1724         << "\nMaxTextLength                " << m_etelStoreInfo.iMaxTextLength
       
  1725         << "\nLocation                     " << m_etelStoreInfo.iLocation
       
  1726         << "\nChangeCounter                " << m_etelStoreInfo.iChangeCounter
       
  1727         << "\nIdentity                     " << QString::fromUtf8((const char*)identity.Ptr(), identity.Length())
       
  1728 #ifdef SYMBIANSIM_BACKEND_PHONEBOOKINFOV1
       
  1729         ;
       
  1730 #else
       
  1731         << "\nMaxSecondNames               " << m_etelStoreInfo.iMaxSecondNames
       
  1732         << "\nMaxTextLengthSecondName      " << m_etelStoreInfo.iMaxTextLengthSecondName
       
  1733         << "\nMaxAdditionalNumbers         " << m_etelStoreInfo.iMaxAdditionalNumbers
       
  1734         << "\nMaxNumLengthAdditionalNumber " << m_etelStoreInfo.iMaxNumLengthAdditionalNumber
       
  1735         << "\nMaxTextLengthAdditionalNumber" << m_etelStoreInfo.iMaxTextLengthAdditionalNumber
       
  1736         << "\nMaxGroupNames                " << m_etelStoreInfo.iMaxGroupNames
       
  1737         << "\nMaxTextLengthGroupName       " << m_etelStoreInfo.iMaxTextLengthGroupName
       
  1738         << "\nMaxEmailAddr                 " << m_etelStoreInfo.iMaxEmailAddr
       
  1739         << "\nMaxTextLengthEmailAddr       " << m_etelStoreInfo.iMaxTextLengthEmailAddr;    
       
  1740 #endif
       
  1741 }
       
  1742 
       
  1743 bool tst_SimCM::compareContactLists(QList<QContact> lista, QList<QContact> listb)
       
  1744 {
       
  1745     // NOTE: This compare is contact order insensitive.  
       
  1746     
       
  1747     // Remove matching contacts
       
  1748     foreach (QContact a, lista) {
       
  1749         foreach (QContact b, listb) {
       
  1750             if (compareContacts(a, b)) {
       
  1751                 lista.removeOne(a);
       
  1752                 listb.removeOne(b);
       
  1753                 break;
       
  1754             }
       
  1755         }
       
  1756     }
       
  1757     
       
  1758     //if (lista.count() != 0) qDebug() << "\nList A:\n" << lista;
       
  1759     //if (listb.count() != 0) qDebug() << "\nList B:\n" << listb;
       
  1760         
       
  1761     return (lista.count() == 0 && listb.count() == 0);
       
  1762 }
       
  1763 
       
  1764 bool tst_SimCM::compareContacts(QContact ca, QContact cb)
       
  1765 {
       
  1766     // NOTE: This compare is contact detail order insensitive.
       
  1767     
       
  1768     if (ca.localId() != cb.localId())
       
  1769         return false;
       
  1770     
       
  1771     QList<QContactDetail> aDetails = ca.details();
       
  1772     QList<QContactDetail> bDetails = cb.details();
       
  1773 
       
  1774     // Remove matching details
       
  1775     foreach (QContactDetail ad, aDetails) {
       
  1776         foreach (QContactDetail bd, bDetails) {
       
  1777             if (ad == bd) {
       
  1778                 ca.removeDetail(&ad);
       
  1779                 cb.removeDetail(&bd);
       
  1780                 break;
       
  1781             }
       
  1782         }
       
  1783     }
       
  1784     
       
  1785     if (ca != cb)
       
  1786         qDebug() << "\nCompare failed:\n" << "A:\n" << ca << "\nB:\n" << cb;
       
  1787     
       
  1788     return (ca == cb);
       
  1789 }
       
  1790 
  1221 QTEST_MAIN(tst_SimCM)
  1791 QTEST_MAIN(tst_SimCM)
  1222 #include "tst_simcm.moc"
  1792 #include "tst_simcm.moc"