--- /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);
+ }
+
+
+