--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stif/TestServer/src/Testserversession.cpp Tue Feb 02 01:57:15 2010 +0200
@@ -0,0 +1,1406 @@
+/*
+* Copyright (c) 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: This module contains implementation of CTestServer
+* class member functions.
+*
+*/
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <e32svr.h>
+#include "TestEngineClient.h"
+#include <StifTestModule.h>
+#include <stifinternal/TestServerClient.h>
+#include "TestServer.h"
+#include "TestServerCommon.h"
+#include "TestServerModuleIf.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+// Struct to pass parameters to server thread
+struct TThreadStartTestServerSession
+ {
+ RThread iServerThread; // The server thread
+ RSemaphore iStarted; // Startup syncronisation semaphore
+ TInt iStartupResult;// Start-up result
+ };
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ==================== LOCAL FUNCTIONS =======================================
+
+// None
+
+// ================= MEMBER FUNCTIONS =========================================
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: NewL
+
+ Description: Create new Test Module
+
+ Parameters: RThread& aClient :in: Handle to client
+ CTestServer* aServer :in: Pointer to server
+
+ Return Values: CTestModule* Pointer to new test module
+
+ Errors/Exceptions: Leaves if memory allocation fails or ConstructL leaves.
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CTestModule* CTestModule::NewL( CTestServer* aServer )
+ {
+
+ CTestModule* self=new( ELeave ) CTestModule();
+ CleanupStack::PushL( self );
+ self->ConstructL( aServer );
+ CleanupStack::Pop();
+ return self;
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: CTestModule
+
+ Description: Constructor.
+ Initialise base class.
+
+ Parameters: RThread& aClient :in: Handle to client
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CTestModule::CTestModule() :
+ CSession2(),
+ iIni(0, 0)
+ {
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: ~CTestModule
+
+ Description: Destructor.
+ Deallocate memory and close handles.
+
+ Parameters: None
+
+ Return Values: None
+
+ Errors/Exceptions: None.
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestModule::~CTestModule()
+ {
+
+ __TRACE( KVerbose, ( _L( "Closing test module" ) ) );
+
+ // Free test case related data. No error checking here, because if freeing
+ // fails, then nothing can be done in destructor.
+ FreeCaseData();
+
+ // Delete all test module instances.
+ // Cleanup all RTestExecution has been opened by client but not properly
+ // closed for example if timeout occurs and client died. This almost do
+ // same than CloseSession() in "if( iTestExecutionHandle )" branch.
+ if( iTestExecutionHandle )
+ {
+ TInt handle = 0;
+ CObject* theObj = NULL;
+ TInt count = iTestExecutionHandle->Count();
+
+ for( TInt i = 0 ; i < count; i++ )
+ {
+ // Get pointer to CTestExecution
+ theObj=iTestExecutionHandle->operator[]( i );
+ if( theObj )
+ {
+ handle=iTestExecutionHandle->At( theObj );
+
+ CTestExecution* testcase = (CTestExecution*) theObj;
+ // Cancels test(s) execution(timeout, exit, etc)
+ // For example TestCombiner is timeouted => TestCombiner's
+ // TestServer+TestModule(s) should cancel also.
+ testcase->CancelTestExecution();
+ // CTestExecution will panic if test case is ongoing!!! This
+ // should be stopped, client should handless this.
+ iTestExecutionHandle->Remove( handle );
+ }
+ }
+
+ delete iTestExecutionHandle;
+ iTestExecutionHandle = NULL;
+
+ }
+
+ // Delete all FREE Test Module instances.
+ if( iTestModuleInstances )
+ {
+ iTestModuleInstances->ResetAndDestroy();
+ delete iTestModuleInstances;
+ iTestModuleInstances = NULL;
+ }
+
+ // Delete ini file heap buffer
+ delete iIniBuffer;
+ iIniBuffer = NULL;
+
+ // Delete array of test case titles
+ iTestCaseTitles.ResetAndDestroy();
+ iTestCaseTitles.Close();
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: ConstructL
+
+ Description: Second level constructor.
+
+ Parameters: CTestServer* aServer :in: Server
+
+ Return Values: None
+
+ Errors/Exceptions: Leaves if:
+ base class CreateL leaves
+ Object index creation fails
+ Object container creation fails
+ Pointer array construction fails
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModule::ConstructL( CTestServer* aServer )
+ {
+
+ __TRACE( KVerbose, ( _L( "CTestModule::ConstructL - constructing server session" ) ) );
+
+ // second-phase construct base class
+ //CSession2::CreateL( /* *aServer */ );
+ iTestServer = aServer;
+
+ // create new object index
+ iTestExecutionHandle = CObjectIx::NewL();
+
+ // Initialize the object container using the object
+ // container index in the server.
+ iContainer = iTestServer->NewContainerL();
+
+ iTestModuleInstances = new( ELeave ) RPointerArray<CTestModuleContainer>;
+
+ __TRACE( KError, ( _L( "CTestModule::ConstructL - constructing server session done" ) ) );
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: CountResources
+
+ Description: Resource counting
+
+ Parameters: None
+
+ Return Values: TInt Resource count
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::CountResources()
+ {
+
+ return iResourceCount;
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: NumResources
+
+ Description: Get resources, writes to Message()
+
+ Parameters: None
+
+ Return Values: None
+
+ Errors/Exceptions: Panic client if result can't be written to descriptor.
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModule::NumResources( const RMessage2& aMessage )
+ {
+
+ TPckgBuf<TInt> countPckg( iResourceCount );
+
+ TRAPD( r, aMessage.WriteL( 0, countPckg ) );
+ if( r !=KErrNone )
+ {
+ PanicClient( EBadDescriptor, aMessage );
+ }
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: PanicClient
+
+ Description: Panic clients.
+
+ Parameters: TInt aPanic :in: Panic code
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModule::PanicClient( const TInt aPanic, const RMessage2& aMessage ) const
+ {
+
+ __TRACE( KError,( _L( "CTestModule::PanicClient code = %d" ), aPanic ) );
+
+ _LIT( KTxtTestModule,"CTestModule" );
+
+ aMessage.Panic( KTxtTestModule, aPanic );
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: CloseSession
+
+ Description: Close session
+
+ Parameters: None
+
+ Return Values: TInt: Symbian error code.
+
+ Errors/Exceptions: None
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::CloseSession( const RMessage2& aMessage )
+ {
+
+ __TRACE( KMessage,( _L( "CTestModule::CloseSession in" ) ) );
+
+ // Delete all unclosed subsession handle before closing session.
+ // Remove iTestExecutionHandle contents. iTestExecutionHandle countains
+ // CTestExecution that handles test case have been created.
+ if( iTestExecutionHandle )
+ {
+ TInt handle = 0;
+ CObject* theObj = NULL;
+ TInt count = iTestExecutionHandle->Count();
+
+ for( TInt i = 0 ; i < count; i++ )
+ {
+ theObj=iTestExecutionHandle->operator[]( i );
+ if( theObj )
+ {
+ handle=iTestExecutionHandle->At( theObj );
+ // CTestExecution will panic if test case is ongoing!!! This
+ // should be stopped, client should handle this.
+ iTestExecutionHandle->Remove( handle );
+ }
+ }
+
+ delete iTestExecutionHandle;
+ iTestExecutionHandle = NULL;
+
+ }
+
+ // Deletion must be done here, because the "CloseSession" message is
+ // completed before execution continues from CActiveScheduler::Start
+ // location, and the main thread can continue execution
+ // and therefore shutdown itself and all threads in that process.
+
+ // Delete the object container
+ iTestServer->DeleteContainer( iContainer );
+
+ // Free test case related data
+ TInt r = FreeCaseData();
+
+ // Delete all FREE Test Module instances
+ iTestModuleInstances->ResetAndDestroy();
+ delete iTestModuleInstances;
+ iTestModuleInstances = NULL;
+
+ // Inform server that session is closed
+ iTestServer->SessionClosed();
+
+ // Check for avoiding multiple complete, see CTestModule::ServiceL()
+ if( r != KErrNone )
+ {
+ // In error cases do not complete, just return
+ __TRACE( KMessage,( _L( "CTestModule::CloseSession out (1)" ) ) );
+ return r;
+ }
+
+ aMessage.Complete( KErrNone );
+
+ // After active scheduler shutdown is done, execution continues from
+ // CTestServer::ThreadFunction()
+
+ __TRACE( KMessage,( _L( "CTestModule::CloseSession out (2)" ) ) );
+ return r;
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: ServiceL
+
+ Description: Trap harness for dispatcher
+
+ Parameters: const RMessage& aMessage :inout: Message
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModule::ServiceL( const RMessage2& aMessage )
+ {
+
+ // NOTE! HW testing slows down dramatically if adds commants here
+
+ //__TRACE( KMessage,( _L( "CTestModule::ServiceL in" ) ) );
+
+ TInt r = KErrNone;
+ TRAPD( ret, r = DispatchMessageL( aMessage ) );
+
+ if ( ret != KErrNone )
+ {
+ // Complete message on leaving cases with leave code.
+ __TRACE( KError, ( CStifLogger::ERed, _L( "CTestModule::DispatchMessageL leaved" ) ) );
+ aMessage.Complete( ret );
+ }
+
+ // Complete message with error code originating from message handling
+ // function.
+ if ( r != KErrNone )
+ {
+ __TRACE( KError, ( CStifLogger::ERed, _L( "CTestModule::DispatchMessageL returned error" ) ) );
+ aMessage.Complete( r );
+ }
+
+ // __TRACE( KMessage,( _L( "CTestModule::ServiceL out" ) ) );
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: DispatchMessageL
+
+ Description: Dispatch message, calls corresponding function to do it.
+
+ Parameters: const RMessage& aMessage :inout: Message to be handled
+
+ Return Values: TInt Error code
+
+ Errors/Exceptions: Leaves if operation handling function leaves
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::DispatchMessageL( const RMessage2& aMessage )
+ {
+
+ __TRACE( KMessage,( _L( "CTestModule::DispatchMessageL %d" ),
+ aMessage.Function() ) );
+ switch( aMessage.Function() )
+ {
+ // Session specific
+ case ETestServerCloseSession: // Close whole session
+ {
+ __TRACE( KError ,( _L( "Closing test module session" ) ) );
+ return CloseSession( aMessage );
+ }
+ case ETestServerGetServerThreadId: // Get Server ThreadId
+ {
+ __TRACE( KError ,( _L( "Return server thread id" ) ) );
+ return GetServerThreadIdL( aMessage );
+ }
+
+ case ETestModuleCreateSubSession : // Create new test module subsession
+ {
+ __TRACE( KError,( _L( "Creating test module session" ) ) );
+ return CreateModuleSessionL( aMessage );
+ }
+
+ case ETestModuleCloseSubSession: // Close module subsession
+ {
+ // Nothing to do.
+ aMessage.Complete( KErrNone );
+ return KErrNone;
+ }
+
+ case ETestExecutionCreateSubSession: // Create new test execution subsession
+ {
+ return NewTestExecutionL( aMessage );
+ }
+
+ case ETestModuleEnumerateTestCases: // Enumerate test cases
+ {
+ __TRACE( KError,( _L( "Enumerating test cases" ) ) );
+ return EnumerateTestCasesL( aMessage );
+ }
+
+ case ETestModuleGetTestCases: // Get test cases
+ {
+ return GetTestCasesL( aMessage );
+ }
+
+ case ETestModuleErrorNotification: // Request error notification
+ {
+ return HandleErrorNotificationL( aMessage );
+ }
+
+ case ETestModuleCancelAsyncRequest:
+ {
+ return CancelAsyncRequestL( aMessage );
+ }
+
+ // Subsession specific
+ case ETestExecutionRunTestCase: // Run test case
+ {
+ __TRACE( KInit,( _L( "Running test case" ) ) );
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->RunTestCase( aMessage );
+ }
+
+ case ETestExecutionNotifyProgress: // Test case prints
+ {
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->NotifyPrint( aMessage );
+ }
+
+ case ETestExecutionNotifyEvent: // Event notifications
+ {
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->NotifyEvent( aMessage );
+ }
+
+ case ETestExecutionNotifyRemoteCmd: // RemoteCmd notifications
+ {
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->NotifyRemoteCmd( aMessage );
+ }
+ case ETestExecutionReadRemoteCmdInfo: // RemoteCmd reading
+ {
+ //CTestExecution* testCase=CaseFromHandle( aMessage.Int3() );
+ //return testCase->NotifyRemoteCmd( aMessage );
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->ReadRemoteCmdInfo( aMessage );
+ }
+
+
+ case ETestExecutionResume: // Resume case execution
+ {
+ __TRACE( KVerbose,( _L( "Resuming test execution" ) ) );
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->Resume( aMessage );
+ }
+
+ case ETestExecutionPause: // Pause case execution
+ {
+ __TRACE( KVerbose,( _L( "Pausing test execution" ) ) );
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->Pause( aMessage );
+ }
+
+ case ETestExecutionCloseSubSession: // Close execution subsession
+ {
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->CloseTestExecution( aMessage );
+ }
+
+ case ETestExecutionCancelAsyncRequest: // Cancel async request
+ {
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->CancelRequestL( aMessage );
+ }
+ case ETestExecutionNotifyCommand: // Command notifications
+ {
+ CTestExecution* testCase=CaseFromHandle( aMessage.Int3(), aMessage );
+ return testCase->NotifyCommand( aMessage );
+ }
+
+ default: // Invalid request
+ {
+ PanicClient( EBadRequest, aMessage );
+ return KErrNotSupported;
+ }
+ }
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: EnumerateTestCases
+
+ Description: Enumerates test cases and returns test case count by writing
+ result to client side package.
+
+ Function obtains a TestModule and calls EnumerateTestCases from it.
+ Test module will be released when calling GetTestCases function.
+
+ Parameters: const RMessage& aMessage :inout: Message to be handled
+
+ Return Values: TInt Operation result
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::EnumerateTestCasesL( const RMessage2& aMessage )
+ {
+
+ __TRACE( KMessage,( _L( "CTestModule::EnumerateTestCasesL in" ) ) );
+
+ // Get data from message
+ TFileName config;
+ TRAPD( res, aMessage.ReadL( 0, config ) );
+ if( res != KErrNone )
+ {
+ PanicClient( EBadDescriptor, aMessage );
+ return res;
+ }
+
+ // Free old case data
+ User::LeaveIfError( FreeCaseData() );
+
+ // Get test cases from the test module
+ User::LeaveIfError( GetTestModule( iEnumerateModule, config ) );
+
+ // Enumerate test cases
+ iEnumerateModule->EnumerateTestCases( config );
+
+ // Something fatal?
+ TInt r = iEnumerateModule->OperationErrorResult();
+ if( r != KErrNone )
+ {
+ // Enumeration module have crashed.
+ delete iEnumerateModule;
+ iEnumerateModule = NULL;
+
+ return r;
+ }
+
+ // Error from module?
+ if( iEnumerateModule->ModuleResult() != KErrNone )
+ {
+ return iEnumerateModule->ModuleResult();
+ }
+
+ // Write count to Ptr1()
+ const RPointerArray<TTestCaseInfo>* testCases = iEnumerateModule->TestCases();
+
+ if( testCases == NULL )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ // Store titles (for further use, i.e. when asked for title from the interface via CTestModuleIf->CTestThreadContainer->CTestModuleContainer)
+ iTestCaseTitles.ResetAndDestroy();
+ TInt i;
+ for(i = 0; i < testCases->Count(); i++)
+ {
+ //Handle situation when test cases are enumerated not as 0-based (testscripter, ...)
+ if(i == 0 && (*testCases)[i]->iCaseNumber > 0)
+ {
+ iTestCaseTitles.Append(NULL);
+ }
+ HBufC* title = (*testCases)[i]->iTitle.AllocL();
+ iTestCaseTitles.Append(title);
+ }
+
+ TPckgBuf<TInt> countPckg( testCases->Count() );
+ TRAP( res, aMessage.WriteL( 1, countPckg ) );
+ if( res != KErrNone )
+ {
+ PanicClient( EBadDescriptor, aMessage );
+ return res;
+ }
+
+ // All ok, complete message
+ aMessage.Complete( KErrNone );
+
+ __TRACE( KMessage,( _L( "CTestModule::EnumerateTestCasesL out" ) ) );
+
+ return KErrNone;
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: GetTestCasesL
+
+ Description: Get test cases. Enumerate test cases must be called before
+ calling this function.
+
+ Function releases the test module reserved by EnumerateTestCase().
+
+ Parameters: const RMessage& aMessage :inout: Message to be handled
+
+ Return Values: TInt Operation result
+
+ Errors/Exceptions: Leaves if cases have not been enumerated.
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::GetTestCasesL( const RMessage2& aMessage )
+ {
+
+ __TRACE( KMessage,( _L( "CTestModule::GetTestCasesL in" ) ) );
+
+ // Leave if cases have not been enumerated.
+ //User::LeaveIfNull(( TAny* ) iEnumerateModule->TestCases() );
+ if( ( TAny* ) iEnumerateModule->TestCases() == NULL )
+ {
+ User::Leave( KErrGeneral );
+ }
+
+ const TInt len = sizeof( TTestCaseInfo );
+
+ // Get cases
+ const RPointerArray<TTestCaseInfo>& cases = *iEnumerateModule->TestCases();
+
+ // Get number of cases
+ const TInt Kcount = cases.Count();
+
+ // Loop through case and copy then to client's descriptor.
+ for( TInt i = 0; i < Kcount; i++ )
+ {
+
+ // Construct package for source data
+ TTestCaseInfoPckg tmpPackage( *cases[i] );
+
+ // Write to correct location
+ aMessage.WriteL( 0, tmpPackage, i *len );
+
+ }
+
+ // Free case data and the test module
+ User::LeaveIfError( FreeCaseData() );
+
+ // Finished
+ aMessage.Complete( KErrNone );
+
+ __TRACE( KMessage,( _L( "CTestModule::GetTestCasesL out" ) ) );
+
+ return KErrNone;
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: HandleErrorNotification
+
+ Description: Request error notification.
+
+ Parameters: const RMessage& aMessage :inout: Message to be handled
+
+ Return Values: TInt Operation result
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::HandleErrorNotificationL( const RMessage2& aMessage )
+ {
+
+ iErrorMessage = aMessage;
+ iErrorMessageAvailable = ETrue;
+
+ return KErrNone;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: GetServerThreadId
+
+ Description: Request server state notification.
+
+ Parameters: const RMessage& aMessage :inout: Message to be handled
+
+ Return Values: TInt Operation result
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::GetServerThreadIdL( const RMessage2& aMessage )
+ {
+
+ TInt id( iTestServer->GetServerThreadId() );
+
+ TPckg<TThreadId> threadIdPckg( id );
+
+ TRAPD( res, aMessage.WriteL( 0, threadIdPckg ) );
+
+ // Finished
+ aMessage.Complete( res );
+
+ return KErrNone;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: CancelAsyncRequest
+
+ Description: Cancels asynchronous request
+
+ Parameters: const RMessage& aMessage :inout: Message to be handled
+
+ Return Values: TInt Operation result
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::CancelAsyncRequestL( const RMessage2& aMessage )
+ {
+
+ switch ( aMessage.Int0() )
+ {
+ case ETestModuleErrorNotification:
+ {
+ if ( iErrorMessageAvailable )
+ {
+ iErrorMessage.Complete ( KErrCancel );
+ iErrorMessageAvailable = EFalse;
+ }
+ aMessage.Complete ( KErrNone );
+ break;
+ }
+
+ default:
+ {
+ PanicClient( EInvalidRequestCancel, aMessage );
+ break;
+ }
+ }
+
+ return KErrNone;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: ErrorPrint
+
+ Description: Prints error
+
+ Parameters: const TInt aPriority :in: Priority
+ TPtrC aError: in: Error
+
+ Return Values: None
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModule::ErrorPrint( const TInt aPriority,
+ TPtrC aError )
+ {
+
+ if ( iErrorMessageAvailable )
+ {
+ TErrorNotification error;
+ TErrorNotificationPckg errorPckg ( error );
+
+ error.iModule = _L("TestServer");
+ error.iPriority = aPriority;
+ error.iText = aError;
+
+ TRAPD( r, iErrorMessage.WriteL( 0, errorPckg ) );
+
+ // Do not handle errors
+ iErrorMessageAvailable = EFalse;
+ iErrorMessage.Complete( r );
+
+ }
+ else
+ {
+ RDebug::Print (_L("Error message lost %d [%S]"), aPriority, &aError );
+ }
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: FreeCaseData
+
+ Description: Frees the test case data and test module that is used in
+ enumeration.
+
+ Parameters: None
+
+ Return Values: TInt Error code
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::FreeCaseData()
+ {
+
+ __TRACE( KMessage,( _L( "CTestModule::FreeCaseData in" ) ) );
+
+ TInt r = KErrNone;
+
+ if( iEnumerateModule )
+ {
+
+ // Deallocate testcase memory
+ iEnumerateModule->FreeEnumerationData();
+
+ // Free the module
+ r = FreeTestModule( iEnumerateModule );
+
+ iEnumerateModule = NULL;
+
+ }
+
+ __TRACE( KMessage,( _L( "CTestModule::FreeCaseData out" ) ) );
+
+ return r;
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: CreateModuleSessionL
+
+ Description: Creates a new module session.
+ Just take the initialisation file name from message.
+
+ Parameters: const RMessage& aMessage :inout: Message to be handled
+
+ Return Values: TInt Operation result
+
+ Errors/Exceptions: Leaves if memory allocation fails
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::CreateModuleSessionL( const RMessage2& aMessage )
+ {
+
+ __TRACE( KMessage,( _L( "CTestModule::CreateModuleSession in" ) ) );
+
+ // Take parameters
+ TFileName ini;
+ TRAPD( res, aMessage.ReadL( 0, ini ) );
+ if( res != KErrNone )
+ {
+ PanicClient( EBadDescriptor, aMessage );
+ return res;
+ }
+
+ // Construct heap buffer for initialization file name
+ iIniBuffer = HBufC::NewL( ini.Length() );
+ iIni.Set ( iIniBuffer->Des() );
+ iIni.Copy ( ini );
+
+ aMessage.Complete( KErrNone );
+
+ __TRACE( KMessage,( _L( "CTestModule::CreateModuleSession out" ) ) );
+
+ return KErrNone;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: NewTestExecutionL
+
+ Description: Create new test execution subsession
+
+ Parameters: const RMessage& aMessage :inout: Message to be handled
+
+ Return Values: TInt Operation result
+
+ Errors/Exceptions: Function leaves if object can't be created or
+ it can't be added to container.
+ Function panics client if message contains invalid
+ descriptor.
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::NewTestExecutionL( const RMessage2& aMessage )
+ {
+
+ __TRACE( KMessage,( _L( "CTestModule::NewTestExecutionL in" ) ) );
+
+ // Get data from message
+ TInt caseNumber = aMessage.Int0();
+ TFileName config;
+
+ TRAPD( res, aMessage.ReadL( 1, config ) );
+ if( res != KErrNone )
+ {
+ PanicClient( EBadDescriptor, aMessage );
+ return res;
+ }
+
+ // Make new object
+ CTestExecution* execution=CTestExecution::NewL( this, caseNumber, config );
+
+ // add object to object container to generate unique id
+ iContainer->AddL( execution );
+
+ // add object to object index; this returns a unique handle so we can get it again
+ TInt handle=iTestExecutionHandle->AddL( execution );
+
+ // write the handle to client
+ TPckg<TInt> handlePckg( handle );
+ TRAP( res, aMessage.WriteL( 3, handlePckg ) );
+ if( res != KErrNone )
+ {
+ iTestExecutionHandle->Remove( handle );
+ PanicClient( EBadDescriptor, aMessage );
+ return res;
+ }
+
+ // notch up another resource
+ iResourceCount++;
+
+ // Complete message
+ aMessage.Complete( KErrNone );
+
+ __TRACE( KMessage,( _L( "CTestModule::NewTestExecutionL out" ) ) );
+
+ return KErrNone;
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: DeleteTestExecution
+
+ Description: Deletes Test Execution by handle
+
+ Parameters: const TUint aHandle :in: Handle
+
+ Return Values: None
+
+ Errors/Exceptions: Panics client if invalid handle
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModule::DeleteTestExecution( const TUint aHandle, const RMessage2& aMessage )
+ {
+
+ // Verify that handle is valid
+ CaseFromHandle( aHandle, aMessage );
+
+ // Remove object
+ iTestExecutionHandle->Remove( aHandle );
+
+ // Decrement resource count.
+ iResourceCount--;
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: CaseFromHandle
+
+ Description: Return subsession from handle
+
+ Parameters: const TUint aHandle :in: Handle
+
+ Return Values: CTestExecution* Test Execution object
+
+ Errors/Exceptions: Function panics client if invalid handle.
+
+ Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CTestExecution* CTestModule::CaseFromHandle( const TUint aHandle, const RMessage2& aMessage ) const
+ {
+
+ CTestExecution* testcase =( CTestExecution* ) iTestExecutionHandle->At( aHandle );
+
+ if( testcase == NULL )
+ {
+ PanicClient( EBadSubsessionHandle, aMessage );
+ }
+
+ return testcase;
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: GetTestModule
+
+ Description: Gets a CTestModuleBase*. If there is a free entry
+ in the free list, then it is returned. Otherwise a new one is created.
+
+ Parameters: CTestModuleContainer*& aContainer: out: container pointer.
+ const TDesC& aConfig: in: Test case (config) file name.
+
+ Return Values: Symbian OS error code
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::GetTestModule( CTestModuleContainer*& aContainer,
+ const TDesC& aConfig )
+ {
+ TInt ret = KErrNone;
+
+ if( iTestModuleInstances->Count() )
+ {
+ // Return an existing one
+ aContainer =( *iTestModuleInstances )[0];
+ iTestModuleInstances->Remove( 0 );
+ __TRACE( KInit,( _L( "Reusing old test module container instance at 0x%x" ), (TUint32) aContainer ) );
+ }
+ else
+ {
+ // Create a new one
+ __TRACE( KInit,( _L( "Creating new test module instance" ) ) );
+ TRAPD( err, aContainer = CTestModuleContainer::NewL(
+ iTestServer->ModuleName(),
+ this,
+ aConfig ) );
+
+ // If module can't be created, then return NULL.
+ if( err )
+ {
+ __TRACE( KError,( _L( "Can't create new test module container instance" ) ) );
+ aContainer = NULL;
+ ret = err;
+ }
+ else
+ {
+ __TRACE( KInit,( _L( "Test module instance container created" ) ) );
+ }
+
+ if( aContainer )
+ {
+
+ // Initialise module
+ aContainer->Initialize( iTestServer->ModuleName(), iTestServer->FirstTime() );
+
+ if( aContainer->OperationErrorResult() != KErrNone )
+ {
+ // Can't initialise module, delete it
+ __TRACE( KError,( CStifLogger::ERed, _L( "Operation error, can't initialize test module container instance" ) ) );
+ ret = aContainer->OperationErrorResult();
+ delete aContainer;
+ aContainer = NULL;
+ }
+ else if( aContainer->ModuleResult() != KErrNone )
+ {
+ // Can't initialise module, delete it
+ __TRACE( KError,( CStifLogger::ERed, _L( "Module error, can't initialize test module container instance" ) ) );
+ ret = aContainer->ModuleResult();
+ delete aContainer;
+ aContainer = NULL;
+ }
+ else
+ {
+ // Module initialised properly, clear the first time flag.
+ iTestServer->ClearFirstTime();
+ __TRACE( KInit,( _L( "Test module container initialized at 0x%x" ), (TUint32) aContainer ) );
+ }
+ }
+ }
+
+ return ret;
+
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: FreeTestModule
+
+ Description:Frees a CTestModuleContainer. This function can be called
+ from the context of the test execution thread.
+
+ Parameters: CTestModuleContainer* aModule :in: Module to be freed
+
+ Return Values: TInt Error code
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModule::FreeTestModule( CTestModuleContainer* aModule )
+ {
+
+ // Free the module
+ TInt r = iTestModuleInstances->Append( aModule );
+ if( r != KErrNone )
+ {
+ delete aModule;
+ aModule = NULL;
+ }
+
+ return r;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: IniName
+
+ Returns the initialisation file name
+
+ Parameters: None
+
+ Return Values: const TDesC& Initialisation file name
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+
+const TDesC& CTestModule::IniName() const
+ {
+
+ return iIni;
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: Name
+
+ Returns the module name
+
+ Parameters: None
+
+ Return Values: const TDesC& Initialisation file name
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+const TDesC& CTestModule::Name() const
+ {
+
+ return iTestServer->ModuleName();
+
+ }
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: GetTestCaseTitleL
+
+ Gets title of currently running test case
+
+ Parameters: None
+
+ Return Values: TInt aTestCaseNumber: in: index of currently running test case
+ TDes& aTestCaseTitle: out: test case title
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModule::GetTestCaseTitleL(TInt aTestCaseNumber, TDes& aTestCaseTitle)
+ {
+ RDebug::Print(_L("Trying to get test case title from module. Index=%d, count=%d"), aTestCaseNumber, iTestCaseTitles.Count());
+ aTestCaseTitle.Copy(*(iTestCaseTitles[aTestCaseNumber]));
+ }
+
+
+/*
+-------------------------------------------------------------------------------
+
+ Class: CTestModule
+
+ Method: GetTestServer
+
+ Gets pointer to TestServer
+
+ Parameters: None
+
+ Return Values: CTestServer : pointer to TestServer
+
+ Errors/Exceptions: None
+
+ Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestServer* CTestModule::GetTestServer()
+ {
+ return iTestServer;
+ }
+
+
+
+// End of File