phonebookengines_old/contactsmodel/tsrc/t_iccentry.cpp
branchGCC_SURGE
changeset 41 d11de32a5e6f
parent 40 b46a585f6909
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines_old/contactsmodel/tsrc/t_iccentry.cpp	Tue Jun 15 14:45:31 2010 +0100
@@ -0,0 +1,945 @@
+// 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 <e32test.h>
+#include <cntdb.h>
+#include <cntitem.h>
+#include <cntfield.h>
+#include <cntfldst.h>
+#include <phbksync.h>
+
+#include "T_UTILS.H"
+#include "./TestSyncPlugIn/cnttestsynchroniser.h"
+
+// include templates for CleanupResetAndDestroyPushL(T)
+#include "cntviewprivate.h"
+
+
+/** 
+ * @file
+ * Test harness for CContactICCEntry and MContactSynchroniser interface.
+ * todo Find out why telephone field won't match template correctly 
+ *       (Maybe the ICC slot field needs to be added to the "golden" template)
+ *
+ */
+
+_LIT(KDatabaseFileName,"C:T_ICCENTRY");
+
+_LIT(KTestName,"Basic tests for CContactICCEntry");
+_LIT(KGivenName,"Given");
+_LIT(KGivenEditName,"EditedName");
+_LIT(KTelephoneNum,"020 79460111");
+_LIT(KTelephoneNumModified,"020 79460222");
+_LIT(KTemplateName,"SIM Card Contacts"); 
+
+_LIT(KPluginName,"phone book synchronizer Implementation");
+_LIT(KTestPluginName,"Test phone book synchronizer Implementation");
+
+CCntTest* CntTest=NULL;
+LOCAL_D RTest test(KTestName);
+
+LOCAL_D CContactTestSynchroniser* synchroniser;
+LOCAL_D CContactSyncChecker* syncChecker;
+
+LOCAL_C TInt findWordSplitterL(TAny *aParams)
+	{
+	SFindInTextDefWordParser *parser=(SFindInTextDefWordParser *)aParams;
+	parser->iWordArray->AppendL(*parser->iSearchString);
+	return(KErrNone);
+	}
+
+CContactIdArray* TestFindL(CContactDatabase& aDatabase, const TDesC& aText, const CContactItemFieldDef *aFieldDef, RTest& aTest)
+	{
+	CContactIdArray* retval = NULL;
+	
+	retval = aDatabase.FindLC(aText, aFieldDef);
+	aTest(retval == NULL);
+	CleanupStack::Pop( retval );
+	
+	return retval;
+	}
+	
+CContactIdArray* TestFindInTextDefL(CContactDatabase& aDatabase, const MDesCArray& aFindWords,CContactTextDef* aTextDef, const TCallBack &aWordParserCallback, RTest& aTest)
+	{
+	CContactIdArray* retval = NULL;
+	retval = aDatabase.FindInTextDefLC(aFindWords, aTextDef, aWordParserCallback);
+	aTest(retval==NULL);
+	CleanupStack::Pop( retval );
+	return retval;
+	}
+		
+/** 
+ * Test Finding ICC Contacts when the ICC is locked.
+ * @param aDb Contact database
+ */
+
+void TestFindingL(CContactDatabase& aDb)
+	{
+	test.Next(_L("Test FindLC"));
+
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrLocked);
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ESearch,KErrLocked);
+	
+	CContactItemFieldDef* fieldDef=new(ELeave) CContactItemFieldDef;
+	CleanupStack::PushL(fieldDef);
+	fieldDef->AppendL(KUidContactFieldFamilyName); 
+	
+	
+	TRAPD(err,TestFindL(aDb, KGivenEditName, fieldDef, test) );
+	test(err==KErrLocked);
+	CleanupStack::PopAndDestroy(fieldDef);
+
+	CContactItemFieldDef* fieldDef2=new(ELeave) CContactItemFieldDef;
+	CleanupStack::PushL(fieldDef2);
+	fieldDef2->AppendL(KUidContactFieldPhoneNumber); 
+	TRAP(err, TestFindL(aDb, KTelephoneNum, fieldDef2, test) );
+	test(err==KErrLocked);
+	CleanupStack::PopAndDestroy(fieldDef2);
+
+	test.Next(_L("Test FindInTextDefL"));
+
+	TCallBack callBack(findWordSplitterL);
+	CContactTextDef* textDef=CContactTextDef::NewLC();
+	textDef->AppendL(TContactTextDefItem(KUidContactFieldFamilyName));
+	CDesCArray* desArray = new(ELeave) CDesCArrayFlat(5);
+	desArray->AppendL(_L("e"));
+	
+	CContactIdArray* arr = NULL;
+	TRAP(err,arr = TestFindInTextDefL(aDb,*desArray,textDef, callBack, test) );
+	
+//	test(err==KErrLocked);
+	desArray->Delete(0);
+	delete desArray;
+//FIX
+	delete arr;	
+	CleanupStack::PopAndDestroy(textDef); 
+
+	test.Next(_L("Test FindInTextDefL2"));
+
+	TCallBack callBack2(findWordSplitterL);
+	CContactTextDef* textDef2=CContactTextDef::NewLC();
+	textDef2->AppendL(TContactTextDefItem(KUidContactFieldFamilyName));
+	textDef2->AppendL(TContactTextDefItem(KUidContactFieldUrl));
+	CDesCArray* desArray2 = new(ELeave) CDesCArrayFlat(5);
+	desArray2->AppendL(_L("e"));
+	
+	TRAP(err,arr = TestFindInTextDefL(aDb,*desArray2,textDef2, callBack2, test) );
+//	test(err==KErrLocked);
+	desArray2->Delete(0);
+	delete desArray2;
+//FIX
+	delete arr;	
+	CleanupStack::PopAndDestroy(textDef2);
+	}
+
+
+/** 
+ * Test ICC contacts can be matched using MatchPhoneNumberL API. 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.
+ * @param aDb Contact database
+ */
+ 
+
+void TestPhoneMatchingL(CContactDatabase& aDb)
+	{
+	test.Next(_L("Test phone match"));
+
+	CContactIdArray* array = aDb.MatchPhoneNumberL(KTelephoneNum,KMaxPhoneMatchLength);	
+	test(array->Count() == 4);
+	delete array;
+
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone);
+	syncChecker->SetValidateResponseL(MContactSynchroniser::EEdit, KErrNone);
+	syncChecker->SetValidateWriteResponseL(KErrNone);
+	aDb.SetDbViewContactType(KUidContactICCEntry);
+	TContactItemId id = (*aDb.SortedItemsL())[0];
+	CContactItem* item = aDb.OpenContactLX(id);
+	CleanupStack::PushL(item);
+	CContactItemFieldSet& fieldset = item->CardFields();
+	const TInt pos = fieldset.Find(KUidContactFieldPhoneNumber);	
+	CContactItemField& field = fieldset[pos];
+	CContactTextField* textfield = field.TextStorage();
+	textfield->SetTextL(KTelephoneNumModified);
+	aDb.CommitContactL(*item);
+	CleanupStack::PopAndDestroy(2); //item, lock record
+
+	CContactIdArray* array2 = aDb.MatchPhoneNumberL(KTelephoneNumModified,KMaxPhoneMatchLength);	
+	test(array2->Count() == 1);
+	delete array2;
+	}
+
+
+/** 
+ * Test database iteration using TContactIter.
+ * @param aDb Contact database
+ */
+ 
+
+void TestDatabaseIterationL(CContactDatabase& aDb)
+	{
+	test.Next(_L("Test database iteration"));
+
+	aDb.SetDbViewContactType(KUidContactICCEntry);
+	TContactIter iterator(aDb);
+	TContactItemId id = iterator.FirstL();
+	while (id!=KNullContactId)
+		{
+		CContactItem* item = aDb.ReadContactLC(id);
+		test(item->Type() == KUidContactICCEntry);
+		CleanupStack::PopAndDestroy(item);
+		id = iterator.NextL();
+		}
+	}
+
+
+
+CContactItem* ReadItemL( CContactDatabase& aDatabase, TContactItemId aId )
+	{
+	CContactItem* retval = NULL;
+	retval = aDatabase.ReadMinimalContactLC( aId );
+	CleanupStack::Pop( retval );
+	return retval;
+	}
+
+/** 
+ * Verify that the plug-in implementation is called when the 
+ * ReadMinimalContactL API is used. 
+ * 
+ * Tests methods:
+ * IMPORT_C CContactItem* ReadMinimalContactL(TContactItemId aContactId);
+ * IMPORT_C CContactItem* ReadMinimalContactLC(TContactItemId aContactId);
+ * 
+ * @param aDb Contact database
+ * @param aId Contact item ID to read
+ */
+void TestReadMinimalContactL(CContactDatabase& aDb, TContactItemId aId)
+	{
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone);
+	syncChecker->ResetMethodCallCountsL();
+	test(syncChecker->ValidateMethodCallCountL() == 0);	
+	CContactItem* item = aDb.ReadMinimalContactLC(aId);
+	test(syncChecker->ValidateMethodCallCountL() == 1);	
+	CleanupStack::PopAndDestroy(item);
+
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrAccessDenied);
+	syncChecker->ResetMethodCallCountsL();
+	test(syncChecker->ValidateMethodCallCountL() == 0);
+	item=NULL;
+	//TRAPD(err, item = aDb.ReadMinimalContactLC(aId));
+	TRAPD( err, item = ReadItemL( aDb, aId ) );
+	delete item;
+	test(err==KErrAccessDenied);
+	test(syncChecker->ValidateMethodCallCountL() == 1);	
+	}
+
+/** 
+ * Verify that the plug-in implementation is called when the 
+ * ReadContactL API is used. 
+ * 
+ * Tests code called by methods:
+ * IMPORT_C CContactItem* ReadContactL(TContactItemId aContactId);
+ * IMPORT_C CArrayPtr<CContactItem>* ReadContactAndAgentL(TContactItemId aContactId);
+ * IMPORT_C CContactItem* ReadContactL(TContactItemId aContactId,const CContactItemViewDef& aViewDef);
+ * IMPORT_C CContactItem* ReadContactLC(TContactItemId aContactId);
+ * IMPORT_C CContactItem* ReadContactLC(TContactItemId aContactId,const CContactItemViewDef& aViewDef);
+ * 
+ * @param aDb Contact database
+ * @param aId Contact item ID to read
+ */
+void TestReadContactL(CContactDatabase& aDb, TContactItemId aId)
+	{
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone);
+	syncChecker->ResetMethodCallCountsL();
+	test(syncChecker->ValidateMethodCallCountL() == 0);	
+	CContactItem* item = aDb.ReadContactLC(aId);
+	test(syncChecker->ValidateMethodCallCountL() == 1);	
+	CleanupStack::PopAndDestroy(item);
+
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrAccessDenied);
+	syncChecker->ResetMethodCallCountsL();
+	test(syncChecker->ValidateMethodCallCountL() == 0);
+	item=NULL;
+	TRAPD(err, item = aDb.ReadContactL(aId));
+	delete item;
+	test(err==KErrAccessDenied);
+	test(syncChecker->ValidateMethodCallCountL() == 1);	
+	}
+
+/** 
+ * Verify that read validation is done for ReadContactTextDefL
+ * 
+ * @param aDb Contact database
+ * @param aId Contact item ID to read
+ */
+void TestReadTextDefinitionL(CContactDatabase& aDb, TContactItemId aId)
+	{
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone);
+	syncChecker->ResetMethodCallCountsL();
+	test(syncChecker->ValidateMethodCallCountL() == 0);
+	TBuf<64> textDef;
+	aDb.ReadContactTextDefL(aId,textDef);
+	test(syncChecker->ValidateMethodCallCountL() == 1);	
+
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrAccessDenied);
+	syncChecker->ResetMethodCallCountsL();
+	test(syncChecker->ValidateMethodCallCountL() == 0);
+	TRAPD(err, aDb.ReadContactTextDefL(aId,textDef));
+	test(err==KErrAccessDenied);
+	test(syncChecker->ValidateMethodCallCountL() == 1);	
+	}
+
+/** 
+ * Create example ICC Entry 
+ * @param aDb Contact database
+ */
+TContactItemId CreateTestICCEntryL(CContactDatabase& aDb)
+	{
+	TContactItemId templateId = aDb.ICCTemplateIdL(KUidIccGlobalAdnPhonebook);
+	CContactItem* iccTemplate = aDb.ReadContactLC(templateId);
+	CContactICCEntry* entry = CContactICCEntry::NewL(*iccTemplate);
+	CleanupStack::PopAndDestroy(iccTemplate);
+	CleanupStack::PushL(entry);
+	SetNameL(*entry,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,KGivenName,EFalse);
+	SetNameL(*entry,KUidContactFieldPhoneNumber,KUidContactFieldVCardMapTEL,KTelephoneNum,EFalse);
+
+	//Add to database
+	syncChecker->SetValidateWriteResponseL(KErrNone);
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone);
+	syncChecker->SetDeleteContactResponseL(KErrNone);
+
+	TContactItemId id = aDb.AddNewContactL(*entry); 
+
+	CleanupStack::PopAndDestroy(entry);	
+	test(id!=KNullContactId);
+	return id;
+	}
+
+/**
+ * Verify Read validation is being done for reading items.
+ * @param aDb Contact database
+ */
+
+void TestReadL(CContactDatabase& aDb)
+	{
+	TContactItemId id = CreateTestICCEntryL(aDb);
+	test.Next(_L("TestReadMinimalContactL"));
+
+	TestReadMinimalContactL(aDb,id);
+	test.Next(_L("TestReadContactL"));
+
+	TestReadContactL(aDb,id);
+	test.Next(_L("TestReadTextDefinitionL"));
+
+	TestReadTextDefinitionL(aDb,id);
+	}
+
+/**
+ * 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 TestSuccessfulEditL(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
+	}
+
+/**
+ * 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)
+	{
+	TContactItemId id = CreateTestICCEntryL(aDb);
+	test.Next(_L("Test successful edit"));
+
+	TestSuccessfulEditL(aDb,id);
+	test.Next(_L("Test unsuccessful edit - fail edit"));
+
+	FailEditValidationL(aDb,id);
+	test.Next(_L("Test unsuccessful edit - fail write"));
+
+	FailWriteValidationL(aDb,id);
+	}
+
+/** 
+ * Test an unsuccessful delete
+ * @param aDb Contact database
+ */
+void TestUnsuccessfulDeleteL(CContactDatabase& aDb)
+	{
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone);
+	syncChecker->SetValidateResponseL(MContactSynchroniser::EEdit, KErrNone);
+	TContactItemId id = CreateTestICCEntryL(aDb);
+	// Creating the contact sets the delete error to KErrNone, so must do this afterwards
+	syncChecker->SetDeleteContactResponseL(KErrCorrupt);
+	syncChecker->ResetMethodCallCountsL();
+	TRAPD(err, aDb.DeleteContactL(id));
+	test(syncChecker->ValidateMethodCallCountL() == 2);
+	test(err==KErrCorrupt);
+	//Read contact to check it wasn't deleted anyway
+	CContactItem* item = NULL;
+	TRAP(err,item = aDb.ReadContactL(id));
+	test(err==KErrNone);
+	delete item;
+	}
+
+
+/** 
+ * Verify that delete validation is being done for ICC entries.
+ * @param aDb Contact database
+ */
+
+void TestDeleteL(CContactDatabase& aDb)
+	{
+	test.Next(_L("Test successful delete"));
+
+	TContactItemId id = CreateTestICCEntryL(aDb);
+	syncChecker->ResetMethodCallCountsL();
+	aDb.DeleteContactL(id);
+	test(syncChecker->ValidateMethodCallCountL() == 2);
+	test.Next(_L("Test unsuccessful delete"));
+
+	TestUnsuccessfulDeleteL(aDb);
+	}
+
+
+/** 
+ * Create template card for ICC contact items 
+ * @param aDb Contact database
+ */
+TContactItemId CreateICCTemplateL(CContactDatabase& aDb)
+	{
+	CContactItem* temp = aDb.CreateContactCardTemplateLC(KTemplateName);
+	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);
+		
+	CContactItemField* name = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldFamilyName);
+	name->SetMapping(KUidContactFieldVCardMapUnusedN);
+	temp->AddFieldL(*name);
+	CleanupStack::Pop(name);
+
+	CContactItemField* number = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldPhoneNumber);
+	number->SetMapping(KUidContactFieldVCardMapTEL);
+	temp->AddFieldL(*number);
+	CleanupStack::Pop(number);
+				
+	CContactItemField* slotnum = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldICCSlot);
+	temp->AddFieldL(*slotnum);
+	CleanupStack::Pop(slotnum);
+
+	CContactItemField* phonebook = CContactItemField::NewLC(KStorageTypeText,KUidContactFieldICCPhonebook);
+	temp->AddFieldL(*phonebook);
+	CleanupStack::Pop(phonebook);
+
+	aDb.CommitContactL(*temp);
+	CleanupStack::PopAndDestroy(2);	// temp, close template	
+	
+	return templateId;
+	}
+
+/**
+ * Test SetDbViewContactType can be used for KUidContactICCEntry items.
+ * @param aDb Contact database
+ */
+void TestDatabaseViewL(CContactDatabase& aDb)
+	{
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone);
+	syncChecker->SetValidateWriteResponseL(KErrNone);
+	CntTest->CloseDatabase();
+	CntTest->DeleteDatabaseL();
+	// re-initialise the TLS
+	syncChecker->EnableVerboseLoggingL();
+
+	CntTest->CreateDatabaseL();	
+	CntTest->OpenDatabaseL();
+	delete synchroniser;
+	synchroniser = CContactTestSynchroniser::NewL();
+	// test with GSM ADN phonebook only
+	//test(KErrNone == syncChecker->SetGsmPhonebook());
+
+	// Start from clean
+	CContactItem* card = CContactCard::NewLC();
+	aDb.AddNewContactL(*card);
+	aDb.CreateContactGroupLC();
+	aDb.CreateOwnCardLC();
+	TContactItemId id=CreateICCTemplateL(aDb);
+	test(KErrNone == syncChecker->UpdatePhonebookEntryL(KUidIccGlobalAdnPhonebook, id, KNullContactId));
+	TContactItemId templateId = aDb.ICCTemplateIdL(KUidIccGlobalAdnPhonebook);
+	CContactItem* iccTemplate = aDb.ReadContactLC(templateId);
+	CContactICCEntry* iccentry = CContactICCEntry::NewL(*iccTemplate);
+	CleanupStack::PopAndDestroy(iccTemplate);
+	CleanupStack::PushL(iccentry);
+	aDb.AddNewContactL(*iccentry);
+	TContactItemId iccId = iccentry->Id();
+	CleanupStack::PopAndDestroy(4); //card,group,owncard,iccentry
+	
+	test(aDb.SortedItemsL()->Count() == 5); //default view includes ALL contact types
+	CntTest->CloseDatabase();
+	delete synchroniser;
+	synchroniser = NULL;
+	CntTest->OpenDatabaseL();
+	aDb.SetDbViewContactType(KUidContactICCEntry);
+	test(aDb.SortedItemsL()->Count() == 1);
+	test((*aDb.SortedItemsL())[0]==iccId);
+	}
+
+/** 
+ * Create phonebook group 
+ * @param aDb Contact database
+ */
+TContactItemId CreatePhonebookGroupL(CContactDatabase& aDb)
+	{
+	_LIT(KPhbkGroup,"ADN Phonebook"); 
+	CContactItem* group = aDb.CreateContactGroupLC(KPhbkGroup);
+	TContactItemId groupId = group->Id();
+	CleanupStack::PopAndDestroy(group);	
+	return groupId;
+	}
+
+/** 
+ * Verify that the template was correctly added 
+ * @param aTemplate CContactCardTemplate template item
+ */
+void CheckTemplateL(CContactItem& aTemplate)
+	{
+	test(aTemplate.Type() == KUidContactCardTemplate);
+	test(aTemplate.TemplateRefId() == KNullContactId);
+	test(static_cast<CContactCardTemplate&>(aTemplate).GetTemplateLabelL() == KTemplateName);
+	CContactItemFieldSet& fieldset = aTemplate.CardFields();
+	TInt pos = fieldset.Find(KUidContactFieldTemplateLabel);
+	test(pos!=KErrNotFound);
+	TInt count = fieldset.Count();
+	test(count==5); //label, name, number, ICC slot, phonebook
+	}
+
+
+/** 
+ * Check that the field of type aFieldType has the same content as 
+ * aExpectedContent
+ * @param aFieldset Contact item fieldset
+ * @param aFieldType Field type to test
+ * @param aExpectedContent Expected data
+ */
+void CheckFieldContentL(CContactItemFieldSet& aFieldset, TFieldType aFieldType, const TDesC& aExpectedContent)
+	{
+	TInt pos = aFieldset.Find(aFieldType);
+	CContactItemField& field = aFieldset[pos];
+	CContactTextField* textField = field.TextStorage();
+	test(textField != NULL);
+	test(textField->Text() == aExpectedContent);
+	}
+
+/** 
+ * Test creation of CContactICCEntry items.
+ * 
+ * Set-up appropriate template and group ready...
+ * @param aDb Contact database
+ */
+
+/**
+
+@SYMTestCaseID     PIM-T-ICCENTRY-0001
+
+*/
+
+void TestCreationL(CContactDatabase& aDb)
+	{
+	_LIT(KTestCreation,"@SYMTESTCaseID:PIM-T-ICCENTRY-0001 Create CContactICCEntry item");
+	test.Start(KTestCreation);
+
+	//System Template
+	TContactItemId systemTemplateId = aDb.TemplateId();
+	CContactItem* systemTemplate = aDb.ReadContactLC(systemTemplateId);
+	CContactICCEntry* entry = CContactICCEntry::NewL(*systemTemplate);
+	CleanupStack::PopAndDestroy(systemTemplate);
+	CleanupStack::PushL(entry);
+	
+	//Test CContactICCEntry items can be identified from normal contact cards
+	test(entry->Type() == KUidContactICCEntry);
+	test(entry->TemplateRefId() == systemTemplateId);
+	CleanupStack::PopAndDestroy(entry);
+
+	//Create user defined template for ICC contacts
+	test.Next(_L("CContactDatabase::ICCTemplateL()"));
+
+	TContactItemId templateId = CreateICCTemplateL(aDb);
+	test(KErrNone == syncChecker->UpdatePhonebookEntryL(KUidIccGlobalAdnPhonebook, templateId, KNullContactId));
+
+	//Check that contacts model calls the plug-in when asked for the
+	//template ID.
+	TInt callCount = syncChecker->ValidateMethodCallCountL();
+	test(callCount==0);
+	TContactItemId templateIdFromCntmodel;
+	templateIdFromCntmodel = aDb.ICCTemplateIdL(KUidIccGlobalAdnPhonebook);
+
+	test(syncChecker->ValidateMethodCallCountL() == 1);
+	test(templateId == templateIdFromCntmodel);
+	
+	CContactItem* iccTemplate = aDb.ReadContactLC(templateId);
+	CheckTemplateL(*iccTemplate);
+	//create ICC contact
+	CContactICCEntry* iccentry = CContactICCEntry::NewL(*iccTemplate);
+	CleanupStack::PopAndDestroy(iccTemplate);
+	CleanupStack::PushL(iccentry);
+	test(iccentry->Type() == KUidContactICCEntry);
+	test(iccentry->TemplateRefId() == templateId);
+	CleanupStack::PopAndDestroy(iccentry);
+	
+	test.End();
+	}
+
+
+
+/** 
+ * Test successful addition to database.
+ * @param aDb Contact database
+ */
+void TestSuccessfulAddL(CContactDatabase& aDb)
+	{
+	//Create group 
+	TContactItemId groupId = CreatePhonebookGroupL(aDb);
+	test(KErrNone == syncChecker->UpdatePhonebookGroupIdL(KUidIccGlobalAdnPhonebook, groupId));
+	//Create item and add fields
+	TContactItemId templateId = aDb.ICCTemplateIdL(KUidIccGlobalAdnPhonebook);
+	CContactItem* iccTemplate = aDb.ReadContactLC(templateId);
+	CContactICCEntry* entry = CContactICCEntry::NewL(*iccTemplate);
+	CleanupStack::PopAndDestroy(iccTemplate);
+	CleanupStack::PushL(entry);
+	SetNameL(*entry,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,KGivenName,EFalse);
+	SetNameL(*entry,KUidContactFieldPhoneNumber,KUidContactFieldVCardMapTEL,KTelephoneNum,EFalse);
+
+	//Add to database
+	syncChecker->ResetMethodCallCountsL();
+	syncChecker->SetValidateWriteResponseL(KErrNone);
+	syncChecker->SetValidateResponseL(MContactSynchroniser::ERead,KErrNone);
+
+	test(syncChecker->ValidateMethodCallCountL() == 0);
+	TContactItemId id = aDb.AddNewContactL(*entry); 
+	CleanupStack::PopAndDestroy(entry);	
+	test(syncChecker->ValidateMethodCallCountL() == 3);
+	test(id!=KNullContactId);
+
+	CContactICCEntry* fetchedItem = static_cast<CContactICCEntry*>(aDb.ReadContactL(id));
+	CleanupStack::PushL(fetchedItem);
+	//Check group membership	
+	const CContactIdArray* owned = fetchedItem->GroupsJoined();
+	test(owned!=NULL && owned->Count() == 1);
+	test((*owned)[0]==groupId);
+	
+	//Check number of fields and content
+	
+	CContactItemFieldSet& fieldset = fetchedItem->CardFields();
+	TInt pos = fieldset.Find(KUidContactFieldTemplateLabel);
+	test(pos==KErrNotFound);
+	
+//	test(fieldset.Count() == 3); 
+	
+/*	for (TInt i=0; i<fieldset.Count(); i++)
+		{
+		CContactItemField& field = fieldset[i];
+		TInt count = field.ContentType().FieldTypeCount();
+		for (TInt j=0; j<count; j++)
+			{
+			TFieldType ft= field.ContentType().FieldType(j);
+			}
+
+
+		TUid mapping = field.ContentType().Mapping();
+		}
+*/	
+	CheckFieldContentL(fieldset,KUidContactFieldFamilyName,KGivenName);
+//	CheckFieldContentL(fieldset,KUidContactFieldPhoneNumber,KTelephoneNum);
+
+	CleanupStack::PopAndDestroy(fetchedItem);
+	}
+
+/** 
+ * Test an unsuccessful addition to the database
+ * @param aDb Contact database
+ */
+void TestUnsuccessfulAddL(CContactDatabase& aDb)
+	{
+	TContactItemId templateId = aDb.ICCTemplateIdL(KUidIccGlobalAdnPhonebook);
+	CContactItem* iccTemplate = aDb.ReadContactLC(templateId);
+	CContactICCEntry* entry = CContactICCEntry::NewL(*iccTemplate);
+	CleanupStack::PopAndDestroy(iccTemplate);
+	CleanupStack::PushL(entry);
+	SetNameL(*entry,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,KGivenName,EFalse);
+	SetNameL(*entry,KUidContactFieldPhoneNumber,KUidContactFieldVCardMapTEL,KTelephoneNum,EFalse);
+
+	syncChecker->ResetMethodCallCountsL();
+	syncChecker->SetValidateWriteResponseL(KErrAccessDenied);
+	TRAPD(error, aDb.AddNewContactL(*entry)); 	
+	test(error==KErrAccessDenied);
+	test(syncChecker->ValidateMethodCallCountL() == 1);
+	CleanupStack::PopAndDestroy(entry);
+	}
+
+/** 
+ * Test addition to database without adding to a group
+ * @param aDb Contact database
+ */
+void TestAddingWithoutGroupL(CContactDatabase& aDb)
+	{
+	TContactItemId templateId = aDb.ICCTemplateIdL(KUidIccGlobalAdnPhonebook);
+	CContactItem* iccTemplate = aDb.ReadContactLC(templateId);
+	CContactICCEntry* entry = CContactICCEntry::NewL(*iccTemplate);
+	CleanupStack::PopAndDestroy(iccTemplate);
+	CleanupStack::PushL(entry);
+	SetNameL(*entry,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,KGivenName,EFalse);
+	SetNameL(*entry,KUidContactFieldPhoneNumber,KUidContactFieldVCardMapTEL,KTelephoneNum,EFalse);
+
+	syncChecker->ResetMethodCallCountsL();
+	syncChecker->SetValidateWriteResponseL(KErrNone);
+	TInt oldGroupId = syncChecker->GroupIdL(KUidIccGlobalAdnPhonebook);
+	test(KErrNone == syncChecker->UpdatePhonebookGroupIdL(KUidIccGlobalAdnPhonebook, KNullContactId));
+	TContactItemId id = aDb.AddNewContactL(*entry); 	
+	test(syncChecker->ValidateMethodCallCountL() == 3);
+	CleanupStack::PopAndDestroy(entry);
+
+	CContactICCEntry* fetchedItem = static_cast<CContactICCEntry*>(aDb.ReadContactL(id));
+	CleanupStack::PushL(fetchedItem);
+	//Check group membership	
+	const CContactIdArray* owned = fetchedItem->GroupsJoined();
+	test(owned==NULL || owned->Count() == 0);
+	CleanupStack::PopAndDestroy(fetchedItem);
+		
+	test(KErrNone == syncChecker->UpdatePhonebookGroupIdL(KUidIccGlobalAdnPhonebook, oldGroupId));
+	}
+
+/** 
+ * Verify that adding contact cards doesn't call the synchroniser interface
+ * @param aDb Contact database
+ */
+void TestAddingContactCardL(CContactDatabase& aDb)
+	{
+	CContactCard* card = CContactCard::NewLC();
+	syncChecker->ResetMethodCallCountsL();
+	aDb.AddNewContactL(*card);
+	test(syncChecker->ValidateMethodCallCountL() == 0);
+	CleanupStack::PopAndDestroy(card);
+	}
+
+/** 
+ * Test addition of CContactICCEntry items.
+ * @param aDb Contact database
+ */
+void TestAddL(CContactDatabase& aDb)
+	{
+	TestCreationL(aDb);
+	TestSuccessfulAddL(aDb);
+	TestUnsuccessfulAddL(aDb);
+	TestAddingWithoutGroupL(aDb);
+	TestAddingContactCardL(aDb);
+	}
+
+/** 
+ * Test PhonebookGroupIdL method.
+ * @param aDb Contact database
+ */
+void TestPhonebookGroupIdL(CContactDatabase& aDb)
+	{
+	synchroniser = CContactTestSynchroniser::NewL();
+	const TContactItemId expectedGroupId(KNullContactId);
+	test(KErrNone == syncChecker->UpdatePhonebookGroupIdL(KUidIccGlobalAdnPhonebook, expectedGroupId));
+	TContactItemId id = aDb.PhonebookGroupIdL();
+	test(id == expectedGroupId);
+	}
+
+
+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 */
+
+void DoTestsL()
+    {
+	test.Start(_L("Basic tests for CContactICCEntry"));
+
+
+	CheckForPhbkSyncPluginL();
+
+	CntTest->CreateDatabaseL();	
+	CntTest->OpenDatabaseL();
+
+	syncChecker = CContactSyncChecker::NewL();
+	synchroniser = CContactTestSynchroniser::NewL();
+	syncChecker->ResetL();
+	syncChecker->EnableVerboseLoggingL();
+	// test with GSM ADN phonebook only
+	test(KErrNone == syncChecker->SetGsmPhonebookL());
+	
+	CContactDatabase& db= *CntTest->Db();
+	TestAddL(db);
+	TestReadL(db);
+	TestEditL(db);
+	TestPhoneMatchingL(db);
+	TestFindingL(db);
+	TestDeleteL(db);
+	TestDatabaseIterationL(db);
+	TestDatabaseViewL(db);
+	TestPhonebookGroupIdL(db);
+	
+	CntTest->CloseDatabase();
+	CntTest->DeleteDatabaseL();
+
+	delete synchroniser;
+	synchroniser = NULL;
+	delete syncChecker;
+	syncChecker = NULL;
+    }
+
+/** Standard E32Main method */
+GLDEF_C TInt E32Main()
+	{
+	__UHEAP_MARK;
+    CntTest=new(ELeave) CCntTest;
+	CntTest->ConstructL(test,KDatabaseFileName);
+    TRAPD(err,DoTestsL());
+	if (err)
+		{
+		// delete globals
+		delete synchroniser;
+		synchroniser = NULL;
+		delete syncChecker;
+		syncChecker = NULL;
+		}
+	CntTest->EndTestLib(err);
+	__UHEAP_MARKEND;
+	return KErrNone;
+    }