diff -r 000000000000 -r e686773b3f54 phonebookengines/contactsmodel/tsrc/t_iccmultiplephonebook.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines/contactsmodel/tsrc/t_iccmultiplephonebook.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,983 @@ +// Copyright (c) 2001-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: +// + +#include +#include +#include +#include +#include +#include + +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "cntsyncecom.h" +#endif + +// include templates for CleanupResetAndDestroyPushL(T) +#include "cntviewprivate.h" + +#include "T_UTILS.H" +#include "cntsyncchecker.h" + +_LIT(KTestName,"CContactICCEntry tests with multiple phonebooks"); +_LIT(KDatabaseFileName,"C:T_ICCMULTIPLEPHONEBOOK"); +_LIT(KGivenEditName,"edited name"); +_LIT(KIccName,"icc entry name"); +_LIT(KNonIccName,"non-icc name"); +_LIT(KIccNumber,"020 794 60123"); +_LIT(KNonIccNumber,"020 794 60060"); + +_LIT(KPluginName,"phone book synchronizer Implementation"); +_LIT(KTestPluginName,"Test phone book synchronizer Implementation"); + +CCntTest* CntTest=NULL; +LOCAL_D RTest test(KTestName); + +LOCAL_D CContactSyncChecker* syncChecker; + +//=============================================================================================== +// SETUP & UTILITIES +//=============================================================================================== +class TFieldEntry + { + public: + TFieldEntry(TFieldType aField); + TFieldEntry(TFieldType aField,TUid aFieldType); + public: + TFieldType iField; + TUid iFieldType; + }; + +TFieldEntry::TFieldEntry(TFieldType aField) +:iField(aField) +,iFieldType(KUidIccPhonebookNotFound) + {} + +TFieldEntry::TFieldEntry(TFieldType aField,TUid aFieldType) +:iField(aField) +,iFieldType(aFieldType) + {} + +/** + * Create a new template and add it to the database + * @param aDb Contact database + * @param aTemplateName Name for the template + * @param aFieldSet Array of fields which should are added to the template + * @return TContactItemId Id of the newly created template + */ +TContactItemId CreatePhonebookTemplateL(CContactDatabase& aDb, const TDesC& aTemplateName, RArray& aFieldSet) + { + CContactItem* temp = aDb.CreateContactCardTemplateLC(aTemplateName); + TContactItemId templateId = temp->Id(); + CleanupStack::PopAndDestroy(temp); + temp=NULL; + + //Remove all the unnecessary fields + temp = aDb.OpenContactLX(templateId); + CleanupStack::PushL(temp); + const TInt fieldCount = temp->CardFields().Count(); + for(TInt i=fieldCount-1;i>=0;i--) + temp->RemoveField(i); + + // Add each of the required fields to the template + for (TInt j=0; jAddFieldTypeL(fieldEntry.iFieldType); + temp->AddFieldL(*field); + CleanupStack::Pop(field); + } + + aDb.CommitContactL(*temp); + CleanupStack::PopAndDestroy(2); // temp, close template + + return templateId; + } + +/** + * Return an array of fields for the phonebook specified + * @param aPhonebookUid The phonebook uid + * @return RArray Field set for this specific phonebook. Any contact item + * which belongs to this phonebook should contain these fields + */ +RArray fieldSetForPhonebook(TUid aPhonebookUid) + { + RArray entries; + entries.Append(TFieldEntry(KUidContactFieldFamilyName)); + entries.Append(TFieldEntry(KUidContactFieldGivenName)); + entries.Append(TFieldEntry(KUidContactFieldPhoneNumber,KUidContactFieldVCardMapHOME)); + entries.Append(TFieldEntry(KUidContactFieldICCPhonebook)); + + if (aPhonebookUid==KUidUsimAppAdnPhonebook) + { + entries.Append(TFieldEntry(KUidContactFieldEMail,KUidContactFieldVCardMapHOME)); + entries.Append(TFieldEntry(KUidContactFieldEMail,KUidContactFieldVCardMapWORK)); + entries.Append(TFieldEntry(KUidContactFieldPhoneNumber,KUidContactFieldVCardMapHOME)); + entries.Append(TFieldEntry(KUidContactFieldPhoneNumber,KUidContactFieldVCardMapWORK)); + entries.Append(TFieldEntry(KUidContactFieldPhoneNumber,KUidContactFieldVCardMapCELL)); + entries.Append(TFieldEntry(KUidContactFieldPhoneNumber,KUidContactFieldVCardMapPAGER)); + } + + return entries; + } + +void SetUpIccPhonebooksL(CContactDatabase& aDb) + { + test.Next(_L("Set up phonebooks")); + RArray phbkList; + CleanupClosePushL(phbkList); + + phbkList.AppendL(KUidIccGlobalAdnPhonebook); + phbkList.AppendL(KUidIccGlobalSdnPhonebook); + phbkList.AppendL(KUidIccGlobalLndPhonebook); + phbkList.AppendL(KUidUsimAppAdnPhonebook); + // tell phonebook sync simulator what phonebooks to use + test(syncChecker->SetPhonebookListL(phbkList) == KErrNone); + + // simulate synchronisation - includes creating/finding template & group + // also defaults all validate responses to KErrNone + test(syncChecker->SynchroniseIccAllPhonebooksL(aDb, KErrNone, KErrNone) == KErrNone); + + CleanupStack::PopAndDestroy(); // phbkList + } + +/** + * Check the content of the phonebook field in the contact item + * @param aContactItem Contact item + * @param aPhonebookUid The phonebook uid + * @param aFieldIsSet EFalse if the phonebook field should not contain a value, else ETrue + */ +void CheckPhonebookField(CContactItem& aContactItem,TUid aPhonebookUid,TBool aFieldIsSet) + { + const CContactItemFieldSet& fieldset = aContactItem.CardFields(); + const TInt pos = fieldset.Find(KUidContactFieldICCPhonebook); + test(pos!=KErrNotFound); + TPtrC phonebookField=fieldset[pos].TextStorage()->Text(); + + if(aFieldIsSet) + { + TLex input(phonebookField); + TInt phonebookFieldVal; + /*TInt ignore = */ input.Val(phonebookFieldVal); + TUid phonebookFieldUid; + phonebookFieldUid.iUid=phonebookFieldVal; + test(phonebookFieldUid==aPhonebookUid); + } + else + test(phonebookField==KNullDesC); + } + +/** + * Verify that the template id returned by CContactDatabase::ICCTemplateIdL is the + * same as that returned directly from the plugin + * @param aDb Contact database + */ +void VerifyPhonebookTemplateIdsL(CContactDatabase& aDb) + { + test.Next(_L("Verify template ids")); + syncChecker->ResetMethodCallCountsL(); + test(aDb.ICCTemplateIdL() == syncChecker->ICCTemplateIdL(KUidIccGlobalAdnPhonebook)); + test(aDb.ICCTemplateIdL(KUidIccGlobalAdnPhonebook) == syncChecker->ICCTemplateIdL(KUidIccGlobalAdnPhonebook)); + test(aDb.ICCTemplateIdL(KUidIccGlobalSdnPhonebook) == syncChecker->ICCTemplateIdL(KUidIccGlobalSdnPhonebook)); + test(aDb.ICCTemplateIdL(KUidIccGlobalLndPhonebook) == syncChecker->ICCTemplateIdL(KUidIccGlobalLndPhonebook)); + test(aDb.ICCTemplateIdL(KUidUsimAppAdnPhonebook) == syncChecker->ICCTemplateIdL(KUidUsimAppAdnPhonebook)); + test(aDb.ICCTemplateIdL(KNullUid) == KNullContactId); + test(syncChecker->ValidateMethodCallCountL() == 6); + } + +/** + * Set the name field of the contact with id aId to contain the name aName + * @param aDb Contact database + * @param aId Contact item id + * @param aName A name + */ +void SetNameField(CContactDatabase& aDb,TContactItemId aId,const TDesC& aName) + { + syncChecker->ResetMethodCallCountsL(); + CContactItem* item = aDb.OpenContactLX(aId); + CleanupStack::PushL(item); + if (item->Type() == KUidContactICCEntry) + { + test(syncChecker->ValidateMethodCallCountL() == 2); + } + else + { + test(syncChecker->ValidateMethodCallCountL() == 0); + } + CContactItemFieldSet& fieldset = item->CardFields(); + TInt pos = fieldset.Find(KUidContactFieldFamilyName); + test(pos!=KErrNotFound); + CContactItemField& field = fieldset[pos]; + CContactTextField* textfield = field.TextStorage(); + textfield->SetTextL(aName); + + syncChecker->ResetMethodCallCountsL(); + aDb.CommitContactL(*item); + if (item->Type() == KUidContactICCEntry) + { + test(syncChecker->ValidateMethodCallCountL() == 2); + } + else + { + test(syncChecker->ValidateMethodCallCountL() == 0); + } + CleanupStack::PopAndDestroy(2); // item, lock record + } + +/** + * Set the phone number field of the contact with id aId to contain the number aNumber + * @param aDb Contact database + * @param aId Contact item id + * @param aNumber A telephone number + */ +void SetPhoneNumberField(CContactDatabase& aDb,TContactItemId aId,const TDesC& aNumber) + { + syncChecker->ResetMethodCallCountsL(); + CContactItem* item = aDb.OpenContactLX(aId); + CleanupStack::PushL(item); + if (item->Type() == KUidContactICCEntry) + { + test(syncChecker->ValidateMethodCallCountL() == 2); + } + else + { + test(syncChecker->ValidateMethodCallCountL() == 0); + } + CContactItemFieldSet& fieldset = item->CardFields(); + TInt pos = fieldset.Find(KUidContactFieldPhoneNumber); + test(pos!=KErrNotFound); + + CContactItemField& field = fieldset[pos]; + CContactTextField* textfield = field.TextStorage(); + textfield->SetTextL(aNumber); + + syncChecker->ResetMethodCallCountsL(); + aDb.CommitContactL(*item); + if (item->Type() == KUidContactICCEntry) + { + test(syncChecker->ValidateMethodCallCountL() == 2); + } + else + { + test(syncChecker->ValidateMethodCallCountL() == 0); + } + CleanupStack::PopAndDestroy(2); // item, lock record + } + +//=============================================================================================== +// ADDING entries +//=============================================================================================== +/** + * Create an entry based on the template for this specific phonebook, and add + * the entry to the contact database + * @param aDb Contact database + * @param aPhonebookUid The phonebook uid + * @return TContactItemId Id of the newly created icc entry + */ +TContactItemId doAddIccEntryL(CContactDatabase& aDb,TUid aPhonebookUid) + { + syncChecker->ResetMethodCallCountsL(); + TContactItemId templateId = aDb.ICCTemplateIdL(aPhonebookUid); + test(syncChecker->ValidateMethodCallCountL() == 1); + CContactItem* iccTemplate = aDb.ReadContactLC(templateId); + CContactICCEntry* entry = CContactICCEntry::NewL(*iccTemplate); + CleanupStack::PopAndDestroy(iccTemplate); + CleanupStack::PushL(entry); + // Add to the database + CheckPhonebookField(*entry,aPhonebookUid, EFalse); + syncChecker->ResetMethodCallCountsL(); + TContactItemId id = aDb.AddNewContactL(*entry); + test(syncChecker->ValidateMethodCallCountL() == 3); + CleanupStack::PopAndDestroy(entry); + test(id!=KNullContactId); + // Check group membership + syncChecker->ResetMethodCallCountsL(); + CContactICCEntry* fetchedItem = static_cast(aDb.ReadContactL(id)); + test(syncChecker->ValidateMethodCallCountL() == 1); + CleanupStack::PushL(fetchedItem); + const CContactIdArray* owned = fetchedItem->GroupsJoined(); + test(owned!=NULL && owned->Count() == 1); + test((*owned)[0]==syncChecker->GroupIdL(aPhonebookUid)); + test(fetchedItem->Type() == KUidContactICCEntry); + // Verify that the phonebook field has been set + CheckPhonebookField(*fetchedItem,aPhonebookUid, ETrue); + CleanupStack::PopAndDestroy(fetchedItem); + + return id; + } + +TContactItemId AddIccEntryL(CContactDatabase& aDb,TUid aPhonebookUid) + { + syncChecker->SetValidateWriteResponseL(KErrNone); + return doAddIccEntryL(aDb, aPhonebookUid); + } + +void UnsuccessfulAddIccEntryL(CContactDatabase& aDb,TUid aPhonebookUid, TInt aReason) + { + syncChecker->SetValidateWriteResponseL(aReason); + TRAPD(err,doAddIccEntryL(aDb, aPhonebookUid)); + test(err==aReason); + } + +void AddEntriesBasedOnEachOfTheTemplatesL(CContactDatabase& aDb) + { + test.Next(_L("Test successful adding")); + TInt numberOfAdnEntries=3; + TInt numberOfSdnEntries=2; + TInt numberOfLdnEntries=1; + TInt numberOfUsimEntries=4; + TInt iter=0; + for (iter=0; iter(aDb.ReadContactLC(syncChecker->GroupIdL(KUidIccGlobalAdnPhonebook))); + CContactIdArray* entries=group->ItemsContainedLC(); + test(entries->Count() == iter+1); + CleanupStack::PopAndDestroy(entries); + test(group->ContainsItem(id)); + CleanupStack::PopAndDestroy(group); + } + for (iter=0; iter(aDb.ReadContactLC(syncChecker->GroupIdL(KUidIccGlobalSdnPhonebook))); + CContactIdArray* entries=group->ItemsContainedLC(); + test(entries->Count() == iter+1); + CleanupStack::PopAndDestroy(entries); + test(group->ContainsItem(id)); + CleanupStack::PopAndDestroy(group); + } + for (iter=0; iter(aDb.ReadContactLC(syncChecker->GroupIdL(KUidIccGlobalLndPhonebook))); + CContactIdArray* entries=group->ItemsContainedLC(); + test(entries->Count() == iter+1); + CleanupStack::PopAndDestroy(entries); + test(group->ContainsItem(id)); + CleanupStack::PopAndDestroy(group); + } + for (iter=0; iter(aDb.ReadContactLC(syncChecker->GroupIdL(KUidUsimAppAdnPhonebook))); + CContactIdArray* entries=group->ItemsContainedLC(); + test(entries->Count() == iter+1); + CleanupStack::PopAndDestroy(entries); + test(group->ContainsItem(id)); + CleanupStack::PopAndDestroy(group); + } + // Add an ICC entry based on the system template, not one of the ICC templates + TContactItemId templateId=aDb.TemplateId(); + CContactItem* systemTemplate = aDb.ReadContactLC(templateId); + CContactICCEntry* entry = CContactICCEntry::NewL(*systemTemplate); + CleanupStack::PopAndDestroy(systemTemplate); + CleanupStack::PushL(entry); + syncChecker->ResetMethodCallCountsL(); + TContactItemId id = aDb.AddNewContactL(*entry); + test(syncChecker->ValidateMethodCallCountL() == 3); + + syncChecker->ResetMethodCallCountsL(); + CContactItem* item=aDb.ReadContactLC(id); + test(syncChecker->ValidateMethodCallCountL() == 1); + // check the entry hasn't been added to any group + CContactIdArray* array=static_cast(item)->GroupsJoinedLC(); + test(array->Count() == 0); + CleanupStack::PopAndDestroy(3); // array, close item, item + } + +void TestUnsuccessfulAddL(CContactDatabase& aDb) + { + // Test adding entries to each of the phonebooks when the ICC is locked, unaccessible or corrupt + test.Next(_L("Test unsuccessful adding")); + UnsuccessfulAddIccEntryL(aDb,KUidIccGlobalAdnPhonebook,KErrLocked); + UnsuccessfulAddIccEntryL(aDb,KUidIccGlobalAdnPhonebook,KErrAccessDenied); + UnsuccessfulAddIccEntryL(aDb,KUidIccGlobalAdnPhonebook,KErrCorrupt); + UnsuccessfulAddIccEntryL(aDb,KUidIccGlobalSdnPhonebook,KErrLocked); + UnsuccessfulAddIccEntryL(aDb,KUidIccGlobalSdnPhonebook,KErrAccessDenied); + UnsuccessfulAddIccEntryL(aDb,KUidIccGlobalSdnPhonebook,KErrCorrupt); + UnsuccessfulAddIccEntryL(aDb,KUidIccGlobalLndPhonebook,KErrLocked); + UnsuccessfulAddIccEntryL(aDb,KUidIccGlobalLndPhonebook,KErrAccessDenied); + UnsuccessfulAddIccEntryL(aDb,KUidIccGlobalLndPhonebook,KErrCorrupt); + UnsuccessfulAddIccEntryL(aDb,KUidUsimAppAdnPhonebook,KErrLocked); + UnsuccessfulAddIccEntryL(aDb,KUidUsimAppAdnPhonebook,KErrAccessDenied); + UnsuccessfulAddIccEntryL(aDb,KUidUsimAppAdnPhonebook,KErrCorrupt); + } + +/** + * Verify that adding contact cards doesn't call the synchroniser interface + * @param aDb Contact database + */ +TContactItemId AddContactCardL(CContactDatabase& aDb) + { + _LIT(KTemplateName,"contact card template"); + RArray entries=fieldSetForPhonebook(KUidIccGlobalAdnPhonebook); + TContactItemId templateId=CreatePhonebookTemplateL(aDb,KTemplateName,entries); + entries.Close(); + CContactItem* iccTemplate = aDb.ReadContactLC(templateId); + CContactCard* card = CContactCard::NewLC(iccTemplate); + syncChecker->ResetMethodCallCountsL(); + TContactItemId id=aDb.AddNewContactL(*card); + test(syncChecker->ValidateMethodCallCountL() == 0); + CleanupStack::PopAndDestroy(2,iccTemplate); + return id; + } +//=============================================================================================== +// DELETING entries +//=============================================================================================== +/** + * Verify that the synchroniser is called when deleting an icc entry, and that the + * deletion of an icc entry fails if the icc is locked. + * @param aDb Contact database + */ +void TestDeleteL(CContactDatabase& aDb) + { + test.Next(_L("Test delete when ICC locked")); + syncChecker->SetDeleteContactResponseL(KErrLocked); + TContactItemId iccId=AddIccEntryL(aDb,KUidIccGlobalAdnPhonebook); + syncChecker->ResetMethodCallCountsL(); + TRAPD(err,aDb.DeleteContactL(iccId)); + test(err==KErrLocked); + test(syncChecker->ValidateMethodCallCountL() == 2); + syncChecker->ResetMethodCallCountsL(); + CContactItem* item=aDb.ReadContactLC(iccId); + test(syncChecker->ValidateMethodCallCountL() == 1); + test(item!=NULL); + CleanupStack::PopAndDestroy(item); + item=NULL; + + test.Next(_L("Test successful delete of non-icc entry when ICC locked")); + TContactItemId nonIccId=AddContactCardL(aDb); + syncChecker->ResetMethodCallCountsL(); + TRAP(err,aDb.DeleteContactL(nonIccId)); + test(err==KErrNone); + test(syncChecker->ValidateMethodCallCountL() == 0); + + test.Next(_L("Test successful delete")); + syncChecker->SetDeleteContactResponseL(KErrNone); + syncChecker->ResetMethodCallCountsL(); + TRAP(err,aDb.DeleteContactL(iccId)); + test(syncChecker->ValidateMethodCallCountL() == 2); + test(err==KErrNone); + syncChecker->ResetMethodCallCountsL(); + TRAP(err,aDb.ReadContactLC(iccId)); + test(syncChecker->ValidateMethodCallCountL() == 0); + test(err==KErrNotFound); + } + +//=============================================================================================== +// READING entries +//=============================================================================================== +void TestReadMinimalContactL(CContactDatabase& aDb, TContactItemId aIccId, TContactItemId aNonIccId) + { + test.Next(_L("Test ReadMinimalContactL")); + // Successful read of icc entry + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + syncChecker->ResetMethodCallCountsL(); + CContactItem* item=aDb.ReadMinimalContactLC(aIccId); + test(syncChecker->ValidateMethodCallCountL() == 1); + test(item!=NULL); + CleanupStack::PopAndDestroy(item); + item=NULL; + + // Unsuccessful read of icc entry because icc locked + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrAccessDenied); + syncChecker->ResetMethodCallCountsL(); + TRAPD(err,item=aDb.ReadMinimalContactLC(aIccId)); + test(syncChecker->ValidateMethodCallCountL() == 1); + test(item==NULL); + test(err==KErrAccessDenied); + + // successful read of non-icc entry, even though icc locked + syncChecker->ResetMethodCallCountsL(); + item=aDb.ReadMinimalContactLC(aNonIccId); + test(syncChecker->ValidateMethodCallCountL() == 0); + test(item!=NULL); + CleanupStack::PopAndDestroy(item); + item=NULL; + } + +void TestReadContactL(CContactDatabase& aDb, TContactItemId aIccId, TContactItemId aNonIccId) + { + test.Next(_L("Test ReadContactL")); + // Successful read of icc entry + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + syncChecker->ResetMethodCallCountsL(); + test(syncChecker->ValidateMethodCallCountL() == 0); + CContactItem* item=aDb.ReadContactLC(aIccId); + test(syncChecker->ValidateMethodCallCountL() == 1); + test(item!=NULL); + CleanupStack::PopAndDestroy(item); + item=NULL; + + // Unsuccessful read of icc entry because icc locked + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrAccessDenied); + syncChecker->ResetMethodCallCountsL(); + test(syncChecker->ValidateMethodCallCountL() == 0); + TRAPD(err,item=aDb.ReadContactL(aIccId)); + test(item==NULL); + test(err==KErrAccessDenied); + test(syncChecker->ValidateMethodCallCountL() == 1); + + // successful read of non-icc entry, even though icc locked + syncChecker->ResetMethodCallCountsL(); + test(syncChecker->ValidateMethodCallCountL() == 0); + item=aDb.ReadContactLC(aNonIccId); + test(syncChecker->ValidateMethodCallCountL() == 0); + test(item!=NULL); + CleanupStack::PopAndDestroy(item); + item=NULL; + } + +void TestReadTextDefinitionL(CContactDatabase& aDb, TContactItemId aIccId, TContactItemId aNonIccId) + { + test.Next(_L("Test ReadTextDefinitionL")); + // Successful read of icc entry + CContactTextDef* textDef=CContactTextDef::NewLC(); + textDef->AppendL(TContactTextDefItem(KUidContactFieldFamilyName)); + TBuf<64> result; + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + syncChecker->ResetMethodCallCountsL(); + aDb.ReadContactTextDefL(aIccId,result,textDef); + test(syncChecker->ValidateMethodCallCountL() == 1); + test(result==KIccName); + result.Zero(); + + // Unsuccessful read of icc entry because icc locked + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrAccessDenied); + syncChecker->ResetMethodCallCountsL(); + TRAPD(err, aDb.ReadContactTextDefL(aIccId,result,textDef)); + test(err==KErrAccessDenied); + test(result.Length() == 0); + test(syncChecker->ValidateMethodCallCountL() == 1); + + // successful read of non-icc entry, even though icc locked + syncChecker->ResetMethodCallCountsL(); + TRAP(err, aDb.ReadContactTextDefL(aNonIccId,result,textDef)); + test(err==KErrNone); + test(result==KNonIccName); + test(syncChecker->ValidateMethodCallCountL() == 0); + CleanupStack::PopAndDestroy(textDef); + } + +/** + * Verify that the synchroniser is called when reading an icc entry + * @param aDb Contact database + */ +void TestReadL(CContactDatabase& aDb) + { + TContactItemId iccId=AddIccEntryL(aDb,KUidIccGlobalAdnPhonebook); + SetNameField(aDb,iccId,KIccName); + TContactItemId nonIccId = AddContactCardL(aDb); + SetNameField(aDb,nonIccId,KNonIccName); + TestReadMinimalContactL(aDb,iccId,nonIccId); + TestReadContactL(aDb,iccId,nonIccId); + TestReadTextDefinitionL(aDb,iccId,nonIccId); + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + syncChecker->ResetMethodCallCountsL(); + aDb.DeleteContactL(iccId); + aDb.DeleteContactL(nonIccId); + test(syncChecker->ValidateMethodCallCountL() == 2); + } + +//=============================================================================================== +// EDITING entries +//=============================================================================================== +/** + * Verify that edit validation is being done for ICC entries + * and write validation is done when Commit is called. + * @param aDb Contact database + * @param aId Item Id to edit + */ +void TestSuccessfulIccEditL(CContactDatabase& aDb, TContactItemId aId) + { + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + syncChecker->SetValidateResponseL(MContactSynchroniser::EEdit, KErrNone); + syncChecker->SetValidateWriteResponseL(KErrNone); + syncChecker->ResetMethodCallCountsL(); + test(syncChecker->ValidateMethodCallCountL() == 0); + CContactItem* item = aDb.OpenContactLX(aId); + CleanupStack::PushL(item); + test(syncChecker->ValidateMethodCallCountL() == 2); + + CContactItemFieldSet& fieldset = item->CardFields(); + const TInt pos = fieldset.Find(KUidContactFieldFamilyName); + CContactItemField& field = fieldset[pos]; + CContactTextField* textfield = field.TextStorage(); + textfield->SetTextL(KGivenEditName); + + aDb.CommitContactL(*item); + test(syncChecker->ValidateMethodCallCountL() == 4); + CleanupStack::PopAndDestroy(2); //item, lock record + } + +/** + * Verify that edit of non-icc entries is successful when the icc is + * locked, and that the synchroniser is not called + * @param aDb Contact database + * @param aId Item Id to edit + */ +void TestSuccessfulNonIccEditL(CContactDatabase& aDb, TContactItemId aId) + { + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrLocked); + syncChecker->SetValidateResponseL(MContactSynchroniser::EEdit, KErrLocked); + syncChecker->SetValidateWriteResponseL(KErrLocked); + syncChecker->ResetMethodCallCountsL(); + test(syncChecker->ValidateMethodCallCountL() == 0); + CContactItem* item = aDb.OpenContactLX(aId); + CleanupStack::PushL(item); + test(syncChecker->ValidateMethodCallCountL() == 0); + + CContactItemFieldSet& fieldset = item->CardFields(); + const TInt pos = fieldset.Find(KUidContactFieldFamilyName); + CContactItemField& field = fieldset[pos]; + CContactTextField* textfield = field.TextStorage(); + textfield->SetTextL(KGivenEditName); + + aDb.CommitContactL(*item); + test(syncChecker->ValidateMethodCallCountL() == 0); + CleanupStack::PopAndDestroy(2); //item, lock record + } + +/** + * Unsuccessful edit. Fail the edit validation request + * @param aDb Contact database + * @param aId Item Id to edit + */ +void FailEditValidationL(CContactDatabase& aDb, TContactItemId aId) + { + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + syncChecker->SetValidateResponseL(MContactSynchroniser::EEdit, KErrAccessDenied); + syncChecker->ResetMethodCallCountsL(); + test(syncChecker->ValidateMethodCallCountL() == 0); + TRAPD(err, aDb.OpenContactL(aId)); + test(syncChecker->ValidateMethodCallCountL() == 2); + test(err==KErrAccessDenied); + } + +/** + * Unsuccessful edit. Fail the write validation request + * @param aDb Contact database + * @param aId Item Id to edit + */ +void FailWriteValidationL(CContactDatabase& aDb, TContactItemId aId) + { + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + syncChecker->SetValidateResponseL(MContactSynchroniser::EEdit, KErrNone); + syncChecker->SetValidateWriteResponseL(KErrAccessDenied); + syncChecker->ResetMethodCallCountsL(); + + CContactItem* item = aDb.OpenContactLX(aId); + CleanupStack::PushL(item); + CContactItemFieldSet& fieldset = item->CardFields(); + const TInt pos = fieldset.Find(KUidContactFieldFamilyName); + CContactItemField& field = fieldset[pos]; + CContactTextField* textfield = field.TextStorage(); + textfield->SetTextL(KGivenEditName); + + TRAPD(err, aDb.CommitContactL(*item)); + test(syncChecker->ValidateMethodCallCountL() == 4); + test(err==KErrAccessDenied); + CleanupStack::PopAndDestroy(2); //item, lock record + } + +/** + * Verify that edit validation is being done for ICC entries + * and write validation is done when Commit is called. + * @param aDb Contact database + */ +void TestEditL(CContactDatabase& aDb) + { + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + TContactItemId iccId = AddIccEntryL(aDb,KUidIccGlobalAdnPhonebook); + TContactItemId nonIccId = AddContactCardL(aDb); + test.Next(_L("Test successful edit")); + TestSuccessfulIccEditL(aDb,iccId); + TestSuccessfulNonIccEditL(aDb,nonIccId); + test.Next(_L("Test unsuccessful edit - fail edit")); + FailEditValidationL(aDb,iccId); + test.Next(_L("Test unsuccessful edit - fail write")); + FailWriteValidationL(aDb,iccId); + } +//=============================================================================================== +// SEARCHING entries +//=============================================================================================== +void TestFindLC(CContactDatabase& aDb, TContactItemId aIccId, TContactItemId aNonIccId) + { + test.Next(_L("Test FindLC")); + // Successful find of icc entry + CContactItemFieldDef* fieldDef=new(ELeave) CContactItemFieldDef; + CleanupStack::PushL(fieldDef); + fieldDef->AppendL(KUidContactFieldFamilyName); + syncChecker->ResetMethodCallCountsL(); + CContactIdArray* array = aDb.FindLC(KIccName,fieldDef); + test(syncChecker->ValidateMethodCallCountL() == 1); + test(array!=NULL); + test(array->Count() == 1); + test((*array)[0]==aIccId); + CleanupStack::PopAndDestroy(array); + array=NULL; + + test.Next(_L("Test searching when ICC locked")); + // Unsuccessful find of icc entry because icc locked + syncChecker->SetValidateResponseL(MContactSynchroniser::ESearch,KErrLocked); + syncChecker->ResetMethodCallCountsL(); + TRAPD(err,array = aDb.FindLC(KIccName,fieldDef)); + test(syncChecker->ValidateMethodCallCountL() == 1); + test(err==KErrLocked); + test(array==NULL); + + // successful find of non-icc entry, even though icc locked + syncChecker->ResetMethodCallCountsL(); + array = aDb.FindLC(KNonIccName,fieldDef); + test(syncChecker->ValidateMethodCallCountL() == 0); + test(array!=NULL); + test(array->Count() == 1); + test((*array)[0]==aNonIccId); + CleanupStack::PopAndDestroy(2,fieldDef); // array, fieldDef + } + +TInt findWordSplitterL(TAny *aParams) + { + SFindInTextDefWordParser *parser=(SFindInTextDefWordParser *)aParams; + parser->iWordArray->AppendL(*parser->iSearchString); + return(KErrNone); + } + +void TestFindInTextDefLC(CContactDatabase& aDb, TContactItemId aIccId, TContactItemId aNonIccId) + { + test.Next(_L("Test FindInTextDefLC")); + // Successful find of icc entry + syncChecker->SetValidateResponseL(MContactSynchroniser::ESearch,KErrNone); + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + + TCallBack callBack(findWordSplitterL); + CContactTextDef* textDef=CContactTextDef::NewLC(); + textDef->AppendL(TContactTextDefItem(KUidContactFieldFamilyName)); + CDesCArray* desArray = new(ELeave) CDesCArrayFlat(5); + desArray->AppendL(_L("icc")); + syncChecker->ResetMethodCallCountsL(); + CContactIdArray* array = aDb.FindInTextDefLC(*desArray,textDef,callBack); + //test(syncChecker->ValidateMethodCallCountL() == 3); + test(array!=NULL); + test(array->Count() == 1); + test((*array)[0]==aIccId); + CleanupStack::PopAndDestroy(array); + array=NULL; + + test.Next(_L("Test searching when ICC locked")); + // Unsuccessful find of icc entry because icc locked + syncChecker->SetValidateResponseL(MContactSynchroniser::ESearch,KErrLocked); + syncChecker->ResetMethodCallCountsL(); + TRAPD(err,array = aDb.FindInTextDefLC(*desArray,textDef,callBack)); + test(syncChecker->ValidateMethodCallCountL() == 1); + test(err==KErrLocked); + test(array==NULL); + desArray->Delete(0); + delete desArray; + + // successful find of non-icc entry, even though icc locked + CDesCArray* desArray2 = new(ELeave) CDesCArrayFlat(5); + desArray2->AppendL(_L("non-icc")); + syncChecker->ResetMethodCallCountsL(); + array = aDb.FindInTextDefLC(*desArray2,textDef,callBack); + test(syncChecker->ValidateMethodCallCountL() == 0); + test(array!=NULL); + test(array->Count() == 1); + test((*array)[0]==aNonIccId); + + // both the icc and non-icc entry should match the search criteria, but only the + // non-icc entry should be returned since icc is locked + SetNameField(aDb,aIccId,KNonIccName); + syncChecker->ResetMethodCallCountsL(); + TRAP(err,array = aDb.FindInTextDefLC(*desArray2,textDef,callBack)); + test(syncChecker->ValidateMethodCallCountL() == 1); + test(err==KErrLocked); + test(array!=NULL); + test(array->Count() == 1); + test((*array)[0]==aNonIccId); + desArray2->Delete(0); + delete desArray2; + SetNameField(aDb,aIccId,KIccName); + CleanupStack::PopAndDestroy(2,textDef); // array, textDef + } + +void TestMatchPhoneNumberL(CContactDatabase& aDb, TContactItemId aIccId, TContactItemId aNonIccId) + { + // The synchroniser is not called to validate the IDs at for this method because + // phone number resolution needs to be as quick as possible. + // Instead, validation is done when the client attempts to read the items. + test.Next(_L("Test MatchPhoneNumberL")); + // Successful find of icc entry phone number + syncChecker->ResetMethodCallCountsL(); + CContactIdArray* array = aDb.MatchPhoneNumberL(KIccNumber,KMaxPhoneMatchLength); + test(syncChecker->ValidateMethodCallCountL() == 0); + test(array!=NULL); + test(array->Count() == 1); + test((*array)[0]==aIccId); + delete array; + array=NULL; + + test.Next(_L("Test searching when ICC locked")); + // successful find when icc locked - validation done when entry read + syncChecker->SetValidateResponseL(MContactSynchroniser::ESearch,KErrLocked); + syncChecker->ResetMethodCallCountsL(); + TRAPD(err,array = aDb.MatchPhoneNumberL(KIccNumber,KMaxPhoneMatchLength)); + test(syncChecker->ValidateMethodCallCountL() == 0); + test(array!=NULL); + test(err==KErrNone); + test((*array)[0]==aIccId); + delete array; + array=NULL; + syncChecker->ResetMethodCallCountsL(); + array = aDb.MatchPhoneNumberL(KNonIccNumber,KMaxPhoneMatchLength); + test(syncChecker->ValidateMethodCallCountL() == 0); + test(array!=NULL); + test(array->Count() == 1); + test((*array)[0]==aNonIccId); + delete array; + array=NULL; + } + +void TestSearchL(CContactDatabase& aDb) + { + test.Next(_L("Test searching")); + syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone); + syncChecker->SetValidateResponseL(MContactSynchroniser::ESearch,KErrNone); + TContactItemId iccId = AddIccEntryL(aDb,KUidIccGlobalAdnPhonebook); + SetNameField(aDb,iccId,KIccName); + SetPhoneNumberField(aDb,iccId,KIccNumber); + TContactItemId nonIccId = AddContactCardL(aDb); + SetNameField(aDb,nonIccId,KNonIccName); + SetPhoneNumberField(aDb,nonIccId,KNonIccNumber); + + TestFindLC(aDb,iccId,nonIccId); + TestFindInTextDefLC(aDb,iccId,nonIccId); + TestMatchPhoneNumberL(aDb,iccId,nonIccId); + } + + +void CheckForPhbkSyncPluginL() + { + test.Next(_L("Check for PhbkSync test plug-in")); + + RImplInfoPtrArray implInfoArray; + CleanupResetAndDestroyPushL(implInfoArray); + REComSession::ListImplementationsL(KUidEcomCntPhBkSyncInterface, implInfoArray); + //Find implementations of KUidEcomCntPhBkSyncInterface + TInt availCount = implInfoArray.Count(); + TInt count; + for(count = 0; count < availCount; count++) + { + const TUid firstImplementationFound = implInfoArray[count]->ImplementationUid(); + CImplementationInformation *info = implInfoArray[count]; + test.Printf(_L("\n")); + test.Printf(_L("PhbkSync plugin #%i, Implementation UID 0x%08X version %i\n"), + count + 1, info->ImplementationUid(), info->Version()); + test.Printf(_L("Plugin name = \"%S\"\n"), &(info->DisplayName())); + } + + // is telephony's plug-in in the list? + for(count = 0; count < availCount; count++) + { + const TUid firstImplementationFound = implInfoArray[count]->ImplementationUid(); + CImplementationInformation *info = implInfoArray[count]; + if(info->DisplayName() == KTestPluginName) + { + test.Printf(_L("\n")); + test.Printf(_L("This test has now loaded the test plugin")); + test.Printf(_L("\n")); + availCount = 1; + break; + } + + if(info->DisplayName() == KPluginName) + { + test.Printf(_L("\n")); + test.Printf(_L("This test only works with Contacts the test plugin and not the original phonebooksync plugin.")); + test.Printf(_L("Depending on the build to removed the plugin in different ways:")); + test.Printf(_L("hardware - delete the line \"ECOM_PLUGIN(phbksyncplugin.dll,1020428C.rsc)\" from phbksync.iby")); + test.Printf(_L("winscw - delete phbksyncplugin.dll from %epocroot%/epoc32/release/winscw/udeb or similarly named directory")); + test.Printf(_L("\n")); + test(0); // stop + break; + } + } + + // only continue test if there is exactly one plug-in present + test(availCount == 1); + + CleanupStack::PopAndDestroy(&implInfoArray); + } + + +//=============================================================================================== + +/** Lists tests to execute */ + +/** + +@SYMTestCaseID PIM-T-ICCMULTIPLEPHONEBOOK-0001 + +*/ +void DoTestsL() + { + test.Start(_L("@SYMTestCaseID:PIM-T-ICCMULTIPLEPHONEBOOK-0001 CContactICCEntry tests with multiple phonebooks")); + + CheckForPhbkSyncPluginL(); + + CntTest->CreateDatabaseL(); + CntTest->OpenDatabaseL(); + CContactDatabase& db= *CntTest->Db(); + + syncChecker = CContactSyncChecker::NewL(); + syncChecker->ResetEverythingL(); + + SetUpIccPhonebooksL(db); + VerifyPhonebookTemplateIdsL(db); + AddEntriesBasedOnEachOfTheTemplatesL(db); + TestUnsuccessfulAddL(db); + TestDeleteL(db); + TestReadL(db); + TestEditL(db); + TestSearchL(db); + syncChecker->ResetMethodCallCountsL(); + + CntTest->CloseDatabase(); + CntTest->DeleteDatabaseL(); + + + delete syncChecker; + syncChecker = NULL; + } + + +/** Standard E32Main method */ +GLDEF_C TInt E32Main() + { + CntTest=new(ELeave) CCntTest; + CntTest->ConstructL(test,KDatabaseFileName); + TRAPD(err,DoTestsL()); + if (syncChecker) + { + delete syncChecker; + syncChecker = NULL; + } + CntTest->EndTestLib(err); + return KErrNone; + } +