lowlevellibsandfws/apputils/tsrc/T_BackupSrv.cpp
author andy simpson <andrews@symbian.org>
Wed, 16 Jun 2010 08:14:03 +0100
branchGCC_SURGE
changeset 36 6a60b9d459b4
parent 0 e4d67989cc36
permissions -rw-r--r--
GCCE fixes (Bug 2971) (see also Bug 1713 on CompilerCompatibilty branch) : Remove overqualified method name and change check for ULong to not try and test typedef

// 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 <e32debug.h>
#include <e32test.h>
#include <babackup.h>
#include "T_backupSrv.h"
LOCAL_D RTest MainTest(_L(" T_BackupSrv.cpp"));

_LIT(KFileName1, "FileName1");
_LIT(KFileName2, "FileName2");
_LIT(KFileName3, "FileName3");
_LIT(KFileName4, "FileName4");

// Nasty global convenience function
LOCAL_D void LogThread()
{
	TBuf<150> buf((RThread().Name()));
	RDebug::Print(_L("*** Currently in thread : "));
	RDebug::Print(buf);
}

//
//	class CBackupOperationObserver
//
CBackupOperationObserver* CBackupOperationObserver::NewL(TInt aObserverNumber)
	{
	LogThread();
	RDebug::Print(_L("CBackupOperationObserver::NewL"));

	CBackupOperationObserver* self = new (ELeave) CBackupOperationObserver();
	CleanupStack::PushL(self);
	self->ConstructL(aObserverNumber);
	CleanupStack::Pop();
	return self;
	}

CBackupOperationObserver::CBackupOperationObserver()
 : CActive(0)
	{ ; }

CBackupOperationObserver::~CBackupOperationObserver()
	{
	LogThread();
	RDebug::Print(_L("CBackupOperationObserver::~CBackupOperationObserver"));

	iBackupSession->DeRegisterBackupOperationObserver(*this);
	delete iBackupSession;

	delete iLocalRTest;
	}

void CBackupOperationObserver::ConstructL(TInt aObserverNumber)
	{
	// Set up the AO callback
	CActiveScheduler::Add(this);
	SetActive();
	iStatus = KRequestPending;

	// Create a new session for this backup notification observer
	iBackupSession = CBaBackupSessionWrapper::NewL();
	iBackupSession->RegisterBackupOperationObserverL(*this);
	iObserverNumber = aObserverNumber;
	iLocalRTest = new (ELeave) RTest(_L("BackupOperationObserver"));
	}

void CBackupOperationObserver::HandleBackupOperationEventL(const TBackupOperationAttributes& aBackupOperationAttributes)
	{
	LogThread();
	RDebug::Print(_L("CBackupOperationObserver::HandleBackupOperationEventL"));

	TBuf<150> buf;
	buf.Format(_L("Backup observer number %d received a notification of operation type %d and file lock type: %d\n"),iObserverNumber, aBackupOperationAttributes.iOperation, aBackupOperationAttributes.iFileFlag);
	RDebug::Print(buf);
	}

void CBackupOperationObserver::DoCancel()
	{ ; }

void CBackupOperationObserver::RunL()
	{
	// Okay - we're back in the right thread!
	LogThread();
	RDebug::Print(_L("CBackupOperationObserver::RunL"));

	// Finished with this object
	delete this;

	// And the active scheduler in this thread
	CActiveScheduler::Current()->Stop();

	}

void CBackupOperationObserver::Kill(RThread* aThread)
	{
	LogThread();
	RDebug::Print(_L("CBackupFileObserver::Kill"));

	// Trigger the Active Object locally - in a different thread!
	TRequestStatus* tempStatus=(&iStatus);
	aThread->RequestComplete(tempStatus, KErrNone);
	}

//
//	class CBackupFileObserver
//

CBackupFileObserver::CBackupFileObserver()
 : CActive(0)
  { ;  }

void CBackupFileObserver::ConstructL(TInt aFileObserverNumber)
	{
	// Set up the AO callback
	CActiveScheduler::Add(this);
	SetActive();
	iStatus = KRequestPending;

	// Create a new session for this file lock observer
	iBackupSession = CBaBackupSessionWrapper::NewL();
	iFileObserverNumber = aFileObserverNumber;
	iFileLocksChanged = 0;
	iFileLockState = ELocked;
	iLocalRTest = new (ELeave) RTest(_L("BackupFileObserver"));
	}

CBackupFileObserver* CBackupFileObserver::NewL(TInt aFileObserverNumber)
	{
	LogThread();
	RDebug::Print(_L("CBackupFileObserver::NewL"));

	CBackupFileObserver* self=new(ELeave) CBackupFileObserver();
	CleanupStack::PushL(self);
	self->ConstructL(aFileObserverNumber);
	CleanupStack::Pop();
	return self;
	}

CBackupFileObserver::~CBackupFileObserver()
	{
	LogThread();
	RDebug::Print(_L("CBackupFileObserver::~CBackupFileObserver"));

	delete iBackupSession;

	delete iLocalRTest;
	}

void CBackupFileObserver::AddFileL(TInt aFileNumber)
	{
	LogThread();
	RDebug::Print(_L("CBackupFileObserver::AddFileL"));

	// We base the filename of the number of thread in the RArray
	iFileName.Format(_L("FileName%d"), aFileNumber);

	iBackupSession->RegisterFileL(iFileName,*this);
	}

TInt CBackupFileObserver::GetFileLocksChanged()
	{
	return iFileLocksChanged;
	}

void CBackupFileObserver::ZeroFileLocksChanged()
	{
	iFileLocksChanged = 0;
	}

void CBackupFileObserver::SetDelay(TBool aDelay)
{
	iDelay = aDelay;
}

void CBackupFileObserver::ChangeFileLockL(const TDesC& aFileName,TFileLockFlags aFlags)
	{
	LogThread();
	RDebug::Print(_L("BackupFileObserver::ChangeFileLockL"));

	// Keep a count of how many release notifications there have been
	if (aFlags != MBackupObserver::ETakeLock)
		{
		iFileLocksChanged++;
		}

	// If delay is set then insert wait now
	if (iDelay && (!(aFileName.Compare(KFileName1))))
		{
		User::After(10000000);
		}

	// Check this file is the one for this observer - if not fail test;
	if (iFileName.Compare(aFileName))
		{
		RDebug::Print(_L("\nReceived notification for non-registered file!"));
		(*iLocalRTest)(EFalse);
		}

	// Update the local file lock array
	CBackupFileObserver::TFileLock flag = (CBackupFileObserver::TFileLock) aFlags;
	iFileLockState = flag;

	// Test output
	TBuf<150> buf;
	buf.Format(_L("File backup observer number %d was notified for file %S of file lock type: %d\n"),iFileObserverNumber, &aFileName, flag);
	RDebug::Print(buf);
	}

void CBackupFileObserver::DoCancel()
	{ ; }

void CBackupFileObserver::RunL()
	{
	// Okay - we're back in the right thread!
	LogThread();
	RDebug::Print(_L("CBackupFileObserver::RunL"));

	// Finished with this object
	delete this;

	// And the active scheduler in this thread
	CActiveScheduler::Current()->Stop();

	}

void CBackupFileObserver::Kill(RThread* aThread)
	{
	LogThread();
	RDebug::Print(_L("CBackupFileObserver::Kill"));

	// Trigger the Active Object locally - in a different thread!
	TRequestStatus* tempStatus=(&iStatus);
	aThread->RequestComplete(tempStatus, KErrNone);
	}

//
// class CBackupTestsStateMachine
//

CBackupTestsStateMachine* CBackupTestsStateMachine::NewL()
	{
	CBackupTestsStateMachine* self = new (ELeave) CBackupTestsStateMachine();
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop();
	return self;
	}

CBackupTestsStateMachine::CBackupTestsStateMachine()
 : CActive(0)
{ ; }

void CBackupTestsStateMachine::ConstructL()
	{
	// Set up the RTest for this thread and display we're started
	iLocalRTest = new (ELeave) RTest(_L("T_BACKUP_SRV"));
	iLocalRTest->Title();

	// Set the ititial state
	iState = EStateMachineStart;

	// Zero the EndBackupRecursionCount (see below)
	iEndBackupRecursionCount = 0;

	// Add this to the Active Scheduler and set us active
	CActiveScheduler::Add(this);
	SetActive();

	// Create the backup "command" session
	iBackupSession = CBaBackupSessionWrapper::NewL();

	// Set up the mutex
	iMutex.CreateLocal();
	}

// Observers need to have their own thread
void CBackupTestsStateMachine::CreateObserversThreadsL()
	{
	RDebug::Print(_L("Starting observers threads"));

	TInt i;
	TBuf<30> newThreadNames;
	TInt error;
	for (i = 0; i<4 ; i++)
		{
		// Backup observer
		iBackupObserverThreads.AppendL(new (ELeave) RThread);
		newThreadNames.Format(_L("Backup Observer Thread %d"), i+1);
		error = iBackupObserverThreads[i]->Create(newThreadNames, CBackupTestsStateMachine::BackupObserversThreadStartL, 0x2000, NULL, (TAny*)this);
		(*iLocalRTest)(error==KErrNone);
		iBackupObserverThreads[i]->Resume();

		// File observer
		iFileObserverThreads.AppendL(new (ELeave) RThread);
		newThreadNames.Format(_L("File Observer Thread %d"), i+1);
		error = iFileObserverThreads[i]->Create(newThreadNames, CBackupTestsStateMachine::FileObserversThreadStartL, 0x2000, NULL, (TAny*)this);

		(*iLocalRTest)(error==KErrNone);
		iFileObserverThreads[i]->Resume();

		// Brief delay to let the observer threads get started
		User::After(1000000);
		}

	}

// Static starting function for the backup observers threads
TInt CBackupTestsStateMachine::BackupObserversThreadStartL(TAny* aPtr)
	{
	// Create the Cleanup Stack and Active Scheduler for this thread

	CTrapCleanup* theTrapCleanup = CTrapCleanup::New();
	CActiveScheduler *activeScheduler = new CActiveScheduler;
	CActiveScheduler::Install(activeScheduler);

	// Create the observer instances
	CBackupTestsStateMachine* objectPtr = static_cast<CBackupTestsStateMachine*>(aPtr);
	TRAPD(error, objectPtr->CreateBackupObserverInstanceL());
	User::LeaveIfError(error);

	// Go to Active Scheduler main loop for this thread
	CActiveScheduler::Start();

	// And we're done
	delete activeScheduler;
	delete theTrapCleanup;

	return KErrNone;
	}

// Static starting function for the file observers threads
TInt CBackupTestsStateMachine::FileObserversThreadStartL(TAny* aPtr)
{
	// Create the Cleanup Stack and Active Scheduler for this thread
	CTrapCleanup* theTrapCleanup = CTrapCleanup::New();
	CActiveScheduler* activeScheduler = new CActiveScheduler;
	CActiveScheduler::Install(activeScheduler);

	// Create the observer instances
	CBackupTestsStateMachine* objectPtr = static_cast<CBackupTestsStateMachine*>(aPtr);
	TRAPD(error, objectPtr->CreateFileObserverInstanceL());
	User::LeaveIfError(error);

	// Go to Active Scheduler main loop for this thread
	CActiveScheduler::Start();

	// And we're done
	delete activeScheduler;
	delete theTrapCleanup;

	return KErrNone;
}

void CBackupTestsStateMachine::CreateBackupObserverInstanceL()
	{
	iMutex.Wait();

	TInt count = iBackupObserverThreads.Count();

	// Create the new object instance (one object per thread)
	// We base the thread number of the number of thread in the RArray
	CBackupOperationObserver* newObserver = CBackupOperationObserver::NewL(count);
	iBackupObservers.AppendL(newObserver);

	iMutex.Signal();
	}

void CBackupTestsStateMachine::CreateFileObserverInstanceL()
{
	iMutex.Wait();

	TInt count = iBackupFileObservers.Count();

	// Create the new object instance (one object per thread)
	CBackupFileObserver* newObserver = CBackupFileObserver::NewL(count + 1);
	iBackupFileObservers.AppendL(newObserver);

	// Register the file for this thread / instance
	iBackupFileObservers[count]->AddFileL(count + 1);

	iMutex.Signal();
}

// State Machine destructor
CBackupTestsStateMachine::~CBackupTestsStateMachine()
	{
	// Close our session into the backup server
	delete iBackupSession;

	// Delete all the observers (only 3 of each of by this point)
	TInt i;

	for (i = 0; i<3 ; i++)
		{
		iBackupObservers[i]->Kill(iBackupObserverThreads[i]);
		iBackupFileObservers[i]->Kill(iFileObserverThreads[i]);
		User::After(50000000);
		}
	iBackupObservers.Close();
	iBackupFileObservers.Close();

	// Kill the observer threads
	for (i = 0; i<3 ; i++)

	{
	iBackupObserverThreads[i]->Kill(KErrNone);
	delete iBackupObserverThreads[i];
	iFileObserverThreads[i]->Kill(KErrNone);
	delete iFileObserverThreads[i];
	}
	iBackupObserverThreads.Close();
	iFileObserverThreads.Close();

	// Display we're finished
	iLocalRTest->Close();
	delete iLocalRTest;

	// Cancel this is it's active
	if (IsActive())
		{
		Cancel();
		}
	}

// Common starting function for all test-related calls to CloseAll
void CBackupTestsStateMachine::CloseAllStartL(StateMachineState aNextState, MBackupObserver::TFileLockFlags aFlag)
	{
	StartBackupL();
	iState = aNextState;
	iBackupSession->CloseAll(aFlag, iStatus);
	}

// Common ending function for all test-related calls to CloseAll
void CBackupTestsStateMachine::CloseAllEndL(StateMachineState aNextState, TInt aExpectedNotifications)
	{
	iState = aNextState;
	SignalEndBackupL();
	EndBackup(aExpectedNotifications, ETrue);
	iLocalRTest->End();
	Complete();
	}

// State machine call back - get here by calls to Complete and returns for asynchronous server calls
void CBackupTestsStateMachine::RunL()
	{
	switch(iState)
		{
		case EStateMachineStart:
			// Create observers threads
			CreateObserversThreadsL();
			iState = ECloseAllNormalReadOnly;
			Complete();
			break;
		case ECloseAllNormalReadOnly:
			iLocalRTest->Start(_L("\nCloseAllFiles normal ReadOnly\n"));
			CloseAllStartL(ECloseAllNormalReadOnlyReturned, MBackupObserver::EReleaseLockReadOnly);
			break;
		case ECloseAllNormalReadOnlyReturned:
			CloseAllEndL(ECloseAllNormalNoAccess, 4);
			break;
		case ECloseAllNormalNoAccess:
			iLocalRTest->Start(_L("\nCloseAllFiles normal NoAccess\n"));
			CloseAllStartL(ECloseAllNormalNoAccessReturned, MBackupObserver::EReleaseLockNoAccess);
			break;
		case ECloseAllNormalNoAccessReturned:
			CloseAllEndL(ECloseAllDelayReadOnly, 4);
			break;
		case ECloseAllDelayReadOnly:
			iLocalRTest->Start(_L("\nCloseAllFiles delay ReadOnly\n"));
			iBackupFileObservers[0]->SetDelay(ETrue);
			CloseAllStartL(ECloseAllDelayReadOnlyReturned, MBackupObserver::EReleaseLockReadOnly);
			break;
		case ECloseAllDelayReadOnlyReturned:
			iBackupFileObservers[0]->SetDelay(EFalse);
			CloseAllEndL(ECloseAllDelayNoAccess, 4);
			// Nice long wait for the timer to expire in the other thread
			User::After(10000000);
			break;
		case ECloseAllDelayNoAccess:
			iLocalRTest->Start(_L("\nCloseAllFiles delay NoAccess\n"));
			iBackupFileObservers[0]->SetDelay(ETrue);
			CloseAllStartL(ECloseAllDelayNoAccessReturned, MBackupObserver::EReleaseLockNoAccess);
			break;
		case ECloseAllDelayNoAccessReturned:
			iBackupFileObservers[0]->SetDelay(EFalse);
			CloseAllEndL(ECloseAllDropFileSession, 4);
			// Nice long wait for the timer to expire in the other thread
			User::After(10000000);
			break;
		case ECloseAllDropFileSession:
			iLocalRTest->Start(_L("\nCloseAllFiles dropping file session\n"));
			// Drop one of the file registration / observer sessions
			iBackupFileObservers[0]->Kill(iFileObserverThreads[0]);
			// Nice long wait for the observer to be killed in the other thread
			User::After(10000000);
			// Remove it from the list
			iBackupFileObservers.Remove(0);
			// Kill the thread
			iFileObserverThreads[0]->Kill(KErrNone);
			delete iFileObserverThreads[0];
			iFileObserverThreads.Remove(0);
			// All done - start this sub-test
			CloseAllStartL(ECloseAllDropFileSessionReturned, MBackupObserver::EReleaseLockReadOnly);
			break;
		case ECloseAllDropFileSessionReturned:
			CloseAllEndL(ECloseAllDropBackupObserverSession, 3);
			break;
		case ECloseAllDropBackupObserverSession:
			iLocalRTest->Start(_L("\nCloseAllFiles dropping backup session\n"));
			// Drop one of the backup observer sessions
			iBackupObservers[0]->Kill(iBackupObserverThreads[0]);
			// Nice long wait for the observer to be killed in the other thread
			User::After(10000000);
			// Remove it from the list
			iBackupObservers.Remove(0);
			// Kill the thread
			iBackupObserverThreads[0]->Kill(KErrNone);
			delete iBackupObserverThreads[0];
			iBackupObserverThreads.Remove(0);
			// All done - start this sub-test
			CloseAllStartL(ECloseAllDropBackupObserverSessionReturned, MBackupObserver::EReleaseLockReadOnly);
			break;
		case ECloseAllDropBackupObserverSessionReturned:
			CloseAllEndL(ESingleFileTests, 3);
			break;
		case ESingleFileTests:
			iLocalRTest->Start(_L("\nSingle file lock tests\n"));
			StartBackupL();
			SingleFileLockTestsL();
			SignalEndBackupL();
			// Can call EndBackup synchronously here as nothing in SingleFileLockTests is asynchronous
			EndBackup(3, EFalse);
			iLocalRTest->End();
 			iState = ENoBackupSessionSingleFileTests;
			Complete();
			break;
		// Required to cover the situation when the backup server is used purely for message signalling
		// For example in the LogEng compnent
		case ENoBackupSessionSingleFileTests:
			iLocalRTest->Start(_L("\nNo backup session single file lock tests\n"));
			SingleFileLockTestsL();
			// Can call EndBackup synchronously here as nothing in SingleFileLockTests is asynchronous
			EndBackup(3, EFalse);
			iLocalRTest->End();
			iState = EStateMachineEnd;
			Complete();
			break;
		case EStateMachineEnd:
			RDebug::Print(_L("\nEnd of state machine\n"));
			End();
			break;
		default:
			RDebug::Print(_L("\nCBackupTestsStateMachine::RunL problem"));
			break;
		}
	if (!IsActive())
		{
		SetActive();
		}
	}

void CBackupTestsStateMachine::DoCancel()
	{
	Complete();
	}

void CBackupTestsStateMachine::RunError()
	{ ; }

// Common function to start a backup
void CBackupTestsStateMachine::StartBackupL()
	{
	TBackupOperationAttributes attribs;
	attribs.iFileFlag=MBackupObserver::EReleaseLockNoAccess;
	attribs.iOperation=MBackupOperationObserver::EStart;
	iBackupSession->NotifyBackupOperationL(attribs);
	RDebug::Print(_L("\nStarting backup\n"));
	}

void CBackupTestsStateMachine::SignalEndBackupL()
	{
	// Tell the server the backup is over
	TBackupOperationAttributes attribs;
	attribs.iFileFlag=MBackupObserver::EReleaseLockNoAccess;
	attribs.iOperation=MBackupOperationObserver::EEnd;
	iBackupSession->NotifyBackupOperationL(attribs);
	}

// This function works in two ways. If oneTimeOnly is ETrue then all file lock
// change notifications must have been received before this function is called.
// If oneTimeOnly is EFalse this function recursively calls itself (a finate number
// of times) until all notifications have arrived (this happens with single file testing)
void CBackupTestsStateMachine::EndBackup(TInt aFileLockChangesExpected, TBool oneTimeOnly)
	{
	// Get the total notification count so far
	TInt numberOfObservers = iBackupFileObservers.Count();
	TInt totalNotificationCount = 0;
	for (TInt i=0; i<numberOfObservers ; i++)
		{
		totalNotificationCount += iBackupFileObservers[i]->GetFileLocksChanged();
		}
	if (aFileLockChangesExpected == totalNotificationCount)
		{
		// Reset the recursion count
		iEndBackupRecursionCount = 0;

		// Zero the notification counts in the file lock observers
		for (TInt i = 0 ; i<numberOfObservers ; i++)
			{
			iBackupFileObservers[i]->ZeroFileLocksChanged();
			}

		// Debug output
		TBuf<100> buf;
		buf.Format(_L("\nBackup finished sucsessfully on recusion count %d of EndBackup\n"), iEndBackupRecursionCount);
		RDebug::Print(buf);
		}
	else if (oneTimeOnly)
		{
		// No second chances - fail here
		(*iLocalRTest)(EFalse);
		}
	else
		{
		// Give it 5 more seconds (in 10 .5 second iterations) for the notifications to arrive
		User::After(500000);
		// 5 seconds is more than enough (timeouts in server should have gone off by now anyway)
		iEndBackupRecursionCount++;
		if (iEndBackupRecursionCount > 10)
			{
				(*iLocalRTest)(EFalse);
			}
		// Recursively calling isn't great but it needs to leave the function so the AO can run
		EndBackup(aFileLockChangesExpected, EFalse);
		}

	}

void CBackupTestsStateMachine::Complete()
	{
	// Trigger the Active Object locally
	TRequestStatus* tempStatus=(&iStatus);
	User::RequestComplete(tempStatus, KErrNone);
	}

void CBackupTestsStateMachine::Start()
	{
	// Time to start testing
	RDebug::Print(_L("\nCBackupTestsStateMachine::Start"));
	Complete();
	}

void CBackupTestsStateMachine::End()
	{
	// We're done testing - kill the Active Scheduler
	RDebug::Print(_L("\nAll test complete\n"));
	Cancel();
	CActiveScheduler::Current()->Stop();
	}

void CBackupTestsStateMachine::SingleFileLockTestsL()
	{
	TFileName file;

	// File 1
	file.Copy(KFileName1);
	iLocalRTest->Next(file);

	iBackupSession->CloseFileL(KFileName1, MBackupObserver::EReleaseLockReadOnly);
	iBackupSession->RestartFile(file);

//	iBackupSession->CloseFileL(KFileName1, MBackupObserver::EReleaseLockNoAccess);
//	iBackupSession->RestartFile(file);

	// File 2
	file.Copy(KFileName2);
	iLocalRTest->Next(file);

	iBackupSession->CloseFileL(KFileName2, MBackupObserver::EReleaseLockReadOnly);
	iBackupSession->RestartFile(file);

//	iBackupSession->CloseFileL(KFileName2, MBackupObserver::EReleaseLockNoAccess);
//	iBackupSession->RestartFile(file);

	// File 3
	file.Copy(KFileName3);
	iLocalRTest->Next(file);

	iBackupSession->CloseFileL(KFileName3, MBackupObserver::EReleaseLockReadOnly);
	iBackupSession->RestartFile(file);

//	iBackupSession->CloseFileL(KFileName3, MBackupObserver::EReleaseLockNoAccess);
//	iBackupSession->RestartFile(file);

	// File 3
	file.Copy(KFileName4);
	iLocalRTest->Next(file);

	iBackupSession->CloseFileL(KFileName4, MBackupObserver::EReleaseLockReadOnly);
	iBackupSession->RestartFile(file);

//	iBackupSession->CloseFileL(KFileName4, MBackupObserver::EReleaseLockNoAccess);
//	iBackupSession->RestartFile(file);
	}

/**
@SYMTestCaseID          SYSLIB-BAFL-CT-0467
@SYMTestCaseDesc        Tests the functionality of CBaBackupSessionWrapper class
@SYMTestPriority        High
@SYMTestActions         Tests for the enabling backup of files
@SYMTestExpectedResults Test must not fail
@SYMREQ                 REQ0000
*/
LOCAL_D void StartTestsL()
	{
	// For the sake of logging let's start off by renaming the main "command" thread
	RThread().RenameMe(_L("Main thread"));

	// Create state machine
	CBackupTestsStateMachine* stateMachine = CBackupTestsStateMachine::NewL();

	// Kick it off
	stateMachine->Start();

	// Start the Active Scheduler
	CActiveScheduler::Start();

	// Clean up the state machine
	delete stateMachine;
	}

TInt E32Main()
	{
	MainTest.Title();
	MainTest.Start(_L(" @SYMTestCaseID:SYSLIB-BAFL-CT-0467 Loading Device"));

	__UHEAP_MARK;

	CTrapCleanup* theTrapCleanup=CTrapCleanup::New();
	CActiveScheduler *activeScheduler=new CActiveScheduler;
	CActiveScheduler::Install(activeScheduler);

	TRAPD(error, StartTestsL());
	User::LeaveIfError(error);

	delete activeScheduler;
	delete theTrapCleanup;

	__UHEAP_MARKEND;

	MainTest.End();


	return(KErrNone);
	}