diff -r 000000000000 -r e686773b3f54 phonebookengines/contactsmodel/tsrc/Integration/CntPerfTest/src/TestContactViewCRUDOperationsStep.cpp --- /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(iChunk.Base()); + iCurrentOperation = sizeof(TBool) + reinterpret_cast(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 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(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 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(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 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(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); + } + + +