diff -r d4f567ce2e7c -r 5b6f26637ad3 phonebookengines_old/contactsmodel/tsrc/T_MULTS.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines_old/contactsmodel/tsrc/T_MULTS.CPP Tue Aug 31 15:05:21 2010 +0300 @@ -0,0 +1,1122 @@ +// 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: +// + +#include +#include +#include +#include +#include +#include +#include +#include "t_utils.h" +#include "t_utils2.h" + +RFs fs; +CCntTest* CntTest=NULL; +#define xtest(x) TestErr(x,__LINE__) + +_LIT(KDataBaseName, "c:T_MultReq.cdb"); + +const TInt KDeleteGranularity=16; // Must be kept in step with KDeleteTransactionGranularity in CNTDB.CPP + +struct TUpdatingResults + { +public: + TUpdatingResults(); + void ProcessErrorL(TInt aError); + void ProcessErrorL(TInt aError, TUpdatingResults &aMoreResults); + void PrintResults(const TDesC &aTitle) const; + void AppendResults(TDes &aBuf) const; +public: + TInt iTotalCount; + TInt iLockedCount; + TInt iNotFoundCount; + TInt iModifiedErr; + }; + +struct SDbmsErrParams + { + inline SDbmsErrParams(TBool *aRemoteThreadFinished,TUpdatingResults *aResults) : iRemoteThreadFinished(aRemoteThreadFinished),iResults(aResults) {}; + TBool *iRemoteThreadFinished; + TUpdatingResults *iResults; + }; + +LOCAL_D RTest test(_L("T_MULTS")); +LOCAL_D CContactDatabase* TheDb1; +LOCAL_D CContactDatabase* TheDb2; +LOCAL_D CArrayFix* TheIds; +void DoDEF022709TestL(); + +const TPtrC KDatabaseFileName=_L("C:T_MULTS"); + +// Note long names needed to push record size of 255 bytes to trigger problems with DBMS locking +const TPtrC KTestName1=_L("Test Name No%d, plus some padding to make the data over 255 bytes, 0123456789, 0123456789, 0123456789, 0123456789"); +const TPtrC KTestName2=_L("Test Name 2 No%d, plus some padding to make the data over 255 bytes, 0123456789, 0123456789, 0123456789, 0123456789"); +const TPtrC KTestName3=_L("Test Name 3 No%d, plus some padding to make the data over 255 bytes, 0123456789, 0123456789, 0123456789, 0123456789"); +const TInt KTotalNumRecords=20; + +struct TOpenBaseParams + { + TFileName iDbName; + TInt iParam1; + TInt iParam2; + }; + +enum TTestFuncs + { + EThreadFuncHoldOpenForAWhile, + EThreadFuncHoldOpenForever, + EThreadFuncHoldOpenRangeForAWhile, + EThreadFuncHoldOpenRangeForever, + EThreadFuncKeepUpdatingContacts, + }; + +enum TThreadFuncs + { + EFuncOpenContact, + EFuncDeleteContact, + EFuncKeepReadingContacts, + }; + +class CFred2 : public CBase + { +public: + ~CFred2(); + void ConstructL(TInt aFunc, const TDesC8 &aParams); + inline TInt Func() {return(iFunc);}; + inline const HBufC8 *Params() {return(iParams);}; + void WaitForLogon(); + void Kill(); +// Other thread funcs + void DoTestL(); +protected: + void OpenDbEtcL(); + void RunTestL(); + void CloseDbEtcL(); + void KeepUpdatingContactsL(TInt aNumTimesToLoop,SDbmsErrParams *aResults); +protected: + CContactDatabase* iDb; + TInt iFunc; + HBufC8* iParams; + RThread iThread; + TRequestStatus iLogonStatus; + }; + +class CNotificationRec : public CBase, public MContactDbObserver + { +public: + static CNotificationRec* NewLC(); + ~CNotificationRec(); + void Wait(TContactItemId aTestId, TContactDbObserverEventType aEventType, const CContactDatabase* aDatabase); + static TInt TimerCallBackL(TAny* aSelf); + void Purge(); +public: // from MContactDbObserver + void HandleDatabaseEventL(TContactDbObserverEvent aEvent); +private: + void ConstructL(); +private: + CPeriodic* iTimer; + TBool iWaiting; + TContactItemId iTestId; + TUint iConnectionId; + TContactDbObserverEventType iEventType; + }; + +// +// TUpdatingResults +// + +TUpdatingResults::TUpdatingResults() + { + iTotalCount=0; + iLockedCount=0; + iNotFoundCount=0; + iModifiedErr=0; + } + +void TUpdatingResults::ProcessErrorL(TInt aError) + { + if (aError==KErrLocked) + iLockedCount++; + else if (aError==KErrNotFound) + iNotFoundCount++; + else if (aError==KErrCommsLineFail) + iModifiedErr++; + else + User::LeaveIfError(aError); + iTotalCount++; + } + +void TUpdatingResults::ProcessErrorL(TInt aError, TUpdatingResults &aMoreResults) + { + ProcessErrorL(aError); + aMoreResults.ProcessErrorL(aError); + } + +void TUpdatingResults::PrintResults(const TDesC &aTitle) const + { + test.Printf(aTitle); + test.Printf(_L("-Locked/Not Found/Debug/Total[1] %d/%d/%d/%d\n"),iLockedCount,iNotFoundCount,iModifiedErr,iTotalCount); + } + +void TUpdatingResults::AppendResults(TDes &aBuf) const + { + aBuf.AppendFormat(_L("%d/%d/%d/%d"),iLockedCount,iNotFoundCount,iModifiedErr,iTotalCount); + } + +// + +LOCAL_C CFred2 *LaunchFred2L(TInt aFunc, const TDesC8 &aParams) + { + CFred2 *fred2=new(ELeave) CFred2; + fred2->ConstructL(aFunc, aParams); + return(fred2); + } + +CNotificationRec* CNotificationRec::NewLC() + { // static + CNotificationRec* self=new(ELeave) CNotificationRec; + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +CNotificationRec::~CNotificationRec() + { + delete iTimer; + } + +void CNotificationRec::ConstructL() + { + iTimer=CPeriodic::NewL(0); + } + +void CNotificationRec::Wait(TContactItemId aTestId, TContactDbObserverEventType aEventType, const CContactDatabase* aDatabase) + { + iWaiting=ETrue; + iTestId=aTestId; + iEventType=aEventType; + iConnectionId=aDatabase->ConnectionId(); + iTimer->Start(5000000,5000000,TCallBack(TimerCallBackL,NULL)); // wait for 5 seconds for notification + CActiveScheduler::Start(); + } + +void CNotificationRec::Purge() + { + iWaiting=EFalse; + iTimer->Start(2000000,2000000,TCallBack(TimerCallBackL,this)); // wait for 2 seconds for notification + CActiveScheduler::Start(); + } + +TInt CNotificationRec::TimerCallBackL(TAny* aSelf) + { // static + // if this gets called, notification hasn't happened + if (((CNotificationRec*)aSelf)->iWaiting) + User::Leave(KErrGeneral); + else + { + ((CNotificationRec*)aSelf)->iTimer->Cancel(); + CActiveScheduler::Stop(); + } + return 0; + } + +void CNotificationRec::HandleDatabaseEventL(TContactDbObserverEvent aEvent) + { + if (!iWaiting || aEvent.iType==EContactDbObserverEventRollback) + return; + if (iEventType!=EContactDbObserverEventUnknownChanges) + test(aEvent.iContactId==iTestId); + test(iEventType==aEvent.iType); + switch(iEventType) + { + case EContactDbObserverEventRecover: + case EContactDbObserverEventTablesClosed: + case EContactDbObserverEventTablesOpened: + test(aEvent.iConnectionId==0); + break; + default: + test(iConnectionId==aEvent.iConnectionId); + break; + } + iWaiting=EFalse; + iTimer->Cancel(); + CActiveScheduler::Stop(); + } + + +LOCAL_C void PopulateDatabaseL() +// +// Create and populate the database +// + { + TheIds=new(ELeave) CArrayFixFlat(5); + CContactDatabase* db=CntTest->CreateDatabaseL(); + CntTest->DeleteAllTemplateFieldsL(); + TContactItemId id; + for (TInt ii=0;ii name; + name.Format(KTestName1,ii); + SetNameL(*item,KUidContactFieldCompanyName,KUidContactFieldVCardMapUnusedN,name,ETrue); + name.Format(KTestName2,ii); + SetNameL(*item,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,name,ETrue); + name.Format(KTestName3,ii); + SetNameL(*item,KUidContactFieldGivenName,KUidContactFieldVCardMapUnusedN,name,ETrue); + id=db->AddNewContactL(*item); + TheIds->AppendL(id); + CleanupStack::PopAndDestroy(); // item + } + CntTest->CloseDatabase(); + } + +LOCAL_C TPtrC Name(CContactItem& aItem,TUid aType) + { + CContactItemFieldSet& fieldSet=aItem.CardFields(); + const TInt pos=fieldSet.Find(aType); + if (pos==KErrNotFound) + return _L(""); + return fieldSet[pos].TextStorage()->Text(); + } + +LOCAL_C void ReadL() +// +// Access the database with two clients running in the same thread +// + { + CContactItem* item1=NULL; + CContactItem* item2=NULL; + for (TInt ii=0;iiReadContactLC(id); + item2=TheDb2->ReadContactLC(id); + test(Name(*item1,KUidContactFieldCompanyName)==Name(*item2,KUidContactFieldCompanyName)); + TBuf<256> testName; + testName.Format(KTestName1,ii); + test(Name(*item1,KUidContactFieldCompanyName)==testName); + CleanupStack::PopAndDestroy(2); // item2, item1 + } + } + +LOCAL_C void EditL() + { + CContactItem* item1=NULL; + CContactItem* item2=NULL; + for (TInt ii=0;iiOpenContactL(id); + CleanupStack::PushL(item1); + SetNameL(*item1,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,_L("Family"),EFalse); + TheDb1->CommitContactL(*item1); + CleanupStack::PopAndDestroy(); // item1 + // test db2 picks up changes and re-edit items + item2=TheDb2->OpenContactL(id); + CleanupStack::PushL(item2); + test(Name(*item2,KUidContactFieldFamilyName)==_L("Family")); + SetNameL(*item2,KUidContactFieldGivenName,KUidContactFieldVCardMapUnusedN,_L(""),EFalse); + TheDb2->CommitContactL(*item2); + CleanupStack::PopAndDestroy(); // item2 + // check db1 notices changes + item1=TheDb1->ReadContactL(id); + test(Name(*item1,KUidContactFieldGivenName)==_L("")); + delete item1; + } + // test each one can lock records + TContactItemId id=(*TheIds)[0]; + item1=TheDb1->OpenContactL(id); + CleanupStack::PushL(item1); + TRAPD(err,TheDb2->OpenContactL(id)); + test(err==KErrInUse); + TheDb1->CloseContactL(id); + CleanupStack::PopAndDestroy(); // item1 + + item2=TheDb2->OpenContactL(id); + CleanupStack::PushL(item2); + TRAP(err,TheDb1->OpenContactL(id)); + test(err==KErrInUse); + TheDb2->CloseContactL(id); + CleanupStack::PopAndDestroy(); // item2 + } + +LOCAL_C void AddL() + { + CContactItem* item=CContactCard::NewLC(); + TContactItemId id1=TheDb1->AddNewContactL(*item); + TContactItemId id2=TheDb2->AddNewContactL(*item); + CleanupStack::PopAndDestroy(); // item + delete TheDb1->ReadContactL(id2); + delete TheDb2->ReadContactL(id1); + TheDb1->DeleteContactL(id2); + TheDb2->DeleteContactL(id1); + } + +LOCAL_C void TouchContactL(CContactDatabase* aDb, TContactItemId aId) + { + CContactItem* item=aDb->OpenContactL(aId); + SetNameL(*item,KUidContactFieldGivenName,KUidContactFieldVCardMapUnusedN,_L(""),EFalse); + aDb->CommitContactL(*item); + delete item; + } + +LOCAL_C void AdjustContactAccessCountL(CContactDatabase* aDb, TContactItemId aItemId, TInt aCount) + { + CContactItem *incItem=aDb->OpenContactLX(aItemId); + CleanupStack::PushL(incItem); + while(aCount>0) + { + incItem->IncAccessCount(); + aCount--; + } + while(aCount<0) + { + incItem->DecAccessCount(); + aCount++; + } + aDb->CommitContactL(*incItem); + CleanupStack::PopAndDestroy(2); // incItem, Close(incItem) + } + +LOCAL_C void WaitAndCheckEvent(CNotificationRec* aRec1,CNotificationRec* aRec2,TContactItemId aTestId, TContactDbObserverEventType aEventType, const CContactDatabase* aDatabase) + { + aRec1->Wait(aTestId,aEventType,aDatabase); + if (aRec2) + aRec2->Wait(aTestId,aEventType,aDatabase); + } + +LOCAL_C void SetSortOrderL(CContactDatabase* aDb, TFieldType aFieldType) + { + CArrayFix* sortOrder=new(ELeave) CArrayFixFlat(3); + CleanupStack::PushL(sortOrder); + sortOrder->AppendL(CContactDatabase::TSortPref(aFieldType,CContactDatabase::TSortPref::EAsc)); + aDb->SortL(sortOrder); + CleanupStack::Pop(); // sortOrder + } + +LOCAL_C void TestDeleteContactsErrorL(CContactDatabase* aDb, CContactDatabase* aDb2, CNotificationRec* aRec, CNotificationRec* aRec2, TInt aErrorPos, TBool aChangedMessage) + { + aRec2->Purge(); + SetSortOrderL(aDb,KUidContactFieldGivenName); + CContactIdArray *deleteIds=CContactIdArray::NewLC(); + CContactItem *openItem=NULL; + TInt startCount=aDb->SortedItemsL()->Count(); + TInt startCount2=aDb2->SortedItemsL()->Count(); + for(TInt loop=0;loop<(aErrorPos+10);loop++) + { + TContactItemId add=AddContactL(aDb,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,_L("Add1")); + deleteIds->AddL(add); + aRec->Wait(add,EContactDbObserverEventContactAdded,aDb); + aRec2->Wait(add,EContactDbObserverEventContactAdded,aDb); + if (loop==aErrorPos) + { + openItem=aDb2->OpenContactLX(add); + CleanupStack::PushL(openItem); + } + TInt db2Count=aDb2->SortedItemsL()->Count(); + test(db2Count==(startCount2+loop+1)); + } + test(openItem!=NULL); + TRAPD(delErr,aDb->DeleteContactsL(*deleteIds)); + test(delErr==KErrInUse); + User::After(500000); // Let rollback event arrive + if (aChangedMessage) + aRec->Wait(0,EContactDbObserverEventUnknownChanges,aDb); +// + CleanupStack::PopAndDestroy(3); // deleteIds, openItem, openItem->Close() +// + aDb2->RecoverL(); +// + if (aChangedMessage) + { + aRec->Wait(0,EContactDbObserverEventTablesClosed,aDb); +// aRec->Wait(0,EContactDbObserverEventUnknownChanges,aDb); + } +// + aDb->OpenTablesL(); + aRec->Purge(); + aRec2->Purge(); + SetSortOrderL(aDb,KUidContactFieldFamilyName); + TInt db1Count=aDb->SortedItemsL()->Count(); + TInt db2Count=aDb2->SortedItemsL()->Count(); + test(db1Count==db2Count); + if (aChangedMessage) + test(db1Count==(startCount+10+aErrorPos-KDeleteGranularity)); + else + test(db1Count==(startCount+10+aErrorPos)); +// + deleteIds=CContactIdArray::NewLC(aDb->SortedItemsL()); + aDb->DeleteContactsL(*deleteIds); + aRec->Wait(0,EContactDbObserverEventUnknownChanges,aDb); + CleanupStack::PopAndDestroy(); // deleteIds + } + +LOCAL_C void WaitForNotificationL() + { + CNotificationRec* rec1=CNotificationRec::NewLC(); + CNotificationRec* rec2=CNotificationRec::NewLC(); + CContactDatabase* db1=CContactDatabase::OpenL(CntTest->DatabaseName()); + CleanupStack::PushL(db1); + CContactChangeNotifier *notify1=CContactChangeNotifier::NewL(*db1,rec1); + CleanupStack::PushL(notify1); + CContactDatabase* db2=CContactDatabase::OpenL(CntTest->DatabaseName()); + CleanupStack::PushL(db2); + CContactChangeNotifier *notify2=CContactChangeNotifier::NewL(*db2,rec2); + CleanupStack::PushL(notify2); + TContactItemId touchId=(*TheIds)[0]; + TouchContactL(db1,touchId); + WaitAndCheckEvent(rec1,rec2,touchId,EContactDbObserverEventContactChanged,db1); // shouldn't return until the change is notified +// + touchId=(*TheIds)[1]; + TouchContactL(db2,touchId); + WaitAndCheckEvent(rec1,rec2,touchId,EContactDbObserverEventContactChanged,db2); +// + TouchContactL(db2,(*TheIds)[0]); + TouchContactL(db2,(*TheIds)[1]); + TouchContactL(db2,(*TheIds)[2]); + db2->DeleteContactL((*TheIds)[1]); + TouchContactL(db2,(*TheIds)[3]); + TouchContactL(db2,(*TheIds)[0]); +// zzz Beef up test code to have a queue of expected events and read rec & rec2 in parallel + WaitAndCheckEvent(rec1,NULL,(*TheIds)[0],EContactDbObserverEventContactChanged,db2); + WaitAndCheckEvent(rec1,NULL,(*TheIds)[1],EContactDbObserverEventContactChanged,db2); + WaitAndCheckEvent(rec1,NULL,(*TheIds)[2],EContactDbObserverEventContactChanged,db2); + WaitAndCheckEvent(rec1,NULL,(*TheIds)[1],EContactDbObserverEventContactDeleted,db2); + WaitAndCheckEvent(rec1,NULL,(*TheIds)[3],EContactDbObserverEventContactChanged,db2); + WaitAndCheckEvent(rec1,NULL,(*TheIds)[0],EContactDbObserverEventContactChanged,db2); +// + AdjustContactAccessCountL(db2,(*TheIds)[2],1); + rec1->Wait((*TheIds)[2],EContactDbObserverEventContactChanged,db2); + db2->DeleteContactL((*TheIds)[2]); + rec1->Wait((*TheIds)[2],EContactDbObserverEventContactDeleted,db2); + AdjustContactAccessCountL(db2,(*TheIds)[2],-1); + TouchContactL(db2,(*TheIds)[0]); + rec1->Wait((*TheIds)[0],EContactDbObserverEventContactChanged,db2); +// + TContactItemId add1=AddContactL(db1,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,_L("Add1")); + TContactItemId add2=AddContactL(db2,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,_L("Add2")); + TContactItemId add3=AddContactL(db1,KUidContactFieldFamilyName,KUidContactFieldVCardMapUnusedN,_L("Add3")); + rec1->Wait(add1,EContactDbObserverEventContactAdded,db1); + rec1->Wait(add2,EContactDbObserverEventContactAdded,db2); + rec1->Wait(add3,EContactDbObserverEventContactAdded,db1); +// + CContactIdArray* deleteIds=CContactIdArray::NewLC(); + deleteIds->AddL(add2); + deleteIds->AddL(add1); + deleteIds->AddL(add3); + db1->DeleteContactsL(*deleteIds); + rec1->Wait(0,EContactDbObserverEventUnknownChanges,db1); + CleanupStack::PopAndDestroy(); // deleteIds +// + TestDeleteContactsErrorL(db1,db2,rec1,rec2,KDeleteGranularity-4,EFalse); // Count lower than delete granularity + TestDeleteContactsErrorL(db1,db2,rec1,rec2,KDeleteGranularity+4,ETrue); // Count Higher than delete granularity +// + CleanupStack::PopAndDestroy(6); // db2, db1, notify2, notify1, rec2, rec1 + } + +void TestErr(TInt aErr,TInt aLineNum) + { + if (aErr!=KErrNone) + { + test.Printf(_L("Error %d, line %d\n"),aErr,aLineNum); + test(EFalse); + } + } + +LOCAL_C void KeepReadingContactsL(TInt ,SDbmsErrParams *aParams) + { + const CContactIdArray* idarray=CContactIdArray::NewLC(TheDb1->SortedItemsL()); + User::After(200000); // Synch with other thread + while(!(*aParams->iRemoteThreadFinished)) + { + for(TInt idIndex=idarray->Count();idIndex>0;) + { + CContactItem *readItem=NULL; + TContactItemId id=(*idarray)[--idIndex]; + TRAPD(err,readItem=TheDb1->ReadContactL(id)); + CleanupStack::PushL(readItem); + aParams->iResults->ProcessErrorL(err); + if (err==KErrLocked) + test.Printf(_L("*")); + else if (err==KErrNotFound) + test.Printf(_L("#")); + else if (err==KErrCommsLineFail) + test.Printf(_L("%")); + else + test.Printf(_L(".")); + CleanupStack::PopAndDestroy(); // readItem + } + } + test.Printf(_L("\n")); + CleanupStack::PopAndDestroy(); // idArray + } + +LOCAL_C void MultiAccessTestL(TInt aFredFunc,TInt aFredParam1,TInt aFredParam2,TInt aFunc,TInt aParam1,TInt aParam2) + { + TOpenBaseParams params; + params.iDbName.Copy(CntTest->DatabaseName()); + params.iParam1=aFredParam1; + params.iParam2=aFredParam2; + CFred2* fred2=LaunchFred2L(aFredFunc,TPtrC8((TUint8 *)¶ms,sizeof(params))); + User::After(600000); // Let Fred2 get going +// + switch(aFunc) + { + case EFuncOpenContact: + { + CContactItem *item=NULL; + TRAPD(openErr,item=TheDb1->OpenContactL((*TheIds)[aParam1])); + CleanupStack::PushL(item); + xtest(openErr); + TheDb1->CommitContactL(*item); + CleanupStack::PopAndDestroy(); + } + break; + case EFuncDeleteContact: + TheDb1->DeleteContactL((*TheIds)[aParam1]); + break; + case EFuncKeepReadingContacts: + KeepReadingContactsL(aParam1,(SDbmsErrParams *)aParam2); + break; + } +// + if (aFredFunc==EThreadFuncHoldOpenForever || aFredFunc==EThreadFuncHoldOpenRangeForever) + fred2->Kill(); + fred2->WaitForLogon(); + delete fred2; + User::After(400000); // Let Fred2 shutdown properly + } + +/** + +@SYMTestCaseID PIM-T-MULTS-0001 + +*/ + +LOCAL_C void MultiAccessTestL() + { + test.Start(_L("@SYMTestCaseID:PIM-T-MULTS-0001 Multi 1")); +// + MultiAccessTestL(EThreadFuncHoldOpenForAWhile,1,0,EFuncOpenContact,1,0); + test.Next(_L("Multi 2")); + MultiAccessTestL(EThreadFuncHoldOpenForever,2,0,EFuncOpenContact,3,0); +// + test.Next(_L("Multi 3")); + MultiAccessTestL(EThreadFuncHoldOpenRangeForAWhile,8,9,EFuncOpenContact,5,0); + test.Next(_L("Multi 4")); + MultiAccessTestL(EThreadFuncHoldOpenRangeForever,2,16,EFuncOpenContact,18,0); +// + test.Next(_L("Multi 5")); + MultiAccessTestL(EThreadFuncHoldOpenForAWhile,1,0,EFuncDeleteContact,1,0); + test.Next(_L("Multi 6")); + MultiAccessTestL(EThreadFuncHoldOpenForever,0,0,EFuncDeleteContact,3,0); +// + test.Next(_L("Multi 7")); + TUpdatingResults updateResults1; + TUpdatingResults updateResults2[4]; + TBool remoteThreadFinished=EFalse; + SDbmsErrParams params1(&remoteThreadFinished,&updateResults1); + SDbmsErrParams params2(&remoteThreadFinished,&updateResults2[0]); + MultiAccessTestL(EThreadFuncKeepUpdatingContacts,5,(TInt)¶ms2,EFuncKeepReadingContacts,0,(TInt)¶ms1); + updateResults1.PrintResults(_L("Reading")); + updateResults2[0].PrintResults(_L("Open/Commit")); + updateResults2[1].PrintResults(_L("Export")); + updateResults2[2].PrintResults(_L("Import")); + updateResults2[3].PrintResults(_L("Delete")); +// + test.End(); + } + +void InitialiseDatabaseEtcL() + { + TRAPD(err,PopulateDatabaseL()); + xtest(err); + TheDb1=CContactDatabase::OpenL(CntTest->DatabaseName()); + TheDb2=CContactDatabase::OpenL(CntTest->DatabaseName()); + } + +void DeleteDatabaseEtc() + { + delete TheDb1; + delete TheDb2; + delete TheIds; + TheDb1=NULL; + TheDb2=NULL; + TheIds=NULL; + } + +class RTestSession : public RSessionBase + { +public: + TInt CreateSession(); + }; + +TInt RTestSession::CreateSession() + { + TVersion version; + return(RSessionBase::CreateSession(_L("CntLockServer"),version,1)); + } + +void TestServerGoneL() + { + test(CntTest->LockServerProcessCount(ETrue,EFalse,ETrue)==0); + if (CntTest->LockServerSessionExists()) + { + test.Printf(_L("Warning - Lock server still exists")); + test.Getch(); + } + } + +void DoTestsL() + { + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + CTestRegister* TempFiles = CTestRegister::NewLC(); + TempFiles->RegisterL(KDataBaseName, EFileTypeCnt); + TempFiles->RegisterL(KDatabaseFileName, EFileTypeCnt); + + CntTest->SelectDriveL(); + test.Start(_L("Create new database")); + TInt err; +// + TRAP(err,InitialiseDatabaseEtcL()); + test.Next(_L("Wait for change notification")); + TRAP(err,WaitForNotificationL()); + xtest(err); + DeleteDatabaseEtc(); +// + TRAP(err,InitialiseDatabaseEtcL()); + xtest(err); + test.Next(_L("Lock tests")); + TRAP(err,MultiAccessTestL()); + xtest(err); + DeleteDatabaseEtc(); +// + TRAP(err,InitialiseDatabaseEtcL()); + xtest(err); + test.Next(_L("Read items")); + TRAP(err,ReadL()); + xtest(err); + test.Next(_L("Edit items")); + TRAP(err,EditL()); + xtest(err); + test.Next(_L("Add / delete items")); + TRAP(err,AddL()); + xtest(err); + test.Next(_L("Wait for change notification")); + TRAP(err,WaitForNotificationL()); + xtest(err); + DeleteDatabaseEtc(); + TestServerGoneL(); + + // Now do test for DEF022709 (Propagated) Contact DB Monitoring Error Messages + TRAP(err,DoDEF022709TestL()); + xtest(err); + + CleanupStack::PopAndDestroy(2); // TempFiles, close fs + } + +LOCAL_C TInt FredIIFunc(TAny *aParam); + +GLDEF_C TInt E32Main() + { + CntTest=new(ELeave) CCntTest; + CntTest->ConstructL(test,KDatabaseFileName); + TRAPD(err,DoTestsL()); + CntTest->EndTestLib(err); + return KErrNone; + } + +// +// CFred2 +// + +CFred2::~CFred2() + { + iThread.Close(); + delete iParams; + } + +void CFred2::ConstructL(TInt aFunc, const TDesC8 &aParams) + { + iFunc=aFunc; + iParams=aParams.AllocL(); + User::LeaveIfError(iThread.Create(_L("FredII"),FredIIFunc,KDefaultStackSize,0x2000,0x20000,this,EOwnerThread)); + iThread.Logon(iLogonStatus); + iThread.Resume(); + } + +void CFred2::Kill() + { + iThread.Kill(0); + } + +void CFred2::WaitForLogon() + { + User::WaitForRequest(iLogonStatus); + xtest(iLogonStatus.Int()); + } + +// +// Fred II from here on +// + +LOCAL_C TInt FredIIFunc(TAny *aParam) + { + CActiveScheduler::Install(new(ELeave) CActiveScheduler); + CTrapCleanup* cleanup=CTrapCleanup::New(); + TRAPD(err,((CFred2 *)aParam)->DoTestL()); + delete cleanup; + delete CActiveScheduler::Current(); + return(err); + } + +void CFred2::OpenDbEtcL() + { + switch(Func()) + { + case EThreadFuncHoldOpenForAWhile: + case EThreadFuncHoldOpenForever: + case EThreadFuncHoldOpenRangeForAWhile: + case EThreadFuncHoldOpenRangeForever: + case EThreadFuncKeepUpdatingContacts: + iDb=CContactDatabase::OpenL(((TOpenBaseParams *)Params()->Ptr())->iDbName); + break; + } + } + +void CFred2::CloseDbEtcL() + { + delete iDb; + } + +void CFred2::KeepUpdatingContactsL(TInt aNumTimesToLoop,SDbmsErrParams *aParams) + { + TUpdatingResults *openResults=aParams->iResults; + TUpdatingResults *exportResults=aParams->iResults+1; + TUpdatingResults *importResults=aParams->iResults+2; + TUpdatingResults *deleteResults=aParams->iResults+3; + TUpdatingResults totalResults; + const CContactIdArray* idarray=CContactIdArray::NewLC(iDb->SortedItemsL()); + for(TInt mode=0;mode<2;mode++) + { + for(TInt loop=0;loopCount();idIndex++) + { + CContactItem *openItem=NULL; + TContactItemId id=(*idarray)[idIndex]; + TRAP(err,openItem=iDb->OpenContactL(id)); + CleanupStack::PushL(openItem); + if (err==KErrNone) + { + TRAP(err,iDb->CommitContactL(*openItem)); + iDb->CloseContactL(id); + } + CleanupStack::PopAndDestroy(); // openItem + openResults->ProcessErrorL(err,totalResults); + } + break; + } + case 1: + { + CVCardTestStore* store=NULL; + TRAP(err,store=ExportContactsL(iDb,idarray,CContactDatabase::EExcludeUid,KVCardStoreTypeBuf,NULL,1000)); + exportResults->ProcessErrorL(err,totalResults); + if (err==KErrNone) + { + CleanupStack::PushL(store); + CArrayPtr* items=NULL; + TRAP(err,items=ImportContactsL(iDb,store,CContactDatabase::EExcludeUid)); + importResults->ProcessErrorL(err,totalResults); + if (err==KErrNone) + { + CleanupStack::PushL(TCleanupItem(CleanUpResetAndDestroy,items)); + for(TInt delLoop=0;delLoopCount();delLoop++) + { + TRAP(err,iDb->DeleteContactL((*items)[delLoop]->Id())); + deleteResults->ProcessErrorL(err,totalResults); + } + CleanupStack::PopAndDestroy(); // items + } + CleanupStack::PopAndDestroy(); // store + } + } + break; + } + TBuf<128> buf; + buf.Format(_L("M:%d,C:%d "),mode,loop); + totalResults.AppendResults(buf); + User::InfoPrint(buf); + } + } + CleanupStack::PopAndDestroy(); // idArray + *aParams->iRemoteThreadFinished=ETrue; + } + +void CFred2::RunTestL() + { + switch(Func()) + { + case EThreadFuncHoldOpenForever: + case EThreadFuncHoldOpenForAWhile: + { + TContactItemId id=(*TheIds)[((TOpenBaseParams *)(Params()->Ptr()))->iParam1]; + CContactItem *item=iDb->OpenContactL(id); + CleanupStack::PushL(item); + if (Func()==EThreadFuncHoldOpenForAWhile) + { + User::After(1000000); + iDb->CommitContactL(*item); + CleanupStack::PopAndDestroy(); // item + } + else + { + TRequestStatus request; + User::WaitForRequest(request); // Wait forever + } + } + break; + case EThreadFuncHoldOpenRangeForAWhile: + case EThreadFuncHoldOpenRangeForever: + { + TInt start=((TOpenBaseParams *)(Params()->Ptr()))->iParam1; + TInt end=((TOpenBaseParams *)(Params()->Ptr()))->iParam2; + CContactItem *items[KTotalNumRecords]; + for(TInt loop=start;loopOpenContactL(id); +/* Weird MARM Death + TRAPD(x,items[loop]=iDb->OpenContactL(id)); + TBuf<32> buf; + buf.Format(_L("oc-%d"),x); + test.Printf(buf);*/ + CleanupStack::PushL(items[loop]); + } + if (Func()==EThreadFuncHoldOpenRangeForAWhile) + { + User::After(100000); + for(TInt loop=start;loopCommitContactL(*items[loop]); + CleanupStack::PopAndDestroy(end-start); + } + else + { + TRequestStatus request; + User::WaitForRequest(request); // Wait forever + } + } + break; + case EThreadFuncKeepUpdatingContacts: + { + TOpenBaseParams *params=(TOpenBaseParams *)(Params()->Ptr()); + KeepUpdatingContactsL(params->iParam1,(SDbmsErrParams *)params->iParam2); + } + break; + } + } + +void CFred2::DoTestL() + { + OpenDbEtcL(); + RunTestL(); + CloseDbEtcL(); + } + +// +// Test code for DEF022709 (Propagated) Contact DB Monitoring Error Messages // +// + +const TInt32 KNumContactsToAdd=50; +// If there are many contacts, it is worth using the #define below. +// This will compact the database when necessary. +#define __KEEP_DB_SMALL__ + +// CWaitForCompletion implementation +class CWaitForCompletion : public CActive + { + public: + CWaitForCompletion() : CActive(EPriorityStandard) + { + CActiveScheduler::Add(this); + } + virtual ~CWaitForCompletion() {} + + void Activate() { SetActive(); } + TRequestStatus& RequestStatus() { return iStatus; } + protected: + // From CActive + virtual void DoCancel() { ; } + virtual void RunL() { CActiveScheduler::Stop(); } + }; + +class CTestMultipleRequests : public CBase + { + public: + static CTestMultipleRequests* NewLC(TRequestStatus& aRequest); + void ConstructL(TRequestStatus& aRequest); + TContactItemId CreateTestContactL(const TDesC& aFamilyName, TBool aWithPhoneNumber); + CTestMultipleRequests(); + ~CTestMultipleRequests(); + TBool Synchronize(); + static TInt OnIdle(TAny* aObject); + TInt DoIdle(); + void Complete(); + private: +// CPbkContactEngine* iPbkEngine; + CContactDatabase* iContactDatabase; + CContactChangeNotifier* iContactChangeNotifier; + TBool iRepeat; + CContactIdArray* iContactDbIdArray; + CIdle* iIdleTask; + TInt iContactIdCount; + TInt iCount; + TInt iTimesThrough; + TRequestStatus* iClientRequest; + TBool iFinished; + }; + +CTestMultipleRequests::CTestMultipleRequests() + { + } + +CTestMultipleRequests::~CTestMultipleRequests() + { +// delete iPbkEngine; + delete iContactChangeNotifier; + delete iContactDbIdArray; + delete iIdleTask; + delete iContactDatabase; + } + +CTestMultipleRequests* CTestMultipleRequests::NewLC(TRequestStatus& aRequest) + { + CTestMultipleRequests* self=new(ELeave) CTestMultipleRequests(); + CleanupStack::PushL(self); + self->ConstructL(aRequest); + return self; + } + +void CTestMultipleRequests::ConstructL(TRequestStatus& aRequest) + { + iCount = 0; + iTimesThrough = 0; + iIdleTask = CIdle::NewL(-20); + iRepeat = EFalse; + iFinished=EFalse; + iClientRequest=&aRequest; + *iClientRequest=KRequestPending; +// BaseConstructL(); +// iPbkEngine = CPbkContactEngine::NewL(); + +// iContactDatabase = CContactDatabase::CreateL(KDatabaseFileName); + iContactDatabase = CContactDatabase::ReplaceL(KDataBaseName); + + CRandomContactGenerator* randomGenerator=CRandomContactGenerator::NewL(); + CleanupStack::PushL(randomGenerator); + randomGenerator->SetDbL(*iContactDatabase); + for (TInt i=0; iAddTypicalRandomContactL(); + CleanupStack::PopAndDestroy(randomGenerator); + + const CContactIdArray* contactDbIdArray = iContactDatabase->SortedItemsL(); + iContactDbIdArray = CContactIdArray::NewL(contactDbIdArray); + iContactIdCount = iContactDbIdArray->Count(); + + User::After(15000000); // 15 seconds + iIdleTask->Start(TCallBack(OnIdle,this)); // sync the VoCoS and Contact DB using CIdle + } + +TBool CTestMultipleRequests::Synchronize() + { + + if (iTimesThrough == 5) + return EFalse; + if (iCount == iContactIdCount) + { + iCount = 0; + iTimesThrough++; + } + CContactItem* item = iContactDatabase->OpenContactLX((*iContactDbIdArray)[iCount]); + CleanupStack::PushL(item); + iContactDatabase->CommitContactL( *item ); + CleanupStack::PopAndDestroy(item); + CleanupStack::PopAndDestroy(); // lock +#ifdef __KEEP_DB_SMALL__ + if (iContactDatabase->CompressRequired()) + iContactDatabase->CompactL(); // keep the database to a sensible size. +#endif + iCount++; + return ETrue; + } + + +TInt CTestMultipleRequests::OnIdle(TAny* aObject) + { + TBool ret = ((CTestMultipleRequests*)aObject)->DoIdle(); + if (!ret) + ((CTestMultipleRequests*)aObject)->Complete(); + return ret; + } + +TInt CTestMultipleRequests::DoIdle() + { + TBool ret=EFalse; + if (!iFinished) + { + ret = Synchronize(); + if (!ret) + { + iFinished=ETrue; + } + } + return ret; + } + +void CTestMultipleRequests::Complete() + { + if (iIdleTask) + { + iIdleTask->Cancel(); + } + User::RequestComplete(iClientRequest, KErrNone); + } + + +void DoDEF022709TestL() + { + test.Start(_L("Test for defect DEF022709")); + + // Create test resources + CWaitForCompletion* transactionWait=new (ELeave)CWaitForCompletion(); + CleanupStack::PushL(transactionWait); + CTestMultipleRequests* res = CTestMultipleRequests::NewLC(transactionWait->RequestStatus()); + transactionWait->Activate(); + CActiveScheduler::Start(); + + // Cleanup + CleanupStack::PopAndDestroy(res); + CleanupStack::PopAndDestroy(transactionWait); + + test.End(); + }