phonebookengines/contactsmodel/tsrc/Integration/PerfFuncSuite/src/TransactionsStep.cpp
// Copyright (c) 2006-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:
//
/**
@file
@publishedAll
@released
*/
#include "TransactionsStep.h"
#include "PerformanceFunctionalityDefs.h"
_LIT(KVcardFile,"c:\\ExportedContacts.vcf");
const TInt KTransactionSize = 16;//number of crud operations performed within a transaction
//number of contacts used by transaction performance
const TInt KMinContacts = 10;
const TInt KMidContacts = 100;
const TInt KManyContacts = 300;
const TInt KMaxContacts = 1000;
const TInt KPerfIter = 1;//number of times performance tests are repeated to get a more accurate average
const TInt KMediumFields = 10;//number of fields to use when a contact is partially filled
const TInt KManyFields = 69;//number of (template-derived) fields in a Contact Item
_LIT(KRun1,"Nested");
_LIT(KRun2,"EmptyCommit");
_LIT(KRun3,"EmptyRevert");
_LIT(KRun4,"UpdateCommit");
_LIT(KRun5,"UpdateRevert");
_LIT(KRun6,"CreateCommit");
_LIT(KRun7,"CreatRevert");
_LIT(KRun8,"DeleteCommit");
_LIT(KRun9,"DeleteRevert");
_LIT(KRun10,"CudCommit");
_LIT(KRun11,"CudRevert");
_LIT(KRun12,"EmptyPerfomance");
_LIT(KRun13,"EmptyEmptyPerformance");
_LIT(KRun14,"MediumPerformance");
_LIT(KRun15,"MediumEmptyPerformance");
_LIT(KRun16,"FullPerformance");
_LIT(KRun17,"FullEmptyPerformance");
_LIT(KRun18,"MultipleCommit");
_LIT(KRun19,"TransactionMultiple");
_LIT(KTest1, "Nested Transaction tests");
_LIT(KTest2, "Empty; Commit Transaction tests");
_LIT(KTest3, "Empty; Revert Transaction tests");
_LIT(KTest4, "Update; Commit Transaction tests");
_LIT(KTest5, "Update; Revert Transaction tests");
_LIT(KTest6, "Create; Commit Transaction tests");
_LIT(KTest7, "Create; Revert Transaction tests");
_LIT(KTest8, "Delete; Commit Transaction tests");
_LIT(KTest9, "Delete; Revert Transaction tests");
_LIT(KTest10, "Many CUD; Commit Transaction tests");
_LIT(KTest11, "Many CUD; Revert Transaction tests");
_LIT(KTest12, "***Empty fields; Performance Transaction tests***");
_LIT(KTest13, "***Empty fields, Empty DB; Performance Transaction tests***");
_LIT(KTest14, "***Medium fields; Performance Transaction tests***");
_LIT(KTest15, "***Medium fields, Empty DB; Performance Transaction tests***");
_LIT(KTest16, "***Full fields; Performance Transaction tests***");
_LIT(KTest17, "***Full fields, Empty DB; Performance Transaction tests***");
_LIT(KTest18, "Multiple commit test");
_LIT(KTest19, "Transaction Multiple commit test");
//number of contacts used by this test step
#define KNumberOfContacts 10
#ifdef __WINSCW__
#define KMaxTimeAllowed 500 //seconds, minimum performance
#else
#define KMaxTimeAllowed 10000 //hardware is much slower
#endif
#define KNumCUDOperations 3
_LIT(KMinContactsPrint,"$Min contacts$");
_LIT(KMidContactsPrint,"$Mid contacts$");
_LIT(KManyContactsPrint,"$Many contacts$");
_LIT(KMaxContactsPrint,"$Max contacts$");
CTransactionsStep::CTransactionsStep(CPerformanceFunctionalityTestsSuite &aParent) : CPerformanceFunctionalityBase(KNumberOfContacts, aParent)
{
SetTestStepName(KTransactionsStep);
}
TVerdict CTransactionsStep::doTestStepPostambleL()
{
const TInt error = iParent->Fs().Delete(KVcardFile);
if( KErrNotFound != error && KErrNone != KErrNone )
{
_LIT(KDeleteError,"Unexpected error when deleting vcard file, error: %d");
ERR_PRINTF2(KDeleteError, error);
}
return CPerformanceFunctionalityBase::doTestStepPostambleL();
}
void CTransactionsStep::PreTestL()
{
User::LeaveIfError( iParent->Fs().Connect() );
}
TVerdict CTransactionsStep::doTestStepL()
/**
* @return - TVerdict code
* Override of base class pure virtual
* Our implementation only gets called if the base class doTestStepPreambleL() did
* not leave. That being the case, the current test result value will be EPass.
*/
{
__UHEAP_MARK;
InitializeL();
_LIT(KStartTest,"CTransactionsStep::doTestStepL()");
ALLPRINT(KStartTest); //Block start
iIterate->Reset();
const TDesC &run = ConfigSection();
if( run == KRun1 )
{
ALLPRINT(KTest1);
NestedTransactionTestL();
}
else if( run == KRun2 )
{
ALLPRINT(KTest2);
EmptyCommitTransactionTestL(EFalse);
}
else if( run == KRun3 )
{
ALLPRINT(KTest3);
EmptyCommitTransactionTestL(ETrue);
}
else if( run == KRun4 )
{
ALLPRINT(KTest4);
UpdateCommitTransactionTestL(EFalse);
}
else if( run == KRun5 )
{
ALLPRINT(KTest5);
UpdateCommitTransactionTestL(ETrue);
}
else if( run == KRun6 )
{
ALLPRINT(KTest6);
CreateCommitTransactionTestL(EFalse);
}
else if( run == KRun7 )
{
ALLPRINT(KTest7);
CreateCommitTransactionTestL(ETrue);
}
else if( run == KRun8 )
{
ALLPRINT(KTest8);
DeleteCommitTransactionTestL(EFalse);
}
else if( run == KRun9 )
{
ALLPRINT(KTest9);
DeleteCommitTransactionTestL(ETrue);
}
else if( run == KRun10 )
{
ALLPRINT(KTest10);
ManyUpdateCommitTransactionTestL(EFalse);
}
else if( run == KRun11 )
{
ALLPRINT(KTest11);
ManyUpdateCommitTransactionTestL(ETrue);
}
else if( run == KRun12 )
{
ALLPRINT(KTest12);
EmptyTransactionPerformanceTestL( EFalse);
}
else if( run == KRun13 )
{
ALLPRINT(KTest13);
EmptyTransactionPerformanceTestL( ETrue );
}
else if( run == KRun14 )
{
ALLPRINT(KTest14);
MediumTransactionPerformanceTestL( EFalse);
}
else if( run == KRun15 )
{
ALLPRINT(KTest15);
MediumTransactionPerformanceTestL( ETrue);
}
else if( run == KRun16 )
{
ALLPRINT(KTest16);
FullTransactionPerformanceTestL( EFalse);
}
else if( run == KRun17 )
{
ALLPRINT(KTest17);
FullTransactionPerformanceTestL( ETrue);
}
else if( run == KRun18 )
{
ALLPRINT(KTest18);
MultipleCommitTestL( EFalse);
}
else if( run == KRun19 )
{
ALLPRINT(KTest19);
MultipleCommitTestL( ETrue);
}
else
{
MissingTestPanic();
}
Cleanup();
__UHEAP_MARKEND;
return TestStepResult();
}
/**
if in revert mode rollback transaction, otherwise commit
*/
void CTransactionsStep::EndTransactionL(const TBool aRevert)
{
if(aRevert)
{
iContactsDatabase->DatabaseRollback();
CleanupStack::Pop();
if( iContactsDatabase->IsDamaged() )
{
iContactsDatabase->RecoverL();
}
}
else
{
iContactsDatabase->DatabaseCommitLP(EFalse);
}
}
void CTransactionsStep::NestedTransactionTestL()
{
TContactItemId cid = iIterate->NextL();
iContactsDatabase->DatabaseBeginLC(EFalse);
iContactsDatabase->DatabaseBeginLC(ETrue);
OpenL(cid);
SetFieldL(1, GetFieldL(KStringFields, KField, 1) );
CommitL(ETrue);
iContactsDatabase->DatabaseCommitLP(ETrue);
OpenL(cid);
SetFieldL(2, GetFieldL(KStringFields, KField, 2) );
CommitL(ETrue);
EndTransactionL(ETrue);
iIterate->Reset();
TInt err = KErrNone;
TInt k = 0;
TESTPRINT( iContactsDatabase->CountL() == iContacts );
for( k = 0; k < iContacts; ++k)
{
TRAP(err, ReadL( iIterate->NextL() ) );
TESTPRINTI( KErrNone == err, k );
TESTPRINTI( CheckAllFieldsL(KNullDesC), k );
CloseL( ETrue );
}
}
void CTransactionsStep::EmptyCommitTransactionTestL(const TBool aRevert)
{
CPerformanceFunctionalityBase::InitializeL();
iContactsDatabase->DatabaseBeginLC(EFalse);
EndTransactionL(aRevert);
iContactsDatabase->DatabaseBeginLC(EFalse);
ReadL( iIterate->NextL() );
EndTransactionL(aRevert);
CloseL( ETrue );
iIterate->Reset();
TInt i = 0;
for(; i < iContacts; ++i)
{
ReadL( iIterate->NextL() );
TESTPRINTI( CheckAllFieldsL(KNullDesC), i );
CloseL( ETrue );
}
}
void CTransactionsStep::UpdateCommitTransactionTestL(const TBool aRevert)
{
CPerformanceFunctionalityBase::InitializeL();
const TContactItemId cid = iIterate->NextL();
const TContactItemId cid2 = iIterate->NextL();
iContactsDatabase->DatabaseBeginLC(EFalse);
OpenL( cid );
SetAllFieldsL( GetNextFieldL(KStringFields, KField, ETrue) );
CommitL(ETrue);
EndTransactionL(aRevert);
iContactsDatabase->DatabaseBeginLC(EFalse);
ReadL( cid2 );
SetAllFieldsL( GetNextFieldL(KStringFields, KField, EFalse) );
iContactsDatabase->UpdateContactLC(cid2, iContactItem);
CleanupStack::PopAndDestroy();
CloseL( ETrue );
EndTransactionL(aRevert);
if(aRevert)
{
iIterate->Reset();
TInt i = 0;
for(; i < iContacts; ++i)
{
ReadL( iIterate->NextL() );
TESTPRINTI( CheckAllFieldsL(KNullDesC), i );
CloseL( ETrue );
}
}
else
{
ReadL( cid );
TESTPRINT( CheckAllFieldsL( GetNextFieldL(KStringFields, KField, ETrue) ) );
CloseL( ETrue );
ReadL( cid2 );
TESTPRINT( CheckAllFieldsL( GetNextFieldL(KStringFields, KField, EFalse) ) );
CloseL( ETrue );
}
}
void CTransactionsStep::CreateCommitTransactionTestL(const TBool aRevert)
{
iContacts = 0;
CPerformanceFunctionalityBase::InitializeL();
CContactItemFieldSet& templateFields = iTemplate->CardFields();
TInt fieldsCount = templateFields.Count() - 1;
iContactsDatabase->DatabaseBeginLC(EFalse);
iContacts = 2;
TInt k = 0;
CContactCard* contact = CContactCard::NewLC(iTemplate);
for(; k < iContacts; k++)
{
iIterate->AddL( iContactsDatabase->doAddNewContactL(*contact,EFalse,ETrue) );
}
CleanupStack::PopAndDestroy(contact);
EndTransactionL(aRevert);
if(aRevert)
{
iIterate->Reset();
TInt err = KErrNone;
TESTPRINT( iContactsDatabase->CountL() == 0 );
for( k = 0; k < iContacts; ++k)
{
TRAP(err, ReadL( iIterate->NextL() ) );
TESTPRINTI( KErrNotFound == err, k );
CloseL( ETrue );
}
}
else
{
iIterate->Reset();
TESTPRINT( ( iContactsDatabase->CountL() == iContacts ) );
for(k = 0; k < iContacts; ++k)
{
ReadL( iIterate->NextL() );
TESTPRINTI( iFields->Count() == fieldsCount, k );
TESTPRINTI( CheckAllFieldsL(KNullDesC), k );
CloseL( ETrue );
}
}
}
void CTransactionsStep::DeleteCommitTransactionTestL(const TBool aRevert)
{
iContacts = 10;
CPerformanceFunctionalityBase::InitializeL();
iContactsDatabase->DatabaseBeginLC(EFalse);
TInt k = 0;
for(; k < iContacts; k++)
{
iContactsDatabase->doDeleteContactL(iIterate->NextL(), ETrue, ETrue);
}
EndTransactionL(aRevert);
if(aRevert)
{
TESTPRINT( iContactsDatabase->CountL() == iContacts );
iIterate->Reset();
TInt err = KErrNone;
for(k = 0; k < iContacts; ++k)
{
TRAP(err, ReadL( iIterate->NextL() ) );
TESTPRINTI( KErrNone == err, k );
TESTPRINTI( CheckAllFieldsL( KNullDesC ), k );
CloseL( ETrue );
}
}
else
{
TESTPRINT( iContactsDatabase->CountL() == 0 );
iIterate->Reset();
TInt err = KErrNone;
for(k = 0; k < iContacts; ++k)
{
TRAP(err, ReadL( iIterate->NextL() ) );
TESTPRINTI( KErrNotFound == err, k );
CloseL( ETrue );
}
iIterate->Clear();
}
}
void CTransactionsStep::ManyUpdateCommitTransactionTestL( const TBool aRevert )
{
iContacts = 1000;
CPerformanceFunctionalityBase::InitializeL();
RCntList backuplist;
backuplist.CopyL( *iIterate );
iContactsDatabase->DatabaseBeginLC(EFalse);
TInt added = 0;
TInt deleted = 0;
TInt updated = 0;
TInt k = 0;
for(; k < iContacts; k++)
{
switch( k % KNumCUDOperations )
{
case ( EOpen ):
{
OpenL( iIterate->NextL() );
//if setting first contact read first field from stringfields section
//otherwise read next field in list of fields stored in ini file secion
SetAllFieldsL( GetNextFieldL(KStringFields, KField, 0 == k ) );
CommitL(ETrue);
++updated;
}
break;
case ( EUpdate ):
{
TContactItemId cid = iIterate->NextL();
ReadL( cid );
//if setting first contact read first field from stringfields section
//otherwise read next field in list of fields stored in ini file secion
SetAllFieldsL( GetNextFieldL(KStringFields, KField, 0 == k ) );
iContactsDatabase->UpdateContactLC(cid, iContactItem);
CleanupStack::PopAndDestroy();
CloseL( ETrue );
++updated;
}
break;
case ( EAddDelete ):
{
DeleteContactL( iIterate->NextL(), ETrue );
//iterator position is shifted back, so that next nextL call is correct
iIterate->PreviousL();
++deleted;
//Empty contact is appended to the database,
//Contact id is stored at the end of iterator list not at current iterator position
AddEmptyContactsL( 1, ETrue );
++added;
}
break;
default:
{
_LIT(KInvalidTest, "Invalid Case");
User::Panic(KInvalidTest, 555);
}
break;
}
}
EndTransactionL(aRevert);
TESTPRINT( iContactsDatabase->CountL() == iContacts );
CContactItemFieldSet& templateFields = iTemplate->CardFields();
TInt fieldsCount = templateFields.Count() - 1;
if(aRevert)
{
//if transaction is reverted / rolledback, all contacts should be
//unchanged, i.e. they should all contain empty fields only
backuplist.Reset();
TInt err = KErrNone;
for(k = 0; k < iContacts; ++k)
{
TRAP(err, ReadL( backuplist.NextL() ) );
TESTPRINTI( KErrNone == err, k );
TESTPRINTI( CheckAllFieldsL( KNullDesC ), k );
CloseL( ETrue );
}
}
else
{
iIterate->Reset();
//all updated contact should contain the appropriated updated field value
for(k = 0; k < updated; ++k)
{
ReadL( iIterate->NextL() );
TESTPRINTI(iFields->Count() == fieldsCount, k);
//if reading first contact read first field from stringfields section
//otherwise read next field in list of fields stored in ini file secion
TESTPRINTI( CheckAllFieldsL( GetNextFieldL(KStringFields, KField, 0 == k ) ), k );
CloseL( ETrue );
}
//all newly added contacts, should contain empty fields only.
for(k = 0; k < added; ++k)
{
ReadL( iIterate->NextL() );
TESTPRINTI( iFields->Count() == fieldsCount, k);
TESTPRINTI( CheckAllFieldsL( KNullDesC ), k);
CloseL( ETrue );
}
}
}
void CTransactionsStep::TransactionPerformanceL( const TBool aDelete,
const FieldFullness aField,
const TInt aContacts,
TReal &aDiffseconds,
TReal &aCumseconds)
{
iContacts = ( ( aContacts / KTransactionSize ) + 1 ) * KTransactionSize ;
TInt64 cumlative = 0;
TInt64 diff = 0;
TTime startT;
TTime finishT;
TTime start;
TTime finish;
TInt j = 0;
for(; j < KPerfIter; ++j)
{
CPerformanceFunctionalityBase::InitializeL();
ModifyContactsL(aField);
ExportVcardL( aDelete, KVcardFile );
RFileReadStream rfrs;
CleanupClosePushL( rfrs );
User::LeaveIfError( rfrs.Open( iParent->Fs(), KVcardFile, EFileRead | EFileShareAny ) );
TInt i = 0;
start.UniversalTime();
for(; i < iContacts; i+=KTransactionSize)
{
iContactsDatabase->DatabaseBeginLC(EFalse);
ImportVcardL(KTransactionSize, rfrs);
startT.UniversalTime();
iContactsDatabase->DatabaseCommitLP(EFalse);
finishT.UniversalTime();
cumlative += ( finishT.MicroSecondsFrom( startT ).Int64() );
}
finish.UniversalTime();
diff += ( finish.MicroSecondsFrom(start).Int64() );
CleanupStack::PopAndDestroy(&rfrs);
}
User::LeaveIfError( iParent->Fs().Delete(KVcardFile) );
aDiffseconds = (TReal) diff / (1000000 * KPerfIter);
aCumseconds = (TReal) cumlative / (1000000 * KPerfIter);
_LIT(KMicroPerformance, "Micro performance: %d");
_LIT(KSecondsPerformance, "performance in seconds: %f");
_LIT(KCommitPerformance, "commit performance in seconds: %f");
ALLPRINT2(KMicroPerformance, diff);
ALLPRINT2(KSecondsPerformance, aDiffseconds );
ALLPRINT2(KCommitPerformance, aCumseconds );
}
void CTransactionsStep::EmptyTransactionPerformanceTestL(const TBool aDelete)
{
TReal diffsecondsMax = 0;
TReal commitsecondsMax = 0;
_LIT(KMaxContactsPrint,"$Max contacts$");
ALLPRINT(KMaxContactsPrint);
TransactionPerformanceL(aDelete, EEmpty, KMaxContacts, diffsecondsMax, commitsecondsMax);
TESTPRINT( diffsecondsMax < KMaxTimeAllowed );
}
void CTransactionsStep::MediumTransactionPerformanceTestL(const TBool aDelete)
{
TReal diffsecondsMin = 0;
TReal commitsecondsMin = 0;
TReal diffsecondsMid = 0;
TReal commitsecondsMid = 0;
TReal diffsecondsMan = 0;
TReal commitsecondsMan = 0;
TReal diffsecondsMax = 0;
TReal commitsecondsMax = 0;
ALLPRINT(KMinContactsPrint);
TransactionPerformanceL(aDelete, EMedium, KMinContacts, diffsecondsMin, commitsecondsMin);
ALLPRINT(KMidContactsPrint);
TransactionPerformanceL(aDelete, EMedium, KMidContacts, diffsecondsMid, commitsecondsMid);
ALLPRINT(KManyContactsPrint);
TransactionPerformanceL(aDelete, EMedium, KManyContacts, diffsecondsMan, commitsecondsMan);
ALLPRINT(KMaxContactsPrint);
TransactionPerformanceL(aDelete, EMedium, KMaxContacts, diffsecondsMax, commitsecondsMax);
TESTPRINT( diffsecondsMax < KMaxTimeAllowed );
}
void CTransactionsStep::FullTransactionPerformanceTestL(const TBool aDelete)
{
TReal diffsecondsMin = 0;
TReal commitsecondsMin = 0;
TReal diffsecondsMid = 0;
TReal commitsecondsMid = 0;
TReal diffsecondsMan = 0;
TReal commitsecondsMan = 0;
TReal diffsecondsMax = 0;
#ifdef __WINSCW__
TReal commitsecondsMax = 0;
#endif
ALLPRINT(KMinContactsPrint);
TransactionPerformanceL(aDelete, EFull, KMinContacts, diffsecondsMin, commitsecondsMin);
ALLPRINT(KMidContactsPrint);
TransactionPerformanceL(aDelete, EFull, KMidContacts, diffsecondsMid, commitsecondsMid);
ALLPRINT(KManyContactsPrint);
TransactionPerformanceL(aDelete, EFull, KManyContacts, diffsecondsMan, commitsecondsMan);
//is too slow on hardware, also takes up too much disk space
#ifdef __WINSCW__
ALLPRINT(KMaxContactsPrint);
TransactionPerformanceL(aDelete, EFull, KMaxContacts, diffsecondsMax, commitsecondsMax);
#endif
TESTPRINT( diffsecondsMax < KMaxTimeAllowed );
}
void CTransactionsStep::MultipleCommitTestL(const TBool aTrans)
{
iContacts = 40;
CPerformanceFunctionalityBase::InitializeL();
if(aTrans)
{
iContactsDatabase->DatabaseBeginLC(EFalse);
}
MultipleCommitL(aTrans);
if(aTrans)
{
EndTransactionL(EFalse);
}
TInt k = 0;
iIterate->Reset();
for(; k < iContacts; ++k)
{
ReadL( iIterate->NextL() );
TESTPRINTI( CheckAllFieldsL( GetNextFieldL(KStringFields, KField, 0 == k ) ), k );
CloseL( ETrue );
}
}
/**
destroy array from within cleanupstack
*/
static void ArrayCleanup(TAny *aArray)
{
RPointerArray<CContactItem> *parray = static_cast< RPointerArray<CContactItem> * >(aArray);
parray->ResetAndDestroy();
}
void CTransactionsStep::MultipleCommitL(const TBool aTrans)
{
RPointerArray<CContactItem> itemarray( 500, 512 );
TCleanupItem tclean(ArrayCleanup,&itemarray);
CleanupStack::PushL( tclean );
TInt k = 0;
iIterate->Reset();
for(; k < iContacts; ++k)
{
itemarray.Append( iContactsDatabase->OpenContactLX( iIterate->NextL(), *iViewAll ) );
iFields = &( itemarray[k]->CardFields() );
SetAllFieldsL( GetNextFieldL(KStringFields, KField, 0 == k ) );
}
iIterate->Reset();
if(aTrans)
{
for( k = iContacts - 1; k >=0 ; --k )
{
iContactsDatabase->doCommitContactL(*itemarray[k], ETrue, ETrue );
CleanupStack::Pop();
}
}
else
{
for( k = iContacts - 1; k >=0 ; --k )
{
iContactsDatabase->CommitContactL(*itemarray[k]);
CleanupStack::Pop();
}
}
CleanupStack::PopAndDestroy();//tclean
}
/**
populates all contacts either moderately, fully, or not at all
*/
void CTransactionsStep::ModifyContactsL(const FieldFullness aField)
{
if(aField == EEmpty)
{
return;
}
iIterate->Reset();
TInt j = 0;
for(; j < iContacts; ++j)
{
OpenL(iIterate->NextL());
if(aField == EFull)
{
SetAllFieldsL( GetFieldL(KStringFields, KField, 2) );
}
else
{
SetManyFieldsL(GetFieldL(KStringFields, KField, 4) , KMediumFields);
}
CommitL(EFalse);
}
}