phonebookengines/contactsmodel/tsrc/Integration/CntPerfTest/src/TestContactViewCRUDOperationsStep.cpp
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/tsrc/Integration/CntPerfTest/src/TestContactViewCRUDOperationsStep.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,575 @@
+// Copyright (c) 2007-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 "TestContactViewCRUDOperationsStep.h"
+
+/**
+ * Test Step Constructor
+ */
+CTestContactViewCRUDOperationsStep::CTestContactViewCRUDOperationsStep()
+:CTestContactViewDatabaseUtilitiesStep()
+	{
+	// Mandatory call to base class method to set up the human readable name for logging.
+	SetTestStepName(KTestContactViewCRUDOperationsStep);
+	}
+
+/**
+ * Test Step Destructor
+ */
+CTestContactViewCRUDOperationsStep::~CTestContactViewCRUDOperationsStep()
+	{
+	iChunk.Close();
+	iThread.Close();
+	iSemaphore.Close();
+	}
+
+/**
+ * Test Step preamble function, setups the environment required for the test step
+ */
+TVerdict CTestContactViewCRUDOperationsStep::doTestStepPreambleL()
+	{
+	CTestContactViewDatabaseUtilitiesStep::doTestStepPreambleL();
+	iChunk.CreateGlobal(KChunkName(), sizeof(TBool) + sizeof(TPtrC), sizeof(TBool) + sizeof(TPtrC));
+	iChunk.OpenGlobal(KChunkName(), ETrue);
+	iExecutionCompleted = reinterpret_cast<TBool*>(iChunk.Base());
+	iCurrentOperation = sizeof(TBool) + reinterpret_cast<TPtrC*>(iChunk.Base());
+	*iExecutionCompleted = EFalse;
+	return TestStepResult();
+	}
+
+/**
+ * Test Step postamble function, part of cleanup activity for the test step
+ */
+TVerdict CTestContactViewCRUDOperationsStep::doTestStepPostambleL()
+	{
+	CTestContactViewDatabaseUtilitiesStep::doTestStepPostambleL();
+	return TestStepResult();
+	}
+
+/**
+* Base class pure virtual.
+* @return EPass or EFail indicating the result of the test step.
+*/
+TVerdict CTestContactViewCRUDOperationsStep::doTestStepL()
+	{
+	// Share the current teststep logger across threads
+	Logger().ShareAuto();
+
+	// Starts a separate contact views thread and reumes the same
+	LaunchContactViewsThreadL();
+	ResumeContactViewsThreadL();
+
+	CreateContactItemsL();
+	UpdateContactItemsL();
+	RemoveContactItemsL();
+
+	// Mark the execution completed flag to true and thereby stop the contact views thread
+	SetExecutionCompleted();
+	ResumeContactViewsThreadL();
+	return TestStepResult();
+	}
+
+
+/**
+* Adds contact cards and groups in the database
+*/
+void CTestContactViewCRUDOperationsStep::CreateContactItemsL()
+	{
+	_LIT(KAddContacts, "add");
+	TBool addContacts = EFalse;
+	GetBoolFromConfig(ConfigSection(), KAddContacts, addContacts);
+
+	if(!addContacts)
+		{
+		return;
+		}
+
+	// Add contacts and groups in the main thread and validate the view count and view notifications
+	// in the contact views thread
+	TPtrC currentOperation(KAddContactOperations);
+	SetCurrentOperation(currentOperation);
+	AddContactEntriesL();
+	CloseDatabaseL();
+	OpenDataBaseL();
+	ResumeContactViewsThreadL();
+	}
+
+/**
+* Updates contact cards and groups in the database
+*/
+void CTestContactViewCRUDOperationsStep::UpdateContactItemsL()
+	{
+	_LIT(KUpdateContacts, "update");
+	TBool updateContacts = EFalse;
+	GetBoolFromConfig(ConfigSection(), KUpdateContacts, updateContacts);
+
+	if(!updateContacts)
+		{
+		return;
+		}
+
+
+	// Update contacts in the main thread and validate the view count and view notifications
+	// in the contact views thread
+	TPtrC currentOperation(KUpdateContactOperations);
+	SetCurrentOperation(currentOperation);
+	UpdateContactEntriesL();
+	CloseDatabaseL();
+	OpenDataBaseL();
+	ResumeContactViewsThreadL();
+	}
+
+/**
+* Deletes contact items in the database
+*/
+void CTestContactViewCRUDOperationsStep::RemoveContactItemsL()
+	{
+	_LIT(KDeleteContacts, "delete");
+	TBool deleteContacts = EFalse;
+	GetBoolFromConfig(ConfigSection(), KDeleteContacts, deleteContacts);
+
+	if(!deleteContacts)
+		{
+		return;
+		}
+
+	// Delete Contacts in the main thread and validate the view count and view notifications
+	// in the contact views thread
+	TPtrC currentOperation(KRemoveContactsOperations);
+	SetCurrentOperation(currentOperation);
+	DeleteContactCardsL();
+	CloseDatabaseL();
+	OpenDataBaseL();
+	ResumeContactViewsThreadL();
+	}
+
+
+/*
+* Creates a Contact Views Thread. This thread constructs the desired contact views
+* After every CRUD operation performed on the database, the contact views thread
+* validates the updated view count and view notifications
+*/
+void CTestContactViewCRUDOperationsStep::LaunchContactViewsThreadL()
+	{
+
+	TInt error = iSemaphore.CreateGlobal(KSemaphoreName, 0);
+
+	if (error == KErrAlreadyExists || error == KErrNone)
+		{
+		iSemaphore.OpenGlobal(KSemaphoreName);
+		}
+	else
+		{
+		User::Leave(error);
+		}
+
+	HBufC* contactViewsThread = HBufC::NewLC(SharedConstants::KMaxBufferLength);
+	TPtr contactViewsThreadHandle = contactViewsThread->Des();
+
+	SetRandomAlphaString(contactViewsThreadHandle, SharedConstants::KMaxBufferLength);
+    User::LeaveIfError( iThread.Create(contactViewsThreadHandle, RunContactViewsThreadL, KDefaultStackSize, NULL, this, EOwnerProcess));
+    _LIT(KInfoContactsViewThread, "The contact views thread was created successfully");
+   	INFO_PRINTF1(KInfoContactsViewThread);
+
+	CleanupStack::PopAndDestroy(contactViewsThread);
+
+	}
+
+/**
+* Resumes the contact views thread
+*/
+void CTestContactViewCRUDOperationsStep::ResumeContactViewsThreadL()
+	{
+	iThread.Resume();
+	iSemaphore.Wait();
+	}
+
+/**
+* New contact entries are added in the database. The newly added contacts can have fields that meet the sort order
+* of some existing views, With the addition of such contact fields, the existing views needs resorting. The newly added
+* fields may also meet the filter criteria of some existing views. This is useful while testing filtered views
+* The new added contacts can have fields with some predefined string content, this is useful in case of Find Views and Sub Views.
+*/
+void CTestContactViewCRUDOperationsStep::AddContactEntriesL()
+	{
+	_LIT(KViewSortOrder, "SortOrder");
+	TPtrC viewSortOrderString;
+	GetStringFromConfig(ConfigSection(), KViewSortOrder, viewSortOrderString);
+
+	RContactViewSortOrder sortOrder = ViewUtilityReference().ConvertStringToSortOrderL(viewSortOrderString);
+	CleanupClosePushL(sortOrder);
+
+	_LIT(KNumOfContactsToBeAdded, "NumOfContactsToBeAdded");
+	TInt numOfContactsToBeAdded;
+	GetIntFromConfig(ConfigSection(), KNumOfContactsToBeAdded, numOfContactsToBeAdded);
+
+
+	for(TInt i = 0; i < numOfContactsToBeAdded; ++i)
+		{
+		CContactCard* contactCard = CContactCard::NewL();
+		CleanupStack::PushL(contactCard);
+		AddContactFieldL(*contactCard, sortOrder);
+
+		TBool filterBasedFields;
+		_LIT(KFilterBasedFields, "FilterBasedFields");
+		GetBoolFromConfig(ConfigSection(), KFilterBasedFields, filterBasedFields);
+		if(filterBasedFields)
+			{
+			AddFieldsSpecificToFilterL(*contactCard);
+			}
+
+		TBool contactsWithDesiredString;
+		_LIT(KContactsWithDesiredString, "ContactsWithDesiredString");
+		GetBoolFromConfig(ConfigSection(), KContactsWithDesiredString, contactsWithDesiredString);
+		if(contactsWithDesiredString)
+			{
+			AddMatchingStringToContactL(*contactCard);
+			}
+
+
+		TContactItemId contactId = DatabaseReference().AddNewContactL(*contactCard);
+
+		TPtrC addContactToGroup;
+		_LIT(KAddContactToGroup, "grouplist");
+		GetStringFromConfig(ConfigSection(), KAddContactToGroup, addContactToGroup);
+		if(addContactToGroup != KNullDesC)
+			{
+			IterateThroAllGroupSectionsAndUpdateContactL(addContactToGroup, *contactCard);
+			}
+
+		CleanupStack::PopAndDestroy();// contactCard
+		DatabaseReference().CloseContactL(contactId);
+		}
+	CleanupStack::PopAndDestroy(); // sortOrder
+	}
+
+/**
+* Add fields that meet some desired sort order
+* @param aContact - Contact to be updated woth desired fields
+* @param aSortOrder - specifies information about the desired fields
+*/
+void CTestContactViewCRUDOperationsStep::AddContactFieldL(CContactItem& aContact,
+															 const RContactViewSortOrder& aSortOrder)
+	{
+	const TInt KMaxSortOrderCount = 3;
+	for(TInt i = 0; i < KMaxSortOrderCount; ++i)
+		{
+		TFieldType fieldType = aSortOrder[i];
+		TStorageType storageType = GetStorageType(fieldType);
+		CContentType* contentType = CContentType::NewL();
+		CleanupStack::PushL(contentType);
+		contentType->AddFieldTypeL(fieldType);
+		CContactItemField* field = 	CContactItemField::NewL(storageType, *contentType);
+		CleanupStack::PushL(field);
+		SetDataL(fieldType, *field);
+		aContact.AddFieldL(*field);
+		CleanupStack::Pop(field);
+		CleanupStack::PopAndDestroy(contentType);
+		}
+	}
+
+/**
+ * Adds contact fields to the contact, as per the desired contact view filter
+ */
+void CTestContactViewCRUDOperationsStep::AddFieldsSpecificToFilterL(CContactItem& aContact)
+	{
+	_LIT(KDesiredFilterString, "desiredFilter");
+	TPtrC desiredFilterString;
+	GetStringFromConfig(ConfigSection(), KDesiredFilterString, desiredFilterString);
+	CContactDatabase::TContactViewFilter	viewFilter = ViewUtilityReference().GetContactViewFilterL(desiredFilterString);
+	AddFilterBasedFieldsL(aContact, viewFilter);
+	}
+
+/**
+ * Updates the specified contact items with desired matching string
+ */
+
+void CTestContactViewCRUDOperationsStep::AddMatchingStringToContactL(CContactItem& aContact)
+	{
+	_LIT(KDesiredMatchingString, "matchingstring");
+	TPtrC desiredMatchingString;
+	GetStringFromConfig(ConfigSection(), KDesiredMatchingString, desiredMatchingString);
+
+	_LIT(KDesiredContactField, "contactfield");
+	TPtrC desiredContactField;
+	GetStringFromConfig(ConfigSection(), KDesiredContactField, desiredContactField);
+
+	TUid uidInfo = GetContactFieldType(desiredContactField);
+
+	CContactItemFieldSet& fieldSet = aContact.CardFields();
+	TInt pos = fieldSet.Find(uidInfo);
+	if(pos == KErrNotFound)
+		{
+		TFieldType fieldType = uidInfo;
+		TStorageType storageType = GetStorageType(fieldType);
+		CContentType* contentType = CContentType::NewL();
+		CleanupStack::PushL(contentType);
+
+		contentType->AddFieldTypeL(fieldType);
+		CContactItemField* field = 	CContactItemField::NewL(storageType, *contentType);
+		CleanupStack::PushL(field);
+		field->TextStorage()->SetTextL(desiredMatchingString);
+		aContact.AddFieldL(*field);
+		CleanupStack::Pop(field);
+
+		CleanupStack::PopAndDestroy(contentType);
+		}
+	else
+		{
+		CContactItemField& field = fieldSet[pos];
+		field.TextStorage()->SetTextL(desiredMatchingString);
+		}
+	}
+
+/**
+ * Updates the specified number of contact items from the database
+ */
+void CTestContactViewCRUDOperationsStep::UpdateContactEntriesL()
+	{
+	_LIT(KNumOfContactsToBeUpdated, "NumOfContactsToBeUpdated");
+	TInt numOfContactToBeUpdated;
+	GetIntFromConfig(ConfigSection(), KNumOfContactsToBeUpdated, numOfContactToBeUpdated);
+
+	TPtrC deleteContactInGroups;
+	_LIT(KDeleteContactInGroups, "grouplist");
+	GetStringFromConfig(ConfigSection(), KDeleteContactInGroups, deleteContactInGroups);
+
+
+	if(deleteContactInGroups != KNullDesC)
+		{
+		UpdateContactsInGroupL(numOfContactToBeUpdated, deleteContactInGroups);
+		}
+	else
+		{
+		CCntFilter* filter = CCntFilter::NewL();
+		CleanupStack::PushL(filter);
+		filter->SetContactFilterTypeCard(ETrue);
+		DatabaseReference().FilterDatabaseL(*filter);
+
+		for(TInt i = 0; i < numOfContactToBeUpdated; ++i)
+			{
+			TContactItemId contactItemId = (*filter->iIds)[i];
+			CContactItem* contactItem = DatabaseReference().ReadContactL(contactItemId);
+			CleanupStack::PushL(contactItem);
+			UpdateFieldsL(*contactItem);
+			CContactItem* updatedContactItem = DatabaseReference().UpdateContactLC(contactItemId, contactItem);
+			CleanupStack::PopAndDestroy(updatedContactItem);
+			CleanupStack::PopAndDestroy(contactItem);
+			}
+
+		CleanupStack::PopAndDestroy(filter);
+		}
+	}
+
+/**
+ * Deletes the specified number of contact cards from the database
+ */
+void CTestContactViewCRUDOperationsStep::DeleteContactCardsL()
+	{
+	_LIT(KNumOfContactsToBeDeleted, "NumOfContactsToBeDeleted");
+	TInt numOfContactsToBeDeleted;
+	GetIntFromConfig(ConfigSection(), KNumOfContactsToBeDeleted, numOfContactsToBeDeleted);
+
+
+	TPtrC deleteContactInGroups;
+	_LIT(KDeleteContactInGroups, "grouplist");
+	GetStringFromConfig(ConfigSection(), KDeleteContactInGroups, deleteContactInGroups);
+
+	if(deleteContactInGroups != KNullDesC)
+		{
+		DeleteContactsInGroupL(numOfContactsToBeDeleted, deleteContactInGroups);
+		}
+	else
+		{
+		CCntFilter* filter = CCntFilter::NewL();
+		CleanupStack::PushL(filter);
+		filter->SetContactFilterTypeCard(ETrue);
+		DatabaseReference().FilterDatabaseL(*filter);
+
+		for(TInt i = 0; i < numOfContactsToBeDeleted; ++i)
+			{
+			TContactItemId contactItemId = (*filter->iIds)[i];
+			DatabaseReference().DeleteContactL(contactItemId);
+			}
+
+		CleanupStack::PopAndDestroy(filter);
+		}
+	}
+
+
+
+/**
+* Sets the program completion flag to True, thereby enables the
+* contact views thread to release all its resources
+*/
+void CTestContactViewCRUDOperationsStep::SetExecutionCompleted()
+	{
+	*iExecutionCompleted = ETrue;
+	}
+
+/*
+* Sets information about the current operation being performed
+* This information is used by the contact views thread to validate the
+* view count and view notifications at the end of each CRUD Operations
+*/
+void CTestContactViewCRUDOperationsStep::SetCurrentOperation
+		(TPtrC aCurrentOperation)
+	{
+	(*iCurrentOperation).Set(aCurrentOperation);
+	}
+
+
+/* In this section, we edit the desired number of groups in the database
+ * Set label for them and associate them with contacts
+ @ param aGroupSection - Desired Group Name
+ @ param aContact - Contact to be updated
+ */
+void CTestContactViewCRUDOperationsStep::IterateThroAllGroupSectionsAndUpdateContactL(const TPtrC& aGroupSection,
+																									 CContactCard& aContact)
+	{
+	RArray<TPtrC>	listOfGroupsSections;
+	CleanupClosePushL(listOfGroupsSections);
+	ViewUtilityReference().TokenizeStringL(aGroupSection, listOfGroupsSections);
+
+	for ( TInt i = 0; i < listOfGroupsSections.Count(); ++i )
+		{
+		CCntFilter* filter = CCntFilter::NewL();
+		CleanupStack::PushL(filter);
+		filter->SetContactFilterTypeGroup(ETrue);
+		DatabaseReference().FilterDatabaseL(*filter);
+
+		for ( TInt i = 0; i < filter->iIds->Count(); ++i )
+			{
+			TContactItemId groupId = (*filter->iIds)[i];
+			CContactItem* group = DatabaseReference().OpenContactL(groupId);
+			CContactGroup* newGroup = static_cast<CContactGroup*>(group);
+			if(aGroupSection.Compare(newGroup->GetGroupLabelL())  == 0)
+				{
+				TRAP_IGNORE(DatabaseReference().RemoveContactFromGroupL(aContact, *newGroup));
+				TRAP_IGNORE(DatabaseReference().AddContactToGroupL(aContact, *newGroup));
+				DatabaseReference().CommitContactL(*group);
+				const CContactIdArray* listOfContacts = newGroup->ItemsContained();
+				const TInt count = listOfContacts->Count();
+				delete listOfContacts;
+				DatabaseReference().CloseContactL(groupId);
+				break;
+				}
+			DatabaseReference().CloseContactL(groupId);
+			}
+
+    	CleanupStack::PopAndDestroy(filter);
+		}
+
+	CleanupStack::PopAndDestroy(&listOfGroupsSections);
+	}
+
+/* In this section, we edit the desired number of groups in the database
+ * Set label for them and associate them with contacts
+ @ param aGroupSection - Desired Group Name
+ @ param aContact - Contact to be updated
+ */
+void CTestContactViewCRUDOperationsStep::DeleteContactsInGroupL(const TInt aNumberOfContactsToBeUpdated, const TPtrC& aGroupSection)
+	{
+	RArray<TPtrC>	listOfGroupsSections;
+	CleanupClosePushL(listOfGroupsSections);
+	ViewUtilityReference().TokenizeStringL(aGroupSection, listOfGroupsSections);
+
+	for ( TInt i = 0; i < listOfGroupsSections.Count(); ++i )
+		{
+		CCntFilter* filter = CCntFilter::NewL();
+		CleanupStack::PushL(filter);
+		filter->SetContactFilterTypeGroup(ETrue);
+		DatabaseReference().FilterDatabaseL(*filter);
+
+		for ( TInt i = 0; i < filter->iIds->Count(); ++i )
+			{
+			TContactItemId groupId = (*filter->iIds)[i];
+			CContactItem* group = DatabaseReference().OpenContactL(groupId);
+			CContactGroup* newGroup = static_cast<CContactGroup*>(group);
+
+
+			if(aGroupSection.Compare(newGroup->GetGroupLabelL())  == 0)
+				{
+				const CContactIdArray* listOfContacts = newGroup->ItemsContained();
+				for(TInt i(0); i < aNumberOfContactsToBeUpdated; i++)
+					{
+					TRAP_IGNORE(DatabaseReference().DeleteContactL((*listOfContacts)[i]));
+					}
+				delete listOfContacts;
+				DatabaseReference().CloseContactL(groupId);
+				break;
+				}
+			DatabaseReference().CloseContactL(groupId);
+			}
+
+    	CleanupStack::PopAndDestroy(filter);
+		}
+
+	CleanupStack::PopAndDestroy(&listOfGroupsSections);
+	}
+
+/* In this section, we edit the desired number of groups in the database
+ * Set label for them and associate them with contacts
+ @ param aGroupSection - Desired Group Name
+ @ param aContact - Contact to be updated
+ */
+void CTestContactViewCRUDOperationsStep::UpdateContactsInGroupL(const TInt aNumberOfContactsToBeUpdated, const TPtrC& aGroupSection)
+	{
+	RArray<TPtrC>	listOfGroupsSections;
+	CleanupClosePushL(listOfGroupsSections);
+	ViewUtilityReference().TokenizeStringL(aGroupSection, listOfGroupsSections);
+
+	for ( TInt i = 0; i < listOfGroupsSections.Count(); ++i )
+		{
+		CCntFilter* filter = CCntFilter::NewL();
+		CleanupStack::PushL(filter);
+		filter->SetContactFilterTypeGroup(ETrue);
+		DatabaseReference().FilterDatabaseL(*filter);
+
+		for ( TInt i = 0; i < filter->iIds->Count(); ++i )
+			{
+			TContactItemId groupId = (*filter->iIds)[i];
+			CContactItem* group = DatabaseReference().OpenContactL(groupId);
+			CContactGroup* newGroup = static_cast<CContactGroup*>(group);
+
+
+			if(aGroupSection.Compare(newGroup->GetGroupLabelL())  == 0)
+				{
+				const CContactIdArray* listOfContacts = newGroup->ItemsContained();
+				for(TInt i(0); i < aNumberOfContactsToBeUpdated; i++)
+					{
+					TContactItemId contactItemId = (*listOfContacts)[i];
+					CContactItem* contactItem = DatabaseReference().ReadContactL(contactItemId);
+					CleanupStack::PushL(contactItem);
+					UpdateFieldsL(*contactItem);
+					CContactItem* updatedContactItem = DatabaseReference().UpdateContactLC(contactItemId, contactItem);
+					CleanupStack::PopAndDestroy(updatedContactItem);
+					CleanupStack::PopAndDestroy(contactItem);
+					}
+				delete listOfContacts;
+				DatabaseReference().CloseContactL(groupId);
+				break;
+				}
+			DatabaseReference().CloseContactL(groupId);
+			}
+
+    	CleanupStack::PopAndDestroy(filter);
+		}
+
+	CleanupStack::PopAndDestroy(&listOfGroupsSections);
+	}
+
+
+