sl@0: // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include <e32debug.h>
sl@0: #include <e32test.h>
sl@0: #include <babackup.h>
sl@0: #include "T_backupSrv.h"
sl@0: LOCAL_D RTest MainTest(_L(" T_BackupSrv.cpp"));
sl@0: 
sl@0: _LIT(KFileName1, "FileName1");
sl@0: _LIT(KFileName2, "FileName2");
sl@0: _LIT(KFileName3, "FileName3");
sl@0: _LIT(KFileName4, "FileName4");
sl@0: 
sl@0: // Nasty global convenience function
sl@0: LOCAL_D void LogThread()
sl@0: {
sl@0: 	TBuf<150> buf((RThread().Name()));
sl@0: 	RDebug::Print(_L("*** Currently in thread : "));
sl@0: 	RDebug::Print(buf);
sl@0: }
sl@0: 
sl@0: //
sl@0: //	class CBackupOperationObserver
sl@0: //
sl@0: CBackupOperationObserver* CBackupOperationObserver::NewL(TInt aObserverNumber)
sl@0: 	{
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupOperationObserver::NewL"));
sl@0: 
sl@0: 	CBackupOperationObserver* self = new (ELeave) CBackupOperationObserver();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL(aObserverNumber);
sl@0: 	CleanupStack::Pop();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: CBackupOperationObserver::CBackupOperationObserver()
sl@0:  : CActive(0)
sl@0: 	{ ; }
sl@0: 
sl@0: CBackupOperationObserver::~CBackupOperationObserver()
sl@0: 	{
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupOperationObserver::~CBackupOperationObserver"));
sl@0: 
sl@0: 	iBackupSession->DeRegisterBackupOperationObserver(*this);
sl@0: 	delete iBackupSession;
sl@0: 
sl@0: 	delete iLocalRTest;
sl@0: 	}
sl@0: 
sl@0: void CBackupOperationObserver::ConstructL(TInt aObserverNumber)
sl@0: 	{
sl@0: 	// Set up the AO callback
sl@0: 	CActiveScheduler::Add(this);
sl@0: 	SetActive();
sl@0: 	iStatus = KRequestPending;
sl@0: 
sl@0: 	// Create a new session for this backup notification observer
sl@0: 	iBackupSession = CBaBackupSessionWrapper::NewL();
sl@0: 	iBackupSession->RegisterBackupOperationObserverL(*this);
sl@0: 	iObserverNumber = aObserverNumber;
sl@0: 	iLocalRTest = new (ELeave) RTest(_L("BackupOperationObserver"));
sl@0: 	}
sl@0: 
sl@0: void CBackupOperationObserver::HandleBackupOperationEventL(const TBackupOperationAttributes& aBackupOperationAttributes)
sl@0: 	{
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupOperationObserver::HandleBackupOperationEventL"));
sl@0: 
sl@0: 	TBuf<150> buf;
sl@0: 	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);
sl@0: 	RDebug::Print(buf);
sl@0: 	}
sl@0: 
sl@0: void CBackupOperationObserver::DoCancel()
sl@0: 	{ ; }
sl@0: 
sl@0: void CBackupOperationObserver::RunL()
sl@0: 	{
sl@0: 	// Okay - we're back in the right thread!
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupOperationObserver::RunL"));
sl@0: 
sl@0: 	// Finished with this object
sl@0: 	delete this;
sl@0: 
sl@0: 	// And the active scheduler in this thread
sl@0: 	CActiveScheduler::Current()->Stop();
sl@0: 
sl@0: 	}
sl@0: 
sl@0: void CBackupOperationObserver::Kill(RThread* aThread)
sl@0: 	{
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupFileObserver::Kill"));
sl@0: 
sl@0: 	// Trigger the Active Object locally - in a different thread!
sl@0: 	TRequestStatus* tempStatus=(&iStatus);
sl@0: 	aThread->RequestComplete(tempStatus, KErrNone);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: //	class CBackupFileObserver
sl@0: //
sl@0: 
sl@0: CBackupFileObserver::CBackupFileObserver()
sl@0:  : CActive(0)
sl@0:   { ;  }
sl@0: 
sl@0: void CBackupFileObserver::ConstructL(TInt aFileObserverNumber)
sl@0: 	{
sl@0: 	// Set up the AO callback
sl@0: 	CActiveScheduler::Add(this);
sl@0: 	SetActive();
sl@0: 	iStatus = KRequestPending;
sl@0: 
sl@0: 	// Create a new session for this file lock observer
sl@0: 	iBackupSession = CBaBackupSessionWrapper::NewL();
sl@0: 	iFileObserverNumber = aFileObserverNumber;
sl@0: 	iFileLocksChanged = 0;
sl@0: 	iFileLockState = ELocked;
sl@0: 	iLocalRTest = new (ELeave) RTest(_L("BackupFileObserver"));
sl@0: 	}
sl@0: 
sl@0: CBackupFileObserver* CBackupFileObserver::NewL(TInt aFileObserverNumber)
sl@0: 	{
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupFileObserver::NewL"));
sl@0: 
sl@0: 	CBackupFileObserver* self=new(ELeave) CBackupFileObserver();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL(aFileObserverNumber);
sl@0: 	CleanupStack::Pop();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: CBackupFileObserver::~CBackupFileObserver()
sl@0: 	{
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupFileObserver::~CBackupFileObserver"));
sl@0: 
sl@0: 	delete iBackupSession;
sl@0: 
sl@0: 	delete iLocalRTest;
sl@0: 	}
sl@0: 
sl@0: void CBackupFileObserver::AddFileL(TInt aFileNumber)
sl@0: 	{
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupFileObserver::AddFileL"));
sl@0: 
sl@0: 	// We base the filename of the number of thread in the RArray
sl@0: 	iFileName.Format(_L("FileName%d"), aFileNumber);
sl@0: 
sl@0: 	iBackupSession->RegisterFileL(iFileName,*this);
sl@0: 	}
sl@0: 
sl@0: TInt CBackupFileObserver::GetFileLocksChanged()
sl@0: 	{
sl@0: 	return iFileLocksChanged;
sl@0: 	}
sl@0: 
sl@0: void CBackupFileObserver::ZeroFileLocksChanged()
sl@0: 	{
sl@0: 	iFileLocksChanged = 0;
sl@0: 	}
sl@0: 
sl@0: void CBackupFileObserver::SetDelay(TBool aDelay)
sl@0: {
sl@0: 	iDelay = aDelay;
sl@0: }
sl@0: 
sl@0: void CBackupFileObserver::ChangeFileLockL(const TDesC& aFileName,TFileLockFlags aFlags)
sl@0: 	{
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("BackupFileObserver::ChangeFileLockL"));
sl@0: 
sl@0: 	// Keep a count of how many release notifications there have been
sl@0: 	if (aFlags != MBackupObserver::ETakeLock)
sl@0: 		{
sl@0: 		iFileLocksChanged++;
sl@0: 		}
sl@0: 
sl@0: 	// If delay is set then insert wait now
sl@0: 	if (iDelay && (!(aFileName.Compare(KFileName1))))
sl@0: 		{
sl@0: 		User::After(10000000);
sl@0: 		}
sl@0: 
sl@0: 	// Check this file is the one for this observer - if not fail test;
sl@0: 	if (iFileName.Compare(aFileName))
sl@0: 		{
sl@0: 		RDebug::Print(_L("\nReceived notification for non-registered file!"));
sl@0: 		(*iLocalRTest)(EFalse);
sl@0: 		}
sl@0: 
sl@0: 	// Update the local file lock array
sl@0: 	CBackupFileObserver::TFileLock flag = (CBackupFileObserver::TFileLock) aFlags;
sl@0: 	iFileLockState = flag;
sl@0: 
sl@0: 	// Test output
sl@0: 	TBuf<150> buf;
sl@0: 	buf.Format(_L("File backup observer number %d was notified for file %S of file lock type: %d\n"),iFileObserverNumber, &aFileName, flag);
sl@0: 	RDebug::Print(buf);
sl@0: 	}
sl@0: 
sl@0: void CBackupFileObserver::DoCancel()
sl@0: 	{ ; }
sl@0: 
sl@0: void CBackupFileObserver::RunL()
sl@0: 	{
sl@0: 	// Okay - we're back in the right thread!
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupFileObserver::RunL"));
sl@0: 
sl@0: 	// Finished with this object
sl@0: 	delete this;
sl@0: 
sl@0: 	// And the active scheduler in this thread
sl@0: 	CActiveScheduler::Current()->Stop();
sl@0: 
sl@0: 	}
sl@0: 
sl@0: void CBackupFileObserver::Kill(RThread* aThread)
sl@0: 	{
sl@0: 	LogThread();
sl@0: 	RDebug::Print(_L("CBackupFileObserver::Kill"));
sl@0: 
sl@0: 	// Trigger the Active Object locally - in a different thread!
sl@0: 	TRequestStatus* tempStatus=(&iStatus);
sl@0: 	aThread->RequestComplete(tempStatus, KErrNone);
sl@0: 	}
sl@0: 
sl@0: //
sl@0: // class CBackupTestsStateMachine
sl@0: //
sl@0: 
sl@0: CBackupTestsStateMachine* CBackupTestsStateMachine::NewL()
sl@0: 	{
sl@0: 	CBackupTestsStateMachine* self = new (ELeave) CBackupTestsStateMachine();
sl@0: 	CleanupStack::PushL(self);
sl@0: 	self->ConstructL();
sl@0: 	CleanupStack::Pop();
sl@0: 	return self;
sl@0: 	}
sl@0: 
sl@0: CBackupTestsStateMachine::CBackupTestsStateMachine()
sl@0:  : CActive(0)
sl@0: { ; }
sl@0: 
sl@0: void CBackupTestsStateMachine::ConstructL()
sl@0: 	{
sl@0: 	// Set up the RTest for this thread and display we're started
sl@0: 	iLocalRTest = new (ELeave) RTest(_L("T_BACKUP_SRV"));
sl@0: 	iLocalRTest->Title();
sl@0: 
sl@0: 	// Set the ititial state
sl@0: 	iState = EStateMachineStart;
sl@0: 
sl@0: 	// Zero the EndBackupRecursionCount (see below)
sl@0: 	iEndBackupRecursionCount = 0;
sl@0: 
sl@0: 	// Add this to the Active Scheduler and set us active
sl@0: 	CActiveScheduler::Add(this);
sl@0: 	SetActive();
sl@0: 
sl@0: 	// Create the backup "command" session
sl@0: 	iBackupSession = CBaBackupSessionWrapper::NewL();
sl@0: 
sl@0: 	// Set up the mutex
sl@0: 	iMutex.CreateLocal();
sl@0: 	}
sl@0: 
sl@0: // Observers need to have their own thread
sl@0: void CBackupTestsStateMachine::CreateObserversThreadsL()
sl@0: 	{
sl@0: 	RDebug::Print(_L("Starting observers threads"));
sl@0: 
sl@0: 	TInt i;
sl@0: 	TBuf<30> newThreadNames;
sl@0: 	TInt error;
sl@0: 	for (i = 0; i<4 ; i++)
sl@0: 		{
sl@0: 		// Backup observer
sl@0: 		iBackupObserverThreads.AppendL(new (ELeave) RThread);
sl@0: 		newThreadNames.Format(_L("Backup Observer Thread %d"), i+1);
sl@0: 		error = iBackupObserverThreads[i]->Create(newThreadNames, CBackupTestsStateMachine::BackupObserversThreadStartL, 0x2000, NULL, (TAny*)this);
sl@0: 		(*iLocalRTest)(error==KErrNone);
sl@0: 		iBackupObserverThreads[i]->Resume();
sl@0: 
sl@0: 		// File observer
sl@0: 		iFileObserverThreads.AppendL(new (ELeave) RThread);
sl@0: 		newThreadNames.Format(_L("File Observer Thread %d"), i+1);
sl@0: 		error = iFileObserverThreads[i]->Create(newThreadNames, CBackupTestsStateMachine::FileObserversThreadStartL, 0x2000, NULL, (TAny*)this);
sl@0: 
sl@0: 		(*iLocalRTest)(error==KErrNone);
sl@0: 		iFileObserverThreads[i]->Resume();
sl@0: 
sl@0: 		// Brief delay to let the observer threads get started
sl@0: 		User::After(1000000);
sl@0: 		}
sl@0: 
sl@0: 	}
sl@0: 
sl@0: // Static starting function for the backup observers threads
sl@0: TInt CBackupTestsStateMachine::BackupObserversThreadStartL(TAny* aPtr)
sl@0: 	{
sl@0: 	// Create the Cleanup Stack and Active Scheduler for this thread
sl@0: 
sl@0: 	CTrapCleanup* theTrapCleanup = CTrapCleanup::New();
sl@0: 	CActiveScheduler *activeScheduler = new CActiveScheduler;
sl@0: 	CActiveScheduler::Install(activeScheduler);
sl@0: 
sl@0: 	// Create the observer instances
sl@0: 	CBackupTestsStateMachine* objectPtr = static_cast<CBackupTestsStateMachine*>(aPtr);
sl@0: 	TRAPD(error, objectPtr->CreateBackupObserverInstanceL());
sl@0: 	User::LeaveIfError(error);
sl@0: 
sl@0: 	// Go to Active Scheduler main loop for this thread
sl@0: 	CActiveScheduler::Start();
sl@0: 
sl@0: 	// And we're done
sl@0: 	delete activeScheduler;
sl@0: 	delete theTrapCleanup;
sl@0: 
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: // Static starting function for the file observers threads
sl@0: TInt CBackupTestsStateMachine::FileObserversThreadStartL(TAny* aPtr)
sl@0: {
sl@0: 	// Create the Cleanup Stack and Active Scheduler for this thread
sl@0: 	CTrapCleanup* theTrapCleanup = CTrapCleanup::New();
sl@0: 	CActiveScheduler* activeScheduler = new CActiveScheduler;
sl@0: 	CActiveScheduler::Install(activeScheduler);
sl@0: 
sl@0: 	// Create the observer instances
sl@0: 	CBackupTestsStateMachine* objectPtr = static_cast<CBackupTestsStateMachine*>(aPtr);
sl@0: 	TRAPD(error, objectPtr->CreateFileObserverInstanceL());
sl@0: 	User::LeaveIfError(error);
sl@0: 
sl@0: 	// Go to Active Scheduler main loop for this thread
sl@0: 	CActiveScheduler::Start();
sl@0: 
sl@0: 	// And we're done
sl@0: 	delete activeScheduler;
sl@0: 	delete theTrapCleanup;
sl@0: 
sl@0: 	return KErrNone;
sl@0: }
sl@0: 
sl@0: void CBackupTestsStateMachine::CreateBackupObserverInstanceL()
sl@0: 	{
sl@0: 	iMutex.Wait();
sl@0: 
sl@0: 	TInt count = iBackupObserverThreads.Count();
sl@0: 
sl@0: 	// Create the new object instance (one object per thread)
sl@0: 	// We base the thread number of the number of thread in the RArray
sl@0: 	CBackupOperationObserver* newObserver = CBackupOperationObserver::NewL(count);
sl@0: 	iBackupObservers.AppendL(newObserver);
sl@0: 
sl@0: 	iMutex.Signal();
sl@0: 	}
sl@0: 
sl@0: void CBackupTestsStateMachine::CreateFileObserverInstanceL()
sl@0: {
sl@0: 	iMutex.Wait();
sl@0: 
sl@0: 	TInt count = iBackupFileObservers.Count();
sl@0: 
sl@0: 	// Create the new object instance (one object per thread)
sl@0: 	CBackupFileObserver* newObserver = CBackupFileObserver::NewL(count + 1);
sl@0: 	iBackupFileObservers.AppendL(newObserver);
sl@0: 
sl@0: 	// Register the file for this thread / instance
sl@0: 	iBackupFileObservers[count]->AddFileL(count + 1);
sl@0: 
sl@0: 	iMutex.Signal();
sl@0: }
sl@0: 
sl@0: // State Machine destructor
sl@0: CBackupTestsStateMachine::~CBackupTestsStateMachine()
sl@0: 	{
sl@0: 	// Close our session into the backup server
sl@0: 	delete iBackupSession;
sl@0: 
sl@0: 	// Delete all the observers (only 3 of each of by this point)
sl@0: 	TInt i;
sl@0: 
sl@0: 	for (i = 0; i<3 ; i++)
sl@0: 		{
sl@0: 		iBackupObservers[i]->Kill(iBackupObserverThreads[i]);
sl@0: 		iBackupFileObservers[i]->Kill(iFileObserverThreads[i]);
sl@0: 		User::After(50000000);
sl@0: 		}
sl@0: 	iBackupObservers.Close();
sl@0: 	iBackupFileObservers.Close();
sl@0: 
sl@0: 	// Kill the observer threads
sl@0: 	for (i = 0; i<3 ; i++)
sl@0: 
sl@0: 	{
sl@0: 	iBackupObserverThreads[i]->Kill(KErrNone);
sl@0: 	delete iBackupObserverThreads[i];
sl@0: 	iFileObserverThreads[i]->Kill(KErrNone);
sl@0: 	delete iFileObserverThreads[i];
sl@0: 	}
sl@0: 	iBackupObserverThreads.Close();
sl@0: 	iFileObserverThreads.Close();
sl@0: 
sl@0: 	// Display we're finished
sl@0: 	iLocalRTest->Close();
sl@0: 	delete iLocalRTest;
sl@0: 
sl@0: 	// Cancel this is it's active
sl@0: 	if (IsActive())
sl@0: 		{
sl@0: 		Cancel();
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: // Common starting function for all test-related calls to CloseAll
sl@0: void CBackupTestsStateMachine::CloseAllStartL(StateMachineState aNextState, MBackupObserver::TFileLockFlags aFlag)
sl@0: 	{
sl@0: 	StartBackupL();
sl@0: 	iState = aNextState;
sl@0: 	iBackupSession->CloseAll(aFlag, iStatus);
sl@0: 	}
sl@0: 
sl@0: // Common ending function for all test-related calls to CloseAll
sl@0: void CBackupTestsStateMachine::CloseAllEndL(StateMachineState aNextState, TInt aExpectedNotifications)
sl@0: 	{
sl@0: 	iState = aNextState;
sl@0: 	SignalEndBackupL();
sl@0: 	EndBackup(aExpectedNotifications, ETrue);
sl@0: 	iLocalRTest->End();
sl@0: 	Complete();
sl@0: 	}
sl@0: 
sl@0: // State machine call back - get here by calls to Complete and returns for asynchronous server calls
sl@0: void CBackupTestsStateMachine::RunL()
sl@0: 	{
sl@0: 	switch(iState)
sl@0: 		{
sl@0: 		case EStateMachineStart:
sl@0: 			// Create observers threads
sl@0: 			CreateObserversThreadsL();
sl@0: 			iState = ECloseAllNormalReadOnly;
sl@0: 			Complete();
sl@0: 			break;
sl@0: 		case ECloseAllNormalReadOnly:
sl@0: 			iLocalRTest->Start(_L("\nCloseAllFiles normal ReadOnly\n"));
sl@0: 			CloseAllStartL(ECloseAllNormalReadOnlyReturned, MBackupObserver::EReleaseLockReadOnly);
sl@0: 			break;
sl@0: 		case ECloseAllNormalReadOnlyReturned:
sl@0: 			CloseAllEndL(ECloseAllNormalNoAccess, 4);
sl@0: 			break;
sl@0: 		case ECloseAllNormalNoAccess:
sl@0: 			iLocalRTest->Start(_L("\nCloseAllFiles normal NoAccess\n"));
sl@0: 			CloseAllStartL(ECloseAllNormalNoAccessReturned, MBackupObserver::EReleaseLockNoAccess);
sl@0: 			break;
sl@0: 		case ECloseAllNormalNoAccessReturned:
sl@0: 			CloseAllEndL(ECloseAllDelayReadOnly, 4);
sl@0: 			break;
sl@0: 		case ECloseAllDelayReadOnly:
sl@0: 			iLocalRTest->Start(_L("\nCloseAllFiles delay ReadOnly\n"));
sl@0: 			iBackupFileObservers[0]->SetDelay(ETrue);
sl@0: 			CloseAllStartL(ECloseAllDelayReadOnlyReturned, MBackupObserver::EReleaseLockReadOnly);
sl@0: 			break;
sl@0: 		case ECloseAllDelayReadOnlyReturned:
sl@0: 			iBackupFileObservers[0]->SetDelay(EFalse);
sl@0: 			CloseAllEndL(ECloseAllDelayNoAccess, 4);
sl@0: 			// Nice long wait for the timer to expire in the other thread
sl@0: 			User::After(10000000);
sl@0: 			break;
sl@0: 		case ECloseAllDelayNoAccess:
sl@0: 			iLocalRTest->Start(_L("\nCloseAllFiles delay NoAccess\n"));
sl@0: 			iBackupFileObservers[0]->SetDelay(ETrue);
sl@0: 			CloseAllStartL(ECloseAllDelayNoAccessReturned, MBackupObserver::EReleaseLockNoAccess);
sl@0: 			break;
sl@0: 		case ECloseAllDelayNoAccessReturned:
sl@0: 			iBackupFileObservers[0]->SetDelay(EFalse);
sl@0: 			CloseAllEndL(ECloseAllDropFileSession, 4);
sl@0: 			// Nice long wait for the timer to expire in the other thread
sl@0: 			User::After(10000000);
sl@0: 			break;
sl@0: 		case ECloseAllDropFileSession:
sl@0: 			iLocalRTest->Start(_L("\nCloseAllFiles dropping file session\n"));
sl@0: 			// Drop one of the file registration / observer sessions
sl@0: 			iBackupFileObservers[0]->Kill(iFileObserverThreads[0]);
sl@0: 			// Nice long wait for the observer to be killed in the other thread
sl@0: 			User::After(10000000);
sl@0: 			// Remove it from the list
sl@0: 			iBackupFileObservers.Remove(0);
sl@0: 			// Kill the thread
sl@0: 			iFileObserverThreads[0]->Kill(KErrNone);
sl@0: 			delete iFileObserverThreads[0];
sl@0: 			iFileObserverThreads.Remove(0);
sl@0: 			// All done - start this sub-test
sl@0: 			CloseAllStartL(ECloseAllDropFileSessionReturned, MBackupObserver::EReleaseLockReadOnly);
sl@0: 			break;
sl@0: 		case ECloseAllDropFileSessionReturned:
sl@0: 			CloseAllEndL(ECloseAllDropBackupObserverSession, 3);
sl@0: 			break;
sl@0: 		case ECloseAllDropBackupObserverSession:
sl@0: 			iLocalRTest->Start(_L("\nCloseAllFiles dropping backup session\n"));
sl@0: 			// Drop one of the backup observer sessions
sl@0: 			iBackupObservers[0]->Kill(iBackupObserverThreads[0]);
sl@0: 			// Nice long wait for the observer to be killed in the other thread
sl@0: 			User::After(10000000);
sl@0: 			// Remove it from the list
sl@0: 			iBackupObservers.Remove(0);
sl@0: 			// Kill the thread
sl@0: 			iBackupObserverThreads[0]->Kill(KErrNone);
sl@0: 			delete iBackupObserverThreads[0];
sl@0: 			iBackupObserverThreads.Remove(0);
sl@0: 			// All done - start this sub-test
sl@0: 			CloseAllStartL(ECloseAllDropBackupObserverSessionReturned, MBackupObserver::EReleaseLockReadOnly);
sl@0: 			break;
sl@0: 		case ECloseAllDropBackupObserverSessionReturned:
sl@0: 			CloseAllEndL(ESingleFileTests, 3);
sl@0: 			break;
sl@0: 		case ESingleFileTests:
sl@0: 			iLocalRTest->Start(_L("\nSingle file lock tests\n"));
sl@0: 			StartBackupL();
sl@0: 			SingleFileLockTestsL();
sl@0: 			SignalEndBackupL();
sl@0: 			// Can call EndBackup synchronously here as nothing in SingleFileLockTests is asynchronous
sl@0: 			EndBackup(3, EFalse);
sl@0: 			iLocalRTest->End();
sl@0:  			iState = ENoBackupSessionSingleFileTests;
sl@0: 			Complete();
sl@0: 			break;
sl@0: 		// Required to cover the situation when the backup server is used purely for message signalling
sl@0: 		// For example in the LogEng compnent
sl@0: 		case ENoBackupSessionSingleFileTests:
sl@0: 			iLocalRTest->Start(_L("\nNo backup session single file lock tests\n"));
sl@0: 			SingleFileLockTestsL();
sl@0: 			// Can call EndBackup synchronously here as nothing in SingleFileLockTests is asynchronous
sl@0: 			EndBackup(3, EFalse);
sl@0: 			iLocalRTest->End();
sl@0: 			iState = EStateMachineEnd;
sl@0: 			Complete();
sl@0: 			break;
sl@0: 		case EStateMachineEnd:
sl@0: 			RDebug::Print(_L("\nEnd of state machine\n"));
sl@0: 			End();
sl@0: 			break;
sl@0: 		default:
sl@0: 			RDebug::Print(_L("\nCBackupTestsStateMachine::RunL problem"));
sl@0: 			break;
sl@0: 		}
sl@0: 	if (!IsActive())
sl@0: 		{
sl@0: 		SetActive();
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: void CBackupTestsStateMachine::DoCancel()
sl@0: 	{
sl@0: 	Complete();
sl@0: 	}
sl@0: 
sl@0: void CBackupTestsStateMachine::RunError()
sl@0: 	{ ; }
sl@0: 
sl@0: // Common function to start a backup
sl@0: void CBackupTestsStateMachine::StartBackupL()
sl@0: 	{
sl@0: 	TBackupOperationAttributes attribs;
sl@0: 	attribs.iFileFlag=MBackupObserver::EReleaseLockNoAccess;
sl@0: 	attribs.iOperation=MBackupOperationObserver::EStart;
sl@0: 	iBackupSession->NotifyBackupOperationL(attribs);
sl@0: 	RDebug::Print(_L("\nStarting backup\n"));
sl@0: 	}
sl@0: 
sl@0: void CBackupTestsStateMachine::SignalEndBackupL()
sl@0: 	{
sl@0: 	// Tell the server the backup is over
sl@0: 	TBackupOperationAttributes attribs;
sl@0: 	attribs.iFileFlag=MBackupObserver::EReleaseLockNoAccess;
sl@0: 	attribs.iOperation=MBackupOperationObserver::EEnd;
sl@0: 	iBackupSession->NotifyBackupOperationL(attribs);
sl@0: 	}
sl@0: 
sl@0: // This function works in two ways. If oneTimeOnly is ETrue then all file lock
sl@0: // change notifications must have been received before this function is called.
sl@0: // If oneTimeOnly is EFalse this function recursively calls itself (a finate number
sl@0: // of times) until all notifications have arrived (this happens with single file testing)
sl@0: void CBackupTestsStateMachine::EndBackup(TInt aFileLockChangesExpected, TBool oneTimeOnly)
sl@0: 	{
sl@0: 	// Get the total notification count so far
sl@0: 	TInt numberOfObservers = iBackupFileObservers.Count();
sl@0: 	TInt totalNotificationCount = 0;
sl@0: 	for (TInt i=0; i<numberOfObservers ; i++)
sl@0: 		{
sl@0: 		totalNotificationCount += iBackupFileObservers[i]->GetFileLocksChanged();
sl@0: 		}
sl@0: 	if (aFileLockChangesExpected == totalNotificationCount)
sl@0: 		{
sl@0: 		// Reset the recursion count
sl@0: 		iEndBackupRecursionCount = 0;
sl@0: 
sl@0: 		// Zero the notification counts in the file lock observers
sl@0: 		for (TInt i = 0 ; i<numberOfObservers ; i++)
sl@0: 			{
sl@0: 			iBackupFileObservers[i]->ZeroFileLocksChanged();
sl@0: 			}
sl@0: 
sl@0: 		// Debug output
sl@0: 		TBuf<100> buf;
sl@0: 		buf.Format(_L("\nBackup finished sucsessfully on recusion count %d of EndBackup\n"), iEndBackupRecursionCount);
sl@0: 		RDebug::Print(buf);
sl@0: 		}
sl@0: 	else if (oneTimeOnly)
sl@0: 		{
sl@0: 		// No second chances - fail here
sl@0: 		(*iLocalRTest)(EFalse);
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		// Give it 5 more seconds (in 10 .5 second iterations) for the notifications to arrive
sl@0: 		User::After(500000);
sl@0: 		// 5 seconds is more than enough (timeouts in server should have gone off by now anyway)
sl@0: 		iEndBackupRecursionCount++;
sl@0: 		if (iEndBackupRecursionCount > 10)
sl@0: 			{
sl@0: 				(*iLocalRTest)(EFalse);
sl@0: 			}
sl@0: 		// Recursively calling isn't great but it needs to leave the function so the AO can run
sl@0: 		EndBackup(aFileLockChangesExpected, EFalse);
sl@0: 		}
sl@0: 
sl@0: 	}
sl@0: 
sl@0: void CBackupTestsStateMachine::Complete()
sl@0: 	{
sl@0: 	// Trigger the Active Object locally
sl@0: 	TRequestStatus* tempStatus=(&iStatus);
sl@0: 	User::RequestComplete(tempStatus, KErrNone);
sl@0: 	}
sl@0: 
sl@0: void CBackupTestsStateMachine::Start()
sl@0: 	{
sl@0: 	// Time to start testing
sl@0: 	RDebug::Print(_L("\nCBackupTestsStateMachine::Start"));
sl@0: 	Complete();
sl@0: 	}
sl@0: 
sl@0: void CBackupTestsStateMachine::End()
sl@0: 	{
sl@0: 	// We're done testing - kill the Active Scheduler
sl@0: 	RDebug::Print(_L("\nAll test complete\n"));
sl@0: 	Cancel();
sl@0: 	CActiveScheduler::Current()->Stop();
sl@0: 	}
sl@0: 
sl@0: void CBackupTestsStateMachine::SingleFileLockTestsL()
sl@0: 	{
sl@0: 	TFileName file;
sl@0: 
sl@0: 	// File 1
sl@0: 	file.Copy(KFileName1);
sl@0: 	iLocalRTest->Next(file);
sl@0: 
sl@0: 	iBackupSession->CloseFileL(KFileName1, MBackupObserver::EReleaseLockReadOnly);
sl@0: 	iBackupSession->RestartFile(file);
sl@0: 
sl@0: //	iBackupSession->CloseFileL(KFileName1, MBackupObserver::EReleaseLockNoAccess);
sl@0: //	iBackupSession->RestartFile(file);
sl@0: 
sl@0: 	// File 2
sl@0: 	file.Copy(KFileName2);
sl@0: 	iLocalRTest->Next(file);
sl@0: 
sl@0: 	iBackupSession->CloseFileL(KFileName2, MBackupObserver::EReleaseLockReadOnly);
sl@0: 	iBackupSession->RestartFile(file);
sl@0: 
sl@0: //	iBackupSession->CloseFileL(KFileName2, MBackupObserver::EReleaseLockNoAccess);
sl@0: //	iBackupSession->RestartFile(file);
sl@0: 
sl@0: 	// File 3
sl@0: 	file.Copy(KFileName3);
sl@0: 	iLocalRTest->Next(file);
sl@0: 
sl@0: 	iBackupSession->CloseFileL(KFileName3, MBackupObserver::EReleaseLockReadOnly);
sl@0: 	iBackupSession->RestartFile(file);
sl@0: 
sl@0: //	iBackupSession->CloseFileL(KFileName3, MBackupObserver::EReleaseLockNoAccess);
sl@0: //	iBackupSession->RestartFile(file);
sl@0: 
sl@0: 	// File 3
sl@0: 	file.Copy(KFileName4);
sl@0: 	iLocalRTest->Next(file);
sl@0: 
sl@0: 	iBackupSession->CloseFileL(KFileName4, MBackupObserver::EReleaseLockReadOnly);
sl@0: 	iBackupSession->RestartFile(file);
sl@0: 
sl@0: //	iBackupSession->CloseFileL(KFileName4, MBackupObserver::EReleaseLockNoAccess);
sl@0: //	iBackupSession->RestartFile(file);
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: @SYMTestCaseID          SYSLIB-BAFL-CT-0467
sl@0: @SYMTestCaseDesc        Tests the functionality of CBaBackupSessionWrapper class
sl@0: @SYMTestPriority        High
sl@0: @SYMTestActions         Tests for the enabling backup of files
sl@0: @SYMTestExpectedResults Test must not fail
sl@0: @SYMREQ                 REQ0000
sl@0: */
sl@0: LOCAL_D void StartTestsL()
sl@0: 	{
sl@0: 	// For the sake of logging let's start off by renaming the main "command" thread
sl@0: 	RThread().RenameMe(_L("Main thread"));
sl@0: 
sl@0: 	// Create state machine
sl@0: 	CBackupTestsStateMachine* stateMachine = CBackupTestsStateMachine::NewL();
sl@0: 
sl@0: 	// Kick it off
sl@0: 	stateMachine->Start();
sl@0: 
sl@0: 	// Start the Active Scheduler
sl@0: 	CActiveScheduler::Start();
sl@0: 
sl@0: 	// Clean up the state machine
sl@0: 	delete stateMachine;
sl@0: 	}
sl@0: 
sl@0: TInt E32Main()
sl@0: 	{
sl@0: 	MainTest.Title();
sl@0: 	MainTest.Start(_L(" @SYMTestCaseID:SYSLIB-BAFL-CT-0467 Loading Device"));
sl@0: 
sl@0: 	__UHEAP_MARK;
sl@0: 
sl@0: 	CTrapCleanup* theTrapCleanup=CTrapCleanup::New();
sl@0: 	CActiveScheduler *activeScheduler=new CActiveScheduler;
sl@0: 	CActiveScheduler::Install(activeScheduler);
sl@0: 
sl@0: 	TRAPD(error, StartTestsL());
sl@0: 	User::LeaveIfError(error);
sl@0: 
sl@0: 	delete activeScheduler;
sl@0: 	delete theTrapCleanup;
sl@0: 
sl@0: 	__UHEAP_MARKEND;
sl@0: 
sl@0: 	MainTest.End();
sl@0: 
sl@0: 
sl@0: 	return(KErrNone);
sl@0: 	}