phonebookengines/contactsmodel/tsrc/T_FIND.CPP
changeset 0 e686773b3f54
child 24 0ba2181d7c28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/tsrc/T_FIND.CPP	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,839 @@
+// Copyright (c) 1997-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:
+// Run as part T_DBASE2, tests find
+// 
+//
+
+#include <e32test.h>
+#include <f32file.h>
+#include <s32file.h>
+#include <s32mem.h>
+#include <cntdb.h>
+#include <cntitem.h>
+#include <cntfield.h>
+#include <cntfldst.h>
+#include "T_UTILS.H"
+#include "T_DBASE2.H"
+
+class CAsyncFinder : public CBase, public MIdleFindObserver
+	{
+public:
+	~CAsyncFinder();
+	void ConstructL(CContactDatabase *aContactDatabase, const TDesC& aText,const CContactItemFieldDef *aFieldDef);
+	void ConstructL(CContactDatabase *aContactDatabase, const CDesCArray& aFindWords,const CContactTextDef *aTextDef,const TCallBack &aCallBack);
+	inline CContactIdArray *TakeContactIds() {return(iFinder->TakeContactIds());};
+	inline TInt Error() const {return(iFinder->Error());};
+protected:
+// from MIdleFindObserver
+	void IdleFindCallback();
+private:
+	CIdleFinder *iFinder;
+	};
+
+CAsyncFinder::~CAsyncFinder()
+	{
+	delete iFinder;
+	}
+
+void CAsyncFinder::ConstructL(CContactDatabase *aContactDatabase, const TDesC& aText,const CContactItemFieldDef *aFieldDef)
+	{
+	iFinder=aContactDatabase->FindAsyncL(aText, aFieldDef, this);
+	}
+
+void CAsyncFinder::ConstructL(CContactDatabase *aContactDatabase, const CDesCArray& aFindWords,const CContactTextDef *aTextDef,const TCallBack &aCallBack)
+	{
+	if (aTextDef)
+		iFinder=aContactDatabase->FindInTextDefAsyncL(aFindWords, aTextDef, this, aCallBack);
+	else
+		iFinder=aContactDatabase->FindInTextDefAsyncL(aFindWords, this, aCallBack);
+	}
+
+void CAsyncFinder::IdleFindCallback()
+	{
+	if (iFinder->IsComplete())
+		CActiveScheduler::Stop();
+	}
+
+GLDEF_C TBool CompareIdArrays(CContactIdArray* aIds1,CContactIdArray* aIds2)
+	{
+	if (aIds1->Count()!=aIds2->Count())
+		return(EFalse);
+	for(TInt loop=0;loop<aIds1->Count();loop++)
+		{
+		if ((*aIds1)[loop]!=(*aIds2)[loop])
+			return(EFalse);
+		}
+	return(ETrue);
+	}
+
+GLDEF_C CContactIdArray* CreateIdArrayLC(TContactItemId *aId1, TContactItemId *aId2=NULL, TContactItemId *aId3=NULL, TContactItemId *aId4=NULL, TContactItemId *aId5=NULL)
+	{
+	CContactIdArray* ids=CContactIdArray::NewLC();
+	if (aId1)
+		ids->AddL(*aId1);
+	if (aId2)
+		ids->AddL(*aId2);
+	if (aId3)
+		ids->AddL(*aId3);
+	if (aId4)
+		ids->AddL(*aId4);
+	if (aId5)
+		ids->AddL(*aId5);
+	return(ids);
+	}
+
+LOCAL_C CDesCArray *CreateFindWordsL(const TDesC &aFind1,const TDesC &aFind2,const TDesC &aFind3)
+	{
+	CDesCArray *desCA=new(ELeave) CDesCArrayFlat(5);
+	CleanupStack::PushL(desCA);
+	if (aFind1.Length()>0)
+		desCA->AppendL(aFind1);
+	if (aFind2.Length()>0)
+		desCA->AppendL(aFind2);
+	if (aFind3.Length()>0)
+		desCA->AppendL(aFind3);
+	CleanupStack::Pop();	// desCA
+	return(desCA);
+	}
+
+LOCAL_C void CheckResult(CContactIdArray* aIds,CContactIdArray* aResultIds)
+	{
+	if (aResultIds)
+		test(CompareIdArrays(aIds,aResultIds));
+	else
+		test(aIds->Count()==0);
+	}
+
+LOCAL_C void runAsyncFindL(CAsyncFinder *aFinder, CContactIdArray* aResultIds)
+	{
+	CActiveScheduler::Start();
+	CContactIdArray* ids=aFinder->TakeContactIds();
+	CheckResult(ids,aResultIds);
+	delete ids;
+	}
+
+LOCAL_C TInt findWordSplitterL(TAny *aParams)
+	{
+	SFindInTextDefWordParser *parser=(SFindInTextDefWordParser *)aParams;
+	const TText *ptr=parser->iSearchString->Ptr();
+	const TText *end=ptr+parser->iSearchString->Length();
+	const TText *startOfWord=NULL;
+	FOREVER
+		{
+		if (ptr==end || !TChar(*ptr).IsAlphaDigit())
+			{
+			if (startOfWord)
+				{
+				TPtrC addWord(startOfWord,ptr-startOfWord);
+				parser->iWordArray->AppendL(addWord);
+				startOfWord=NULL;
+				}
+			if (ptr==end)
+				break;
+			}
+		else if (!startOfWord)
+			startOfWord=ptr;
+		ptr++;
+		}
+	return(KErrNone);
+	}
+
+GLDEF_C void doDoFindInTextDefTestL(CDesCArray *aFindWords, CContactTextDef *aTextDef, CContactIdArray* aResultIds)
+	{
+	TCallBack callBack(findWordSplitterL);
+	CAsyncFinder *finder=new(ELeave) CAsyncFinder;
+	CleanupStack::PushL(finder);
+	finder->ConstructL(CntTest->Db(),*aFindWords,aTextDef,callBack);
+	runAsyncFindL(finder, aResultIds);
+	CleanupStack::PopAndDestroy(); // finder
+//
+	CContactIdArray* ids=NULL;
+	if (aTextDef)
+		ids=CntTest->Db()->FindInTextDefLC(*aFindWords,aTextDef,callBack);
+	else
+		ids=CntTest->Db()->FindInTextDefLC(*aFindWords,callBack);
+	CheckResult(ids,aResultIds);
+	CleanupStack::PopAndDestroy(); // ids
+	}
+
+GLDEF_C void DoFindInTextDefTestL(CDesCArray *aFindWords, CContactTextDef *aTextDef, CContactIdArray* aResultIds)
+	{
+	CleanupStack::PushL(aFindWords);
+	doDoFindInTextDefTestL(aFindWords, aTextDef, aResultIds);
+	CContactTextDef* textDef=CContactTextDef::NewLC();
+	if (aTextDef)
+		{
+		for(TInt loop=0;loop<aTextDef->Count();loop++)
+			textDef->AppendL((*aTextDef)[loop]);
+		textDef->SetFallbackField(aTextDef->FallbackField());
+		}
+	CntTest->Db()->SetTextDefinitionL(textDef);
+	CleanupStack::Pop();	// textDef
+	doDoFindInTextDefTestL(aFindWords, NULL, aResultIds);
+	CntTest->Db()->SetTextDefinitionL(NULL);
+	CleanupStack::Pop(); // aFindWords
+	}
+
+GLDEF_C void DoFindInTextDefTestLD(CDesCArray *aFindWords, CContactTextDef *aTextDef, CContactIdArray* aResultIds)
+	{
+	DoFindInTextDefTestL(aFindWords, aTextDef, aResultIds);
+	if (aFindWords->Count()>0)
+		{
+		CDesCArray *reverseArray=new(ELeave) CDesCArrayFlat(10);
+		CleanupStack::PushL(reverseArray);
+		for(TInt loop=aFindWords->Count()-1;loop>=0;loop--)
+			reverseArray->AppendL((*aFindWords)[loop]);
+		DoFindInTextDefTestL(reverseArray, aTextDef, aResultIds);
+		CleanupStack::PopAndDestroy();
+		}
+	delete aFindWords;
+	}
+
+GLDEF_C void DoAsyncFindL(const TDesC &aText, CContactItemFieldDef *aFieldDef,CContactIdArray* aResultIds)
+	{
+	CAsyncFinder *finder=new(ELeave) CAsyncFinder;
+	CleanupStack::PushL(finder);
+	finder->ConstructL(CntTest->Db(),aText,aFieldDef);
+	runAsyncFindL(finder, aResultIds);
+	CleanupStack::PopAndDestroy(); // finder
+	}
+
+GLDEF_C void DoAsyncFindL(const TDesC &aText, CContactItemFieldDef *aFieldDef, TInt aCount)
+	{
+	CAsyncFinder *finder=new(ELeave) CAsyncFinder;
+	CleanupStack::PushL(finder);
+	finder->ConstructL(CntTest->Db(),aText,aFieldDef);
+	CActiveScheduler::Start();
+	CContactIdArray* ids=finder->TakeContactIds();
+	test(ids->Count()==aCount);
+	delete ids;
+	CleanupStack::PopAndDestroy(); // finder
+	}
+
+/**
+
+@SYMTestCaseID     PIM-T-FIND-0001
+
+*/
+
+GLDEF_C void FindAsyncL()
+	{
+	test.Next(_L("@SYMTestCaseID:PIM-T-FIND-0001 Async search 1"));
+//
+	TBuf<32> name;
+	name.Format(KTestName,7);
+	DoAsyncFindL(name,NULL,1);
+//
+	test.Next(_L("Async search 2"));
+	CContactItemFieldDef *fieldDef=new(ELeave) CContactItemFieldDef;
+	CleanupStack::PushL(fieldDef);
+	fieldDef->AppendL(KUidContactFieldFamilyName);
+	DoAsyncFindL(_L("Test Name No"),fieldDef,CntTest->Db()->CountL()-3); // ..empty groups & own card
+	CleanupStack::PopAndDestroy(); // fieldDef
+//
+	test.Next(_L("Async search 3"));
+	CContactItemFieldDef *fieldDef2=new(ELeave) CContactItemFieldDef;
+	CleanupStack::PushL(fieldDef2);
+	fieldDef2->AppendL(KUidContactFieldAddress);
+	DoAsyncFindL(_L("Test Name No"),fieldDef2,0);
+	CleanupStack::PopAndDestroy(); // fieldDef2
+//
+#if defined(_DEBUG)
+	CAsyncFinder *finder=new(ELeave) CAsyncFinder;
+	CleanupStack::PushL(finder);
+	TBuf<32> name2;
+	name2.Format(KTestName,7);
+	finder->ConstructL(CntTest->Db(),name2,NULL);
+	__UHEAP_SETFAIL(RHeap::EDeterministic,10);
+	CActiveScheduler::Start();
+	__UHEAP_RESET;
+//
+	CContactIdArray* ids=finder->TakeContactIds();
+	test(finder->Error()==KErrNoMemory || finder->Error()==KErrNone);
+	delete ids;
+	CleanupStack::PopAndDestroy(); // finder
+#endif
+//
+	CAsyncFinder *asyncFinder=new(ELeave) CAsyncFinder;
+	asyncFinder->ConstructL(CntTest->Db(), _L("a"), NULL);
+	delete asyncFinder;	// Checks ids get deleted if not claimed with TakeContactIds()
+	}
+
+LOCAL_C TContactItemId AddFindRecordL(const TDesC &aFirstName, const TDesC &aLastName, const TDesC &aCompanyName, const TDesC &aAddress)
+	{
+	CContactItem *item=CContactCard::NewLC();
+	if (aFirstName.Length()>0)
+		SetNameL(*item,KUidContactFieldGivenName,KUidContactFieldVCardMapUnusedN,aFirstName,ETrue);
+	if (aLastName.Length()>0)
+		SetNameL(*item,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,aLastName,ETrue);
+	if (aCompanyName.Length()>0)
+		SetNameL(*item,KUidContactFieldCompanyName,KUidContactFieldVCardMapORG,aCompanyName,ETrue);
+	if (aAddress.Length()>0)
+		SetNameL(*item,KUidContactFieldAddress,KUidContactFieldVCardMapADR,aAddress,ETrue);
+	TContactItemId id=CntTest->Db()->AddNewContactL(*item);
+	CleanupStack::PopAndDestroy();	// item
+	return(id);
+	}
+
+GLDEF_C void FindAsyncInTextDefL()
+	{
+	CContactTextDef* textDef1=CContactTextDef::NewLC();
+	textDef1->AppendL(TContactTextDefItem(KUidContactFieldGivenName));
+	textDef1->AppendL(TContactTextDefItem(KUidContactFieldFamilyName));
+	textDef1->SetFallbackField(KUidContactFieldCompanyName);
+	CContactTextDef* textDef2=CContactTextDef::NewLC();
+	textDef2->AppendL(TContactTextDefItem(KUidContactFieldGivenName));
+	textDef2->AppendL(TContactTextDefItem(KUidContactFieldFamilyName));
+	textDef2->AppendL(TContactTextDefItem(KUidContactFieldCompanyName));
+	textDef2->SetFallbackField(KUidContactFieldAddress);
+//
+	TContactItemId wally=AddFindRecordL(_L("Wally"),_L("Example"),_L("Example Comp Inc"),_L(""));
+	TContactItemId vincent=AddFindRecordL(_L("Vincent"),_L("Jones"),_L(""),_L(""));
+	TContactItemId wilbert=AddFindRecordL(_L("Wilbert"),_L("Example"),_L("Sample Test Name"),_L(""));
+	TContactItemId vincent2=AddFindRecordL(_L("Vincent"),_L("Vincent"),_L(""),_L(""));
+	TContactItemId death=AddFindRecordL(_L("Black"),_L("De'ath"),_L("Hell"),_L("Sample of ExampleH"));
+//
+	CContactIdArray* wallyResults=CreateIdArrayLC(&wally);
+	CContactIdArray* wombatResults=CreateIdArrayLC(&wally,&wilbert);
+	CContactIdArray* vjResults=CreateIdArrayLC(&vincent);
+	CContactIdArray* v2Results=CreateIdArrayLC(&vincent2);
+	CContactIdArray* vjv2Results=CreateIdArrayLC(&vincent,&vincent2);
+	CContactIdArray* deathResults=CreateIdArrayLC(&death);
+//	
+	CDesCArray *findWords=CreateFindWordsL(_L("Wally"),_L(""),_L(""));
+//chrisd: the behaviour of the new code has changed because if you pass a null 
+//chrisd: textdef to ER5/ER6 or 6.1 it doesn't find anything
+	DoFindInTextDefTestL(findWords, NULL, NULL);	// No text def defined
+//
+	DoFindInTextDefTestLD(findWords, textDef1, wallyResults);
+	findWords=CreateFindWordsL(_L("Wally"),_L("NotFound"),_L(""));
+	DoFindInTextDefTestLD(findWords, textDef1, NULL);
+	findWords=CreateFindWordsL(_L("Wally"),_L("Example"),_L(""));
+	DoFindInTextDefTestLD(findWords, textDef1, wallyResults);
+	findWords=CreateFindWordsL(_L("Wally"),_L("Example"),_L("xxx"));
+	DoFindInTextDefTestLD(findWords, textDef1, NULL);
+	findWords=CreateFindWordsL(_L("W"),_L("Example"),_L(""));
+	DoFindInTextDefTestLD(findWords, textDef1, wombatResults);
+	findWords=CreateFindWordsL(_L("Wally"),_L("Wally"),_L(""));
+	DoFindInTextDefTestLD(findWords, textDef1, NULL);
+	findWords=CreateFindWordsL(_L("Example"),_L("Example"),_L(""));
+	DoFindInTextDefTestLD(findWords, textDef1, wallyResults);
+	findWords=CreateFindWordsL(_L("Example"),_L("Example"),_L("Example"));
+	DoFindInTextDefTestLD(findWords, textDef1, NULL);
+	findWords=CreateFindWordsL(_L("Example"),_L("Comp"),_L("Inc"));
+//chrisd: new code doesn't find anything here and should have - this is
+//chrisd: all words are contained in the company field
+DoFindInTextDefTestLD(findWords, textDef1, wallyResults);
+//
+	findWords=CreateFindWordsL(_L("ample"),_L("omp"),_L("lly"));
+	DoFindInTextDefTestLD(findWords, textDef1, NULL);
+	findWords=CreateFindWordsL(_L("Example"),_L("Comp"),_L("Inc"));
+//chrisd: new code doesn't find anything here and should have - this is
+//chrisd: all words are contained in the company field
+DoFindInTextDefTestLD(findWords, textDef1, wallyResults);
+//
+	findWords=CreateFindWordsL(_L("Vincent"),_L("J"),_L(""));
+	DoFindInTextDefTestLD(findWords, textDef1, vjResults);
+	findWords=CreateFindWordsL(_L("Vincent"),_L("V"),_L(""));
+	DoFindInTextDefTestLD(findWords, textDef1, v2Results);
+	findWords=CreateFindWordsL(_L("Vincent"),_L(""),_L(""));
+	DoFindInTextDefTestLD(findWords, textDef1, vjv2Results);
+
+	findWords=CreateFindWordsL(_L("De"),_L("Ath"),_L(""));
+//chrisd: new code fails here
+//chrisd: last name contains both first & last names (PC PIM syncs both to one field)
+DoFindInTextDefTestLD(findWords, textDef1, deathResults);
+	findWords=CreateFindWordsL(_L("De"),_L("Ath"),_L("ExampleH"));
+	DoFindInTextDefTestLD(findWords, textDef1, NULL);
+//chrisd: new code fails here
+//chrisd: last name contains first and last
+findWords=CreateFindWordsL(_L("De"),_L("Ath"),_L("ExampleH"));
+DoFindInTextDefTestLD(findWords, textDef2, deathResults);
+	findWords=CreateFindWordsL(_L("ExampleH"),_L(""),_L(""));
+//chrisd:one word at the end - partial match - so doesn't need to match
+DoFindInTextDefTestLD(findWords, textDef1, NULL);
+	findWords=CreateFindWordsL(_L("ExampleH"),_L(""),_L(""));
+//chrisd:one word at the end - partial match - so doesn't need to match
+DoFindInTextDefTestLD(findWords, textDef2, deathResults);
+findWords=CreateFindWordsL(_L("of"),_L("Sample"),_L("ExampleH"));
+//chrisd:all words are in one field - this doesn't need to match
+DoFindInTextDefTestLD(findWords, textDef2, deathResults);
+//
+	CntTest->DeleteContact(wally);
+	CntTest->DeleteContact(vincent);
+	CntTest->DeleteContact(wilbert);
+	CntTest->DeleteContact(vincent2);
+	CntTest->DeleteContact(death);
+	CleanupStack::PopAndDestroy(6);	// wallyResults,wombatResults,vjResults,v2Results,deathResults
+	CleanupStack::PopAndDestroy(2);	// textDef1,textDef2
+	}
+
+GLDEF_C void FindL()
+	{
+	CContactItemFieldDef* fieldDef=new(ELeave) CContactItemFieldDef;
+	CleanupStack::PushL(fieldDef);
+	fieldDef->AppendL(KUidContactFieldAddress);
+	fieldDef->AppendL(KUidContactFieldFamilyName);
+	fieldDef->AppendL(KUidContactFieldGivenName);
+	fieldDef->AppendL(KUidContactFieldCompanyName);
+	fieldDef->AppendL(KUidContactFieldBirthday);
+	fieldDef->AppendL(KUidContactFieldTemplateLabel);
+//
+	test.Next(_L("Search for full given name"));
+	TBuf<16> name;
+	name.Format(KTestName,7);
+	CContactIdArray* ids=CntTest->Db()->FindLC(name,fieldDef);
+	test(ids->Count()==1);
+	CleanupStack::PopAndDestroy(); // ids
+
+	test.Next(_L("Search for full given name in only contact groups"));
+	// same test but only looking in groups so shouldn't find anything
+	name.Format(KTestName,7);
+	CntTest->Db()->SetDbViewContactType(KUidContactGroup);
+	ids=CntTest->Db()->FindLC(name,fieldDef);
+	test(ids->Count()==0); // nothing found.
+	CleanupStack::PopAndDestroy(); // ids
+
+	CntTest->Db()->SetDbViewContactType(KUidContactItem); //reset view
+	test.Next(_L("Search for partial name"));
+	TBuf<8> shortName(name.Left(8));
+	ids=CntTest->Db()->FindLC(shortName,fieldDef);
+	test(ids->Count()==KTotalNumRecords);
+	CleanupStack::PopAndDestroy(); // ids
+
+	shortName=name.Right(8);
+	ids=CntTest->Db()->FindLC(shortName,fieldDef);
+	test(ids->Count()==1);
+	CleanupStack::PopAndDestroy(); // ids
+	shortName=name.Mid(3,8);
+	ids=CntTest->Db()->FindLC(shortName,fieldDef);
+	test(ids->Count()>1);
+	CleanupStack::PopAndDestroy(); // ids
+
+	test.Next(_L("Search for full address"));
+	TBuf<16> address;
+	address.Format(KTestAddress,11);
+	ids=CntTest->Db()->FindLC(address,fieldDef);
+	test(ids->Count()==1);
+	CleanupStack::PopAndDestroy(); // ids
+
+	test.Next(_L("NULL search string"));
+	ids=CntTest->Db()->FindLC(_L(""),fieldDef);
+	test(ids->Count()==KTotalNumRecords + 3); // 2 groups + 1 owncard
+	CleanupStack::PopAndDestroy(); // ids
+
+	// look in just the groups
+	test.Next(_L("NULL search string in GROUPS"));
+	TInt groupCount = CntTest->Db()->GroupCount();
+	CntTest->Db()->SetDbViewContactType(KUidContactGroup);
+	ids=CntTest->Db()->FindLC(_L(""),fieldDef);
+	test(ids->Count()==groupCount);
+	CleanupStack::PopAndDestroy(); // ids
+//
+	ids=CntTest->Db()->FindLC(_L("New Group"),fieldDef);
+	test(ids->Count()==groupCount);
+	CleanupStack::PopAndDestroy(); // ids
+//
+	CntTest->Db()->SetDbViewContactType(KUidContactItem);
+
+	// look in just the OWN CARD
+	test.Next(_L("NULL search string in OWN CARD"));
+	CntTest->Db()->SetDbViewContactType(KUidContactOwnCard);
+	ids=CntTest->Db()->FindLC(_L(""),fieldDef);
+	test(ids->Count()==1);
+	CleanupStack::PopAndDestroy(); // ids
+//
+	CntTest->Db()->SetDbViewContactType(KUidContactItem);
+
+	test.Next(_L("Search for partial address"));
+	TBuf<8> shortAddress(address.Left(6));
+	ids=CntTest->Db()->FindLC(shortAddress,fieldDef);
+	test(ids->Count()==KTotalNumRecords/2);
+	CleanupStack::PopAndDestroy(); // ids
+	shortAddress=address.Right(6);
+	ids=CntTest->Db()->FindLC(shortAddress,fieldDef);
+	test(ids->Count()==1);
+	CleanupStack::PopAndDestroy(); // ids
+	shortAddress=address.Mid(3,6);
+	ids=CntTest->Db()->FindLC(shortAddress,fieldDef);
+	test(ids->Count()>1);
+	TContactItemId deleteItem=(*ids)[0];
+	CleanupStack::PopAndDestroy(); // ids
+//
+	CntTest->AdjustContactAccessCountL(deleteItem,1);
+	CntTest->Db()->DeleteContactL(deleteItem);
+//
+	ids=CntTest->Db()->FindLC(shortAddress,NULL);
+	test(ids->Count()>1);
+	CleanupStack::PopAndDestroy(); // ids
+//
+	CntTest->AdjustContactAccessCountL(deleteItem,-1);
+	ids=CntTest->Db()->FindLC(shortAddress,NULL);
+	test(ids->Count()>1);
+	CleanupStack::PopAndDestroy(); // ids
+//
+	ids=CntTest->Db()->FindLC(_L("*"),NULL);
+	test(ids->Count()==0); // literal matching now and no asterisks in this file!
+	CleanupStack::PopAndDestroy(); // ids
+//
+	ids=CntTest->Db()->FindLC(shortAddress,fieldDef);
+	test(ids->Count()>1);
+	CleanupStack::PopAndDestroy(); // ids
+//
+	CleanupStack::PopAndDestroy(); // fieldDef
+	}
+
+GLDEF_C TContactItemId AddContactForFindL(const TDesC& aName)
+	{
+	CContactItem* item=CContactCard::NewLC();
+	SetNameL(*item,KUidContactFieldGivenName,KUidContactFieldVCardMapUnusedN,aName,ETrue);	
+	item->SetTemplateRefId(KGoldenTemplateId);
+	TContactItemId id=CntTest->Db()->AddNewContactL(*item);
+	CleanupStack::PopAndDestroy(item); 
+	return id;
+	}
+
+GLDEF_C TContactItemId AddContactWithAddressL(const TDesC& aName, const TDesC& anAddress)
+	{
+	CContactItem* item=CContactCard::NewLC();
+	item->SetTemplateRefId(KGoldenTemplateId);
+	SetNameL(*item,KUidContactFieldGivenName,KUidContactFieldVCardMapUnusedN,aName,ETrue);	
+	SetNameL(*item,KUidContactFieldAddress,  KUidContactFieldVCardMapUnusedN,anAddress,ETrue);	
+	TContactItemId id=CntTest->Db()->AddNewContactL(*item);
+	CleanupStack::PopAndDestroy(item); 
+	return id;
+	}
+
+//
+// Testcode for find defect 
+// EDNAPIN-4L4EN9 "Wildcards should be treated as normal charactersin search"
+//
+// Test case:
+// a contacts database containing contacts with names
+// *,?,chris,c?ris,c*s,??,????
+// 
+// '*' matches contacts with fields containing '*' 
+// '?' matches contacts with fields containing '?'
+// 'chris' matches contacts with fields containing 'chris' but not 'c*s' or 'c?ris'
+// 'c?ris' matches contacts with fields containing 'c?ris' but not 'c*s' or 'chris'
+// 'c*' matches contacts with fields containing 'c*' but not 'chris' or 'c?ris'
+// '??' matches contacts with fields containing '??' but not '?', 'chris', 'c*s' etc.
+//
+GLDEF_C void FindDefectL()
+	{
+	test.Next(_L("Find defect"));
+	CntTest->CreateDatabaseL();
+	_LIT(KAsterisk,"*");
+	_LIT(KQuestionMark,"?");
+	_LIT(KChris,"chris");
+	_LIT(KChrisQuestion,"c?ris");
+	_LIT(KChrisAsterisk,"c*s");
+	_LIT(KTwoQuestionMarks,"??");
+	_LIT(KFourQuestionMarks,"????");
+	TContactItemId asterisk = AddContactForFindL(KAsterisk());
+	AddContactForFindL(KQuestionMark());
+	TContactItemId chris = AddContactForFindL(KChris());
+	TContactItemId chrisquestion = AddContactForFindL(KChrisQuestion());
+	TContactItemId chrisasterisk = AddContactForFindL(KChrisAsterisk());
+	AddContactForFindL(KTwoQuestionMarks());
+	AddContactForFindL(KFourQuestionMarks());
+
+
+	CContactItemFieldDef* fieldDef=new(ELeave) CContactItemFieldDef;
+	CleanupStack::PushL(fieldDef);
+	fieldDef->AppendL(KUidContactFieldGivenName);
+
+	// *	
+	CContactIdArray* ids=CntTest->Db()->FindLC(KAsterisk,fieldDef);
+	test(ids->Count()==2);
+	test((*ids)[0]==asterisk);
+	CleanupStack::PopAndDestroy(); // ids
+
+	// ?
+	ids=CntTest->Db()->FindLC(KQuestionMark,fieldDef);
+	test(ids->Count()==4); // should be 4
+	CleanupStack::PopAndDestroy(); // ids
+
+	// chris
+	ids=CntTest->Db()->FindLC(KChris,fieldDef);
+	test(ids->Count()==1); // should be 1
+	test((*ids)[0]==chris);
+	CleanupStack::PopAndDestroy(); // ids
+
+	// c?ris
+	ids=CntTest->Db()->FindLC(KChrisQuestion,fieldDef);
+	test(ids->Count()==1); // should be 1
+	test((*ids)[0]==chrisquestion);
+	CleanupStack::PopAndDestroy(); // ids
+
+	// c*
+	ids=CntTest->Db()->FindLC(KChrisAsterisk,fieldDef);
+	test(ids->Count()==1); // should be 1
+	test((*ids)[0]==chrisasterisk);
+	CleanupStack::PopAndDestroy(); // ids
+
+	// ??
+	ids=CntTest->Db()->FindLC(KTwoQuestionMarks,fieldDef);
+	test(ids->Count()==2); // should be 2
+	CleanupStack::PopAndDestroy(); // ids
+
+	CleanupStack::PopAndDestroy(fieldDef);
+	CntTest->CloseDatabase();
+	CntTest->DeleteDatabaseL();
+	};
+
+GLDEF_C void FindAndCheckL(const TDesC& aStr, const TInt aNum, const CContactItemFieldDef* const aFieldDef)
+	{
+	CContactIdArray* const ids = CntTest->Db()->FindLC(aStr,aFieldDef);
+	test(aNum == ids->Count());
+	CleanupStack::PopAndDestroy(ids);
+	}
+
+GLDEF_C void FindScandinavianLettersL()
+	{
+	test.Next(_L("Scandinavian Letters defect"));
+	CntTest->CreateDatabaseL();
+
+	//Scandinavian words with their conterparts without accents.
+	_LIT(KMalmoS,"Malm\xF6"); //Malmö
+	_LIT(KMalmo,"Malmo");
+	_LIT(KAraS,"\xC5ra");  //Åra
+	_LIT(KAra,"Ara");
+	_LIT(KAtaS,"\xC4ta");  //Äta
+	_LIT(KAta,"Ata");
+
+	//Adding some contacts with Scandinavian letter in them.
+	//Note that Name is stored in separate field while address is in the BLOB
+	AddContactWithAddressL(KAraS, KMalmoS);
+	AddContactWithAddressL(KAtaS, KAtaS);
+	AddContactWithAddressL(KAtaS, KAraS);
+	AddContactWithAddressL(KMalmoS, KMalmoS);
+
+	//Search only by name column
+	CContactItemFieldDef* fieldDef=new(ELeave) CContactItemFieldDef;
+	CleanupStack::PushL(fieldDef);
+	fieldDef->AppendL(KUidContactFieldGivenName);
+	
+	FindAndCheckL(KAta,  2, fieldDef);
+	FindAndCheckL(KAra,  1, fieldDef);
+	FindAndCheckL(KMalmo,1, fieldDef);
+
+	//Search only by address column
+	fieldDef->Delete(0);
+	fieldDef->AppendL(KUidContactFieldAddress);
+	test(fieldDef->Count() == 1);
+
+//  Uncomment when DBMS collation problem will be sorted out.
+	FindAndCheckL(KMalmo,2, fieldDef);
+	FindAndCheckL(KAra,  1, fieldDef);
+	FindAndCheckL(KAta,1, fieldDef);
+
+	CleanupStack::PopAndDestroy(fieldDef);
+	CntTest->CloseDatabase();
+	CntTest->DeleteDatabaseL();
+	}
+
+GLDEF_C void DoFindL(const TDesC &aTextToFind, CContactItemFieldDef *aFieldDef, TInt aCount)
+	{
+	CContactIdArray* matchList=CntTest->Db()->FindLC(aTextToFind,aFieldDef);
+
+	const TInt numIds=matchList->Count();
+	RDebug::Print(_L("Matched %d contact(s) of %d expected"),numIds,aCount);
+	if(numIds!=aCount)
+		{
+		RDebug::Print(_L("FAILED!"));
+		}
+	test(numIds==aCount);
+	CleanupStack::PopAndDestroy(); // matchList.
+	}
+
+GLDEF_C void FindNameInFirstNameFieldL(const TDesC& aTextToFind, const TInt aNumExpectedFinds,TBool aAsync=EFalse)
+	{
+	RDebug::Print(_L("Find %S in Given name field"),&aTextToFind);	
+	CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+	CleanupStack::PushL(def);
+	def->AppendL(KUidContactFieldGivenName);
+	if(!aAsync)
+		{
+		DoFindL(aTextToFind,def,aNumExpectedFinds);
+		}
+	else
+		{
+		DoAsyncFindL(aTextToFind,def,aNumExpectedFinds);
+		}
+	CleanupStack::PopAndDestroy(); // def.
+	}
+
+GLDEF_C void FindNameInLastNameFieldL(const TDesC& aTextToFind, const TInt aNumExpectedFinds,TBool aAsync=EFalse)
+	{
+	RDebug::Print(_L("Find %S in Family name field"),&aTextToFind);	
+	CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+	CleanupStack::PushL(def);
+	def->AppendL(KUidContactFieldFamilyName);
+	if(!aAsync)
+		{
+		DoFindL(aTextToFind,def,aNumExpectedFinds);
+		}	
+	else
+		{
+		DoAsyncFindL(aTextToFind,def,aNumExpectedFinds);
+		}
+	CleanupStack::PopAndDestroy(); // def.	
+	}
+
+GLDEF_C void FindInAllFieldsL(const TDesC& aTextToFind, const TInt aNumExpectedFinds,TBool aAsync=EFalse)
+	{
+	RDebug::Print(_L("Find %S in All fields"),&aTextToFind);	
+	CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+	CleanupStack::PushL(def);
+	def->AppendL(KUidContactFieldMatchAll);
+	if(!aAsync)
+		{
+		DoFindL(aTextToFind,def,aNumExpectedFinds);
+		}
+	else
+		{
+		DoAsyncFindL(aTextToFind,def,aNumExpectedFinds);
+		}
+	CleanupStack::PopAndDestroy(); // def.
+	}
+
+GLDEF_C void FindInCompanyFieldL(const TDesC& aTextToFind, const TInt aNumExpectedFinds,TBool aAsync=EFalse)
+	{
+	RDebug::Print(_L("Find %S in Company name field"),&aTextToFind);	
+	CContactItemFieldDef* def=new(ELeave) CContactItemFieldDef();
+	CleanupStack::PushL(def);
+	def->AppendL(KUidContactFieldCompanyName);
+	if(!aAsync)
+		{
+		DoFindL(aTextToFind,def,aNumExpectedFinds);
+		}
+	else
+		{
+		DoAsyncFindL(aTextToFind,def,aNumExpectedFinds);
+		}
+	CleanupStack::PopAndDestroy(); // def.
+	}
+
+/**
+@SYMTestCaseID PIM-T-FIND-INC049017-0001
+@SYMTestType CT
+@SYMTestPriority High
+@SYMDEF INC049017
+@SYMTestCaseDependencies cnttutil
+@SYMTestCaseDesc Tests that Identity fields are searched when FindAsyncL and FindLC are used with KUidContactFieldMatchAll.
+@SYMTestActions Create a contact database and add four contacts.
+Search the database by using identity fields: GivenName, FamilyName and CompanyName.
+Search for contacts by providing a name and using KUidContactFieldMatchAll.
+Perform the search synchronously and asynchronously.
+@SYMTestExpectedResults Contacts are found by given name, family name or company name when using KUidContactFieldMatchAll.
+*/
+
+GLDEF_C void FindUsingKUidContactFieldMatchAllL()
+	{
+	//create the database
+	CntTest->CreateDatabaseL();
+
+	//add the contacts
+	//AddFindRecordL(const TDesC &aFirstName, const TDesC &aLastName, const TDesC &aCompanyName, const TDesC &aAddress)
+	AddFindRecordL(_L("NameR"),_L("NameJ"),_L("Symbian Foundation"),_L(" "));
+	AddFindRecordL(_L("NameAm"),_L("NameJ"),_L("Symbian Foundation"),_L(" "));
+	AddFindRecordL(_L("NameB"),_L("NameT"),_L("Test NameH"),_L(" "));
+	AddFindRecordL(_L("NameC"),_L("NameAn"),_L("Test Soft Kicks"),_L(" "));
+
+	//start of tests for defect where identity fields were not searched when using KUidMatchInAllFields
+	test.Next(_L("@SYMTestCaseID:PIM-T-FIND-INC049017-0001 FINDING CONTACTS BY NAME FROM GIVEN NAME FIELD."));
+		{
+		FindNameInFirstNameFieldL(_L("NameC"),1);
+		FindNameInFirstNameFieldL(_L("NameT"),0);
+		FindNameInFirstNameFieldL(_L("e"),4);
+		}
+
+	test.Next(_L("FINDING CONTACTS BY NAME FROM FAMILY NAME FIELD"));
+		{
+		FindNameInLastNameFieldL(_L("NameT"),1);
+		FindNameInLastNameFieldL(_L("NameJ"),2);
+		FindNameInLastNameFieldL(_L("N"),4);
+		FindNameInLastNameFieldL(_L("NameC"),0);
+		}
+
+	test.Next(_L("FINDING CONTACTS BY NAME FROM ALL FIELDS"));
+		{
+		FindInAllFieldsL(_L("NameB"),1);
+		FindInAllFieldsL(_L("NameJ"),2);
+		FindInAllFieldsL(_L("r"),1);
+		FindInAllFieldsL(_L("xxxxxxxxx"),0);
+		}
+
+	test.Next(_L("FINDING CONTACTS BY COMPANY FROM COMPANY NAME FIELD"));
+		{
+		FindInCompanyFieldL(_L("NameB"),0);
+		FindInCompanyFieldL(_L("Test NameH"),1);
+		FindInCompanyFieldL(_L("Symbian Foundation"),2);
+		FindInCompanyFieldL(_L("s"),4);
+		}
+
+	test.Next(_L("FINDING CONTACTS BY COMPANY FROM  ALL FIELDS"));
+		{
+		FindInAllFieldsL(_L("Kick"),1);
+		FindInAllFieldsL(_L("Test NameH"),1);
+		FindInAllFieldsL(_L("Symbian Foundation"),2);
+		FindInAllFieldsL(_L("s"),4);
+		}
+	//end of tests for defect where identity fields were not searched when using KUidMatchInAllFields
+
+	//start of Async tests for defect where identity fields were not searched when using KUidMatchInAllFields
+	test.Next(_L("FINDING CONTACTS BY NAME FROM GIVEN NAME FIELD ASYNCHRONOUSLY"));
+		{
+		FindNameInFirstNameFieldL(_L("NameC"),1,ETrue);
+		FindNameInFirstNameFieldL(_L("NameT"),0,ETrue);
+		FindNameInFirstNameFieldL(_L("e"),4,ETrue);
+		}
+
+	test.Next(_L("FINDING CONTACTS BY NAME FROM FAMILY NAME FIELD ASYNCHRONOUSLY"));
+		{
+		FindNameInLastNameFieldL(_L("NameT"),1,ETrue);
+		FindNameInLastNameFieldL(_L("NameJ"),2,ETrue);
+		FindNameInLastNameFieldL(_L("m"),4,ETrue);
+		FindNameInLastNameFieldL(_L("NameC"),0,ETrue);
+		}
+
+	test.Next(_L("FINDING CONTACTS BY NAME FROM ALL FIELDS ASYNCHRONOUSLY"));
+		{
+		FindInAllFieldsL(_L("NameB"),1,ETrue);
+		FindInAllFieldsL(_L("NameJ"),2,ETrue);
+		FindInAllFieldsL(_L("r"),1,ETrue);
+		FindInAllFieldsL(_L("xxxxxxxxx"),0,ETrue);
+		}
+
+	test.Next(_L("FINDING CONTACTS BY COMPANY FROM COMPANY NAME FIELD ASYNCHRONOUSLY"));
+		{
+		FindInCompanyFieldL(_L("NameB"),0,ETrue);
+		FindInCompanyFieldL(_L("Test NameH"),1,ETrue);
+		FindInCompanyFieldL(_L("Symbian Foundation"),2,ETrue);
+		FindInCompanyFieldL(_L("s"),4,ETrue);
+		}
+
+	test.Next(_L("FINDING CONTACTS BY COMPANY FROM  ALL FIELDS ASYNCHRONOUSLY"));
+		{
+		FindInAllFieldsL(_L("Kick"),1,ETrue);
+		FindInAllFieldsL(_L("Test NameH"),1,ETrue);
+		FindInAllFieldsL(_L("Symbian Foundation"),2,ETrue);
+		FindInAllFieldsL(_L("s"),4,ETrue);
+		}
+	//end of Async tests for defect where identity fields were not searched when using KUidMatchInAllFields
+
+	CntTest->CloseDatabase();
+	CntTest->DeleteDatabaseL();
+	}