phonebookengines/contactsmodel/tsrc/t_owncard.cpp
changeset 0 e686773b3f54
child 24 0ba2181d7c28
--- /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);
+	}