--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/tsrc/t_owncard.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,773 @@
+// Copyright (c) 2003-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:
+//
+
+// System includes
+#include <cntdb.h>
+#include <cntdef.h>
+#include <cntitem.h>
+#include <cntfield.h>
+#include <cntfldst.h>
+
+// System includes
+#include <e32std.h>
+#include <e32twin.h>
+#include <e32test.h>
+#include <cntdbobs.h>
+
+// User includes
+#include "t_utils2.h"
+
+// Constant
+_LIT(KDatabaseFileName, "c:t_owncard.cdb");
+_LIT(KSemaphoreNameOne, "One");
+_LIT(KSemaphoreNameTwo, "Two");
+
+_LIT(KThreadNameOne, "OneThread");
+_LIT(KThreadNameTwo, "TwoThread");
+
+
+const TInt KDelay = 1000000;
+
+static RTest TheTest(_L("t_owncard"));
+
+
+//
+/* CTestActiveScheduler */
+// This class has been nicked from the t_currentdb.h / .cpp files
+class CTestActiveScheduler : public CActiveScheduler
+ {
+ public:
+ void Error (TInt aError) const;
+ };
+void CTestActiveScheduler::Error(TInt aError) const
+ {
+ User::Panic(_L("AScheduler"),aError);
+ }
+
+
+
+//
+/* CConcurrentDatabaseAccessBase - Specification */
+// Forms the base class for both threads.
+class CConcurrentDatabaseAccessBase : public CActive
+ {
+ public: // Data Types
+ enum TStage
+ {
+ EOne_Startup,
+ ETwo_FirstCheck,
+ EThree_ChangeOwner,
+ ENOP_One,
+ ENOP_Two,
+ EFour_SecondCheck,
+ EFive_Cleanup,
+ EFinished
+ } ;
+ public:
+ CConcurrentDatabaseAccessBase();
+ virtual ~CConcurrentDatabaseAccessBase();
+
+ virtual void ConstructL(const TDesC& aFilename);
+
+ void RunTestL();
+
+
+ public: // data
+ RThread iThread;
+
+ protected:
+ void OpenSemaphore();
+ void CloseSemaphore();
+ void SyncronizeSignal();
+ void SyncronizeWait();
+ void OpenDatabaseL();
+ void CloseDatabase();
+ void CloseTest();
+
+ virtual TBool RunTestImplementationL() = 0;
+
+ protected: // from CActive
+ void DoCancel() {};
+ void RunL();
+ TInt RunError(TInt aError);
+ void CallRunLAgain();
+ TBool NextStage();
+
+
+ protected:
+ CContactDatabase* iDb;
+ TStage iStage;
+ TInt iTestError;
+
+ private:
+ RSemaphore iSemaphoreSignal;
+ RSemaphore iSemaphoreWait;
+ TBool iSemaphoreOpen;
+ HBufC* iDatabaseName;
+ };
+
+//
+/* CConcurrentDatabaseAccessBase - Implementation */
+CConcurrentDatabaseAccessBase::CConcurrentDatabaseAccessBase()
+ : CActive( /*EPriorityStandard*/ EPriorityIdle )
+ {
+ iStage = EOne_Startup;
+ }
+
+CConcurrentDatabaseAccessBase::~CConcurrentDatabaseAccessBase()
+ {
+ iThread.Close();
+ CloseSemaphore();
+ delete iDatabaseName;
+ }
+
+void CConcurrentDatabaseAccessBase::ConstructL(const TDesC& aFilename)
+ {
+ iDatabaseName = aFilename.AllocL();
+ }
+
+void CConcurrentDatabaseAccessBase::OpenDatabaseL()
+ {
+ iDb = CContactDatabase::OpenL(*iDatabaseName, CContactDatabase::EMultiThread);
+ }
+
+void CConcurrentDatabaseAccessBase::CloseDatabase()
+ {
+ delete iDb;
+ iDb = NULL;
+ }
+
+void CConcurrentDatabaseAccessBase::CloseTest()
+ {
+ }
+
+void CConcurrentDatabaseAccessBase::CallRunLAgain()
+ {
+ iStatus = KRequestPending;
+
+ TRequestStatus* ptrStatus = &iStatus;
+ User::RequestComplete( ptrStatus, KErrNone );
+ SetActive();
+ }
+
+TBool CConcurrentDatabaseAccessBase::NextStage()
+ {
+ TInt stage = static_cast<TInt>( iStage );
+ stage++;
+ iStage = static_cast<TStage>( stage );
+ return ( iStage == EFinished );
+ }
+
+void CConcurrentDatabaseAccessBase::RunL()
+ {
+ TBool stopProcessing = EFalse;
+
+ stopProcessing = RunTestImplementationL();
+
+ if (stopProcessing)
+ {
+ CActiveScheduler::Stop();
+ }
+ }
+
+TInt CConcurrentDatabaseAccessBase::RunError(TInt aError)
+ {
+ // propagate the error
+ iTestError = aError;
+
+ RDebug::Print(_L("Thread failed at test stage %i, with error %i"), iStage, aError);
+
+ CActiveScheduler::Stop();
+ return KErrNone;
+ }
+
+void CConcurrentDatabaseAccessBase::RunTestL()
+ {
+ // set's up an active scheduler for the thread
+ // and calls the RunTesImplementation function to actually
+ // preform the tests. This function should be implemented in the
+ // child class.
+ CTestActiveScheduler* scheduler = NULL;
+
+ scheduler = new (ELeave) CTestActiveScheduler;
+ CleanupStack::PushL(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+ CActiveScheduler::Add( this );
+
+ OpenDatabaseL();
+
+ CallRunLAgain();
+ CActiveScheduler::Start();
+
+ CloseDatabase();
+
+ CleanupStack::PopAndDestroy( scheduler );
+
+ // propagate error
+ User::LeaveIfError(iTestError);
+ }
+
+void CConcurrentDatabaseAccessBase::OpenSemaphore()
+ {
+ TInt success = KErrNone;
+
+ success = iSemaphoreSignal.OpenGlobal( KSemaphoreNameOne );
+ if ( success == KErrNotFound )
+ {
+ iSemaphoreSignal.CreateGlobal( KSemaphoreNameOne, 0 );
+ success = KErrNone;
+ }
+
+
+ success = iSemaphoreWait.OpenGlobal( KSemaphoreNameTwo );
+ if ( success == KErrNotFound )
+ {
+ iSemaphoreWait.CreateGlobal( KSemaphoreNameTwo, 0 );
+ }
+
+ iSemaphoreOpen = ETrue;
+ }
+
+void CConcurrentDatabaseAccessBase::CloseSemaphore()
+ {
+ if (iSemaphoreOpen)
+ {
+ iSemaphoreSignal.Close();
+ iSemaphoreWait.Close();
+ }
+
+ iSemaphoreOpen = EFalse;
+ }
+
+void CConcurrentDatabaseAccessBase::SyncronizeSignal()
+ {
+ CallRunLAgain();
+ iSemaphoreSignal.Signal();
+ iSemaphoreWait.Wait();
+ }
+
+void CConcurrentDatabaseAccessBase::SyncronizeWait()
+ {
+ CallRunLAgain();
+ iSemaphoreSignal.Wait();
+ iSemaphoreWait.Signal();
+ }
+
+//
+/* CConcurrentOwnerCardModifier - Specification */
+// This class should allow the two threads to compare the owner ID's of there db.
+class TOwnerCardCompare
+ {
+ public:
+ enum EThreadName
+ {
+ EModifier,
+ EChecker
+ };
+ public:
+ TOwnerCardCompare();
+ ~TOwnerCardCompare();
+ void AssignValuesAndCheckL(TContactItemId aValue, EThreadName aThreadName);
+
+ private:
+ void CheckValuesL();
+ void ClearValues();
+
+ private: // data
+ TBool iModifierDataPresent;
+ TBool iCheckerDataPresent;
+ TContactItemId iModifierValue;
+ TContactItemId iCheckerValue;
+ };
+
+//
+/* CConcurrentOwnerCardModifier - Implementatio */
+// This class should allow the two threads to compare the owner ID's of there db.
+TOwnerCardCompare::TOwnerCardCompare()
+ {
+ ClearValues();
+ }
+TOwnerCardCompare::~TOwnerCardCompare()
+ {
+ ClearValues();
+ }
+
+void TOwnerCardCompare::AssignValuesAndCheckL(TContactItemId aValue, EThreadName aThreadName)
+ {
+ switch ( aThreadName )
+ {
+ case EModifier:
+ iModifierDataPresent = ETrue;
+ iModifierValue = aValue;
+ break;
+
+ case EChecker:
+ iCheckerDataPresent = ETrue;
+ iCheckerValue = aValue;
+ break;
+ }
+ CheckValuesL();
+ }
+
+void TOwnerCardCompare::CheckValuesL()
+ {
+ if ( iModifierDataPresent && iCheckerDataPresent )
+ {
+ TheTest( (iCheckerValue == iModifierValue) );
+ ClearValues();
+ }
+ }
+
+void TOwnerCardCompare::ClearValues()
+ {
+ iCheckerDataPresent = EFalse;
+ iModifierDataPresent = EFalse;
+ iCheckerValue = 0;
+ iModifierValue = 0xFFFFFFFF;
+ }
+
+//
+/* CConcurrentOwnerCardModifier - Specification */
+// This class should create the db, and set the owner card.
+class CConcurrentOwnerCardModifier : public CConcurrentDatabaseAccessBase
+ {
+ public:
+ CConcurrentOwnerCardModifier(TOwnerCardCompare& aOwnerCardCompare);
+ ~CConcurrentOwnerCardModifier();
+
+ static CConcurrentOwnerCardModifier* NewLC(const TDesC& aFilename, TOwnerCardCompare& aOwnerCardCompare);
+ virtual void ConstructL(const TDesC& aFilename);
+
+ static TInt ThreadFunction(TAny* aSelf);
+
+
+ protected:
+ TBool RunTestImplementationL();
+
+ private:
+ void AssignAndCompareOwnerCardIdL(TContactItemId aOwner);
+
+ private:
+ TOwnerCardCompare& iOwnerCardCompare;
+ };
+
+//
+/* CConcurrentOwnerCardModifier - Implementation */
+
+CConcurrentOwnerCardModifier* CConcurrentOwnerCardModifier::NewLC(const TDesC& aFilename, TOwnerCardCompare& aOwnerCardCompare)
+ {
+ CConcurrentOwnerCardModifier* self = NULL;
+ self = new (ELeave) CConcurrentOwnerCardModifier(aOwnerCardCompare);
+ CleanupStack::PushL( self );
+ self->ConstructL(aFilename);
+ return self;
+ }
+
+CConcurrentOwnerCardModifier::CConcurrentOwnerCardModifier(TOwnerCardCompare& aOwnerCardCompare)
+ : iOwnerCardCompare( aOwnerCardCompare )
+ {
+ }
+
+CConcurrentOwnerCardModifier::~CConcurrentOwnerCardModifier()
+ {
+ }
+
+TInt CConcurrentOwnerCardModifier::ThreadFunction(TAny* aSelf)
+ {
+ CConcurrentOwnerCardModifier* self = STATIC_CAST(CConcurrentOwnerCardModifier*, aSelf);
+
+ // Prepare the stuff required before we start the
+ // active scheduler.
+ TInt error = KErrNone;
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ if (!cleanup)
+ return KErrNoMemory;
+
+ // Call virtual handler which does anything that needs doing as
+ // a result of the thread function from being created.
+ TRAP(error, self->RunTestL());
+
+
+ delete cleanup;
+ return error;
+ }
+
+void CConcurrentOwnerCardModifier::ConstructL(const TDesC& aFilename)
+ {
+ CConcurrentDatabaseAccessBase::ConstructL(aFilename);
+
+ iThread.Create( KThreadNameOne, CConcurrentOwnerCardModifier::ThreadFunction, KDefaultStackSize, 0x2000, 0x20000, this, EOwnerThread );
+ iThread.Resume();
+ iThread.SetPriority(/*EPriorityNormal*/EPriorityAbsoluteBackground);
+ }
+
+// 1. Set up
+// 2. Check current owner card.
+// 3. Sync
+// 4. modify owner card
+// 5. Sync
+// 6. Check owner card
+// 7. Sync
+// 8. Finished.
+TBool CConcurrentOwnerCardModifier::RunTestImplementationL()
+ {
+ TInt bit = 0;
+ TContactItemId id;
+ CRandomContactGenerator* generator = NULL;
+ CContactItem* item = NULL;
+ TBool retval = EFalse;
+
+ switch( iStage )
+ {
+ case EOne_Startup:
+ OpenSemaphore();
+ retval = NextStage();
+ SyncronizeWait(); // pause until corresponding Searcher thread is ready.
+ break;
+
+ case ETwo_FirstCheck:
+ id = iDb->OwnCardId();
+ AssignAndCompareOwnerCardIdL( id );
+ retval = NextStage();
+ SyncronizeWait();
+ break;
+
+ case EThree_ChangeOwner:
+ generator = CRandomContactGenerator::NewL();
+ CleanupStack::PushL( generator );
+ generator->SetDbL(*iDb);
+
+ bit |= CContactDatabase::ESmsable;
+ id = generator->AddTypicalContactForFilterL(bit);
+ item = iDb->ReadContactL( id );
+ CleanupStack::PushL( item );
+ iDb->SetOwnCardL( *item );
+ CleanupStack::PopAndDestroy( item );
+ item = NULL;
+ CleanupStack::PopAndDestroy( generator );
+ generator = NULL;
+ retval = NextStage();
+ SyncronizeWait(); // wait here.
+ break;
+
+ case ENOP_One:
+ CallRunLAgain();
+ retval = NextStage();
+ break;
+
+ case ENOP_Two:
+ CallRunLAgain();
+ retval = NextStage();
+ break;
+
+ case EFour_SecondCheck:
+ iDb->CountL();
+ id = iDb->OwnCardId();
+ AssignAndCompareOwnerCardIdL( id );
+ retval = NextStage();
+ SyncronizeWait();
+ break;
+
+ case EFive_Cleanup:
+ CloseSemaphore();
+ CloseTest();
+ retval = ETrue;
+ break;
+
+ default:
+ break;
+ }
+
+ return retval;
+ }
+
+
+void CConcurrentOwnerCardModifier::AssignAndCompareOwnerCardIdL(TContactItemId aOwner)
+ {
+ //SyncronizeWait();
+ iOwnerCardCompare.AssignValuesAndCheckL( aOwner, TOwnerCardCompare::EModifier );
+ //SyncronizeWait();
+ //SyncronizeWait();
+ }
+
+//
+/* CConcurrentOwnerCardChecker */
+class CConcurrentOwnerCardChecker : public CConcurrentDatabaseAccessBase
+ {
+ public:
+ CConcurrentOwnerCardChecker(TOwnerCardCompare& aOwnerCardCompare);
+ ~CConcurrentOwnerCardChecker();
+
+ static CConcurrentOwnerCardChecker* NewLC(const TDesC& aFilename, TOwnerCardCompare& aOwnerCardCompare);
+ virtual void ConstructL(const TDesC& aFilename);
+ static TInt ThreadFunction(TAny* aSelf);
+ static TInt FakeFunction(TAny *aParams);
+
+
+
+ protected:
+ TBool RunTestImplementationL();
+
+ private:
+ void AssignAndCompareOwnerCardIdL(TContactItemId aOwner);
+
+ private:
+ TOwnerCardCompare& iOwnerCardCompare;
+ };
+
+CConcurrentOwnerCardChecker* CConcurrentOwnerCardChecker::NewLC(const TDesC& aFilename, TOwnerCardCompare& aOwnerCardCompare)
+ {
+ CConcurrentOwnerCardChecker* self = NULL;
+ self = new (ELeave) CConcurrentOwnerCardChecker(aOwnerCardCompare);
+ CleanupStack::PushL( self );
+ self->ConstructL(aFilename);
+ return self;
+ }
+
+CConcurrentOwnerCardChecker::CConcurrentOwnerCardChecker(TOwnerCardCompare& aOwnerCardCompare)
+ : iOwnerCardCompare( aOwnerCardCompare )
+ {
+ }
+
+CConcurrentOwnerCardChecker::~CConcurrentOwnerCardChecker()
+ {
+ }
+
+TInt CConcurrentOwnerCardChecker::ThreadFunction(TAny* aSelf)
+ {
+ CConcurrentOwnerCardChecker* self = static_cast<CConcurrentOwnerCardChecker*>(aSelf);
+
+ // Prepare the stuff required before we start the
+ // active scheduler.
+ TInt error = KErrNone;
+
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+ if (!cleanup)
+ return KErrNoMemory;
+
+ // Call virtual handler which does anything that needs doing as
+ // a result of the thread function from being created.
+ TRAP(error, self->RunTestL());
+
+
+ delete cleanup;
+ return error;
+ }
+
+void CConcurrentOwnerCardChecker::ConstructL(const TDesC& aFilename)
+ {
+ CConcurrentDatabaseAccessBase::ConstructL(aFilename);
+
+ iThread.Create( KThreadNameTwo, CConcurrentOwnerCardChecker::ThreadFunction, KDefaultStackSize, 0x2000, 0x20000, this, EOwnerThread );
+ iThread.Resume();
+ iThread.SetPriority(/*EPriorityNormal*/EPriorityAbsoluteBackground);
+
+ }
+
+
+TInt CConcurrentOwnerCardChecker::FakeFunction(TAny* /*aParams*/)
+ {
+ return(KErrNone);
+ }
+
+TBool CConcurrentOwnerCardChecker::RunTestImplementationL()
+ {
+ // Prep, and get ready to run. Then before starting the search loop
+ // wait for the other thread.
+ TContactItemId id;
+ TBool retval = EFalse;
+
+ switch( iStage )
+ {
+ case EOne_Startup:
+ //TCallBack callBack(FakeFunction);
+ OpenSemaphore();
+ retval = NextStage();
+ SyncronizeSignal(); // wait for the other thread.
+ break;
+
+ case ETwo_FirstCheck:
+ id = iDb->OwnCardId();
+ AssignAndCompareOwnerCardIdL( id );
+ retval = NextStage();
+ SyncronizeSignal();
+ break;
+
+ case EThree_ChangeOwner:
+ retval = NextStage();
+ SyncronizeSignal();
+ break;
+
+ case ENOP_One:
+ CallRunLAgain();
+ retval = NextStage();
+ break;
+
+ case ENOP_Two:
+ CallRunLAgain();
+ retval = NextStage();
+ break;
+
+ case EFour_SecondCheck:
+ iDb->CountL();
+ id = iDb->OwnCardId();
+ AssignAndCompareOwnerCardIdL( id );
+ retval = NextStage();
+ SyncronizeSignal();
+ break;
+
+ case EFive_Cleanup:
+ CloseSemaphore();
+ CloseTest();
+ retval = NextStage();
+ break;
+
+ default:
+ break;
+ }
+
+ return retval;
+ }
+
+
+void CConcurrentOwnerCardChecker::AssignAndCompareOwnerCardIdL(TContactItemId aOwner)
+ {
+ //SyncronizeSignal();
+ //SyncronizeSignal();
+ iOwnerCardCompare.AssignValuesAndCheckL( aOwner, TOwnerCardCompare::EChecker );
+ //SyncronizeSignal();
+ }
+
+//
+/* Test Function Prototypes */
+//
+void CreateTestDatabaseL(const TDesC& aFilename);
+void TestL();
+void doMainL();
+
+//
+/* Test Function Implementations */
+//
+void CreateTestDatabaseL(const TDesC& aFilename )
+ {
+ TInt counter = 0;
+ TInt bit = 0;
+ CContactDatabase* database = NULL;
+ CRandomContactGenerator* generator = NULL;
+ CContactItem* ownerCardItem = NULL;
+ TContactItemId ownerCard = 0;
+
+ database = CContactDatabase::ReplaceL(aFilename);
+ CleanupStack::PushL( database );
+
+ generator = CRandomContactGenerator::NewL();
+ CleanupStack::PushL( generator );
+
+ generator->SetDbL(*database);
+
+
+ bit |= CContactDatabase::ESmsable;
+ ownerCard = generator->AddTypicalContactForFilterL(bit);
+ TheTest.Printf(_L("Adding SMS contacts %d\n"), counter);
+
+
+ ownerCardItem = database->ReadContactL( ownerCard );
+ CleanupStack::PushL( ownerCardItem );
+ database->SetOwnCardL( *ownerCardItem );
+ CleanupStack::PopAndDestroy( ownerCardItem ); ownerCardItem = NULL;
+
+ CleanupStack::PopAndDestroy( generator );
+ CleanupStack::PopAndDestroy( database );
+ }
+
+
+void TestL()
+ {
+ TRequestStatus thread1;
+ TRequestStatus thread2;
+ TOwnerCardCompare compareTool;
+ CConcurrentOwnerCardChecker* searcher = NULL;
+ CConcurrentOwnerCardModifier* inserter = NULL;
+
+ CreateTestDatabaseL( KDatabaseFileName );
+
+ searcher = CConcurrentOwnerCardChecker::NewLC( KDatabaseFileName, compareTool );
+ User::After(KDelay); // so that checker thread created first
+ inserter = CConcurrentOwnerCardModifier::NewLC( KDatabaseFileName, compareTool );
+
+ searcher->iThread.Logon(thread1);
+ inserter->iThread.Logon(thread2);
+
+ User::WaitForRequest(thread2);
+ User::WaitForRequest(thread1);
+
+ CleanupStack::PopAndDestroy( inserter );
+ CleanupStack::PopAndDestroy( searcher );
+
+ // fail if either thread failed
+ User::LeaveIfError(thread1.Int());
+ User::LeaveIfError(thread2.Int());
+ }
+
+
+//
+// -------> Static global functions (source)
+//
+void doMainL()
+ {
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+ CTestRegister * TempFiles = CTestRegister::NewLC();
+ TempFiles->RegisterL(KDatabaseFileName, EFileTypeCnt);
+
+ CTestActiveScheduler* scheduler = new (ELeave) CTestActiveScheduler;
+ CleanupStack::PushL(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+
+
+ // Delete any existing ini file so that we can be sure this test is ok
+ TestL();
+
+ CleanupStack::PopAndDestroy( 3 ); // scheduler, tempfiles, fs
+
+ }
+
+
+/**
+
+@SYMTestCaseID PIM-T-OWNCARD-0001
+
+*/
+
+GLDEF_C TInt E32Main()
+ {
+ CTrapCleanup* cleanupStack = NULL;
+ __UHEAP_MARK;
+ TheTest.Start(_L("@SYMTESTCaseID:PIM-T-OWNCARD-0001 Multi session testcode"));
+
+ TheTest.Title();
+ cleanupStack = CTrapCleanup::New();
+ TRAPD(ret, doMainL());
+ TheTest(ret == KErrNone);
+ delete cleanupStack;
+
+ TheTest.End();
+ TheTest.Close();
+ __UHEAP_MARKEND;
+ return(KErrNone);
+ }