--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/tsrc/T_Concurrent.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,373 @@
+// Copyright (c) 2000-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 Files
+#include "T_Concurrent.h"
+#include <e32base.h>
+#include <e32std.h>
+#include <e32cons.h>
+#include <cntdb.h>
+#include <cntdbobs.h>
+#include <cntitem.h>
+#include <cntfield.h>
+#include <cntfldst.h>
+
+
+// Constants
+_LIT(KThreadTitle, "Thread2");
+_LIT(KTextFailed, " failed, leave code = %d");
+
+// Global Variables
+RTest MainTest(_L("Concurrent test")); // Main RTest
+CContactDatabase * database = NULL; // Shared database.
+RSemaphore sem; // Synchronising Semaphore
+TInt t1MachineId = 0; // Thread1 machineId from db.
+TInt currentStep = 0; // Current test step.
+
+//
+// CHILD THREAD FUNCTIONS.
+//
+
+/**
+* The main function called when the child thread is invoked.
+*/
+TInt RunChildThread(TAny * /* ptr */)
+ {
+ // Create cleanup stack
+ __UHEAP_MARK;
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+
+ // Create active scheduler (to run active objects)
+ CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
+ CActiveScheduler::Install(scheduler);
+ CChildThread* childThread = NULL;
+
+ TInt err;
+ TRAP(err, childThread = CChildThread::NewL());
+ if (err == KErrNone)
+ {
+ TRAP(err, childThread->AccessDBTestL() );
+ }
+
+ if (err != KErrNone)
+ MainTest.Printf( _L(" Child thread test returned with error = %d"), err);
+
+ delete childThread;
+ delete cleanup;
+ delete scheduler;
+ __UHEAP_MARKEND;
+ return KErrNone;
+ }
+
+/**
+* The child thread accesses the shared db session.
+* A basic operation like getting the count of contacts is performed.
+*/
+CChildThread * CChildThread::NewL()
+ {
+ CChildThread * self = new(ELeave) CChildThread;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+void CChildThread::ConstructL()
+ {
+ TBuf<100> threadName;
+ threadName.Format(_L("Child Thread"));
+ iTest = new(ELeave) RTest(threadName);
+ }
+
+CChildThread::~CChildThread()
+ {
+ iTest->Close();
+ delete iTest;
+ iTest = NULL;
+ }
+
+
+/**
+* This function tries to access the db and check the count, or perform some other action
+* on the db. The session object is shared with the main thread .
+*/
+void CChildThread::AccessDBTestL()
+ {
+
+ while(currentStep != ETestsEnd)
+ {
+ TInt t2MachineId = database->MachineId();
+ TInt count = database->CountL();
+ iTest->Printf( _L("Thread2: Contact Count = %d"), count );
+
+ // Check that the child thread is accessing the shared db session correctly.
+ MainTest(count==1);
+ MainTest( t2MachineId == t1MachineId );
+
+ sem.Signal();
+ RThread().Suspend();
+ }
+
+ // Child thread is now over.
+ sem.Signal();
+
+ }
+
+
+//
+// MAIN THREAD FUNCTIONS.
+//
+/**
+* The main thread object which owns the session with the database in thread shared mode.
+*/
+CMainThread * CMainThread::NewL()
+ {
+ CMainThread * self = new (ELeave) CMainThread;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+void CMainThread::ConstructL()
+ {
+ TBuf<100> threadName;
+ threadName.Format(_L("Main Thread"));
+ iTest = new(ELeave) RTest(threadName);
+ }
+
+CMainThread::~CMainThread()
+ {
+ TRAP_IGNORE(CloseDatabaseSessionL() );
+ iTest->Close();
+ delete iTest;
+ iTest = NULL;
+ iChildThread.Close();
+ }
+
+/**
+* The function to empty the database and close the database session.
+*/
+void CMainThread::CloseDatabaseSessionL()
+ {
+ TestDeleteContactL();
+ delete database;
+ database = NULL;
+ }
+
+/**
+* Create the database in shared mode.
+*/
+void CMainThread::TestCreateDatabaseL()
+ {
+ // Creat the database in the first thread.
+ iTest->Next( _L("CreateDatabaseL :Test creating the db in multi - thread mode.") );
+ TRAP_IGNORE(CContactDatabase::DeleteDefaultFileL());
+ database = CContactDatabase::CreateL( CContactDatabase::EMultiThread );
+ t1MachineId = database->MachineId();
+ }
+
+/**
+* Open the database in shared mode.
+*/
+void CMainThread::TestOpenDatabaseL()
+ {
+ // Open the database in the first thread.
+ iTest->Next( _L("OpenDatabaseL :Test Opening the db in multi - thread mode.") );
+ database = CContactDatabase::OpenL( CContactDatabase::EMultiThread );
+ t1MachineId = database->MachineId();
+ }
+
+/**
+* Replace the database in shared mode.
+*/
+void CMainThread::TestReplaceDatabaseL()
+ {
+ // Replace the database in the first thread, in mutithread mode.
+ iTest->Next( _L("ReplaceDatabaseL :Test Replacing the db in multi - thread mode.") );
+ database = CContactDatabase::ReplaceL( CContactDatabase::EMultiThread );
+ t1MachineId = database->MachineId();
+ }
+
+/**
+* Add one contact to the database.
+*/
+void CMainThread::TestAddContactL()
+ {
+
+ // Add a contact
+ _LIT(KForename,"Jo");
+ _LIT(KSurname,"Stichbury");
+
+ // Create a contact card to contain the data
+ CContactCard* newCard = CContactCard::NewLC();
+
+ // Create the firstName field and add the data to it
+ CContactItemField* firstName = CContactItemField::NewLC(KStorageTypeText, KUidContactFieldGivenName);
+ firstName->TextStorage()->SetTextL(KForename);
+ newCard->AddFieldL(*firstName);
+ CleanupStack::Pop(firstName);
+
+ // Create the lastName field and add the data to it
+ CContactItemField* lastName= CContactItemField::NewLC(KStorageTypeText, KUidContactFieldFamilyName);
+ lastName ->TextStorage()->SetTextL(KSurname);
+ newCard->AddFieldL(*lastName);
+ CleanupStack::Pop(lastName);
+
+ // Add newCard to the database
+ iContactId = database->AddNewContactL(*newCard);
+ CleanupStack::PopAndDestroy(newCard);
+
+ iTest->Printf( _L("Thread1: Added 1 contact to the database."));
+ }
+
+/**
+* Delete the contact from the database.
+*/
+void CMainThread::TestDeleteContactL()
+ {
+ // Check if a contact has been stored in the db and delete it.
+ if (iContactId)
+ {
+ database->DeleteContactL(iContactId);
+ iContactId = 0;
+ }
+ }
+
+/**
+* The main thread controls the child thread
+*/
+void CMainThread::LaunchChildThreadL()
+ {
+
+ TRAPD(err,iChildThread.Create(KThreadTitle, RunChildThread, KDefaultStackSize, NULL, NULL, EOwnerProcess));
+
+ if(err != KErrNone)
+ {
+ iTest->Printf(_L("Failed to create the child thread, error code=%d"), err);
+ User::Leave(err);
+ }
+ }
+
+/**
+* Resume the child thread.
+*/
+
+void CMainThread::ResumeChildThreadL()
+ {
+ iChildThread.Resume();
+ }
+
+
+//
+// MAIN FUNCTIONS.
+//
+
+/**
+* The main function which creates the main thread controller object
+* and invokes all the tests.
+*/
+
+/**
+
+@SYMTestCaseID PIM-T-CONCURRENT-0001
+
+*/
+
+LOCAL_C void DoTestsL()
+ {
+
+ // Initialisation
+ MainTest.Start(_L("@SYMTESTCaseID:PIM-T-CONCURRENT-0001 T_Concurrent"));
+
+
+ // Create active scheduler (to run active objects)
+ CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
+ CleanupStack::PushL(scheduler);
+ CActiveScheduler::Install(scheduler);
+
+ // Create main thread object, child thread and synchnising semaphore.
+ sem.CreateLocal(0);
+ CMainThread * ptr = CMainThread::NewL();
+ CleanupStack::PushL(ptr);
+ ptr->LaunchChildThreadL();
+
+ // Run all the tests
+ while (currentStep <= ETestsEnd)
+ {
+ switch(currentStep)
+ {
+ case ETestCreate:
+ // create the db in shared mode and add a contact.
+ ptr->TestCreateDatabaseL();
+ ptr->TestAddContactL();
+ break;
+ case ETestOpen:
+ // create the db in shared mode
+ ptr->TestOpenDatabaseL();
+ ptr->TestAddContactL();
+ break;
+ case ETestReplace:
+ // create the db in shared mode
+ ptr->TestReplaceDatabaseL();
+ ptr->TestAddContactL();
+ break;
+ case ETestsEnd:
+ break;
+ default:
+ break;
+ } // end of switch
+
+ // Run the child thread and let it access the shared session.
+ ptr->ResumeChildThreadL();
+ sem.Wait();
+ ptr->CloseDatabaseSessionL();
+ currentStep++ ;
+ } // end of while
+
+ // Cleanup and close.
+ sem.Close();
+ CleanupStack::PopAndDestroy(ptr);
+ CleanupStack::PopAndDestroy(scheduler);
+ }
+
+
+/**
+* Entry point function.
+*/
+GLDEF_C TInt E32Main()
+ {
+ // Create cleanup stack
+ __UHEAP_MARK;
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+
+ TRAPD(mainError, DoTestsL());
+ if (mainError)
+ MainTest.Printf(KTextFailed, mainError);
+
+ MainTest.End();
+ MainTest.Close();
+ delete cleanup;
+
+ __UHEAP_MARKEND;
+ return KErrNone;
+ }
+
+
+
+
+
+
+