diff -r d4f567ce2e7c -r 5b6f26637ad3 phonebookengines_old/contactsmodel/tsrc/t_cntvcard.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines_old/contactsmodel/tsrc/t_cntvcard.cpp Tue Aug 31 15:05:21 2010 +0300 @@ -0,0 +1,2139 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Unit tests for functionality delivered by the CNTVCARD.DLL library. +// This test contains the tests originally in T_EXPDEL +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "t_utils2.h" +#include "T_rndutils.h" +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "cntdb_internal.h" +#endif + +_LIT(KTestName,"T_CNTVCARD"); + + + +_LIT(KDatabaseFileName,"C:T_CNTVCARD"); + +_LIT(KVcard1, "Z:\\t_cntvcard\\email1.vcf"); +_LIT(KVcard2, "Z:\\t_cntvcard\\email2.vcf"); + + +_LIT(KOutputFileName, "C:\\Test_Output.txt"); +_LIT(KExpDelAFileName, "c:\\expdela"); +_LIT(KTestVcardFile, "Z:\\cntvcard\\testvcard.vcf"); + +_LIT(KImpTypeVcardName, "Z:\\t_cntvcard\\testTypeVcard.vcf"); +_LIT(KImpNoTypeVcardName, "Z:\\t_cntvcard\\testNoTypeVcard.vcf"); + +_LIT(KTestVcardFile1, "Z:\\cntvcard\\testvcard1.vcf"); +//UpdateVCardL +_LIT(KVCardUpdate1,"Z:\\System\\Programs\\CntmodelTest\\vcardupdate1.vcf"); +_LIT(KVCardUpdate2,"C:\\vcardupdate2.vcf"); +_LIT(KVCardUpdate3,"Z:\\System\\Programs\\CntmodelTest\\vcardupdate3.vcf"); + +// digram data files +_LIT(KFirstNameFileName,"z:\\cntvcard\\names.first.2gm"); +_LIT(KLastNameFileName,"z:\\cntvcard\\names.last.2gm"); + +// vcard terminated by LF +_LIT(KVCardFileLF,"z:\\t_cntvcard\\cntvcardLF.vcf"); +// vcard containing UID property +_LIT(KVCardFileUID,"z:\\t_cntvcard\\cntvcardUID.vcf"); + +_LIT8(KVCardBinaryKeyImportFileDes,"BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "REV:20061120T111808Z\r\n" + "UID:0000000000000000-00e1005eee8a27d8-44\r\n" + "N:Name;;;;\r\n" + "TEL;HOME;VOICE;CELL:1111\r\n" + "KEY;ENCODING=BASE64:MIICajCCAdOgAwIBAgICBEUwDQYJKoZIhvcNAQEEBQA\r\n" + "wdzELMAkGA1UEBhMCVVMxLDAqBgNVBAoTI05ldHNjYXBlIENbW11bmljYX\r\n" + "Rpb25zIENvcnBvcmF0aW9uMRwwGgYDVQQLExNJbmZvcm1hdGlvbiBTeXN0\r\n" + "ZW1zMRwwGgYDVQQDExNyb290Y2EubmV0c2NhcGUuY29tMB4XDTk3MDYwNj\r\n" + "E5NDc1OVoXDTk3MTIwMzE5NDc1OVowgYkxCzAJBgNVBAYTAlVTMSYwJAYD\r\n" + "VQQKEx1OZXRzY2FwZSBDb21tdW5pY2F0aW9ucyBDb3JwLjEYMBYGA1UEAx\r\n" + "MPVGltb3RoeSBBIEhvd2VzMSEwHwYJKoZIhvcNAQkBFhJob3dlc0BuZXRz\r\n" + "Y2FwZS5jb20xFTATBgoJkiaJk/IsZAEBEwVob3dlczBcMA0GCSqGSIb3DQ\r\n" + "EBAQUAA0sAMEgCQQC0JZf6wkg8pLMXHHCUvMfL5H6zjSk4vTTXZpYyrdN2\r\n" + "dXcoX49LKiOmgeJSzoiFKHtLOIboyludF90CgqcxtwKnAgMBAAGjNjA0MB\r\n" + "EGCWCGSAGG+EIBAQQEAwIAoDAfBgNVHSMEGDAWgBT84FToB/GV3jr3mcau\r\n" + "+hUMbsQukjANBgkqhkiG9w0BAQQFAAOBgQBexv7o7mi3PLXadkmNP9LcIP\r\n" + "mx93HGp0Kgyx1jIVMyNgsemeAwBM+MSlhMfcpbTrONwNjZYW8vJDSoi//y\r\n" + "rZlVt9bJbs7MNYZVsyF1unsqaln4/vy6Uawfg8VUMk1U7jt8LYpo4YULU7\r\n" + "UZHPYVUaSgVttImOHZIKi4hlPXBOhcUQ==\r\n" + "\r\n" + "PHOTO;ENCODING=BASE64:\r\n" + " ZmlsZTovLy9qcXB1YmxpYy5naWY=\r\n" + "\r\n" + "END:VCARD\r\n" + ); + +_LIT8(KVCardTextKeyImportFileDes,"BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "REV:20061120T111808Z\r\n" + "UID:0000000000000000-00e1005eee8a27d8-44\r\n" + "N:Name;;;;\r\n" + "TEL;HOME;VOICE;CELL:1111\r\n" + "KEY:X509\r\n" + "PHOTO;ENCODING=BASE64:\r\n" + " ZmlsZTovLy9qcXB1YmxpYy5naWY=\r\n" + "\r\n" + "END:VCARD\r\n" + ); + +_LIT8(KMultiParam,"BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "N:;Neo;;Mr.;\r\n" + "FN:Mr. TestName\r\n" + "TEL;TYPE=HOME;TYPE=VOICE;TYPE=CELL:123\r\n" + "END:VCARD\r\n" + ); +_LIT8(KTelExport, "TEL;HOME;VOICE;CELL:123\r\n"); + +_LIT8(KVCardBeforeChange,"BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "N:Jm;Jg;;;\r\n" + "TEL;HOME:11111\r\n" + "TEL;HOME:67890\r\n" + "TEL;CELL:12345\r\n" + "UID:4c2d2b19ef07adea-00e115956542fd28-1\r\n" + "END:VCARD\r\n" + ); + + _LIT8(KVCardAfterChange,"BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "N:Jm;Jg;;;\r\n" + "TEL;HOME:11112\r\n" + "TEL;HOME:22222\r\n" + "TEL;HOME:22223\r\n" + "TEL;HOME:22224\r\n" + "UID:4c2d2b19ef07adea-00e115956542fd28-1\r\n" + "END:VCARD\r\n" + ); + + _LIT(KGivenName, "Jg"); + _LIT(KFamilyName, "Jm"); + _LIT(KTelHome1,"11111"); + _LIT(KTelHome2,"67890"); + _LIT(KTelCell,"12345"); + _LIT(KTelHome1Modified,"11112"); + _LIT(KTelHome2Modified,"22222"); + _LIT(KTelHome3Modified,"22223"); + _LIT(KTelHome4Modified,"22224"); + +//vCard containing CompanyField +_LIT(KVCardWithCompany, "z:\\t_cntvcard\\withcompany.vcf"); +//vCard without CompanyField +_LIT(KVCardWithoutCompany, "z:\\t_cntvcard\\withoutcompany.vcf"); + +_LIT(KVCardLargePhoto, "Z:\\t_cntvcard\\vcardwithlargephoto.vcf"); + + +CCntTest* CntTest=NULL; +LOCAL_D RTest test(KTestName); + +LOCAL_C void TestCondition(TBool aCondition, TInt aLineNumber); +#define TEST_CONDITION(x) TestCondition(x, __LINE__) + +const TInt KNumAccessCountContacts= 5; +const TInt KMachineUniqueId=0; +const TInt KNumberOfRandomContacts = 40; + +_LIT(KName,"Name"); +_LIT(KPhoneNumber,"1111"); +_LIT8(KModifiedNumberProperty,"TEL;HOME;CELL:11112222\r\n"); //no VOICE parameter! +_LIT8(KModifiedNumberProperty2,"tel;work;cell;2:4444\r\ntel;home;Voice;CELL:\r\n"); //empty property to delete +_LIT8(KModifiedNumberProperty3,"TEL;HOME;CELL:\r\nTEL;HOME;CELL:3333\r\n"); + +_LIT(KVCardFile1,"c:\\cntvcard1.vcf"); +_LIT(KVCardFile2,"c:\\cntvcard2.vcf"); +_LIT(KVCardFile3,"c:\\cntvcard3.vcf"); + +// data we expect to see in KTestVcardFile +_LIT(KFirstName, "first"); +_LIT(KFirstNamePrn, "f-i-r-s-t"); +_LIT(KSurName, "last"); +_LIT(KSurNamePrn, "l-a-s-t"); +_LIT(KOrgName, "I work here"); +_LIT(KOrgNamePrn, "Eye w-o-r-k h-e-r-e"); + +// labels we expect from the conacts resource file +_LIT(KFirstNameLabel, "First name"); +_LIT(KFirstNamePrnLabel, "First name reading"); +_LIT(KSurNameLabel, "Last name"); +_LIT(KSurNamePrnLabel, "Last name reading"); +_LIT(KOrgNameLabel, "Company"); +_LIT(KOrgNamePrnLabel, "Company reading"); + +_LIT(KVCardFile5, "c:\\cntvcard5.vcf"); +_LIT(KVCardFile6, "c:\\cntvcard6.vcf"); +_LIT8(KMasterVcard, "BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "REV:20060821T131829Z\r\n" + "UID:f356da00bfd5320f-00e0f93a015e3ec0-18\r\n" + "N:Aaaa;Pekka;;;\r\n" + "END:VCARD\r\n" + "BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "REV:20060821T131916Z\r\n" + "UID:f356da00bfd5320f-00e0f93a015e8128-19\r\n" + "N:Bbb;Pekka;;;\r\n" + "END:VCARD\r\n" + "BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "REV:20060821T131829Z\r\n" + "UID:f356da00bfd5320f-00e0f93a015eb46d-20\r\n" + "N:Cccc;Pekka;;;\r\n" + "END:VCARD\r\n" +); +_LIT8(KModifierVcard,"BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "REV:20060821T131829Z\r\n" + "UID:f356da00bfd5320f-00e0f93a015e3ec0-18\r\n" + "N:Aaaa;Pekka;;;\r\n" + "END:VCARD\r\n" + "BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "REV:20060821T131916Z\r\n" + "UID:f356da00bfd5320f-00e0f93a015e8128-19\r\n" + "N:;Pekka;;;\r\n" + "END:VCARD\r\n" + "BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "REV:20060821T131829Z\r\n" + "UID:f356da00bfd5320f-00e0f93a015eb46d-20\r\n" + "N:Cccc;Pekka;;;\r\n" + "END:VCARD\r\n" +); + +_LIT8(KPartialVCard,"BEGIN:VCARD\r\n" + "\r" +); + +const TAny* GNames[] = {&KFirstName, &KFirstNamePrn, &KSurName, &KSurNamePrn, &KOrgName, &KOrgNamePrn}; +const TAny* GLabels[] = {&KFirstNameLabel, &KFirstNamePrnLabel, &KSurNameLabel, &KSurNamePrnLabel, &KOrgNameLabel, &KOrgNamePrnLabel}; + +const TInt KNumberOfExtendedFieldNames=6; + +const TInt KExtendedFieldNames[KNumberOfExtendedFieldNames] = + { + KUidContactFieldGivenNameValue, + KUidContactFieldGivenNamePronunciationValue, + KUidContactFieldFamilyNameValue, + KUidContactFieldFamilyNamePronunciationValue, + KUidContactFieldCompanyNameValue, + KUidContactFieldCompanyNamePronunciationValue, + }; + + +/** Tests for default VOICE property parameter handling (tests1-4), and the X-IRMC-x extentions for the SOUND property (tests 5-6) */ +class CDefaultVoiceParamTests : public CBase + { +public : + enum THowToCheck {ECheckValue = 1, ECheckLabel = 2, EAppendValue = 4, EAppendLabel = 8}; + +public: + static CDefaultVoiceParamTests* NewLC(CCntTest& aTestLibrary); + ~CDefaultVoiceParamTests(); + void RunTestsL(); +private: + CDefaultVoiceParamTests(CCntTest& aTestLibrary); + void ConstructL(); + void TestOneL(); + void TestTwoL(); + void TestThreeL(); + void TestFourL(); + void TestFiveL(); + void TestSixL(); + void ImportContactsL(const TDesC& aFileName); + void ExportContactsL(const TDesC& aFileName, const CContactIdArray* aIds); + void CreateTestDataL(TContactItemId aId, const TDesC& aFileName, const TDesC8& aVCardData); + TInt CountPhoneNumberFieldsL(TContactItemId aId); + TContactItemId CreateItemL(const TDesC& aName, const TDesC& aNumber); + static void CheckCard(CContactCard* aCard, CDesCArray* aFields = NULL, CDesCArray* aLabels =NULL, TUint aFlags = ECheckValue|ECheckLabel); + void CheckCardL(TContactItemId aId, CDesCArray* aFields = NULL, CDesCArray* aLabels =NULL, TUint aFlags = ECheckValue|ECheckLabel) const; + +private: + CCntTest& iTest; + CContactDatabase* iDb; + }; + +CDefaultVoiceParamTests* CDefaultVoiceParamTests::NewLC(CCntTest& aTestLibrary) + { + CDefaultVoiceParamTests* self = new(ELeave) CDefaultVoiceParamTests(aTestLibrary); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CDefaultVoiceParamTests::~CDefaultVoiceParamTests() + { + } + +void CDefaultVoiceParamTests::RunTestsL() + { + TestFiveL(); //these two have to run 1st since tests 1-4 leave the db in an inconvenient state + TestSixL(); + TestOneL(); +#if defined(_DEBUG) + //this test cannot be run in release mode due to UID mismatch. + TestTwoL(); +#endif + TestThreeL(); + TestFourL(); + } + +CDefaultVoiceParamTests::CDefaultVoiceParamTests(CCntTest& aTestLibrary) : iTest(aTestLibrary) + { + } + +void CDefaultVoiceParamTests::ConstructL() + { + iDb=iTest.CreateDatabaseL(); + iDb->OverrideMachineUniqueId(KMachineUniqueId); + } + +/** Check all the fields specified by KExtendedFieldNames for correctness. + The specific behaviour on what is checked is regulated by aFlags. + This also prints each field with its label. + + @param aFields If present and the ECheckValue bit of aFlags set, the nth field text value is compared against + the nth descriptor in aFields. + If present and EAppendValue bit of aFlags set, each field's text value is appended to the end of aFields. + + @param aLabels If present and the ECheckLabel bit of aFlags set, the nth field's label is compared against + the nth descriptor in ECheckLabel. + If present and EAppendLabel bit of aFlags set, each field's label is appended to the end of aLabels. + @param aFlags Bitfields indicating how aFields and aLabels are used. Note that some values from THowToCheck + (like ECheckValue and EAppendValue) cannot be used at the same time. + */ +void CDefaultVoiceParamTests::CheckCard(CContactCard* aCard, CDesCArray* aFields, CDesCArray* aLabels, TUint aFlags) + { + CContactItemFieldSet& fieldSet=aCard->CardFields(); + for(TInt i=0;iText()); + succeed = (text.Compare(compare)==0); + if(succeed) + { + break; + } + index = fieldSet.FindNext( TUid::Uid(KExtendedFieldNames[i]), index + 1); + } + TEST_CONDITION(succeed); + } + else if (aFields && (aFlags & EAppendValue)) + { + text.Set(fieldSet[index].TextStorage()->Text()); + TRAP_IGNORE(aFields->AppendL(text)); + } + + TPtrC label(fieldSet[index].Label()); + if(aLabels && (ECheckLabel& aFlags)) + { + TPtrC comparelabel((*aLabels)[i]); + TEST_CONDITION(label.Compare(comparelabel)==0); + } + else if (aLabels && (aFlags & EAppendLabel)) + { + TRAP_IGNORE(aLabels->AppendL(label)); + } + test.Printf(_L("%S: %S\n") ,&label, &text); // print this just to make sure + } +} + +void CDefaultVoiceParamTests::CheckCardL(TContactItemId aId, CDesCArray* aFields, CDesCArray* aLabels, TUint aFlags) const + { + CContactCard* card = STATIC_CAST(CContactCard*, iDb->OpenContactL(aId)); + CleanupStack::PushL(card); + CheckCard(card, aFields, aLabels, aFlags); + iDb->CloseContactL(aId); + CleanupStack::PopAndDestroy(card); + } + +/** +Default number is edited in PIM and synchronisation is started. +Default number is not edited in phone but new number is inserted + +1. Choose a phone number field of a phone contact as a default (For example Tel home: 1111) +2. Start synchronisation +3. Edit the contact's default number in PIM (For example Home: 1111 -> 11112222) +4. Start synchronisation +5. Default number wasn't amended in phone but new edited number detail (Tel Home 11112222) was created. +*/ +void CDefaultVoiceParamTests::TestOneL() + { + TContactItemId id = CreateItemL(KName(),KPhoneNumber()); + + CContactIdArray* array = CContactIdArray::NewLC(); + array->AddL(id); + + + ExportContactsL(KVCardFile1,array); + CreateTestDataL(id, KVCardFile2,KModifiedNumberProperty); + ImportContactsL(KVCardFile2); + ExportContactsL(KVCardFile3,array); //for checking + CleanupStack::PopAndDestroy(array); + + TEST_CONDITION(CountPhoneNumberFieldsL(id)==1); //no new field was created + } + +/** +Case2 +Default number is deleted from PIM and new number is created in PIM. +After synchronisation default number is not deleted from PIM and new number is not created to phone. +(If default number is deleted only and synch is started, default number is not deleted from phone) + + 1. Choose a phone number field of a phone contact as a default + (For example Tel home: 1111) + 2. Start Synchronisation + 3. Delete default number (Home:1111) in PIM and create a new number in PIM (Work2: 4444) + 4. Start synchronisation + 5. Default number wasn't deleted from phone and new number wasn't inserted to phone +*/ +void CDefaultVoiceParamTests::TestTwoL() + { + TContactItemId id = CreateItemL(KName,KPhoneNumber); + + CContactIdArray* array = CContactIdArray::NewLC(); + array->AddL(id); + ExportContactsL(KVCardFile1,array); + CreateTestDataL(id,KVCardFile2,KModifiedNumberProperty2); + ImportContactsL(KVCardFile2); + ExportContactsL(KVCardFile3,array); //for checking + CleanupStack::PopAndDestroy(array); + TEST_CONDITION(CountPhoneNumberFieldsL(id)==1); + + CContactItem* item = iDb->ReadContactLC(id); + CContactItemFieldSet& fieldSet = item->CardFields(); + TInt pos=fieldSet.Find(KUidContactFieldPhoneNumber); + while (pos!=KErrNotFound) + { + const CContactItemField& field = (fieldSet)[pos]; + if (field.Storage()->IsFull()) + { + CContactTextField* textfield = field.TextStorage(); + _LIT(KExpectedNumber,"4444"); + TEST_CONDITION(textfield->Text()==KExpectedNumber); + } + pos=fieldSet.FindNext(KUidContactFieldPhoneNumber,++pos); + } + CleanupStack::PopAndDestroy(item); + } + + +/** +Case3 +Default number is selected in phone, and same number is edited in PIM. +After synchronisation edited number is not syncronised at all + 1. Choose a phone number field of a phone contact as a default + (For example Tel home: 1111) + 2. Edit the same number (phone's default) for example + home 1111 to 11114444 in PIM + 3. Start Synchronisation + 4. Default number was not edited in phone. New number was inserted to phone + but number was same as the default's number. So, edited number wasn't + synchronised at all. + +*/ +void CDefaultVoiceParamTests::TestThreeL() + { + //Not sure how to simulate. I believe this is case is duplicated by TestOneL() + } + +/* +Case 4 +Default number is selected in phone, same number is deleted from PIM and new +number is created in PIM. +After synchronisation default number is not deleted from PIM but it is duplicated. + 1. Choose a phone number field of a phone contact as a default + (For example Tel home: 1111) + 2. Delete the same number (phone's default) in PIM and create a new number in PIM + 3. Start Synchronisation + 4. Default is not deleted from PIM. New number is inserted to phone but number is + same as default's. Number you created in PIM, is copied correctly to phone. + +*/ +void CDefaultVoiceParamTests::TestFourL() + { + TContactItemId id = CreateItemL(KName,KPhoneNumber); + + CContactIdArray* array = CContactIdArray::NewLC(); + array->AddL(id); + ExportContactsL(KVCardFile1,array); + CreateTestDataL(id, KVCardFile2,KModifiedNumberProperty3); + ImportContactsL(KVCardFile2); + ExportContactsL(KVCardFile3,array); //for checking + CleanupStack::PopAndDestroy(array); + TEST_CONDITION(CountPhoneNumberFieldsL(id)==1); //no new field was created + } + + +/**This checks the contact indentity fields extracted from a known vCard (KTestVcardFile) to ensure + the contact is exactly what we expect. This tests both the field value and label in the generated contact. + */ +void CDefaultVoiceParamTests::TestFiveL() + { + CDesCArray* value = new(ELeave) CDesCArrayFlat(KNumberOfExtendedFieldNames); + CleanupStack::PushL(value); + CDesCArray* label = new(ELeave) CDesCArrayFlat(KNumberOfExtendedFieldNames); + CleanupStack::PushL(label); + + for(TInt i=0;iAppendL(*((const TDesC*) GNames[i])); + label->AppendL(*((const TDesC*) GLabels[i])); + } + ImportContactsL(KTestVcardFile); + const CContactIdArray& list = *iDb->SortedItemsL(); + CheckCardL(list[0], value, label); + CleanupStack::PopAndDestroy(2,value); // + label + iDb->DeleteContactL(list[0]); + } + +/** This generates a whole bunch of conacts (KNumberOfRandomContacts) and exports them to a vCard file. + The contacts are then read back in. This tests the merge functionality of vCard parsing. + The retrieved cards' fields are checked against the original cards' fields to make sure they're the same */ +void CDefaultVoiceParamTests::TestSixL() + { + CDesCArray* fields = new(ELeave) CDesC16ArrayFlat(KNumberOfExtendedFieldNames*KNumberOfRandomContacts); + CleanupStack::PushL(fields); + + CDesCArray* labels = new(ELeave) CDesC16ArrayFlat(KNumberOfExtendedFieldNames); + CleanupStack::PushL(labels); + TInt i; + for( i=0;iAppendL(*((const TDesC*) GLabels[i])); + } + RArray allIds; + CleanupClosePushL(allIds); + + TInt64 randseed = 0; + CWordDigrams* firstname = CWordDigrams::NewLC(KFirstNameFileName, randseed); + CWordDigrams* lastname = CWordDigrams::NewLC(KLastNameFileName, randseed); + CleanupStack::Pop(lastname); + CleanupStack::Pop(firstname); + CRandomContactGenerator* generator = CRandomContactGenerator::NewL(firstname,lastname ); + + CleanupStack::PushL(generator); + + generator->SetDbL(*iDb); + RArray nameIds; + CleanupClosePushL(nameIds); + for( i = 0; iAddTypicalRandomContactWithNamesL(nameIds, ETrue); + allIds.AppendL(id); + CContactCard* card = STATIC_CAST(CContactCard*, iDb->OpenContactL(id)); + CleanupStack::PushL(card); + CheckCard(card,fields, labels,ECheckLabel|EAppendValue ); + iDb->CommitContactL(*card); + CleanupStack::PopAndDestroy(card); + } + + CleanupStack::PopAndDestroy( 2, generator ); // + nameIds + + ExportContactsL(KVCardFile1, iDb->SortedItemsL()); + ImportContactsL(KVCardFile1); + + for (i =0; iDelete(0); + } + } + CleanupStack::PopAndDestroy(3, fields ); // +label + + } + + +/** Import contacts from the vCard file specified by aFileName */ +void CDefaultVoiceParamTests::ImportContactsL(const TDesC& aFileName) + { + RFileReadStream vcard; + User::LeaveIfError(vcard.Open(iTest.Fs(), aFileName, EFileRead)); + CleanupClosePushL(vcard); + + TBool success=EFalse; + CArrayPtr* contactItems=iDb->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), vcard, success, CContactDatabase::EImportSingleContact+CContactDatabase::ETTFormat); + CleanupStack::PopAndDestroy(&vcard); + contactItems->ResetAndDestroy(); + delete contactItems; + } + +/** Export contact items specified by aIds to aFileName */ +void CDefaultVoiceParamTests::ExportContactsL(const TDesC& aFileName, const CContactIdArray* aIds) + { + RFile outfile; + outfile.Replace(iTest.Fs(),aFileName,EFileWrite); + CleanupClosePushL(outfile); + RFileWriteStream writeStream(outfile); + CleanupClosePushL(writeStream); + + TUid uid; + uid.iUid=KUidVCardConvDefaultImpl; + iDb->ExportSelectedContactsL(uid,*aIds,writeStream,CContactDatabase::EDefault); + + writeStream.CommitL(); + CleanupStack::PopAndDestroy(2); //writeStream.Close(), outfile.Close() + } + + +/** Creates a vCard with the correct UID for the contact item specified by aId. */ +void CDefaultVoiceParamTests::CreateTestDataL(TContactItemId aId, const TDesC& aFileName, const TDesC8& aVCardData) + { + RFile file; + TInt err=file.Replace(iTest.Fs(), aFileName, EFileWrite+EFileShareAny+EFileStreamText); + User::LeaveIfError(err); + TPtrC8 header((const TText8*) "BEGIN:VCARD\r\n" + "VERSION:2.1\r\n" + "REV:20020520T134824Z\r\n" + "N:Name;;;;\r\n"); + TPtrC8 footer((const TText8*) "END:VCARD\r\n"); + TPtrC8 uidProperty((const TText8*) "UID:"); + TPtrC8 endProperty((const TText8*) "\r\n"); + file.Write(header); + file.Write(uidProperty); + HBufC* buffer = iTest.ContactUidLC(aId,KMachineUniqueId); + TBuf8 des; + des.Copy(*buffer); + file.Write(des); + CleanupStack::PopAndDestroy(buffer); + file.Write(endProperty); + file.Write(aVCardData); + file.Write(footer); + file.Close(); + } + +/** Count the number of non-empty phone number fields */ +TInt CDefaultVoiceParamTests::CountPhoneNumberFieldsL(TContactItemId aId) + { + CContactItem* item = iDb->ReadContactLC(aId); + CContactItemFieldSet& fieldSet = item->CardFields(); + TInt numPhoneNumbers=0; + TInt pos=fieldSet.Find(KUidContactFieldPhoneNumber); + while (pos!=KErrNotFound) + { + const CContactItemField& field = (fieldSet)[pos]; + if (field.Storage()->IsFull()) + numPhoneNumbers++; + pos=fieldSet.FindNext(KUidContactFieldPhoneNumber,++pos); + } + CleanupStack::PopAndDestroy(item); + return numPhoneNumbers; + } + +/** Create a contact item */ +TContactItemId CDefaultVoiceParamTests::CreateItemL(const TDesC& aName, const TDesC& aNumber) + { + TContactItemId templateId = iDb->TemplateId(); + CContactItem* templateCard = iDb->ReadContactLC(templateId); + CContactCard* card=CContactCard::NewL(templateCard); + CleanupStack::PushL(card); + SetNameL(*card, KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN, aName, EFalse); + SetNameL(*card, KUidContactFieldPhoneNumber,KUidContactFieldVCardMapTEL, aNumber, EFalse); + TContactItemId id = iDb->AddNewContactL(*card); + CleanupStack::PopAndDestroy(2,templateCard); + return id; + } + + +/** + * Regression testcode for defect EXT-599EF6 "Problems appear when contact's + * default number is deleted / edited in PIM - Lotus Organizer 6.0" + * + * The basic problem is: + * SymbianOS uses TEL;VOICE in a vCard to represent a phone number + * TimeIS PC Connectivity code sends TEL;VOICE to PIM + * PIM removes VOICE property parameter + * TimeIS sends TEL back + * Contacts model does not match TEL;VOICE and TEL, so a duplicate number is added + * + */ +LOCAL_C void DefaultVoiceParamTestsL() + { + CDefaultVoiceParamTests* test = CDefaultVoiceParamTests::NewLC(*CntTest); + test->RunTestsL(); + CleanupStack::PopAndDestroy(test); + } + +/** Add KNumAccessCountContacts contacts **/ +LOCAL_C void AddNewContactsL() + { + _LIT(KNameFormat,"NAME #%d"); + _LIT(KPhoneNumber,"123"); + for (TInt ii=0;ii name; + name.Format(KNameFormat,ii); + SetNameL(*card, KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN, name, EFalse); + SetNameL(*card, KUidContactFieldPhoneNumber,KUidContactFieldVCardMapTEL, KPhoneNumber, EFalse); + CntTest->Db()->AddNewContactL(*card); + CleanupStack::PopAndDestroy(card); + } + } + + +LOCAL_C void EmptyDatabase() + { + TContactItemId theid; + TContactIter iter(*CntTest->Db()); + theid=iter.FirstL(); + while(theid!=KNullContactId ) + { + CntTest->Db()->DeleteContactL(theid); + theid=iter.NextL(); + } + } + + +enum TAccessCountFlags {EIncAccessCount,EDecAccessCount}; + +LOCAL_C void UpdateAccessCountL(TAccessCountFlags aUpdateType) + { + TContactItemId theid; + TContactIter iter(*CntTest->Db()); + theid=iter.FirstL(); + while(theid!=KNullContactId ) + { + CContactItem* contactItem=CntTest->Db()->OpenContactL(theid); + CleanupStack::PushL(contactItem); + if (contactItem->IsDeleted()) + test.Next(_L("Synchronizer knows record 2 is deleted")); + + if(aUpdateType==EIncAccessCount) + contactItem->IncAccessCount(); + else + contactItem->DecAccessCount(); + + theid=iter.NextL(); + CntTest->Db()->CommitContactL(*contactItem); + CleanupStack::PopAndDestroy(contactItem); + } + } + +/** Tests from T_EXPDEL */ +LOCAL_C void AccessCountTestsL() + { + CContactDatabase* db=CntTest->CreateDatabaseL(); + AddNewContactsL(); + TEST_CONDITION(db->CountL()==KNumAccessCountContacts); + + test.Next(_L("Increase Access Count")); + UpdateAccessCountL(EIncAccessCount); + + test.Next(_L("Removing second contact")); + TContactIter iter(*db); + TContactItemId theid=iter.FirstL(); + theid=iter.NextL(); + db->DeleteContactL(theid); + TEST_CONDITION(db->CountL()==KNumAccessCountContacts-1); + +#if defined(_DEBUG) //test case only valid in debug mode, see CContactDatabase::DeletedContactsLC for detail. + test.Next(_L("Checking DeletedContactsLC Deleted Count and Identity")); + CContactIdArray* delArray = db->DeletedContactsLC(); + TEST_CONDITION(delArray->Count() == 1); // as second contact is deleted but has access count of > 1 + TEST_CONDITION((*delArray)[0] == theid); // test the DeletedContact Id is the second Id (that was deleted above) + + CleanupStack::PopAndDestroy(delArray); +#endif //defined(_DEBUG) + + test.Next(_L("Synchronizing")); + UpdateAccessCountL(EDecAccessCount); + TEST_CONDITION(db->CountL()==KNumAccessCountContacts-1); + test.Next(_L("Exporting")); + CContactIdArray* TheIds=CContactIdArray::NewLC(); + theid=iter.FirstL(); + while(theid!=KNullContactId ) + { + TheIds->AddL(theid); + theid=iter.NextL(); + } + CFileStore* store = CDirectFileStore::ReplaceLC(CntTest->Fs(),KExpDelAFileName(),EFileWrite); + store->SetTypeL(KDirectFileStoreLayoutUid); + RStoreWriteStream outstream; + TStreamId id = outstream.CreateLC(*store); + TUid uid; + uid.iUid= KVersitEntityUidVCard; // KUidVCardConvDefaultImpl; + db->ExportSelectedContactsL(uid,*TheIds,outstream,CContactDatabase::EIncludeX); + outstream.CommitL(); + store->SetRootL(id); + store->CommitL(); + CleanupStack::PopAndDestroy(2); // store+ oustream + CleanupStack::PopAndDestroy(TheIds); + test.Next(_L("Emptying database")); + EmptyDatabase(); + } + +// +/* Test Function Implementations */ +// +TContactItemId AddContactL (CContactDatabase& aDatabase) + { + TInt bit = 0; + TContactItemId retval; + CRandomContactGenerator* generator = NULL; + + generator = CRandomContactGenerator::NewL(); + CleanupStack::PushL(generator); + + generator->SetDbL(aDatabase); + + bit |= CContactDatabase::ESmsable; + retval = generator->AddTypicalContactForFilterL(bit); + + CleanupStack::PopAndDestroy( generator ); + + return retval; + } + +void ExportContactTestL() + { + TContactItemId itemId; + RFs fsSession; + RFileWriteStream fileStream; + CContactIdArray* idArray = NULL; + CContactItem* contactAdded = NULL; + TInt firstNameIndex = KErrNotFound; + + idArray = CContactIdArray::NewL(); + + CleanupStack::PushL(idArray); + + User::LeaveIfError(fsSession.Connect()); + User::LeaveIfError(fileStream.Replace(fsSession, KOutputFileName, EFileWrite)); + + + itemId = AddContactL(*CntTest->Db()); + contactAdded = CntTest->Db()->OpenContactL(itemId); + CleanupStack::PushL(contactAdded); + + CContactItemFieldSet& fieldSet = contactAdded->CardFields(); + + firstNameIndex = fieldSet.Find(KUidContactFieldGivenName); + TEST_CONDITION(firstNameIndex != KErrNotFound); + + CContactItemField& field = fieldSet[firstNameIndex]; + field.SetLabelL(_L(" New Label ")); + + CntTest->Db()->CommitContactL(*contactAdded); + CleanupStack::PopAndDestroy(contactAdded); + contactAdded = NULL; + + + idArray->InsertL(0, itemId); + + CntTest->Db()->ExportSelectedContactsL(TUid::Uid(KUidVCardConvDefaultImpl), *idArray, fileStream, 0 /*option*/); + CntTest->Db()->ExportSelectedContactsL(TUid::Uid(KUidVCardConvDefaultImpl), *idArray, fileStream, 1 /*option*/); + + CleanupStack::PopAndDestroy(idArray); + + fileStream.Close(); + fsSession.Close(); + } + +// Export a contact which has no name field, +// and check that the exported file doesn't contain a name field: +void ExportNamelessContactTestL() + { + TContactItemId itemId; + RFs fsSession; + RFileWriteStream fileStream; + RFileReadStream readStream; + CContactIdArray* idArray = NULL; + CContactItem* contactAdded = NULL; + TInt Index = KErrNotFound; + + idArray = CContactIdArray::NewL(); + + CleanupStack::PushL(idArray); + + User::LeaveIfError(fsSession.Connect()); + User::LeaveIfError(fileStream.Replace(fsSession, KOutputFileName, EFileWrite)); + + // Create the usual random contact: + itemId = AddContactL(*CntTest->Db()); + contactAdded = CntTest->Db()->OpenContactL(itemId); + CleanupStack::PushL(contactAdded); + + // Find the name fields and remove them: + CContactItemFieldSet& fieldSet = contactAdded->CardFields(); + Index = fieldSet.Find(KUidContactFieldGivenName); + if(Index != KErrNotFound) + fieldSet.Remove(Index); + Index = fieldSet.Find(KUidContactFieldFamilyName); + if(Index != KErrNotFound) + fieldSet.Remove(Index); + Index = fieldSet.Find(KUidContactFieldAdditionalName); + if(Index != KErrNotFound) + fieldSet.Remove(Index); + Index = fieldSet.Find(KUidContactFieldPrefixName); + if(Index != KErrNotFound) + fieldSet.Remove(Index); + Index = fieldSet.Find(KUidContactFieldSuffixName); + if(Index != KErrNotFound) + fieldSet.Remove(Index); + + // Put the contact back: + CntTest->Db()->CommitContactL(*contactAdded); + CleanupStack::PopAndDestroy(contactAdded); + contactAdded = NULL; + + // Export it: + idArray->InsertL(0, itemId); + CntTest->Db()->ExportSelectedContactsL(TUid::Uid(KUidVCardConvDefaultImpl), *idArray, fileStream, 0 /*option*/); + CleanupStack::PopAndDestroy(idArray); + fileStream.Close(); + + // Verify the output by reading it in and searching it long hand: + User::LeaveIfError(readStream.Open(fsSession, KOutputFileName, EFileRead)); + HBufC8 * buf = HBufC8::NewLC(100); + TPtr8 ptr = buf->Des(); + TRAPD(ret, readStream.ReadL(ptr)); + TEST_CONDITION(ret == KErrNone || (ret == KErrEof && buf->Length() > 0)); + + // This is the important test - we should not find a name entry: + _LIT8(str, "\nN:"); + TEST_CONDITION(buf->Find(str) == KErrNotFound); + + // Clean up: + CleanupStack::PopAndDestroy(buf); + + readStream.Close(); + fsSession.Close(); + } + +//======================================================================= +//FindInFields +//Finds a given value in the field set, assumes that the fields are text. +//Used by CheckTypeSupport. +//======================================================================= +TBool FindInFields(CContactItemFieldSet& aFieldSet,TPtrC aExpectedValue) + { + for (TInt i = 0; i< aFieldSet.Count(); i++ ) + { + CContactItemField& aFieldValue = aFieldSet[i]; + TPtrC value = aFieldValue.TextStorage()->Text(); + if (value == aExpectedValue) + { + return ETrue; + } + } + + // Value not found, return false. + return EFalse; + } + +//======================================================================= +//FieldCheck +//Compares the value of the CContactItemField at aIndex of aFieldSet +//with the expected value. Used by UpdateVCardTestL +//======================================================================= +TBool FieldCheck(CContactItemFieldSet& aFieldSet,TInt aIndex,TPtrC aExpectedValue) + { + CContactItemField& aPhoneNum = aFieldSet[aIndex]; + TPtrC value = aPhoneNum.TextStorage()->Text(); + return (value == aExpectedValue); + } +//======================================================================= +//UpdateVCardTestL() +//Checks updating of a contact via a modified vcard. +//1: Contact is imported from vcardupdate1.vcf +//2: Contact is exported to vcardupdate2.vcf +//3: Contact is updated from vcardupdate3.vcf +//======================================================================= +void UpdateVCardTestL() + { + test.Next(_L("Update VCard Test")); + //Check the database is empty before we start + EmptyDatabase(); + TInt count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 0); + test.Next(_L("Database Empty")); + + RFs fsSession; + User::LeaveIfError(fsSession.Connect()); + + RFileReadStream readStream; + RFileWriteStream writeStream; + CContactIdArray* idArray = NULL; + + idArray = CContactIdArray::NewL(); + CleanupStack::PushL(idArray); + + //Import vcardupdate1.vcf + test.Next(_L("Importing contact from vcardupdate1.vcf")); + User::LeaveIfError(readStream.Open(fsSession,KVCardUpdate1, EFileRead)); + CleanupClosePushL(readStream); + TBool success=EFalse; + CArrayPtr* contactItems=CntTest->Db()->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), readStream, success, CContactDatabase::EImportSingleContact+CContactDatabase::ETTFormat); + //Store the id of the new contact - we need this later + TContactItemId contactId = (*contactItems)[0]->Id(); + idArray->InsertL(0, contactId); + readStream.Close(); + //Should be the only contact in the database at this point + count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 1); + test.Next(_L("Imported")); + + //Retrieve the new contact from the database and check the fields + CContactItem* importedContact = CntTest->Db()->ReadContactLC(contactId); + CContactItemFieldSet& importedContactFieldSet = importedContact->CardFields(); + + /* + * For this particular test we are only interested in the following field indexes: + * 5: Mobile 1 + * 6: Mobile 2 + * 29: Work tel 1 + * 30: Work tel 2 + * 31: Work tel 3 + * 32: Work tel 4 + * 33: Work tel 5 + * You can get other field indexes by using: + * + _LIT(KFormat,"%d:\t"); + for (TInt i = 0; i < importedContactFieldSet.Count();i++) + { + CContactItemField& aPhoneNum = importedContactFieldSet[i]; + TPtrC label = aPhoneNum.Label(); + test.Printf(KFormat,i); + test.Printf(label); + } + */ + + test.Next(_L("Check Mobile Number 1")); + TEST_CONDITION(FieldCheck(importedContactFieldSet,5,_L("07905111"))); + + test.Next(_L("Check Mobile Number 2")); + TEST_CONDITION(FieldCheck(importedContactFieldSet,6,_L("07906222"))); + + test.Next(_L("Check Work Number 1")); + TEST_CONDITION(FieldCheck(importedContactFieldSet,29,_L("1111111111"))); + + test.Next(_L("Check Work Number 2")); + TEST_CONDITION(FieldCheck(importedContactFieldSet,30,_L("2222222222"))); + + test.Next(_L("Check Work Number 3")); + TEST_CONDITION(FieldCheck(importedContactFieldSet,31,_L("3333333333"))); + + test.Next(_L("Check Work Number 4")); + TEST_CONDITION(FieldCheck(importedContactFieldSet,32,_L("4444444444"))); + + test.Next(_L("Check Work Number 5")); + TEST_CONDITION(FieldCheck(importedContactFieldSet,33,_L("5555555555"))); + + CleanupStack::PopAndDestroy(importedContact); + + //Export the contact to vcardupdate2.vcf + test.Next(_L("Exporting contact to vcardupdate2.vcf")); + User::LeaveIfError(writeStream.Replace(fsSession,KVCardUpdate2,EFileWrite)); + CleanupClosePushL(writeStream); + CntTest->Db()->ExportSelectedContactsL(TUid::Uid(KUidVCardConvDefaultImpl), *idArray, writeStream,0); + CleanupStack::PopAndDestroy(&writeStream); + + //Import vcardupdate3.vcf - this should have the same UID as vcardupdate2.vcf + test.Next(_L("Updating contact from vcardupdate3.vcf")); + User::LeaveIfError(readStream.Open(fsSession,KVCardUpdate3, EFileRead)); + success=EFalse; + contactItems->ResetAndDestroy(); + delete contactItems; + contactItems = CntTest->Db()->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), readStream, success, CContactDatabase::EImportSingleContact+CContactDatabase::ETTFormat); + + //We are updating the previous contact so we should still only have + //one database entry. If count == 2 here check the uids of C:\\vcardupdate2.vcf and + //Z:\\System\\Programs\\CntmodelTest\\vcardupdate3.vcf - the last digits of vcardupdate3 should match vcardupdate2 + count = CntTest->Db()->CountL(); + //TEST_CONDITION(count == 1); + test.Next(_L("Imported")); + + //Retrieve the updated contact from the database and check the fields + //Use the same contact id as before + CContactItem* updatedContact = CntTest->Db()->ReadContactLC(contactId); + CContactItemFieldSet& updatedContactFieldSet = updatedContact->CardFields(); + + test.Next(_L("Check Updated Mobile Number 1")); + TEST_CONDITION(FieldCheck(updatedContactFieldSet,5,_L("7700900329"))); + + test.Next(_L("Check Updated Mobile Number 2")); + TEST_CONDITION(FieldCheck(updatedContactFieldSet,6,_L("07700900529"))); + + test.Next(_L("Check Updated Work Number 1")); + TEST_CONDITION(FieldCheck(updatedContactFieldSet,29,_L("7700900999"))); + + test.Next(_L("Check Updated Work Number 2")); + TEST_CONDITION(FieldCheck(updatedContactFieldSet,30,_L("7700900888"))); + + test.Next(_L("Check Updated Work Number 3")); + TEST_CONDITION(FieldCheck(updatedContactFieldSet,31,_L("7700900777"))); + + test.Next(_L("Check Updated Work Number 4")); + TEST_CONDITION(FieldCheck(updatedContactFieldSet,32,_L("7700900666"))); + + test.Next(_L("Check Updated Work Number 5")); + TEST_CONDITION(FieldCheck(updatedContactFieldSet,33,_L("7700900555"))); + + //cleanup + CleanupStack::PopAndDestroy(updatedContact); + CleanupStack::PopAndDestroy(&readStream); + CleanupStack::PopAndDestroy(idArray); + fsSession.Close(); + contactItems->ResetAndDestroy(); + delete contactItems; + } + +/* +The following is the test for trailing space to test DEF051853. +*/ + +const TUint KSpaceChar = 0x20; + +_LIT( KSearchText, "\x2029" ); +_LIT( KIncommingVCard, "z:\\cntvcard\\address-with-trailing-white-space.vcf" ); +_LIT( KOutgoingVCard, "c:\\address-with-trailing-white-space-out.vcf" ); + +/** Import contacts from the vCard file specified by aFileName */ +CArrayPtr* ImportContactsL(const TDesC& aFileName, CContactDatabase& aDatabase); +void CheckForWhiteSpaceL( const TDesC& aFieldToCheck ); +void ImportAndCheckForNoTrailSpaceStrippingL(const TDesC& aFileName, CContactIdArray& aArray); +void TrailingSpaceExportContactsL(const TDesC& aFileName, CContactIdArray* aIds); +void DoTrailingSpaceImportAndExportTestL(); + +// Implementations +CArrayPtr* ImportContactsL(const TDesC& aFileName, CContactDatabase& aDatabase) + { + CArrayPtr* retval = NULL; + RFileReadStream vcard; + RFs fileSystem; + User::LeaveIfError( fileSystem.Connect() ); + CleanupClosePushL( fileSystem ); + User::LeaveIfError(vcard.Open( fileSystem, aFileName, EFileRead)); + CleanupClosePushL(vcard); + + TBool success=EFalse; + retval = aDatabase.ImportContactsL(TUid::Uid(KVersitEntityUidVCard), vcard, success, CContactDatabase::EImportSingleContact+CContactDatabase::ETTFormat); + CleanupStack::PopAndDestroy(&vcard); + CleanupStack::PopAndDestroy(&fileSystem); + + return retval; + } + +void CheckForWhiteSpaceL( const TDesC& aFieldToCheck ) + { + TInt trailingSpaceLocation = KErrNotFound; + TUint thisShouldBeASpaceChar = 0; + + trailingSpaceLocation = ( aFieldToCheck.Find(KSearchText) -1 ); + + thisShouldBeASpaceChar = aFieldToCheck[ trailingSpaceLocation ]; + test ( thisShouldBeASpaceChar == KSpaceChar ); + + } + +void ImportAndCheckForNoTrailSpaceStrippingL(const TDesC& aFileName, CContactIdArray& aArray) + { + CArrayPtr* contactList = NULL; + CContactItem* item = NULL; + TInt addressIndex = KErrNotFound; + + aArray.Reset(); + + contactList = ImportContactsL( aFileName, *CntTest->Db() ); + CleanupStack::PushL( contactList ); + + item = (*contactList)[0]; + aArray.AddL( item->Id() ); + CContactItemFieldSet& fieldSet = item->CardFields(); + + addressIndex = fieldSet.Find( KUidContactFieldAddress ); + + CContactItemField& addressField = fieldSet[ addressIndex ]; + + + TPtrC data = addressField.TextStorage()->Text(); + + CheckForWhiteSpaceL( data ); + + contactList->ResetAndDestroy(); + CleanupStack::PopAndDestroy( contactList ); + + } + +/** Export contact items specified by aIds to aFileName */ +void TrailingSpaceExportContactsL(const TDesC& aFileName, CContactIdArray* aIds) + { + RFs fsSession; + RFileWriteStream fileStream; + + User::LeaveIfError(fsSession.Connect()); + User::LeaveIfError(fileStream.Replace(fsSession, aFileName, EFileWrite)); + + CntTest->Db()->ExportSelectedContactsL(TUid::Uid(KVersitEntityUidVCard), *aIds, fileStream, 0 /*option*/); + + fileStream.Close(); + fsSession.Close(); + + } + + +void DoTrailingSpaceImportAndExportTestL() + { + CContactIdArray* idArray = NULL; + + idArray = CContactIdArray::NewL(); + CleanupStack::PushL( idArray ); + + ImportAndCheckForNoTrailSpaceStrippingL(KIncommingVCard, *idArray); + TrailingSpaceExportContactsL( KOutgoingVCard, idArray ); + + ImportAndCheckForNoTrailSpaceStrippingL(KOutgoingVCard, *idArray); + CleanupStack::PopAndDestroy( idArray ); + } + + +void ImportLargeVCardTestL() + { + test.Printf(_L("Importing large VCards")); + + EmptyDatabase(); + + RFs fsSession; + User::LeaveIfError(fsSession.Connect()); + + RFileReadStream readStream; + + // Import vcardupdate1.vcf. + test.Printf(_L("Importing contact from testvcard1.vcf")); + User::LeaveIfError(readStream.Open(fsSession,KTestVcardFile1, EFileRead)); + + CleanupClosePushL(readStream); + + TBool success=EFalse; + CArrayPtr* contactItems=CntTest->Db()->ImportContactsL( + TUid::Uid(KUidVCardConvDefaultImpl), readStream, success, + CContactDatabase::EImportSingleContact+CContactDatabase::ETTFormat); + + // If the above function does not leave or panic test has been successful. + + TEST_CONDITION(contactItems->Count() == 1); + + test.Printf(_L("Importing large VCards successful\n")); + + contactItems->ResetAndDestroy(); + delete contactItems; + + CleanupStack::PopAndDestroy(&readStream); + + fsSession.Close(); + } + + +//return the number of email fields within a contact +TInt ContactEmailCountL(TContactItemId aContactId) + { + + CContactItem *item = CntTest->Db()->ReadContactLC(aContactId); + TInt pos = 0; + TInt many = 0; + while (pos < item->CardFields().Count() ) + { + pos = item->CardFields().FindNext(KUidContactFieldEMail, pos); + if( pos == KErrNotFound ) + { + break; + } + else + { + ++many; + ++pos; + } + } + + CleanupStack::PopAndDestroy(item); + return many; + + } + +//import a single contact item from vcard into db, return id of contact in db +TContactItemId ImportVCardL(const TDesC &aVcard, const TInt aOption) + { + RFs fsSession; + User::LeaveIfError(fsSession.Connect()); + + RFileReadStream readStream; + + //Import vcf + User::LeaveIfError(readStream.Open(fsSession,aVcard, EFileRead)); + CleanupClosePushL(readStream); + TBool success=EFalse; + CArrayPtr* contactItems = CntTest->Db()->ImportContactsL( + TUid::Uid(KVersitEntityUidVCard), readStream, success, + aOption + ); + + //Store the id of the new contact - we need this later + TContactItemId contactId = (*contactItems)[0]->Id(); + contactItems->ResetAndDestroy(); + delete contactItems; + contactItems = NULL; + //cleanup + CleanupStack::PopAndDestroy(&readStream); + fsSession.Close(); + return contactId; + } + +//returns the number of non empty fields in contact +TInt ContactFilledFields(TContactItemId aContactId) + { + CContactItem *item = CntTest->Db()->ReadMinimalContactLC(aContactId); + TInt ret = item->CardFields().Count(); + CleanupStack::PopAndDestroy(item); + return ret; + } + +/** +@SYMTestCaseID PIM-T-CNTVCARD-DEF084708-0001 +@SYMTestType UT +@SYMTestPriority High +@SYMDEF DEF084708 +@SYMTestCaseDesc Vcard with full parameter description of TYPE=VALUE for properties +ADDR or TEL should be correctly imported. + +@SYMTestActions +1) import vcard with home and tel properties with parameters of TYPE=HOME and TYPE=WORK +2) check that imported contact contains the correct home and work address + +@SYMTestExpectedResults For the above tests: +On importing, the type=home and type=work fields should not be deleted. + +*/ +void CheckTypeSupport(const TDesC &inputVcard) +{ + test.Next(_L("@SYMTestCaseID:PIM-T-CNTVCARD-DEF084708-0001 Checking if the type=value parameter is handled correctly.")); + + //Check the database is empty before we start + EmptyDatabase(); + TInt count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 0); + + // First import the vcard file. + RFs fsSession; + RFileReadStream readStream; + User::LeaveIfError(fsSession.Connect()); + test.Printf(_L("Importing contact ")); + User::LeaveIfError(readStream.Open(fsSession,inputVcard, EFileRead)); + CleanupClosePushL(readStream); + TBool success=EFalse; + CArrayPtr* contactItems=CntTest->Db()->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), readStream, success, CContactDatabase::EImportSingleContact+CContactDatabase::ETTFormat); + readStream.Close(); + + //Should be the only contact in the database at this point + count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 1); + test.Printf(_L("Imported the contact item")); + + // Check that the home address and work address has been imported correctly into the card. + test.Printf(_L("Find whether all the address fields are present.")); + TContactItemId contactId = (*contactItems)[0]->Id(); + CContactItem* importedContact = CntTest->Db()->ReadContactLC(contactId); + CContactItemFieldSet& fieldSet = importedContact->CardFields(); + + TEST_CONDITION(FindInFields(fieldSet, _L("W211"))); + TEST_CONDITION(FindInFields(fieldSet, _L("W212"))); + TEST_CONDITION(FindInFields(fieldSet, _L("W213"))); + TEST_CONDITION(FindInFields(fieldSet, _L("W214"))); + TEST_CONDITION(FindInFields(fieldSet, _L("W215"))); + + TEST_CONDITION(FindInFields(fieldSet, _L("H211"))); + TEST_CONDITION(FindInFields(fieldSet, _L("H212"))); + TEST_CONDITION(FindInFields(fieldSet, _L("H213"))); + TEST_CONDITION(FindInFields(fieldSet, _L("H214"))); + TEST_CONDITION(FindInFields(fieldSet, _L("H215"))); + + // Check that the phone number has been correctly imported + TEST_CONDITION(FindInFields(fieldSet, _L("222222222222222222"))); + TEST_CONDITION(FindInFields(fieldSet, _L("333333333333333333"))); + + //cleanup + CleanupStack::PopAndDestroy(importedContact); + CleanupStack::PopAndDestroy(&readStream); + fsSession.Close(); + contactItems->ResetAndDestroy(); + delete contactItems; +} + +/** +@SYMTestCaseID PIM-T-CNTVCARD-DEF081712-0001 +@SYMTestType UT +@SYMTestPriority High +@SYMDEF DEF081712 +@SYMTestCaseDesc Contact properties on device not deleted during synchronisation + +@SYMTestActions +1) import vcard with 3 emails +2) check that imported contact contains 3 email fields +3) update uid of imported contact to 8 +4) import vcard with no email fields and uid 8 +5) check that all email fields are deleted +6) check that no other fields have been deleted + +@SYMTestExpectedResults For the above tests: +It should be possible to delete multiple fields of the same type when a vcard is imported +*/ + +void VCardEmailTestL() + { + const TInt importOption = + CContactDatabase::ELocalTime | + CContactDatabase::EImportSingleContact | + CContactDatabase::ENullTemplateId; + + test.Next(_L("@SYMTestCaseID:PIM-T-CNTVCARD-DEF081712-0001 VCard Email Test")); + //start with fresh/clean database + CntTest->CreateDatabaseL(); + TInt count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 0); + + test.Next(_L("Importing initial contact from 1.vcf")); + TContactItemId contactId = ImportVCardL( KVcard1, importOption ); + TInt initialcount = ContactFilledFields(contactId); + + count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 1); + + CContactItem *item = CntTest->Db()->OpenContactLX(contactId); + CleanupStack::PushL( item ); + + _LIT(guid, "8"); + item->SetUidStringL( const_cast( guid() ) ); + CntTest->Db()->CommitContactL( *item ); + CleanupStack::PopAndDestroy(item); + CleanupStack::Pop();//lock + item = NULL; + + test.Next(_L("check number of email fields")); + TEST_CONDITION(ContactEmailCountL(contactId) == 3); + + test.Next(_L("reimport contact from 2.vcf")); + contactId = ImportVCardL( KVcard2, importOption ); + count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 1); + + TInt updatedcount = ContactFilledFields(contactId); + + test.Next(_L("check email fields are deleted")); + TEST_CONDITION(ContactEmailCountL(contactId) == 0); + + test.Next(_L("check no other fields are cleared or deleted")); + TEST_CONDITION( updatedcount == (initialcount - 3) ); + + } + +/** +@SYMTestCaseID PIM-T-CNTVCARD-DEF083613-0001 +@SYMTestType UT +@SYMTestPriority High +@SYMDEF DEF083613 +@SYMTestCaseDesc A VCard with lines terminated by LF(line-feed)s only is not imported correctly. + +@SYMTestActions +1) import a vcard containing only line-feed line terminators. +2) Check that the import was successful. + +@SYMTestExpectedResults The vcard containing only LF line terminators is imported correctly. +*/ + +void VCardLineFeedOnlyTestL() + { + const TInt importOption = + CContactDatabase::ELocalTime | + CContactDatabase::EImportSingleContact | + CContactDatabase::ENullTemplateId; + + TRAPD(err, ImportVCardL( KVCardFileLF, importOption )); + TEST_CONDITION(err==0); + } +/** +@SYMTestCaseID PIM-T-CNTVCARD-DEF085873-0001 +@SYMTestType UT +@SYMTestPriority High +@SYMDEF DEF085873 +@SYMTestCaseDesc Check that use of the CContactVCardConverter::EIgnoreUid flag +behaves correctly. + +@SYMTestActions +1) Empty database. +2) Import a vcard containing a UID without using the flag. +3) Check there is only one contact in the database. +4) Import the same vcard without using the flag. The import should count as an +update of the existing contact item. +5) Check there is only one contact in the database. +6) Import the same vcard using the flag. The import should count as an add of +a new item. +7) Check there are now 2 contacts in the database. + +@SYMTestExpectedResults The vcard is added to the database a second time when +the CContactVCardConverter::EIgnoreUid flag is used. +*/ +void VCardIgnoreUidTestL() + { + const TInt importOption1 = CContactDatabase::ELocalTime; + + const TInt importOption2 = + CContactDatabase::ELocalTime | + CContactVCardConverter::EIgnoreUid; + + test.Next(_L("@SYMTestCaseID:PIM-T-CNTVCARD-DEF085873-0001 Check that use of the CContactVCardConverter::EIgnoreUid flag behaves correctly.")); + + // 1) Empty database. + EmptyDatabase(); + TInt count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 0); + + // 2) Import a vcard containing a UID without using the flag. + TRAPD(err, ImportVCardL( KVCardFileUID, importOption1 )); + TEST_CONDITION(err==0); + + // 3) Check there is only one contact in the database. + count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 1); + + // 4) Import the same vcard without using the flag. The import should count + // as an update of the existing contact item. + TRAP(err, ImportVCardL( KVCardFileUID, importOption1 )); + TEST_CONDITION(err==0); + + // 5) Check there is only one contact in the database. + count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 1); + + // 6) Import the same vcard using the flag. The import should count as an + // add of a new item. + TRAP(err, ImportVCardL( KVCardFileUID, importOption2 )); + TEST_CONDITION(err==0); + + // 7) Check there are now 2 contacts in the database. + count = CntTest->Db()->CountL(); + TEST_CONDITION(count == 2); + } +/*@SYMTestPriority High +@SYMDEF PDEF097999 +@SYMTestCaseDesc The identity table is not updated if we pass a null value for +updation (as a result sorting goes wrong) +@SYMTestActions +1) Import a vcard containing firstname and lastname. +2) Import the same vcf file but without having lastname for one entry +3) Check whether the old lastname is present for that entry. + +@SYMTestExpectedResults The identity table must be updated even if we give a null value for lastname. +so if we search for the old lastname it should not be there . +*/ +LOCAL_C void TestImportContactsL(const TDesC& aFileName1 , const TDesC& aFileName2 , const TDesC8& aVcfData1 , const TDesC8& aVcfData2) + { + test.Next(_L("checking Updation of Identity table")); + CContactDatabase *db=CntTest->CreateDatabaseL(); + + RFs fileSystem; + User::LeaveIfError( fileSystem.Connect() ); + CleanupClosePushL( fileSystem ); + //Creating input Vcf files + RFile file; + file.Replace(fileSystem, aFileName1, EFileWrite+EFileShareAny+EFileStreamText); + file.Write(aVcfData1); + file.Close(); + + file.Replace(fileSystem, aFileName2, EFileWrite+EFileShareAny+EFileStreamText); + file.Write(aVcfData2); + file.Close(); + + RFileReadStream vcard; + User::LeaveIfError(vcard.Open(fileSystem, aFileName1, EFileRead)); + CleanupClosePushL(vcard); + TBool success=EFalse; + CArrayPtr* contactItems=db->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), vcard, success, CContactDatabase::ETTFormat); + CleanupStack::PopAndDestroy(&vcard); + contactItems->ResetAndDestroy(); + delete contactItems; + + User::LeaveIfError(vcard.Open(fileSystem, aFileName2, EFileRead)); + CleanupClosePushL(vcard); + success=EFalse; + contactItems=db->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), vcard, success, CContactDatabase::ETTFormat); + CleanupStack::PopAndDestroy(&vcard); + + //Search for "Bbb" it must not be there + CContactItemFieldDef* fieldDef = new(ELeave) CContactItemFieldDef; + TFieldType fieldtype = KUidContactFieldFamilyName; + fieldDef->AppendL(fieldtype); + CContactIdArray* matchList = db->FindLC(_L("Bbb"), fieldDef); + TInt matchCount = matchList->Count(); + //Count zero means the vcard has been updated properly + TEST_CONDITION(matchCount==0); + test.Printf (_L("Sucessfully modified identity table")); + CleanupStack::PopAndDestroy(matchList); + contactItems->ResetAndDestroy(); + delete contactItems; + delete fieldDef; + CntTest->CloseDatabase(); + CleanupStack::PopAndDestroy(&fileSystem); + } + + CArrayPtr* ImportContactsL(const TDesC8& aImportFileInputDescriptor, CContactDatabase* aDatabase) + { + CArrayPtr* retval = NULL; + + // read the input contents + RDesReadStream vCard(aImportFileInputDescriptor); + CleanupClosePushL(vCard); + + //import + TBool success=EFalse; + retval = aDatabase->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), vCard, success, CContactDatabase::EDefault); + + CleanupStack::PopAndDestroy(&vCard); + return retval; + } + +void TestStorageType( CContactItem *aContactItem, TStorageType aExpectedStorageType) + { + //verify test + TInt fieldIndex = aContactItem->CardFields().Find(KUidContactFieldVCardMapKEY); + TStorageType storageType = aContactItem->CardFields()[fieldIndex].StorageType(); + TEST_CONDITION(storageType == aExpectedStorageType); + test.Next(_L("ImportExportVCardWithKeyL passed")); + } + + /** + @SYMTestCaseID PIM-T-CNTVCARD-DEF097565-0001 + @SYMTestType UT + @SYMTestPriority Medium + @SYMDEF DEF097565 + @SYMTestCaseDesc Importr the vcf file and then check whether the BInary Key is imported + properly or not. + + @SYMTestActions + 1) Create an empty database. + 2) Import a vcard. + 3) Check there is Key field imported is having storage type KStorageTypeStore. + + @SYMTestExpectedResults The vcard is containing the Binary Key value. + */ + void ImportExportVCardWithKeyL(const TDesC8& aImportFileInputDescriptor, TStorageType aExpectedStorageType) + { + test.Next(_L("@SYMTestCaseID:PIM-T-CNTVCARD-DEF097565-0001 ImportExportVCardWithKeyL Begins")); + + CntTest->CreateDatabaseL(); + + //import + CArrayPtr * contactItems = NULL; + contactItems = ImportContactsL(aImportFileInputDescriptor, CntTest->Db()); + + //verify test + TestStorageType((contactItems->At(0)), aExpectedStorageType); + + // reclaim memory + contactItems->ResetAndDestroy() ; + delete contactItems; + + CntTest->CloseDatabase(); + } +/** +@SYMTestCaseID PIM-T-CNTVCARD-INC096705-0001 +@SYMTestType UT +@SYMTestPriority Medium +@SYMDEF INC096705 +@SYMTestCaseDesc Check that use of the CContactVCardConverter::EReplaceIfExists flag +behaves correctly. + +@SYMTestActions +1) Empty database. +2) Import a vcard containing a company field with EDefault flag. +3) Check of company field is imported +4) Import the same vcard without company field and using CContactVCardConverter::EReplaceIfExists option + +@SYMTestExpectedResults The vcard is replaced with the contact in the database when +the CContactVCardConverter::EReplaceIfExists flag is used. +*/ +void ImportVCardWithFlagReplaceIfExitstL() +{ + CContactDatabase *db=CntTest->CreateDatabaseL(); + test.Next(_L("@SYMTestCaseID:PIM-T-CNTVCARD-INC096705-0001 hecking Replacing old contact with new one")); + const TInt importOption1 = CContactDatabase::EDefault; + const TInt importOption2 = CContactDatabase::EConverterReserved2; + + // 1) Empty database. + EmptyDatabase(); + TInt count = db->CountL(); + TEST_CONDITION(count == 0); + + // 2) Import a vcard containing company filed with CContactDatabase::EDefault flag. + // and ensure company field gets imported + test.Next(_L("Importing Contact with Company field")); + TContactItemId aContactId = ImportVCardL( KVCardWithCompany, importOption1 ); + CContactItem *item = db->ReadContactLC(aContactId); + CContactItemFieldSet& fieldSet = item->CardFields(); + TInt companyIndex = fieldSet.Find( KUidContactFieldCompanyName ); + TEST_CONDITION(companyIndex != KErrNotFound ); + const CContactItemField& field = (fieldSet)[companyIndex]; + TEST_CONDITION(field.Storage()->IsFull() != 0); + CContactTextField* textfield = field.TextStorage(); + _LIT(KExpectedNumber,"XYZ ltd"); + TEST_CONDITION(textfield->Text()==KExpectedNumber); + CleanupStack::PopAndDestroy(item); + + //3)Import a vcard without containing company filed with CContactDatabase::EDefault flag. + // and ensure company field gets merged + test.Next(_L("Importing Same Contact and merging the old contact without company field")); + TContactItemId aContactId1 = ImportVCardL( KVCardWithoutCompany, importOption1 ); + + //4) Ensure that company field should be there + CContactItem *item1 = db->ReadContactLC(aContactId1); + CContactItemFieldSet& fieldSet1 = item1->CardFields(); + TInt companyIndex1 = fieldSet1.Find( KUidContactFieldCompanyName ); + TEST_CONDITION(companyIndex1 != KErrNotFound ); + const CContactItemField& field1 = (fieldSet1)[companyIndex1]; + TEST_CONDITION(field1.Storage()->IsFull() != 0); + CContactTextField* textfield1 = field1.TextStorage(); + _LIT(KExpectedNumber1,"XYZ ltd"); + TEST_CONDITION(textfield1->Text()==KExpectedNumber1); + + CleanupStack::PopAndDestroy(item1); + + //5) Import the same vcard without company field and using CContactVCardConverter::EReplaceIfExists option + test.Next(_L("Importing Same Contact and replacing with the old contact without company field")); + TContactItemId aContactId2 = ImportVCardL( KVCardWithoutCompany, importOption2 ); + + //6) Ensure that company field should not be there + CContactItem *item2 = db->ReadContactLC(aContactId2); + CContactItemFieldSet& fieldSet2 = item2->CardFields(); + TInt companyIndex2 = fieldSet2.Find( KUidContactFieldCompanyName ); + const CContactItemField& field2 = (fieldSet2)[companyIndex2]; + TEST_CONDITION(field2.Storage()->IsFull() == 0); + CleanupStack::PopAndDestroy(item2); +} + + /** + @SYMTestCaseID PIM-T-CNTVCARD-INC110795-0001 + @SYMTestType UT + @SYMTestPriority Medium + @SYMDEF INC110795 + @SYMTestCaseDesc Check the use of import option with CContactVCardConverter::EReplaceIfExists flag + behaves correctly with duplicate fields. + + @SYMTestActions + 1) Empty database. + 2) Import a vcard containing 2 Home Tel fields with EDefault flag. + 3) Check of all fields are imported + 4) Import the same vcard with 4 modified Home Tel fields and using CContactVCardConverter::EReplaceIfExists option + + @SYMTestExpectedResults The vcard is replaced with the contact in the database when + the CContactVCardConverter::EReplaceIfExists flag is used. + */ + void ImportDuplicateFieldVCardWithReplaceIfExitstL() + { + + test.Next(_L("@SYMTestCaseID:PIM-T-CNTVCARD-INC110795-0001 checking Replacing existing contact with new one (has duplicate fields) using EReplaceIfExists")); + + const TInt importOption1 = CContactDatabase::EDefault; + const TInt importOption2 = CContactDatabase::EDefault| + CContactDatabase::EImportSingleContact| + CContactDatabase::ENullTemplateId | + CContactVCardConverter::EReplaceIfExists; + + + CContactDatabase *db=CntTest->CreateDatabaseL(); + + // 1) Empty database. + EmptyDatabase(); + TInt count = db->CountL(); + test(count == 0); + + // 2) Import a vcard containing 2 Home Tel fields with CContactDatabase::EDefault flag. + test.Next(_L("Importing Contact with 2 duplicate Home Tel fields")); + TContactItemId contactId; + + RDesReadStream vcard(KVCardBeforeChange()); + CleanupClosePushL(vcard); + + CArrayPtr* contactItems; + TBool success = EFalse; + contactItems = db->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), vcard, success, importOption1); + CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,contactItems)); + contactId = (*contactItems)[0]->Id(); + CleanupStack::PopAndDestroy(contactItems); + CleanupStack::PopAndDestroy(&vcard); + + CContactItem *item = db->ReadContactLC(contactId); + CContactItemFieldSet& fieldSet = item->CardFields(); + + // Ensure all fields get imported + test(FindInFields(fieldSet, TPtrC16(KGivenName()))); + test(FindInFields(fieldSet, TPtrC16(KFamilyName()))); + test(FindInFields(fieldSet, TPtrC16(KTelHome1()))); + test(FindInFields(fieldSet, TPtrC16(KTelHome2()))); + test(FindInFields(fieldSet, TPtrC16(KTelCell()))); + + CleanupStack::PopAndDestroy(item); + + + //3) Import the same vcard with 4 modified Home tel fields and using + //CContactVCardConverter::EReplaceIfExists option + test.Next(_L("Importing Same Contact and replacing the old contact with 4 modified Home Tel field using EReplaceIfExists")); + + RDesReadStream vcard2(KVCardAfterChange()); + CleanupClosePushL(vcard2); + + success = EFalse; + contactItems = db->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), vcard2, success, importOption2); + CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,contactItems)); + contactId = (*contactItems)[0]->Id(); + CleanupStack::PopAndDestroy(contactItems); + CleanupStack::PopAndDestroy(&vcard2); + + item = db->ReadContactLC(contactId); + + CContactItemFieldSet& fieldSet2 = item->CardFields(); + + //4) Ensure that the all 4 Home TEL field have been modified + test(FindInFields(fieldSet2, TPtrC16(KGivenName()))); + test(FindInFields(fieldSet2, TPtrC16(KFamilyName()))); + test(FindInFields(fieldSet2, TPtrC16(KTelHome1Modified()))); + test(FindInFields(fieldSet2, TPtrC16(KTelHome2Modified()))); + test(FindInFields(fieldSet2, TPtrC16(KTelHome3Modified()))); + test(FindInFields(fieldSet2, TPtrC16(KTelHome4Modified()))); + + CleanupStack::PopAndDestroy(item); + } + +/** +Utility function to check if a specific line is present in a file +*/ +TBool CheckExportFilesL(const TDesC8& aString, const TDesC16& aFile) + { + RFile fileHandle; + TBool patternFound = EFalse; + fileHandle.Open(CntTest->Fs(), aFile, EFileRead|EFileStreamText); + CleanupClosePushL(fileHandle); + TBuf8<256> line; + + while(fileHandle.Read(line) == KErrNone && line.Length() != 0) + { + if (line.Find(aString) != KErrNotFound) + { + patternFound = ETrue; + break; + } + } + + CleanupStack::PopAndDestroy(&fileHandle); + return patternFound; + } + +/** +@SYMTestCaseID PIM-T-CNTVCARD-INC102410-0001 +@SYMTestType UT +@SYMTestPriority Critical +@SYMTestCaseDesc Properties having multiple parameters should be imported properly. + +@SYMTestActions +1.Import vCard having property with multiple parameter. +2.Open imported contact and check if parameter values have been added as fields. +3.Export imported contact and check if the property has been exported properly. + +@SYMTestExpectedResults For the above tests: +1.vCard should be imported without losing data. +2.Necessary parameters should be added as fields in contact. +3.Exported file should contain all the parameters which were there while importing. +4.No leaves or panics should occur +*/ +void TestMultipleParamsInVCardPropertyL() + { + test.Next(_L("@SYMTestCaseID:PIM-T-CNTVCARD-INC102410-0001 Test Import of property having multiple parameters")); + CntTest->CreateDatabaseL(); + TContactItemId contactId; + + RDesReadStream vcard(KMultiParam()); + CleanupClosePushL(vcard); + + CArrayPtr* contactItems; + TBool success = EFalse; + contactItems = CntTest->Db()->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), vcard, success, CContactDatabase::ETTFormat); + CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,contactItems)); + contactId = (*contactItems)[0]->Id(); + CleanupStack::PopAndDestroy(contactItems); + CleanupStack::PopAndDestroy(&vcard); + + CContactItem* item = CntTest->Db()->ReadContactLC(contactId); + + CContactItemFieldSet& fields = item->CardFields(); + TInt fieldPos = fields.FindNext(KUidContactFieldVCardMapTEL, KContactFieldSetSearchAll); + const CContentType& content = fields[fieldPos].ContentType(); + + TBool result = 0; + result = content.ContainsFieldType(KUidContactFieldVCardMapCELL); + TEST_CONDITION(result > 0); + + result = content.ContainsFieldType(KUidContactFieldVCardMapVOICE); + TEST_CONDITION(result > 0); + + result = content.ContainsFieldType(KUidContactFieldVCardMapHOME); + TEST_CONDITION(result > 0); + + CleanupStack::PopAndDestroy(item); //destroying contact item + + CContactIdArray* idArray = CContactIdArray::NewL(); + CleanupStack::PushL(idArray); + idArray->AddL(contactId); + + RFileWriteStream fileStream; + User::LeaveIfError(fileStream.Replace(CntTest->Fs(), KOutputFileName, EFileWrite)); + CleanupClosePushL(fileStream); + + CntTest->Db()->ExportSelectedContactsL(TUid::Uid(KUidVCardConvDefaultImpl), *idArray, fileStream,0); + fileStream.CommitL(); + CleanupStack::PopAndDestroy(&fileStream); + + result = CheckExportFilesL(KTelExport(), KOutputFileName()); + TEST_CONDITION(result > 0); + + + CleanupStack::PopAndDestroy(); //destroying id array + } + +/** +@SYMTestCaseID PIM-T-CNTVCARD-PDEF103252-0001 +@SYMTestType UT +@SYMTestPriority High +@SYMTestCaseDesc Contact item having a large binary field should be exported properly without any leaves. + +@SYMTestActions +1.Import vCard having PHOTO propery with very large property value. +2.Export the imported contacts. +3.Import the exported contacts. +4.Compare the value of the PICTURE field present in the contact items resultin from two Import actions performed. + +@SYMTestExpectedResults For the above tests: +1.vCard should be Exported without losing data or causing any low memory leaves. +2.The Imported PHOTO data should be same in both cases. +.No leaves or panics should occur +*/ +void TestExportofContactHavingLargeBinaryFieldL() + { + test.Next(_L("@SYMTestCaseID:PIM-T-CNTVCARD-PDEF103252-0001 Test Export of contact having large binary field")); + + // Empty the Database + CntTest->CreateDatabaseL(); + CContactIdArray* idarray = CContactIdArray::NewL(); + CleanupStack::PushL(idarray); + RFs fsSession; + User::LeaveIfError(fsSession.Connect()); + RFileReadStream readStream; + + //Import vcard with large PHOTO property + test.Printf(_L("Importing contacts from VCard")); + User::LeaveIfError(readStream.Open(fsSession, KVCardLargePhoto, EFileRead)); + CleanupClosePushL(readStream); + TBool success = EFalse; + CArrayPtr* contactItems = CntTest->Db()->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), + readStream, success, CContactDatabase::ETTFormat); + + CleanupStack::PushL( TCleanupItem( CleanUpResetAndDestroy, contactItems ) ); + + TEST_CONDITION(contactItems->Count() == 1) ; + + //adding imported contact Id's to idarray for export + idarray->AddL((*contactItems)[0]->Id()); + + CleanupStack::PopAndDestroy(contactItems); + CleanupStack::PopAndDestroy(&readStream); + + test.Printf(_L("Exporting the Imported contacts, Testing it for both vCard2.1 and vCard3.0 export.")); + RFileWriteStream writeStream; + TUid uid; + + //vCard3.0 + User::LeaveIfError(writeStream.Replace(fsSession,KVCardFile2, EFileWrite)); + CleanupClosePushL(writeStream); + uid.iUid = KUidPBAPVCardConvImpl; + TInt64 filter = 0; + filter |= 0x08; + //This call should not leave with a Low memory Error + CntTest->Db()->ExportSelectedContactsL(uid, *idarray, writeStream, CContactDatabase::EDefault, filter, NULL, EPBAPVCard30,ETrue); + writeStream.CommitL(); + CleanupStack::PopAndDestroy(&writeStream); + + //vCard2.1 + User::LeaveIfError(writeStream.Replace(fsSession, KVCardFile3, EFileWrite)); + CleanupClosePushL(writeStream); + uid.iUid = KUidVCardConvDefaultImpl; + //This call should not leave with a Low memory Error + CntTest->Db()->ExportSelectedContactsL(uid, *idarray, writeStream, CContactDatabase::EDefault); + writeStream.CommitL(); + CleanupStack::PopAndDestroy(&writeStream); + CleanupStack::PopAndDestroy(idarray); + + test.Printf(_L("Export of large binary property completed successfully")); + +} + +/** +@SYMTestCaseID PIM-T-CNTVCARD-PDEF140328-0001 +@SYMTestType UT +@SYMTestPriority High +@SYMTestCaseDesc Partial vCard's should be processed without any panics + +@SYMTestActions +1.Import a partial vCard. + +@SYMTestExpectedResults For the above tests: +1.There should be no panics while import is happening. +*/ + void TestImportingPartialOrEmptyVCardsL() +{ + test.Next(_L("Test import of partial vCard")); + CArrayPtr* contactItems = NULL; + RDesReadStream vcard(KPartialVCard()); + CleanupClosePushL(vcard); + TInt success = EFalse; + CContactDatabase* db = CntTest->CreateDatabaseL(); + contactItems = db->ImportContactsL(TUid::Uid(KUidVCardConvDefaultImpl), vcard, success, CContactDatabase::EImportSingleContact); + CleanupStack::PushL( TCleanupItem( CleanUpResetAndDestroy, contactItems ) ); + CleanupStack::PopAndDestroy(contactItems); + CleanupStack::PopAndDestroy(&vcard); + test.Printf(_L("Import of partial vCard completed successfully")); +} + + +/** + +@SYMTestCaseID PIM-T-CNTVCARD-0001 + +*/ + +LOCAL_C void DoTestsL() + { + test.Start(_L("@SYMTestCaseID:PIM-T-CNTVCARD-0001 Preparing tests")); + CTestRegister* TempFiles = CTestRegister::NewLC(); + TempFiles->RegisterL(KVCardFile1); + TempFiles->RegisterL(KVCardFile2); + TempFiles->RegisterL(KVCardFile3); + TempFiles->RegisterL(KVCardUpdate2); + TempFiles->RegisterL(KDatabaseFileName, EFileTypeCnt); + TempFiles->RegisterL(KOutputFileName); + TempFiles->RegisterL(KExpDelAFileName); + TempFiles->RegisterL(KImpTypeVcardName); + TempFiles->RegisterL(KImpNoTypeVcardName); + TempFiles->RegisterL(KVCardFile5); + TempFiles->RegisterL(KVCardFile6); + + //without the fix this test will cause User 21 panic in versit + TestImportingPartialOrEmptyVCardsL(); + VCardEmailTestL(); + AccessCountTestsL(); + DefaultVoiceParamTestsL(); + ExportContactTestL(); + ExportNamelessContactTestL(); +#if defined(_DEBUG) + //this test cannot be run in release mode due to UID mismatch + //UpdateVCardTestL(); +#endif + + ImportLargeVCardTestL() ; + + DoTrailingSpaceImportAndExportTestL() ; + VCardLineFeedOnlyTestL(); + VCardIgnoreUidTestL(); + CheckTypeSupport(KImpTypeVcardName); + CheckTypeSupport(KImpNoTypeVcardName); + TestImportContactsL(KVCardFile5, KVCardFile6, KMasterVcard, KModifierVcard); + // ImportExportVCardWithBinaryKeyL called with binary KEY value + ImportExportVCardWithKeyL(KVCardBinaryKeyImportFileDes, KStorageTypeStore); + // ImportExportVCardWithBinaryKeyL called with text KEY value + ImportExportVCardWithKeyL(KVCardTextKeyImportFileDes, KStorageTypeText); + ImportVCardWithFlagReplaceIfExitstL(); + ImportDuplicateFieldVCardWithReplaceIfExitstL(); + + TestMultipleParamsInVCardPropertyL(); + TestExportofContactHavingLargeBinaryFieldL(); + + CntTest->CloseDatabase(); + CleanupStack::PopAndDestroy(TempFiles); + } + + +LOCAL_C void CleanupFilesL() + { + // delete the database file + if (CContactDatabase::ContactDatabaseExistsL(KDatabaseFileName) ) + { + CContactDatabase::DeleteDatabaseL(KDatabaseFileName); + } + } + + +LOCAL_C void TestCondition(TBool aCondition, TInt aLineNumber) + { + // if the test is about to fail, cleanup files first + if (!aCondition) + { + TRAP_IGNORE(CleanupFilesL()); + } + test.operator()(aCondition, aLineNumber); + } + + +GLDEF_C TInt E32Main() + { + __UHEAP_MARK; + CntTest=new(ELeave) CCntTest(); + CntTest->ConstructL(test,KDatabaseFileName); + TRAPD(err,DoTestsL()); + // ensure files are cleaned up even if DoTestsL() leaves + TRAP_IGNORE(CleanupFilesL() ); + CntTest->EndTestLib(err); + __UHEAP_MARKEND; + return KErrNone; + }