diff -r 000000000000 -r e686773b3f54 phonebookengines/contactsmodel/tsrc/T_Concurrent.cpp --- /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 +#include +#include +#include +#include +#include +#include +#include + + +// 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; + } + + + + + + +