diff -r 000000000000 -r e4d67989cc36 lowlevellibsandfws/apputils/tsrc/T_BackupSrv.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lowlevellibsandfws/apputils/tsrc/T_BackupSrv.cpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,767 @@ +// 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 +#include +#include +#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(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(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; iGetFileLocksChanged(); + } + if (aFileLockChangesExpected == totalNotificationCount) + { + // Reset the recursion count + iEndBackupRecursionCount = 0; + + // Zero the notification counts in the file lock observers + for (TInt i = 0 ; iZeroFileLocksChanged(); + } + + // 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); + }