diff -r bbd31066657e -r 8bb370ba6d1d testexecfw/stf/stffw/testengine/src/TestEngine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testexecfw/stf/stffw/testengine/src/TestEngine.cpp Fri Apr 09 10:46:28 2010 +0800 @@ -0,0 +1,5698 @@ +/* +* 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 +* CTestEngineServer class member functions. +* +*/ + +// INCLUDE FILES +#include +#include +#include +#include "TestEngineServer.h" +#include "TestEngine.h" +#include +#include "TestEngineClientServer.h" +#include +#include "TestModuleController.h" +#include "TestCaseController.h" +#include "TestReport.h" +#include "Logging.h" +#include "SettingServerClient.h" +//--PYTHON-- begin +#include "StifPython.h" +#include "StifPythonFunEng.h" +//--PYTHON-- end + +// EXTERNAL DATA STRUCTURES +// None + +// EXTERNAL FUNCTION PROTOTYPES +// None + +// CONSTANTS +_LIT( KTestModule, "TestModule=" ); +_LIT( KTestCaseFile, "TestCaseFile=" ); +_LIT( KTestCaseNumber, "TestCaseNumber=" ); +_LIT( KTestCaseTitle, "TestCaseTitle=" ); +_LIT( KStateCode, "StateCode=" ); +_LIT( KStateName, "StateName=" ); + +// MACROS +// None + +// LOCAL CONSTANTS AND MACROS +// None + +// MODULE DATA STRUCTURES +struct TThreadStartTestEngine + { + RThread iEngineThread; // The server thread + RSemaphore iStarted; // Startup syncronisation semaphore + }; + +// LOCAL FUNCTION PROTOTYPES +// None + +// FORWARD DECLARATIONS +// None + +// ==================== LOCAL FUNCTIONS ======================================= +// None + +// ================= MEMBER FUNCTIONS ========================================= + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Function: ErrorPrint + + Description: ErrorPrint + + Parameters: const TInt aPriority: in: Priority of error + TPtrC aError: in: Error description + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::ErrorPrint( const TInt aPriority, + TPtrC aError ) + { + TErrorNotification error; + TErrorNotificationPckg errorPckg ( error ); + + error.iModule = _L("TestEngine"); + error.iPriority = aPriority; + error.iText = aError; + + ErrorPrint( errorPckg ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestModule + + Method: ErrorPrint + + Description: Sends error notification + + Parameters: TErrorNotificationPckg aError: in: Error + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::ErrorPrint( TErrorNotificationPckg aError ) + { + // Add new item to end of queue + if ( iErrorQueue.Append ( aError() ) != KErrNone ) + { + RDebug::Print (_L("Error message lost")); + return; + } + + ProcessErrorQueue(); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestModule + + Method: ProcessErrorQueue + + Description: Process error queue + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::ProcessErrorQueue() + { + // If message is available, complete first item from queue + if ( iErrorMessageAvailable ) + { + + if ( iErrorQueue.Count() > 0 ) + { + TErrorNotification err = iErrorQueue[0]; + TErrorNotificationPckg errPckg(err); + iErrorQueue.Remove(0); + + TInt r( KErrNone ); + + TRAP( r, iErrorMessage.WriteL( 0, errPckg ) ); + + // Do not handle errors + + iErrorMessageAvailable = EFalse; + iErrorMessage.Complete( KErrNone ); + } + } + + } + +/* +------------------------------------------------------------------------------- + + Function: LeaveIfErrorWithNotify + + Description: If error leave with notify + + Parameters: TInt aCode: in: Error code + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::LeaveIfErrorWithNotify( TInt aCode ) + { + LeaveIfErrorWithNotify ( aCode, _L("Check testengine log") ); + + } + +/* +------------------------------------------------------------------------------- + + Function: LeaveIfErrorWithNotify + + Description: If error leave with notify + + Parameters: TInt aCode: in: Error code + const TDesC& aText: in: Descriptive text + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::LeaveIfErrorWithNotify( TInt aCode, + const TDesC& aText ) + { + if ( aCode != KErrNone ) + { + LeaveWithNotifyL ( aCode, aText ); + } + + } + +/* +------------------------------------------------------------------------------- + + Function: LeaveWithNotifyL + + Description: Leave with notify + + Parameters: TInt aCode: in: Error code + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::LeaveWithNotifyL( TInt aCode ) + { + LeaveWithNotifyL ( aCode, _L("Check testengine log") ); + + } + +/* +------------------------------------------------------------------------------- + + Function: LeaveWithNotifyL + + Description: Leave with notify + + Parameters: TInt aCode: in: Error code + const TDesC& aText: in: Descriptive text + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::LeaveWithNotifyL( TInt aCode, + const TDesC& aText ) + { + ErrorPrint ( 0, aText ); + User::Leave ( aCode ); + + } + +/* +------------------------------------------------------------------------------- + + DESCRIPTION + + This module contains implementation of CTestEngine class member functions. + +------------------------------------------------------------------------------- +*/ +#undef LOGGER +#define LOGGER Logger() + +// ================= MEMBER FUNCTIONS ========================================= + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: CTestEngine + + Description: Default constructor + + C++ default constructor can NOT contain any code, that + might leave. + + Parameters: RThread& aClient: in: Client's thread + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ + CTestEngine::CTestEngine() : + CSession2(), + iTestReport(NULL), + iReportMode( CTestReport::ETestReportFull ), + iReportOutput( CTestReport::ETestReportNone ), + iEnumerateModuleCount( 0 ), + iIsTestReportGenerated( EFalse ), + iDisableMeasurement( EEnableAll) + + { + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: ConstructL + + Description: Symbian OS second phase constructor + + Symbian OS default constructor can leave. + + Parameters: CTestEngineServer* aServer: in: Pointer to CTestEngineServer + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::ConstructL( CTestEngineServer* aServer ) + { + // Create report setting + iTestReportSettings = CTestReportSettings::NewL(); + + // Second-phase construct base class + //CSession2::CreateL(); + + iTestEngineServer = aServer; + + // Create new object index + iTestCases = CObjectIx::NewL(); + + // Initialize the object container from Server + iContainer = iTestEngineServer->NewContainerL(); + + __TRACE( KInit, ( _L( "CTestEngine::ConstructL: Test Engine Created" ) ) ); + + RFs iFs; + User::LeaveIfError( iFs.Connect() ); + _LIT(KCSteve,"C:\\Testframework\\"); + iFs.MkDirAll(KCSteve); + + iFs.Close(); + + iIndexTestModuleControllers = 1; + + SetTestEngineDefaultSettings(); + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: NewL + + Description: Two-phased constructor. + + Parameters: RThread& aClient : Client's thread + CTestEngineServer* aServer : Pointer to CTestEngineServer + + Return Values: CTestEngine* : pointer to CTestEngine object + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CTestEngine* CTestEngine::NewL( CTestEngineServer* aServer ) + { + CTestEngine* self = new ( ELeave ) CTestEngine(); + CleanupStack::PushL( self ); + self->ConstructL( aServer ); + CleanupStack::Pop(); + return self; + } + +CTestEngine::~CTestEngine() + { + // Remove contents of iTestCases + if ( iTestCases ) + { + TInt handle; + CObject* object = NULL; + TInt count = iTestCases->Count(); + + for ( TInt i = 0; i < count; i++ ) + { + object = iTestCases->operator[](i); + if ( object ) + { + handle = iTestCases->At( object ); + iTestCases->Remove( handle ); + } + } + + delete iTestCases; + iTestCases = NULL; + } + + iTestCaseArray.Close(); + + CloseTestEngineL(); + + if ( !iIsTestReportGenerated && RetrieveTestReport() ) + { + iTestReport->GenerateReportL(); + iIsTestReportGenerated = ETrue; + } + CloseSession(); + delete iTestReportSettings; + iTestReportSettings = NULL; + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: CloseSession + + Description: Close client server session to Test Engine + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::CloseSession() + { + __TRACE( KInit, ( _L( "CTestEngine::CloseSession" ) ) ); + + iErrorQueue.Close(); + + // Delete device reset module's DLL name + delete iDeviceResetDllName; + iDeviceResetDllName = NULL; + + // Delete state events + iStateEvents.ResetAndDestroy(); + iStateEvents.Close(); + + //Delete Client events + iClientEvents.ResetAndDestroy(); + iClientEvents.Close(); + + // Delete the object container + // This provides unique ids for the objects of this session + iTestEngineServer->DeleteContainer( iContainer ); + + // Inform server that session is closed + iTestEngineServer->SessionClosed(); + + // Delete test report + delete iTestReport; + iTestReport = NULL; + + delete iIniFile; + iIniFile = NULL; + + delete iRebootPath; + iRebootPath = NULL; + + delete iRebootFilename; + iRebootFilename = NULL; + + delete iRebootParams; + iRebootParams = 0; + + __TRACE(KVerbose, ( _L( "CTestEngine::CloseSession finished" ) ) ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: CountResources + + Description: Resource counding + + Parameters: None + + Return Values: TInt Resource count + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::CountResources() + { + return iResourceCount; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: NumResources + + Description: Get resources, writes to Message() + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::NumResources( const RMessage2& aMessage ) + { + + TInt ret( 0 ); + + TPckgBuf countPckg( iResourceCount ); + + TRAP( ret, aMessage.WriteL( 0, countPckg ) ); + + if ( ret != KErrNone ) + { + PanicClient( EBadDescriptor, aMessage ); + } + + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: PanicClient + + Description: Panic the client + + Parameters: TTestEnginePanic aPanic: in: Panic number + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::PanicClient( TTestEnginePanic aPanic, + const RMessage2& aMessage ) const + { + iTestEngineServer->Logger()->Log( CStifLogger::ERed, _L( "CTestEngine::PanicClient [%d]" ), aPanic ); + + _LIT( KTestEngine, "CTestEngine" ); + + aMessage.Panic( KTestEngine, aPanic ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: ServiceL + + Description: Message handling method that calls trapped DispatchMessageL + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Error from DispatchMessageL is trapped and handled + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::ServiceL( const RMessage2& aMessage ) + { + TRAPD( ret, DispatchMessageL( aMessage ) ); + if ( ret != KErrNone ) + { + __TRACE(KError, ( CStifLogger::ERed, _L( "CTestEngine::DispatchMessageL Function=[%d], left with [%d]" ), + aMessage.Function(), ret ) ); + if( ret == KErrNoMemory ) + { + __TRACE( KError, ( CStifLogger::ERed, _L( "No memory available. Some possibility to do: 1. Reduce test case count. 2. Increase StifTestEngine's heap size." ) ) ); + } + aMessage.Complete( ret ); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: DispatchMessageL + + Description: Actual message handling + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::DispatchMessageL( const RMessage2& aMessage ) + { + iComplete = ETrue; + iReturn = KErrNone; + + switch ( aMessage.Function() ) + { + case ETestEngineLoadConfiguration: + { + LoadConfigurationL( aMessage ); + break; + } + case ETestEngineUpdateLogConfiguration: + { + UpdateLogConfigurationL( aMessage ); + break; + } + case ETestEngineUpdateEngineConfiguration: + { + UpdateEngineConfigurationL( aMessage ); + break; + } + case ETestEngineSetAttribute: + { + SetAttributeL( aMessage ); + break; + } + case ETestEngineAddTestModule: + { + AddTestModuleL( aMessage ); + break; + } + case ETestEngineRemoveTestModule: + { + iReturn = RemoveTestModuleL( aMessage ); + break; + } + case ETestEngineAddConfigFile: + { + AddConfigFileL( aMessage ); + break; + } + case ETestEngineRemoveConfigFile: + { + RemoveConfigFileL( aMessage ); + break; + } + case ETestEngineEnumerateTestCases: + { + EnumerateTestCasesL( aMessage ); + break; + } + case ETestEngineGetTestCases: + { + GetTestCasesL( aMessage ); + break; + } + case ETestEngineCancelAsyncRequest: + { + CancelAsyncRequest( aMessage ); + break; + } + case ETestEngineEvent: + { + EventControlL( aMessage ); + iComplete = EFalse; + break; + } + case ETestEngineErrorNotification: + { + HandleErrorNotificationL( aMessage ); + iComplete = EFalse; + break; + } + case ETestEngineLoggerSettings: + { + LoggerSettings( aMessage ); + break; + } + case ETestEngineReportTestCase: + { + iReturn = AddTestCaseToTestReport(aMessage); + break; + } + // Subsession specific functions + case ETestCaseCreateSubSession: + { + NewTestCaseL( aMessage ); + break; + } + case ETestCaseCloseSubSession: + { + DeleteTestCase( aMessage.Int3() ); + break; + } + case ETestCaseRunTestCase: + { + TestCaseByHandle( aMessage.Int3(), aMessage )->RunTestCaseL( aMessage ); + iComplete = EFalse; + break; + } + case ETestCasePause: + { + iReturn = TestCaseByHandle( aMessage.Int3(), aMessage )->Pause(); + break; + } + case ETestCaseResume: + { + iReturn = TestCaseByHandle( aMessage.Int3(), aMessage )->Resume(); + break; + } + case ETestCaseNotifyProgress: + { + TestCaseByHandle( aMessage.Int3(), aMessage )->NotifyProgressL( aMessage ); + iComplete = EFalse; + break; + } + case ETestCaseNotifyRemoteType: + { + TestCaseByHandle( aMessage.Int3(), aMessage )->NotifyRemoteTypeL( aMessage ); + iComplete = EFalse; + break; + } + case ETestCaseNotifyRemoteMsg: + { + TestCaseByHandle( aMessage.Int3(), aMessage )->NotifyRemoteMsgL( aMessage ); + iComplete = EFalse; + break; + } + case ETestCaseCancelAsyncRequest: + { + TestCaseByHandle( + aMessage.Int3(), aMessage )->CancelAsyncRequest( aMessage ); + break; + } + default: + { + User::Leave( KErrNotSupported ); + break; + } + } + + if ( iComplete ) + { + aMessage.Complete( iReturn ); + } + + } + +void CTestEngine::SetTestEngineDefaultSettings() + { + // Test report settings initialization + iTestReportSettings->iCreateTestReport = ETrue; + _LIT( path, "C:\\LOGS\\TestFramework\\"); + _LIT( name, "TestReport"); + delete iTestReportSettings->iPath; + iTestReportSettings->iPath = NULL; + iTestReportSettings->iPath = path().AllocL(); + delete iTestReportSettings->iName; + iTestReportSettings->iName = NULL; + iTestReportSettings->iName = name().AllocL(); + iTestReportSettings->iFormat = CStifLogger::ETxt; + iTestReportSettings->iOutput = CStifLogger::EFile; + iTestReportSettings->iOverwrite = ETrue; + + iRebootDefaultPath.Set( _L( "C:\\TestFramework\\" ) ); + iRebootDefaultFilename.Set( _L( "Reboot.txt" ) ); + + TPtrC dllName; + dllName.Set( _L( "StifHWResetStub.dll" ) ); + iDeviceResetDllName = dllName.AllocL(); + + iDefaultTimeout = 0; + iUITestingSupport = EFalse; + iSeparateProcesses = EFalse; + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: InitEngineL + + Description: Init the test engine + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::LoadConfigurationL( const RMessage2& aMessage ) + { + + // Parse reboot file + ParseRebootParamsL(); + + TName iniFileName; + + // Read ini file name from aMessage + aMessage.ReadL( 0, iniFileName ); + TStifUtil::CorrectFilePathL( iniFileName ); + + iIniFile = iniFileName.AllocL(); + + __TRACE( KInit, ( CStifLogger::EBold, _L( "CTestEngine::InitEngineL\t iIniFile=[%S]" ), iIniFile ) ); + + // Connect to the Setting server and open handle(Handle will close when + // closing TestEngine). + TInt ret = iSettingServer.Connect(); + if ( ret != KErrNone ) + { + User::Leave( ret ); + } + + if ( iIniFile->Length() > 0 ) + { + Logger()->WriteDelimiter(); + __TRACE( KInit,( _L( "Starting to parse initialization file" ) ) ); + + // Struct to Logger settigs. + TLoggerSettings loggerSettings; + // Parse Logger defaults from STIF initialization file. + User::LeaveIfError( iSettingServer.LoadLoggerSettingsFromIniFile( loggerSettings, iniFileName, EFalse ) ); + + // Create parser for parsing ini file + CStifParser* parser = NULL; + TRAPD( r, parser = CStifParser::NewL( _L(""), *iIniFile ) ); + if ( r != KErrNone ) + { + __TRACE( KError,( CStifLogger::ERed, _L( "Can't open ini-file [%S], code %d" ), iIniFile, r ) ); + LeaveWithNotifyL(r); + } + + CleanupStack::PushL( parser ); + + CSTIFTestFrameworkSettings* settings = NULL; + TRAPD( settings_ret, settings = CSTIFTestFrameworkSettings::NewL() ); + CleanupStack::PushL( settings ); + if ( settings_ret != KErrNone ) + { + __TRACE( KError,( CStifLogger::ERed, _L( "CSTIFTestFrameworkSettings class object creation fails") ) ); + LeaveWithNotifyL( settings_ret ); + } + + ReadEngineDefaultsL( parser, settings ); + + iTestEngineServer->SetLoggerSettings( loggerSettings ); + + TRAP(r, ReadTestModulesL( parser )); + if(r != KErrNone) + { + __TRACE(KError, (CStifLogger::ERed, _L("Reading test modules finished with error [%d]"), r)); + User::Leave(r); + } + + CleanupStack::PopAndDestroy( settings ); + CleanupStack::PopAndDestroy( parser ); + __TRACE( KInit, ( _L( "Configuration file reading finished" ) ) ); + } + else + { + __TRACE( KInit,( CStifLogger::EBold, _L( "Initialisation file not specified." ) ) ); + } + + Logger()->WriteDelimiter(); + // Notch up another resource + iResourceCount++; + } + +void CTestEngine::UpdateLogConfigurationL( const RMessage2& aMessage ) + { + TBuf<256> logconfiguration; + aMessage.ReadL( 0, logconfiguration ); + iSettingServer.LoadLoggerSettingsFromCommandLine(logconfiguration); + } + + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: ReadEngineDefaults + + Description: Parse Test Engine defaults from STIF + initialization file. + + Parameters: CStifParser& parser: in: CStifParser object + CSTIFTestFrameworkSettings* aSettings: in: + CSTIFTestFrameworkSettings object + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::ReadEngineDefaultsL( CStifParser* aParser, + CSTIFTestFrameworkSettings* aSettings ) + { + __TRACE( KInit,( _L( "" ) ) ); + __TRACE( KInit,( _L( "Start parsing engine defaults" ) ) ); + TInt get_ret( KErrNone ); + + CStifSectionParser* sectionParser = NULL; + + // Parse Engine's default values + _LIT( KDefaultsStart, "[Engine_Defaults]" ); + _LIT( KDefaultsEnd, "[End_Defaults]" ); + __TRACE( KInit,( _L( "Starting to search sections" ) ) ); + sectionParser = aParser->SectionL( KDefaultsStart, KDefaultsEnd ); + CleanupStack::PushL( sectionParser ); + if ( sectionParser ) + { + __TRACE( KInit,( _L( "Found '%S' and '%S' sections" ), &KDefaultsStart, &KDefaultsEnd ) ); + + // Get Test Report Mode + __TRACE( KInit,( _L( "Parsing Test report mode" ) ) ); + TUint reportMode( 0 ); + get_ret = aSettings->GetReportModeL( sectionParser, + _L( "TestReportMode=" ), reportMode ); + if ( get_ret == KErrNone ) + { + __TRACE( KInit,( _L( "Report mode: %d"), reportMode ) ); + iReportMode = reportMode; + } + else + { + __TRACE( KInit,( _L( "Report mode not found or not given" ) ) ); + } + + // Indicator to test report creation + __TRACE( KInit,( _L( "Parsing Test report creation indicator" ) ) ); + TBool createTestReport( 0 ); + get_ret = aSettings->GetBooleanSettingsL( sectionParser, + _L( "CreateTestReport=" ), createTestReport ); + if ( get_ret == KErrNone ) + { + __TRACE( KInit,( _L( "Test report creation indicator: %d"), createTestReport ) ); + iTestReportSettings->iCreateTestReport = createTestReport; + } + else + { + __TRACE( KInit,( _L( "Creation indicator not found or not given" ) ) ); + } + + // Get Test report path settings + if ( iTestReportSettings->iCreateTestReport ) + { + __TRACE( KInit,( _L( "Parsing Test report path" ) ) ); + TPtrC path; + get_ret = aSettings->GetFileSetting( sectionParser, + _L( "TestReportFilePath=" ), path ); + if ( get_ret == KErrNone ) + { + __TRACE( KInit,( _L( "Test report path: %S"), &path ) ); + // Delete old one before setting new one + delete iTestReportSettings->iPath; + iTestReportSettings->iPath = NULL; + iTestReportSettings->iPath = path.AllocL(); + } + else + { + __TRACE( KInit,( _L( "Path not found or not given" ) ) ); + } + } + + // Get Test report name settings + if ( iTestReportSettings->iCreateTestReport ) + { + __TRACE( KInit,( _L( "Parsing Test report filename" ) ) ); + TPtrC name; + get_ret = aSettings->GetFileSetting( sectionParser, + _L( "TestReportFileName=" ), name ); + if ( get_ret == KErrNone ) + { + __TRACE( KInit,( _L( "Test report filename: %S"), &name ) ); + // Delete old one before setting new one + delete iTestReportSettings->iName; + iTestReportSettings->iName = NULL; + iTestReportSettings->iName = name.AllocL(); + } + else + { + __TRACE( KInit,( _L( "Filename not found or not given" ) ) ); + } + + } + + // Get Test report format settings + if ( iTestReportSettings->iCreateTestReport ) + { + __TRACE( KInit,( _L( "Parsing Test report format" ) ) ); + CStifLogger::TLoggerType type; + TBool xml; + get_ret = aSettings->GetFormatL( sectionParser, + _L( "TestReportFormat=" ), type, xml ); + if ( get_ret == KErrNone ) + { + __TRACE( KInit,( _L( "Test report format: %d, xml: %d"), type, xml ) ); + iTestReportSettings->iFormat = type; + iTestReportSettings->iXML = xml; + } + else + { + __TRACE( KInit,( _L( "Format not found or not given" ) ) ); + } + } + + // Get Test report output settings + if ( iTestReportSettings->iCreateTestReport ) + { + __TRACE( KInit,( _L( "Parsing Test report output" ) ) ); + CStifLogger::TOutput output; + get_ret = aSettings->GetOutputL( sectionParser, + _L( "TestReportOutput=" ), output ); + if ( get_ret == KErrNone ) + { + __TRACE( KInit,( _L( "Test report output: %d"), output ) ); + iTestReportSettings->iOutput = output; + } + else + { + __TRACE( KInit,( _L( "Output not found or not given" ) ) ); + } + } + + // Get Test report file creation mode (overwrite settings) + if ( iTestReportSettings->iCreateTestReport ) + { + __TRACE( KInit,( _L( "Parsing Test report file writing mode" ) ) ); + TBool overwrite; + get_ret = aSettings->GetOverwriteL( sectionParser, + _L( "TestReportFileCreationMode=" ), overwrite ); + if ( get_ret == KErrNone ) + { + __TRACE( KInit,( _L( "Test report file creation mode: %d"), overwrite ) ); + iTestReportSettings->iOverwrite = overwrite; + } + else + { + __TRACE( KInit,( _L( "Writing mode not found or not given" ) ) ); + } + } + // Get device reset module's DLL name + __TRACE( KInit,( _L( "Parsing device reset module's DLL name" ) ) ); + TPtrC deviceResetName; + get_ret = aSettings->GetFileSetting( sectionParser, + _L( "DeviceResetDllName=" ), deviceResetName ); + if ( get_ret == KErrNone ) + { + __TRACE( KInit,( _L( "Device reset module's name: %S"), &deviceResetName ) ); + // Delete old one before setting new one + delete iDeviceResetDllName; + iDeviceResetDllName = NULL; + iDeviceResetDllName = deviceResetName.AllocL(); + } + else + { + __TRACE( KInit,( _L( "Device reset module's name not found or not given" ) ) ); + } + + // Get measurement disable option + CStifItemParser* item = NULL; + TRAPD( ret, item = sectionParser->GetItemLineL( _L( "DisableMeasurement=" ), ENoTag ) ); + if( ( ret != KErrNone ) || ( item == NULL ) ) + { + __TRACE( KInit,( _L( "Measurement 'DiableMeasurement=' not found or not given" ) ) ); + delete item; + item = NULL; + } + else + { + CleanupStack::PushL( item ); + TPtrC string; + ret = item->GetString( KNullDesC(), string ); + while( ret == KErrNone ) + { + HBufC* stringHbuf = string.AllocL(); + TPtr modifiableString = stringHbuf->Des(); + modifiableString.LowerCase(); + + if( modifiableString == KStifMeasurementDisableNone || + modifiableString == KStifMeasurementDisableAll || + modifiableString == KStifMeasurement01 || + modifiableString == KStifMeasurement02 || + modifiableString == KStifMeasurement03 || + modifiableString == KStifMeasurement04 || + modifiableString == KStifMeasurement05 || + modifiableString == KStifMeasurementBappea ) + { + __TRACE( KInit,( _L( "Measurement disable option: %S"), &modifiableString ) ); + DisableStifMeasurement( modifiableString ); + } + else if( modifiableString == _L( "#" ) ) + { + delete stringHbuf; + stringHbuf = NULL; + break; + } + else + { + __TRACE( KInit,( _L( "Measurement disable option not found or not given" ) ) ); + delete stringHbuf; + stringHbuf = NULL; + break; + } + delete stringHbuf; + ret = item->GetNextString( string ); + } + CleanupStack::PopAndDestroy( item ); + item = NULL; + } + + // Get timeout value option + __TRACE(KInit, (_L("Parsing default timeout value"))); + iDefaultTimeout = 0; + item = NULL; + TRAP(ret, item = sectionParser->GetItemLineL(_L("Timeout=" ), ENoTag)); + if( ( ret != KErrNone ) || ( item == NULL ) ) + { + __TRACE(KInit, (_L("'Timeout' option not found or not given"))); + delete item; + item = NULL; + } + else + { + CleanupStack::PushL( item ); + TPtrC string; + ret = item->GetString(KNullDesC(), string); + if(string.Length() > 0) + { + TLex lex(string); + ret = lex.Val(iDefaultTimeout); + if(ret != KErrNone) + { + __TRACE(KError, (_L("Could not convert timeout value '%S' to integer. Error %d. Ignoring this setting."), &string, ret)); + } + if(iDefaultTimeout < 0) + { + __TRACE(KError, (_L("'Timeout' value cannot be negative. Resetting to 0."))); + iDefaultTimeout = 0; + } + } + else + { + __TRACE(KInit, (_L("'Timeout' value not given"))); + } + CleanupStack::PopAndDestroy( item ); + item = NULL; + } + __TRACE(KInit, (_L("'Timeout' value set to %d"), iDefaultTimeout)); + iDefaultTimeout *= 1000; + + // Get UITestingSupport value option + __TRACE(KInit, (_L("Parsing UITestingSupport value"))); + iUITestingSupport = EFalse; + item = NULL; + TRAP(ret, item = sectionParser->GetItemLineL(_L("UITestingSupport=" ), ENoTag)); + if((ret != KErrNone) || (item == NULL)) + { + __TRACE(KInit, (_L("'UITestingSupport' option not found"))); + delete item; + item = NULL; + } + else + { + CleanupStack::PushL(item); + TPtrC string; + ret = item->GetString(KNullDesC(), string); + if(string.Length() > 0) + { + iUITestingSupport = (string == _L("YES")); + } + else + { + __TRACE(KInit, (_L("'UITestingSupport' value not given"))); + } + CleanupStack::PopAndDestroy(item); + item = NULL; + } + __TRACE(KInit, (_L("'UITestingSupport' value set to %d"), iUITestingSupport)); + + // Get SeparateProcesses value option + __TRACE(KInit, (_L("Parsing SeparateProcesses value"))); + iSeparateProcesses = EFalse; + item = NULL; + TRAP(ret, item = sectionParser->GetItemLineL(_L("SeparateProcesses=" ), ENoTag)); + if((ret != KErrNone) || (item == NULL)) + { + __TRACE(KInit, (_L("'SeparateProcesses' option not found"))); + delete item; + item = NULL; + } + else + { + CleanupStack::PushL(item); + TPtrC string; + ret = item->GetString(KNullDesC(), string); + if(string.Length() > 0) + { + iSeparateProcesses = (string == _L("YES")); + } + else + { + __TRACE(KInit, (_L("'SeparateProcesses' value not given"))); + } + CleanupStack::PopAndDestroy(item); + item = NULL; + } + __TRACE(KInit, (_L("'SeparateProcesses' value set to %d"), iSeparateProcesses)); + } + else + { + __TRACE( KInit,( _L( "Not found '%S' and '%S' sections" ), &KDefaultsStart, &KDefaultsEnd ) ); + } + __TRACE( KInit,( _L( "End parsing engine defaults" ) ) ); + CleanupStack::PopAndDestroy( sectionParser ); + + } + +void CTestEngine::ReadEngineFromCommandLineL(const TDesC& aCommand) + { + _LIT(KTestReportMode,"TestReportMode"); + _LIT(KCreateTestReport,"CreateTestReport"); + _LIT(KTestReportFilePath,"TestReportFilePath"); + _LIT(KTestReportFileName,"TestReportFileName"); + _LIT(KTestReportFormat,"TestReportFormat"); + _LIT(KTestReportOutput,"TestReportOutput"); + _LIT(KTestReportFileCreationMode,"TestReportFileCreationMode"); + _LIT(KDeviceResetDllName,"DeviceResetDllName"); + _LIT(KDisableMeasurement,"DisableMeasurement"); + _LIT(KTimeout,"Timeout"); + _LIT(KUITestingSupport,"UITestingSupport"); + _LIT(KSeparateProcesses,"SeparateProcesses"); + TInt i=0; + TLex lex(aCommand); + while ( !lex.Eos() ) + { + TPtrC key=lex.NextToken(); + i++; + TPtrC value=lex.NextToken(); + i++; + if(key !=KNullDesC && value !=KNullDesC) + { + if(key==KTestReportMode) + { + if( value == _L( "EMPTY" ) ) + { + // No test report + iReportMode = CTestReport::ETestReportBlank; + } + else if( value == _L( "SUMMARY" ) ) + { + // Increment aSetting + iReportMode += CTestReport::ETestReportSummary; + } + else if( value == _L( "ENVIRONMENT" ) ) + { + // Increment aSetting + iReportMode += CTestReport::ETestReportEnvironment; + } + else if( value == _L( "TESTCASES" ) ) + { + // Increment aSetting + iReportMode += CTestReport::ETestReportCases; + } + else if( value == _L( "FULLREPORT" ) ) + { + // Set aSettings to max value and break + iReportMode = CTestReport::ETestReportFull; + + } + else if( value == _L( "#" ) ) + { + + } + } + else if(key==KCreateTestReport) + { + if( value == _L( "NO" ) ) + { + iTestReportSettings->iCreateTestReport = EFalse; + } + // Parsed parameter is true + else if( value == _L( "YES" ) ) + { + iTestReportSettings->iCreateTestReport = ETrue; + } + + } + else if(key==KTestReportFilePath) + { + if(iTestReportSettings->iCreateTestReport) + { + delete iTestReportSettings->iPath; + iTestReportSettings->iPath = NULL; + iTestReportSettings->iPath = value.AllocL(); + } + + } + else if(key==KTestReportFileName) + { + if(iTestReportSettings->iCreateTestReport) + { + delete iTestReportSettings->iName; + iTestReportSettings->iName = NULL; + iTestReportSettings->iName = value.AllocL(); + } + + } + else if(key==KTestReportFormat) + { + if( value == _L( "TXT" ) ) + { + iTestReportSettings->iFormat = CStifLogger::ETxt; + + } + else if( value == _L( "HTML" ) ) + { + iTestReportSettings->iFormat = CStifLogger::EHtml; + } + else if( value == _L( "DATA" ) ) + { + iTestReportSettings->iFormat = CStifLogger::EData; + } + else if( value == _L( "XML" ) ) + { + iTestReportSettings->iFormat = CStifLogger::ETxt; + iTestReportSettings->iXML = ETrue; + } + + } + else if(key==KTestReportOutput) + { + if( value == _L( "FILE" ) ) + { + iTestReportSettings->iOutput = CStifLogger::EFile; + } + else if( value == _L( "RDEBUG" ) ) + { + iTestReportSettings->iOutput = CStifLogger::ERDebug; + } + + } + else if(key==KTestReportFileCreationMode) + { + if( value == _L( "APPEND" ) ) + { + iTestReportSettings->iOverwrite = EFalse; + } + else if( value == _L( "OVERWRITE") ) + { + iTestReportSettings->iOverwrite = ETrue; + } + + } + else if(key==KDeviceResetDllName) + { + delete iDeviceResetDllName; + iDeviceResetDllName = NULL; + iDeviceResetDllName = value.AllocL(); + } + else if(key==KTimeout) + { + TLex temp(value); + lex.Val(iDefaultTimeout); + iDefaultTimeout *= 1000; + } + else if(key==KUITestingSupport) + { + iUITestingSupport = (value == _L("YES")); + } + else if(key==KSeparateProcesses) + { + iSeparateProcesses = (value == _L("YES")); + } + else if(key==KDisableMeasurement) + { + if( value == KStifMeasurementDisableNone || + value == KStifMeasurementDisableAll || + value == KStifMeasurement01 || + value == KStifMeasurement02 || + value == KStifMeasurement03 || + value == KStifMeasurement04 || + value == KStifMeasurement05 || + value == KStifMeasurementBappea ) + { + + DisableStifMeasurement( value ); + } + + + } + } + } + + + } +void CTestEngine::UpdateEngineConfigurationL( const RMessage2& aMessage ) + { + TBuf<256> engineconfiguration; + aMessage.ReadL( 0, engineconfiguration ); + engineconfiguration.TrimAll(); + ReadEngineFromCommandLineL(engineconfiguration); + + } + + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: ParseTestModulesL + + Description: Parse and search for module info and fill list of modules. + + Parameters: CStifParser* aParser: in: CStifParser object + CTestModuleList* aModuleList: in: list of modules + TPtrC& aSectionStart: in: descriptor with start of section string + TPTrC& aSectionEnd: in: descriptor with end of section string + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::ParseTestModulesL(CStifParser* aParser, CTestModuleList* aModuleList, const TDesC& aSectionStart, const TDesC& aSectionEnd) + { + //First let's find all modules given in Stif's ini file and store that info in CTestModuleList object + CStifSectionParser* sectionParser = NULL; + CStifItemParser* item = NULL; + + sectionParser = aParser->SectionL(aSectionStart, aSectionEnd); + + TBool sectionOK; + + while(sectionParser) + { + sectionOK = ETrue; + __TRACE(KInit, (_L("Found '%S' and '%S' sections"), &aSectionStart, &aSectionEnd)); + CleanupStack::PushL(sectionParser); + __TRACE(KInit, (_L("Starting to read module information"))); + + // Get name of module + _LIT(KModuleName, "ModuleName="); + item = sectionParser->GetItemLineL(KModuleName); + CleanupStack::PushL(item); + if(!item) + { + __TRACE(KError, (CStifLogger::ERed, _L("'%S' not found from Module section. Skipping whole section."), &KModuleName)); + sectionOK = EFalse; + } + else + { + __TRACE(KInit, (_L("'%S' found"), &KModuleName)); + } + + TName moduleName; + TInt ret(KErrNone); + + if(sectionOK) + { + TPtrC name; + ret = item->GetString(KModuleName, name); + if(ret != KErrNone) + { + __TRACE(KError, (CStifLogger::ERed, _L("Module name parsing ended with error [%d]. Skipping whole section"), ret)); + sectionOK = EFalse; + } + else + { + __TRACE(KInit, (_L("Module '%S' found from ini-file"), &name)); + moduleName.Copy(name); + moduleName.LowerCase(); + ret = aModuleList->AddTestModule(moduleName); + if(ret != KErrNone && ret != KErrAlreadyExists) + { + CleanupStack::PopAndDestroy(item); + __TRACE(KError, (CStifLogger::ERed, _L("Could not add module to list of modules. Error %d"), ret)); + LeaveIfErrorWithNotify(ret); + } + } + } + CleanupStack::PopAndDestroy(item); + + //Get pointer to added module + if(sectionOK) + { + CTestModuleInfo* moduleInfo = aModuleList->GetModule(moduleName); + if(!moduleInfo) + { + __TRACE(KError, (CStifLogger::ERed, _L("Could not add get module info from list"))); + LeaveIfErrorWithNotify(KErrNotFound); + } + + // Get ini file, if it exists + __TRACE(KInit, (_L("Start parsing ini file"))); + _LIT(KIniFile, "IniFile="); + item = sectionParser->GetItemLineL(KIniFile); + if(item) + { + __TRACE(KInit, (_L("'%S' found"), &KIniFile)); + CleanupStack::PushL(item); + TPtrC iniFile; + ret = item->GetString(KIniFile, iniFile); + if(ret == KErrNone) + { + // Module inifile (might be empty) OK + TFileName filename; + filename.Copy(iniFile); + TStifUtil::CorrectFilePathL( filename ); + filename.LowerCase(); + __TRACE(KInit, (CStifLogger::EBold, _L("Initialization file '%S' found, file can be empty"), &iniFile)); + moduleInfo->SetIniFile(filename); + } + else + { + __TRACE(KInit, (_L("Initialization file not found"))); + } + CleanupStack::PopAndDestroy(item); + } + else + { + __TRACE(KInit, (_L("'%S' not found"), &KIniFile)); + } + + // Get config (testcase) file + __TRACE(KInit, (_L("Start parsing cfg files"))); + TPtrC cfgTag; + for(TInt i = 0; i < 2; i++) + { + //Set tag for config files + if(i == 0) + { + cfgTag.Set(_L("ConfigFile=")); + } + else + { + cfgTag.Set(_L("TestCaseFile=")); + } + //Read data + item = sectionParser->GetItemLineL(cfgTag); + while(item) + { + CleanupStack::PushL(item); + __TRACE(KInit, (_L("Item '%S' found"), &cfgTag)); + TPtrC cfgFile; + ret = item->GetString(cfgTag, cfgFile); + if(ret == KErrNone) + { + TFileName ifile; + ifile.Copy(cfgFile); + TStifUtil::CorrectFilePathL( ifile ); + ifile.LowerCase(); + __TRACE(KInit, (_L("Configuration file '%S' found"), &ifile)); + moduleInfo->AddCfgFile(ifile); + } + else + { + __TRACE(KInit, (_L("Configuration file not found"))); + } + CleanupStack::PopAndDestroy(item); + item = sectionParser->GetNextItemLineL(cfgTag); + } + } + + __TRACE(KInit, (_L("Module '%S' information read correctly"), &moduleName)); + } + else + { + __TRACE(KError, (_L("Module '%S' information skipped"), &moduleName)); + } + + // Get next section... + CleanupStack::PopAndDestroy(sectionParser); + sectionParser = aParser->NextSectionL(aSectionStart, aSectionEnd); + } + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: ReadTestModules + + Description: Parse Test modules and module information from + STIF initialization file. + + Parameters: CStifParser& parser: in: CStifParser object + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::ReadTestModulesL(CStifParser* aParser) + { + __TRACE( KInit, (_L(""))); + __TRACE( KInit, (CStifLogger::EBold, _L("Start parsing test modules"))); + + //Create CTestModuleList object. It will keep information about all found test modules, + //its initialization files and test case (config) files. + CTestModuleList* moduleList = CTestModuleList::NewL(Logger()); + CleanupStack::PushL(moduleList); + + // Parse Test Module information + _LIT(KTestModuleStart, "[New_Module]"); + _LIT(KTestModuleEnd, "[End_Module]"); + + __TRACE(KInit, (_L("Starting to search module sections"))); + TRAPD(err, ParseTestModulesL(aParser, moduleList, KTestModuleStart, KTestModuleEnd)); + if(err != KErrNone) + { + __TRACE(KError, (CStifLogger::ERed, _L("Parsing test modules returned error [%d]"), err)); + User::Leave(err); + } + __TRACE(KInit, (CStifLogger::EBold, _L("End parsing test modules"))); + __TRACE(KInit, (_L(""))); + + //Now, find included test modules and also add them to CTestModuleList object. + _LIT(KIncludeModuleStart, "[New_Include_Module]"); + _LIT(KIncludeModuleEnd, "[End_Include_Module]"); + + __TRACE(KInit, (CStifLogger::EBold, _L("Start parsing included modules"))); + CTestCaseFileInfo* finfo = moduleList->GetUncheckedCfgFile(); + while(finfo) + { + TFileName fname; + finfo->GetCfgFileName(fname); + + __TRACE(KInit, (_L("checking file: '%S'"), &fname)); + finfo->SetChecked(); + + CStifParser* parser = NULL; + + TRAPD(err, parser = CStifParser::NewL(_L(""), fname)); + if(err == KErrNotFound) + { + __TRACE(KError, (CStifLogger::ERed, _L("Could not open file '%S'"), &fname)); + } + else if(err != KErrNone) + { + __TRACE(KError, (CStifLogger::ERed, _L("Could not create parser for file '%S'"), &fname)); + LeaveIfErrorWithNotify(err); + } + else + { + CleanupStack::PushL(parser); + + ParseTestModulesL(parser, moduleList, KIncludeModuleStart, KIncludeModuleEnd); + + CleanupStack::PopAndDestroy(parser); + } + + finfo = moduleList->GetUncheckedCfgFile(); + } + + __TRACE(KInit, (CStifLogger::EBold, _L("End parsing included modules"))); + __TRACE(KInit, (_L(""))); + + //Now, when all modules have been found, create them + __TRACE(KInit, (CStifLogger::EBold, _L("Start creating modules"))); + TBool afterReset = EFalse; + if(iRebootParams) + { + afterReset = ETrue; + } + CTestModuleInfo* moduleInfo = NULL; + TInt i; + TInt modCnt = moduleList->Count(); + + for(i = 0; i < modCnt; i++) + { + moduleInfo = moduleList->GetModule(i); + if(!moduleInfo) + { + __TRACE(KInit, (CStifLogger::ERed, _L("Could not get module info at index %d"), i)); + TName error; + error.AppendFormat(_L("Could not get module info at index %d"), i); + ErrorPrint(1, error); + continue; + } + + TName moduleName; + moduleInfo->GetModuleName(moduleName); + + // Create module controller + __TRACE(KInit, (_L("Creating module controller for '%S'"), &moduleName)); + CTestModuleController* module = NULL; + if( moduleName == _L( "testscripter" ) ) + { + module = CTestModuleController::NewL(this, moduleName, afterReset, ETrue); + } + else + { + module = CTestModuleController::NewL(this, moduleName, afterReset); + } + CleanupStack::PushL(module); + __TRACE(KInit, (_L("Module controller created"))); + + // Get ini file, if exists + __TRACE(KInit, (_L("Checking ini file"))); + TFileName ini; + moduleInfo->GetIniFileName(ini); + if(ini.Length() == 0) + { + __TRACE(KInit, (_L("Ini file not found"))); + } + + TRAPD(err, module->InitL(ini, KNullDesC)); + if(err != KErrNone) + { + __TRACE(KInit, (CStifLogger::ERed, _L("Module '%S' loading failed: %d"), &moduleName, err)); + TName error; + error.AppendFormat(_L("Module '%S' loading failed: %d"), &moduleName, err); + ErrorPrint(1, error); + + CleanupStack::PopAndDestroy(module); + continue; + } + + //Add test case files + __TRACE(KInit, (_L("Checking cfg files"))); + TInt cfgCnt = moduleInfo->CountCfgFiles(); + TInt j; + TFileName cfgFile; + for(j = 0; j < cfgCnt; j++) + { + moduleInfo->GetCfgFileName(j, cfgFile); + if(cfgFile.Length() > 0) + { + __TRACE(KInit, (_L("Adding config file '%S'"), &cfgFile)); + module->AddConfigFileL(cfgFile); + } + else + { + __TRACE(KInit, (_L("Got empty config filename"))); + } + } + if(cfgCnt == 0) + { + __TRACE(KInit, (_L("Cfg file not found"))); + } + + __TRACE(KInit, (_L("Module '%S' created correctly"), &moduleName)); + + // Store module for later use + User::LeaveIfError(iModules.Append(module)); + CleanupStack::Pop(module); + } + + __TRACE(KInit, (CStifLogger::EBold, _L("End creating test modules"))); + __TRACE(KInit, (_L(""))); + + //Check if there are any modules added to Stif + if (iModules.Count() == 0) + { + __TRACE(KInit, (_L("Not found '%S' and '%S' sections"), &KTestModuleStart, &KTestModuleEnd)); + __TRACE(KInit, (CStifLogger::EBold, _L("Test module(s) not defined in initialisation file"))); + // Note is printed from UI, not from here anymore + // ErrorPrint( 0 , _L("Test modules not found. Check testengine log")); + } + + //Delete CTestModuleList object. It is not needed any more + CleanupStack::PopAndDestroy(moduleList); + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: TestModuleConfigFileL + + Description: Add config file to test module + + Parameters: CTestModuleController* aModule: in: CTestModuleController + object. + CStifSectionParser* aSectionParser: in: CStifSectionParser + object. + TDesC& aTag :in: Founded tag. + + Return Values: None + + Errors/Exceptions: Leaves if GetNextItemLineL leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::TestModuleConfigFileL( CTestModuleController* aModule, + CStifSectionParser* aSectionParser, + TDesC& aTag ) + { + // Add config files to Test Module + TPtrC configFile; + CStifItemParser* item = NULL; + item = aSectionParser->GetItemLineL( aTag ); + + TInt cfgFiles = 0; + TFileName config; + + TInt ret( 0 ); + + while ( item ) + { + __TRACE( KInit,( _L( "Found '%S' section" ), &aTag ) ); + CleanupStack::PushL( item ); + ret = item->GetString( aTag, configFile ); + if ( ret != KErrNone ) + { + CleanupStack::PopAndDestroy( item ); + __TRACE( KError, ( CStifLogger::ERed, _L( "File parsing left with error [%d]" ), ret ) ); + } + else + { + config = configFile; + aModule->AddConfigFileL( config ); + + // Module configfile (might be empty) OK + __TRACE( KInit,( _L( "Adding configuration file [%S]" ), &config ) ); + cfgFiles++; + CleanupStack::PopAndDestroy( item ); + } + item = aSectionParser->GetNextItemLineL( aTag ); + } + + // Print trace + if ( cfgFiles == 0) + { + __TRACE( KInit,( _L( "Module does not have '%S' files") , &aTag ) ); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: ModuleControllerByName + + Description: Return the module controller specified by given parameter. + + Parameters: const TName& aModuleName: in: Test module name + + Return Values: CTestModuleController* : pointer to CTestModuleController + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CTestModuleController* CTestEngine::ModuleControllerByName( + const TName& aModuleName ) + { + TInt modules = iModules.Count(); + + for ( TInt i = 0; i < modules; i++ ) + { + if ( iModules[i]->ModuleName( aModuleName ) == aModuleName ) + { + return iModules[i]; + } + } + return NULL; + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: GetFreeOrCreateModuleControllerL + + Description: Return free module controller specified by given parameter. + If it can't be found, new one will be created. + + Parameters: TTestInfo& aTestInfo: test info structure + CTestModuleController** aRealModuleController: for test scripter a real module controller will be returned + + Return Values: CTestModuleController* : pointer to CTestModuleController + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CTestModuleController* CTestEngine::GetFreeOrCreateModuleControllerL(TTestInfo& aTestInfo, + CTestModuleController** aRealModuleController) + { + TInt i, j; + *aRealModuleController = NULL; + + TInt modules = iModules.Count(); + + //Find out which way it should be processed + //New way means that Stif is going to find free test module controller + //(free means that it does not run any test case) + TBool oldWay = ETrue; + if((iUITestingSupport && aTestInfo.iModuleName.Find(KTestScripterName) == 0) + || (aTestInfo.iModuleName == KPythonScripter) + || (iSeparateProcesses)) + { + __TRACE(KInit, (_L("Module controllers handling mode: exclusive"))); + //Exclusive mode means that every test case must be run in separate module controller. + oldWay = EFalse; + } + else + { + __TRACE(KInit, (_L("Module controllers handling mode: normal"))); + oldWay = ETrue; + } + + //If option is not set and it is not python scripter case + //(python scripter always should look for free module controller) + //This is the old way + if(oldWay) + { + __TRACE(KInit, (_L("Find test module controller for [%S]"), &aTestInfo.iModuleName)); + for(i = 0; i < modules; i++) + { + if(iModules[i]->ModuleName(aTestInfo.iModuleName) == aTestInfo.iModuleName) + { + __TRACE(KInit, (_L("Found test module controller for [%S]"), &aTestInfo.iModuleName)); + return iModules[i]; + } + } + __TRACE(KInit, (_L("Test module controller for [%S] NOT FOUND"), &aTestInfo.iModuleName)); + return NULL; + } + + //This is a new way + __TRACE(KInit, (_L("Find free test module controller for [%S]"), &aTestInfo.iModuleName)); + + TName moduleName(aTestInfo.iModuleName); + CTestModuleController* parentController = NULL; + + //First find original test module controller (parent) + for(TInt i = 0; i < modules; i++) + { + if(iModules[i]->ModuleName(moduleName) == moduleName) + { + parentController = iModules[i]; + __TRACE(KInit, (_L("Original (parent) module controller found [%S]"), &moduleName)); + break; + } + } + + //Search free module controller among parent's children + if(parentController) + { + //TestScripter is handled in other way + if(moduleName.Find(KTestScripterName) == 0) + { + __TRACE(KInit, (_L("This is testscripter case. Searching real module controller."))); + *aRealModuleController = parentController->GetFreeOrCreateModuleControllerL(aTestInfo, iUITestingSupport); + return parentController; + } + + //When UITestingSupport always create new module controller! + TInt childrenCount = parentController->iChildrenControllers.Count(); + for(TInt i = 0; i < childrenCount; i++) + { + if(parentController->iChildrenControllers[i]->iTestCaseCounter == 0) + { + if(iUITestingSupport && aTestInfo.iModuleName.Find(KTestScripterName) == 0) + { + __TRACE(KInit, (_L("Free module controller found but in UITestingSupport mode always new one will be created"))); + } + else + { + __TRACE(KInit, (_L("Free module controller found [%S]"), parentController->iChildrenControllers[i]->iName)); + return parentController->iChildrenControllers[i]; + } + } + else + { + __TRACE(KInit, (_L("Module controller [%S] found but it is not free (it runs %d test cases)"), parentController->iChildrenControllers[i]->iName, parentController->iChildrenControllers[i]->iTestCaseCounter)); + } + } + } + else + { + __TRACE(KError, (_L("Parent module controller NOT found [%S]"), &moduleName)); + User::Leave(KErrNotFound); + } + + //No free module controller has been found. Create new one. + TBuf<10> ind; + ind.Format(_L("%d"), GetIndexForNewTestModuleController()); + moduleName.Append(_L("@")); + moduleName.Append(ind); + __TRACE(KInit, (_L("Free module controller not found. Creating new one [%S]."), &moduleName)); + + //Create server and active object (This uses CTestModuleController::InitL()) + CTestModuleController* module = CTestModuleController::NewL(this, moduleName, parentController->iAfterReboot); + CleanupStack::PushL(module); + + TRAPD(err, module->InitL(parentController->iInifile, aTestInfo.iConfig)); + if(err != KErrNone) + { + __TRACE(KInit, (_L("InitL fails with error: %d for module [%S]" ), err, &moduleName)); + User::Leave(err); + } + __TRACE(KInit, (_L("New module controller created [%S]."), &moduleName)); + + // Store module for later use + User::LeaveIfError(parentController->iChildrenControllers.Append(module)); + CleanupStack::Pop(module); + __TRACE(KInit, (_L("Child added to [%S] controller. Currently it has %d children:"), parentController->iName, parentController->iChildrenControllers.Count())); + for(j = 0; j < parentController->iChildrenControllers.Count(); j++) + { + __TRACE(KInit, (_L(" %d. [%S]"), j + 1, parentController->iChildrenControllers[j]->iName)); + } + + return module; + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: SetAttributeL + + Description: Sets attributes to Test Framework + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Leave if ReadL leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::SetAttributeL( const RMessage2& aMessage ) + { + __TRACE( KVerbose, ( _L( "CTestEngine::SetAttributeL" ) ) ); + + TAttribute attribute; + TName genericTName; + + // Read attribute from aMessage + attribute = (TAttribute)aMessage.Int0(); + + switch( attribute ) + { + // Path attribute + case ELogPath: + { + // Read path from aMessage. + // NOTE!If message length is over TName, ReadL will cut the message + // to allowed size and won't return any error code or leave code. + aMessage.ReadL( 1, genericTName ); + + // Handle to Setting server. + RSettingServer settingServer; + // Connect to the Setting server and create session + TInt ret = settingServer.Connect(); + if ( ret != KErrNone ) + { + User::Leave( ret ); + } + settingServer.SetLoggerOutputPath( genericTName ); + // Close Setting server session + settingServer.Close(); + break; + } + // Reboot directory + case ERebootPath: + { + // Read reboot path from aMessage. + // NOTE!If message length is over TName, ReadL will cut the message + // to allowed size and won't return any error code or leave code. + aMessage.ReadL( 1, genericTName ); + // Allocated dynamically iRebootPath size and copies aMessage path. + iRebootPath = genericTName.AllocL(); + break; + } + // Reboot path + case ERebootFilename: + { + // Read reboot path from aMessage. + // NOTE!If message length is over TName, ReadL will cut the message + // to allowed size and won't return any error code or leave code. + aMessage.ReadL( 1, genericTName ); + // Allocated dynamically iRebootFilename size and copies aMessage + // filename. + iRebootFilename = genericTName.AllocL(); + break; + } + // Measurement configuration info + case EStifMeasurementOn: + { + // Read Measurement configuration info from aMessage. + aMessage.ReadL( 1, genericTName ); + + // Set info to test engine + User::LeaveIfError( EnableStifMeasurement( genericTName ) ); + break; + } + // Measurement configuration info + case EStifMeasurementOff: + { + // Read Measurement configuration info from aMessage. + aMessage.ReadL( 1, genericTName ); + + // Set info to test engine + User::LeaveIfError( DisableStifMeasurement( genericTName ) ); + break; + } + default: + { + __TRACE( KVerbose, ( _L( "Not valid attribute" ) ) ); + } + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: AddTestModuleL + + Description: Adds new Test Module + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + Leaves if name length is zero + + Status: Approved: Proposal + +------------------------------------------------------------------------------- +*/ +void CTestEngine::AddTestModuleL( const RMessage2& aMessage ) + { + __TRACE( KVerbose, ( _L( "CTestEngine::AddTestModuleL" ) ) ); + TName name; + TFileName iniFile; + + // Read test module name from aMessage + aMessage.ReadL( 0, name ); + + if( name.Length() == 0 ) + { + LeaveWithNotifyL( KErrArgument ); + } + // Read ini file name from aMessage + aMessage.ReadL( 1, iniFile ); + + name.LowerCase(); + // Remove optional '.DLL' from file name + TParse parse; + parse.Set( name, NULL, NULL ); + + if ( parse.Ext() == _L(".dll") ) + { + const TInt len = parse.Ext().Length(); + name.Delete ( name.Length()-len, len ); + } + + __TRACE( KInit, ( + _L( "CTestEngine::AddTestModuleL, Adding Module:[%S]"), &name ) ); + + // Check if test module already exists + CTestModuleController* testModule = ModuleControllerByName( name ); + if ( testModule == NULL ) + { + TBool afterReset = EFalse; + if( iRebootParams && iRebootParams->iTestModule == name ) + { + afterReset = ETrue; + } + + // Create module controller + CTestModuleController* module = NULL; + if( name == _L( "testscripter" ) ) + { + module = CTestModuleController::NewL( this, name, afterReset, ETrue ); + } + else + { + //CTestModuleController* module = + module = CTestModuleController::NewL( this, name, afterReset ); + } + CleanupStack::PushL( module ); + + module->InitL( iniFile, KNullDesC ); + + // Store module for later use + User::LeaveIfError( iModules.Append( module ) ); + CleanupStack::Pop( module ); + // Done + iReturn = KErrNone; + + __TRACE( KInit, ( + _L( "CTestEngine::AddTestModuleL, module added correctly") ) ); + } + else + { + iReturn = KErrAlreadyExists; + __TRACE( KInit, ( + _L( "CTestEngine::AddTestModuleL, module already added, all ok.") ) ); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: RemoveTestModuleL + + Description: Removes Test Module + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: TInt KErrNone: No errors occurred + KErrNotFound: Test module not found + KErrInUse: Test module is in use, cannot be removed + + Errors/Exceptions: Leaves if some of called leaving methods leaves + Leaves if moduleName length is zero + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::RemoveTestModuleL( const RMessage2& aMessage ) + { + __TRACE( KInit, ( _L( "CTestEngine::RemoveTestModuleL" ) ) ); + // Read Module name from message + TName moduleName; + aMessage.ReadL( 0, moduleName ); + if( moduleName.Length() == 0 ) + { + LeaveWithNotifyL( KErrArgument ); + } + + moduleName.LowerCase(); + // Remove optional '.DLL' from file name + TParse parse; + parse.Set( moduleName, NULL, NULL ); + + if ( parse.Ext() == _L(".dll") ) + { + const TInt len = parse.Ext().Length(); + moduleName.Delete ( moduleName.Length()-len, len ); + } + + __TRACE(KInit, (_L("Going to remove module controller [%S]"), &moduleName)); + // Check that the module that will be removed exists + TInt moduleCount = iModules.Count(); + TBool found = EFalse; + TInt moduleIndex; + for ( moduleIndex = 0; moduleIndex < moduleCount; moduleIndex++ ) + { + if ( iModules[moduleIndex]->ModuleName( moduleName ) == moduleName ) + { + found = ETrue; + break; + } + } + + if ( !found ) + { + // Test Module does not exists + __TRACE(KInit, (_L("Module controller [%S] to be removed NOT FOUND"), &moduleName)); + return KErrNotFound; + } + // Check module controller and its children + if(iModules[moduleIndex]->iTestCaseCounter > 0) + { + __TRACE(KInit, (_L("Cannot remove module controller [%S], it is running %d test cases"), &moduleName, iModules[moduleIndex]->iTestCaseCounter)); + return KErrInUse; + } + TInt j; + for(j = 0; j < iModules[moduleIndex]->iChildrenControllers.Count(); j++) + { + if(iModules[moduleIndex]->iChildrenControllers[j]->iTestCaseCounter > 0) + { + __TRACE(KInit, (_L("Cannot remove module controller [%S], its child [%S] is running %d test cases"), &moduleName, iModules[moduleIndex]->iChildrenControllers[j]->iName, iModules[moduleIndex]->iChildrenControllers[j]->iTestCaseCounter)); + return KErrInUse; + } + } + // Test cases not running so we can remove the Test Module + __TRACE(KInit, (_L("Removing module controller [%S]"), &moduleName)); + CTestModuleController* module = iModules[moduleIndex]; + iModules.Remove(moduleIndex); + delete module; + + return KErrNone; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: CloseTestEngineL + + Description: Close test engine + + Parameters: None + + Return Values: None + + Errors/Exceptions: Leaves if GenerateReportL leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::CloseTestEngineL() + { + __TRACE( KInit, ( _L( "CTestEngine::CloseTestEngineL" ) ) ); + // Remove all module controllers + iModules.ResetAndDestroy(); + iModules.Close(); + + // If test report is created + if( RetrieveTestReport() ) + { + iTestReport->GenerateReportL(); + iIsTestReportGenerated = ETrue; + } + + // Close Setting server, no handle available anymore + iSettingServer.Close(); + + // Decrement resource count + iResourceCount--; + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: AddConfigFileL + + Description: Adds new config file to Test Module + + Parameters: const RMessage& aMessage: in: Server Message + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + Leaves if module length is zero + Leaves if configFile length is zero + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::AddConfigFileL( const RMessage2& aMessage ) + { + TName module; + TFileName configFile; + + // Read module name from aMessage + aMessage.ReadL( 0, module ); + + if( module.Length() == 0 ) + { + LeaveWithNotifyL( KErrArgument ); + } + // Read config file name from aMessage + aMessage.ReadL( 1, configFile ); + + if( configFile.Length() == 0 ) + { + LeaveWithNotifyL( KErrArgument ); + } + + module.LowerCase(); + // Remove optional '.DLL' from file name + TParse parse; + parse.Set( module, NULL, NULL ); + + if ( parse.Ext() == _L(".dll") ) + { + const TInt len = parse.Ext().Length(); + module.Delete ( module.Length()-len, len ); + } + + __TRACE( KInit, ( _L( "Adding config file [%S] to [%S] module"), &configFile, &module ) ); + + // Get correct test module controller + CTestModuleController* testModule = ModuleControllerByName( module ); + if ( testModule == NULL ) + { + __TRACE( KError, ( CStifLogger::ERed, _L( "Added configure file has an invalid module:[%S]"), &module ) ); + LeaveWithNotifyL ( KErrNotFound ); + } + + // Add config file to Module + testModule->AddConfigFileL( configFile ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: RemoveConfigFileL + + Description: Removes a config file from test module + + Parameters: const RMessage& aMessage: in: Server Message + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + Leaves if module length is zero + Leaves if configFile length is zero + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void CTestEngine::RemoveConfigFileL( const RMessage2& aMessage ) + { + TName module; + TFileName configFile; + + // Read module name from aMessage + aMessage.ReadL( 0, module ); + + if( module.Length() == 0 ) + { + LeaveWithNotifyL( KErrArgument ); + } + // Read config file name from aMessage + aMessage.ReadL( 1, configFile ); + + if( configFile.Length() == 0 ) + { + LeaveWithNotifyL( KErrArgument ); + } + + module.LowerCase(); + // Remove optional '.DLL' from file name + TParse parse; + parse.Set( module, NULL, NULL ); + + if ( parse.Ext() == _L(".dll") ) + { + const TInt len = parse.Ext().Length(); + module.Delete ( module.Length()-len, len ); + } + + __TRACE( KInit, ( _L( "Removing config file [%S] from [%S] module"), &configFile, &module ) ); + + // Get correct test module controller + CTestModuleController* testModule = ModuleControllerByName( module ); + if ( testModule == NULL ) + { + __TRACE( KError, ( CStifLogger::ERed, _L( "Added configure file has an invalid module:[%S]"), &module ) ); + LeaveWithNotifyL ( KErrNotFound ); + } + + // Remove config file from Module + testModule->RemoveConfigFileL( configFile ); + + } + + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: EnumerateTestCasesL + + Description: Enumerates test cases + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Panics the client if enumeration is already pending + Leaves if called StartEnumerateL method leaves + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void CTestEngine::EnumerateTestCasesL( const RMessage2& aMessage ) + { + __TRACE( KInit, ( _L( "CTestEngine::EnumerateTestCasesL" ) ) ); + // Check if enumerate is ongoing!! + __ASSERT_ALWAYS( iEnumerateModuleCount == 0, PanicClient( EReqPending, aMessage ) ); + + iCaseCount = 0; + iEnumError = KErrNone; + + TInt count = iModules.Count(); + if ( count == 0 ) + { + + __TRACE( KInit, ( CStifLogger::EBold, _L( "Test module(s) not loaded - returning 0 test cases" ) ) ); + + // Note is printed from UI + // ErrorPrint(0, _L("No test modules, check testengine log")); + // Write test case count to client + TCaseCount countPckg( 0 ); + TRAPD( err, aMessage.WriteL( 0, countPckg ) ); + + // Request will be completed in DispatchMessageL + iReturn = err; + } + else + { + for ( TInt i = 0; i < count; i++ ) + { + // Send enumerate request to each test module. + iModules[i]->StartEnumerateL(); + iEnumerateModuleCount++; + } + + // Message is completed later from EnumerationCompleted function + iComplete = EFalse; + + // Store the message + iEnumerationMessage = aMessage; + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: EnumerationCompleted + + Description: Return the module controller specified by given parameter. + + Parameters: TInt aCount: in: Count of test cases + TInt aError: in: Symbian OS Error code: Error from Test Module + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void CTestEngine::EnumerationCompleted( TInt aCount, TInt aError ) + { + // Increment test case count by aCount + iCaseCount+= aCount; + + if ( aError != KErrNone ) + { + iEnumError = aError; + } + + iEnumerateModuleCount--; + + if ( iEnumerateModuleCount == 0 ) + { + + TInt attrib = CStifLogger::ENoStyle; + if ( iCaseCount == 0 ) + { + attrib = CStifLogger::EBold; + } + __TRACE( KInit, ( attrib, _L( "Test case enumeration completed, testcase count %d"), iCaseCount ) ); + + // Write test case count to client + TCaseCount countPckg( iCaseCount ); + TRAPD( err, iEnumerationMessage.WriteL( 0, countPckg ) ); + + if ( err != KErrNone ) + { + iEnumError = err; + __TRACE( KError, ( CStifLogger::ERed, _L( "CTestEngine::EnumerationCompleted: Failed %d"), iEnumError ) ); + } + + // Complete request + iEnumerationMessage.Complete( iEnumError ); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: GetTestCasesL + + Description: Get test cases + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Leaves if enumeration is not yet complete + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::GetTestCasesL( const RMessage2& aMessage ) + { + __TRACE( KVerbose, ( _L( "CTestEngine::GetTestCasesL" ) ) ); + + const TInt len = sizeof( TTestInfo ); + + // Loop through all test modules + TInt moduleCount = iModules.Count(); + TInt pos = 0; + TInt totalCount = 0; + for ( TInt i = 0; i < moduleCount; i++ ) + { + CTestModuleController* module = iModules[i]; + + // Check that test cases are enumerated first + if ( !module->EnumerationComplete() ) + { + __TRACE( KError, ( CStifLogger::ERed, _L( "CTestEngine::GetTestCasesL, Test Cases not yet enumerated!" ) ) ); + LeaveIfErrorWithNotify( KErrNotFound ); + } + + CFixedFlatArray* testCases = module->TestCasesL(); + CleanupStack::PushL( testCases ); + + // Loop through all test cases got from test module + const TInt caseCount = testCases->Count(); + totalCount+=caseCount; + + for ( TInt j = 0; j < caseCount; j++ ) + { + if(((*testCases)[j]).iTestCaseInfo.iTimeout == 0 && iDefaultTimeout > 0) + { + ((*testCases)[j]).iTestCaseInfo.iTimeout = iDefaultTimeout; + } + + // Construct package for source data + TTestInfoPckg tmpPackage( ( *testCases )[j] ); + + // Copy test case package to client's memory + aMessage.WriteL( 0, tmpPackage, pos ) ; + + pos = pos + len; + } + CleanupStack::PopAndDestroy( testCases ); + + // Free allocated test cases because not needed anymore + module->FreeTestCases(); + + } + + __TRACE( KVerbose, ( _L( "CTestEngine::GetTestCasesL, case count %d" ), totalCount ) ); + + // Finished + iReturn = KErrNone; + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: CancelAsyncRequest + + Description: Asynchronous requests are canceled by this function. + + Parameters: const RMessage aMessage + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void CTestEngine::CancelAsyncRequest( const RMessage2& aMessage ) + { + switch ( aMessage.Int0() ) + { + case ETestEngineEnumerateTestCases: + { + TInt count = iModules.Count(); + for ( TInt i=0; i < count; i++ ) + { + // Cancel enumerate + iModules[i]->Cancel(); + } + break; + } + + case ETestEngineErrorNotification: + { + if ( iErrorMessageAvailable ) + { + iErrorMessageAvailable = EFalse; + iErrorMessage.Complete ( KErrCancel ); + } + } + break; + case ETestEngineEvent: + // Event command cannot be cancelled + // Only EWaitEvent can be cancelled with ECancelWait + default: + PanicClient( EBadRequest, aMessage ); + break; + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: EventControlL + + Description: Controls event system. + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void CTestEngine::EventControlL( const RMessage2& aMessage ) + + { + __TRACE( KVerbose, ( _L( "CTestEngine::EventControlL" ) ) ); + TInt ret = KErrNone; + + // Read EventIf from aMessage + TEventIf event; + TEventIfPckg eventIfPckg( event ); + aMessage.ReadL( 0, eventIfPckg ); + + // EWaitEvent, EReqEvent and ERelEvent need processing here + if( ( event.Type() == TEventIf::EWaitEvent ) || + ( event.Type() == TEventIf::EReqEvent ) || + ( event.Type() == TEventIf::ERelEvent ) || + ( event.Type() == TEventIf::ECancelWait ) ) + { + TInt ind = 0; + TInt count = iClientEvents.Count(); + const TDesC& eventName = event.Name(); + // Search event from client event list + for( ind=0; ind < count; ind++ ) + { + if( iClientEvents[ind]->Name() == eventName ) + { + break; + } + } + + switch( event.Type() ) + { + // Handle event waiting + case TEventIf::EWaitEvent: + { + // Check that we found event from client events list + if( ind == count ) + { + ret = KErrNotFound; + } + else + { + TEventMsg* eventEntry = iClientEvents[ind]; + + __TRACE( KVerbose, ( _L( "CTestEngine::EventControlL: Waiting %S (count %i)"), + &event.Name(), count ) ); + + // Waiting is completed either from here in Wait method + // if event is already pending, + // or from Set method in CtlEvent when event is set. + eventEntry->Wait( aMessage ); + return; + } + } + break; + case TEventIf::ECancelWait: + { + // Check that we found event from client events list + if( ind == count ) + { + ret = KErrNotFound; + } + else + { + TEventMsg* eventEntry = iClientEvents[ind]; + + __TRACE( KVerbose, ( _L( "CTestEngine::EventControlL: Cancel waiting %S (count %i)"), + &event.Name(), count ) ); + + eventEntry->CancelWait(); + } + } + break; + // Handle event request + case TEventIf::EReqEvent: + { + // Check that event is not already requested + if( ind < count ) + { + // Already exists + ret = KErrArgument; + } + else + { + // Requested events are added to iClientEvents + TEventMsg* eventEntry = new TEventMsg; + if( eventEntry == NULL ) + { + ret = KErrNoMemory; + } + else + { + CleanupStack::PushL( eventEntry ); + eventEntry->Copy( event ); + // Check if state event is set already + if( IsStateEventAndSet( event.Name() ) ) + { + // If it was set already, set the event + eventEntry->Set( TEventIf::EState ); + } + ret = iClientEvents.Append( eventEntry ); + if( ret != KErrNone ) + { + CleanupStack::PopAndDestroy( eventEntry ); + } + else + { + CleanupStack::Pop( eventEntry ); + + __TRACE( KVerbose, ( _L( "CTestEngine::EventControlL: Req added %S (count %i)"), + &event.Name(), iClientEvents.Count() ) ); + } + } + } + } + break; + // Release event + case TEventIf::ERelEvent: + { + // Released events are deleted from iClientEvents + // Check that we found entry from client events list + if( ind == count ) + { + ret = KErrNotFound; + } + else + { + __TRACE( KVerbose, ( _L( "CTestEngine::EventControlL: Release event %S (count %i)"), + &event.Name(), iClientEvents.Count() ) ); + + TEventMsg* eventEntry = iClientEvents[ind]; + iClientEvents.Remove( ind ); + eventEntry->Release(); + delete eventEntry; + } + } + break; + default: // This should never happen!!! + { + _LIT( KEngine, "CTestEngine" ); + User::Panic( KEngine, KErrGeneral ); + } + break; + } + } + else + { + // ESetEvent and EUnsetEvent are only forwarded + TRequestStatus req; + CtlEventL( event, req ); + User::WaitForRequest( req ); + } + + aMessage.Complete( ret ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: HandleErrorNotificationL + + Description: Handle error notifications. + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::HandleErrorNotificationL( const RMessage2& aMessage ) + { + iErrorMessage = aMessage; + iErrorMessageAvailable = ETrue; + + ProcessErrorQueue(); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: LoggerSettings + + Description: Get Logger's overwrite parameters + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Panics if WriteL fails + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::LoggerSettings( const RMessage2& aMessage ) + { + __TRACE( KInit, ( _L( "CTestEngine::LoggerSettings" ) ) ); + + // Copies logger settings to the package + TPckg loggerSettingsPckg( iTestEngineServer->GetLoggerSettings() ); + + // Writes a packege that includes the logger overwrite settings to aMessage + TRAPD( err, aMessage.WriteL( 0, loggerSettingsPckg ) ); + if ( err != KErrNone ) + { + PanicClient( EBadDescriptor, aMessage ); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: CloseLoggerSettings + + Description: Close logger settings + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::CloseLoggerSettings() + { + __TRACE( KInit, ( _L( "CTestEngine::CloseLoggerSettings" ) ) ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: TestCaseByHandle + + Description: Return test case specified by aHandle + + Parameters: TUint aHandle : in : TUint : Handle to TestCase subsession + + Return Values: CTestCase* : pointer to CTestCase object + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CTestCase* CTestEngine::TestCaseByHandle( TUint aHandle, const RMessage2& aMessage ) + { + // Try to get test case from test case container + CTestCase* testCase = + ( CTestCase* )iTestCases->At( aHandle ); + if ( testCase == NULL ) + { + PanicClient( EBadSubsessionHandle, aMessage ); + } + + return testCase; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: NewTestCaseL + + Description: Create new test execution subsession + + Parameters: const RMessage& aMessage: in: Server Message + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving method leaves + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void CTestEngine::NewTestCaseL( const RMessage2& aMessage ) + { + __TRACE( KVerbose, ( _L( "CTestEngine::NewTestCaseL start" ) ) ); + + // Get data from message + TTestInfo testInfo; + TTestInfoPckg testInfoPckg = testInfo; + + TRAPD( res, aMessage.ReadL( 0, testInfoPckg ) ); + if ( res != KErrNone ) + { + PanicClient( EBadDescriptor, aMessage ); + return; + } + + testInfo.iModuleName.LowerCase(); + // Remove optional '.DLL' from file name + TParse parse; + parse.Set( testInfo.iModuleName, NULL, NULL ); + + if ( parse.Ext() == _L(".dll") ) + { + const TInt len = parse.Ext().Length(); + testInfo.iModuleName.Delete ( testInfo.iModuleName.Length()-len, len ); + } + + // Get correct test module controller + CTestModuleController* scrModule = NULL; + CTestModuleController* module = GetFreeOrCreateModuleControllerL(testInfo, &scrModule); + if ( module == NULL ) + { + //@spe PanicClient( EInvalidModuleName, aMessage ); + //@spe return; + __TRACE( KError, ( CStifLogger::ERed, _L( "Invalid module:[%S]"), &testInfo.iModuleName ) ); + LeaveWithNotifyL ( KErrNotFound ); + } + + // Create test case object + CTestCase* testCase = + CTestCase::NewL( this, module, RetrieveTestReport(), testInfo, scrModule); + CleanupStack::PushL( testCase ); + + // Add object to object container to generate unique id + iContainer->AddL( testCase ); + + // Add object to object index + // This returns a unique handle so we can get it again + TInt handle = iTestCases->AddL( testCase ); + + // Write the handle to client + TPckg handlePckg( handle ); + + TRAP( res, aMessage.WriteL( 3, handlePckg ) ); + if ( res != KErrNone ) + { + iTestCases->Remove( handle ); + PanicClient( EBadDescriptor, aMessage ); + return; + } + + // Add new test case to testcase array + User::LeaveIfError( iTestCaseArray.Append( testCase ) ); + CleanupStack::Pop( testCase ); + + // Notch up another resource + iResourceCount++; + + iReturn = KErrNone; + + __TRACE( KVerbose, ( _L( "CTestEngine::NewTestCaseL done" ) ) ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: DeleteTestCase + + Description: Delete test case from container list + + Parameters: TUint aHandle: in: Handle to test case to be removed + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::DeleteTestCase( TUint aHandle ) + { + __TRACE( KVerbose, ( _L( "CTestEngine::DeleteTestCase" ) ) ); + + // Get test case from container + CTestCase* testCase = ( CTestCase* )iTestCases->At( aHandle ); + + // Do nothing if invalid handle + if ( testCase == NULL ) + { + // Handle might be already deleted, so do nothing. + return; + } + + //Get controllers + CTestModuleController* moduleController; + CTestModuleController* realModuleController; + + moduleController = testCase->GetModuleControllers(&realModuleController); + + // Check if module controllers have crashed + TBool moduleControllerCrashed = EFalse; + TBool realModuleControllerCrashed = EFalse; + + if(moduleController) + { + moduleControllerCrashed = moduleController->iTestModuleCrashDetected; + } + if(realModuleController) + { + realModuleControllerCrashed = realModuleController->iTestModuleCrashDetected; + } + + //__TRACE(KInit, (_L("CTestEngine::DeleteTestCase moduleController=[%x] crashed=[%d] realModuleController=[%x] crashed=[%d]"), moduleController, moduleControllerCrashed, realModuleController, realModuleControllerCrashed)); + // For UITestingSupport, SeparateProcesses and PythonSupport, when module is crashed, + // remove it from module lists, because it will be deleted when closing test case. + if(moduleController) + { + if(moduleControllerCrashed && iUITestingSupport && moduleController->iName->Find(KTestScripterName) == 0 + || moduleControllerCrashed && iSeparateProcesses + || moduleControllerCrashed && moduleController->iName->Find(KPythonScripter) == 0 + ) + { + __TRACE(KInit, (_L("Removing module controller from module list because of crash"))); + //Look for specific module controller and delete it + TInt i; + TInt j, children; + TInt modules = iModules.Count(); + for(i = 0; i < modules; i++) + { + if(iModules[i] == moduleController) + { + __TRACE(KInit, (_L("Module controller found - removing"))); + iModules.Remove(i); + break; + } + + //Check children of the module and if module to be deleted found there, remove it + children = iModules[i]->iChildrenControllers.Count(); + __TRACE(KInit, (_L("Checking %d children of [%S]"), children, iModules[i]->iName)); + for(j = 0; j < children; j++) + { + if(iModules[i]->iChildrenControllers[j] == moduleController) + { + __TRACE(KInit, (_L("Module controller found (child) - removing"))); + + iModules[i]->iChildrenControllers.Remove(j); + + __TRACE(KInit, (_L("Child removed from [%S] controller. Currently it has %d children:"), iModules[i]->iName, iModules[i]->iChildrenControllers.Count())); + for(TInt k = 0; k < iModules[i]->iChildrenControllers.Count(); k++) + { + __TRACE(KInit, (_L(" %d. [%S]"), k + 1, iModules[i]->iChildrenControllers[k]->iName)); + } + break; + } + } + } + } + } + if(moduleController && realModuleController) + { + if(realModuleControllerCrashed && iUITestingSupport && realModuleController->iName->Find(KTestScripterName) == 0 + || realModuleControllerCrashed && iSeparateProcesses + || realModuleControllerCrashed && realModuleController->iName->Find(KPythonScripter) == 0 + ) + { + __TRACE(KInit, (_L("Removing real module controller from module list because of crash"))); + //Remove module controller from scripter controller + moduleController->RemoveModuleController(realModuleController); + } + } + + // Close test case and remove it from container + //testCase->CloseTestCase(); + iTestCases->Remove( aHandle ); + + // Decrement resource count + iResourceCount--; + + // Remove from testcase array + iTestCaseArray.Remove( iTestCaseArray.Find( testCase ) ); + + //If this is UITestingSupport and module is not crashed, delete controller + //(in other words, kill process, because we need somehow reset the test server). + if(moduleController && !moduleControllerCrashed) + { + if(iUITestingSupport && moduleController->iName->Find(KTestScripterName) == 0) + { + if(realModuleController) + { + if(!realModuleControllerCrashed) + { + __TRACE(KInit, (_L("Delete module controller (and kill process in which test case was run)."))); + __TRACE(KInit, (_L("Real module controller provided - processing"))); + //Remove module controller from scripter controller + moduleController->DeleteModuleController(realModuleController); + } + } + else + { + __TRACE(KInit, (_L("Delete module controller (and kill process in which test case was run)."))); + __TRACE(KInit, (_L("Real module controller not provided, checking normal controllers"))); + //Look for specific module controller and delete it + TInt i; + TInt j, children; + TInt modules = iModules.Count(); + for(i = 0; i < modules; i++) + { + if(iModules[i] == moduleController) + { + __TRACE(KInit, (_L("Module controller found - deleting"))); + delete iModules[i]; + iModules.Remove(i); + break; + } + + //Check children of the module and if module to be deleted found there, remove it + children = iModules[i]->iChildrenControllers.Count(); + __TRACE(KInit, (_L("Checking %d children of [%S]"), children, iModules[i]->iName)); + for(j = 0; j < children; j++) + { + if(iModules[i]->iChildrenControllers[j] == moduleController) + { + __TRACE(KInit, (_L("Module controller found (child) - deleting"))); + + delete iModules[i]->iChildrenControllers[j]; + iModules[i]->iChildrenControllers.Remove(j); + + __TRACE(KInit, (_L("Child removed from [%S] controller. Currently it has %d children:"), iModules[i]->iName, iModules[i]->iChildrenControllers.Count())); + for(TInt k = 0; k < iModules[i]->iChildrenControllers.Count(); k++) + { + __TRACE(KInit, (_L(" %d. [%S]"), k + 1, iModules[i]->iChildrenControllers[k]->iName)); + } + break; + } + } + } + } + } + } + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: IsStateEventAndSet + + Description: Callback to check state event status. + + Parameters: const TName& aEventName: in: Event name + + Return Values: ETrue: event is set + EFalse: event is not set + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TBool CTestEngine::IsStateEventAndSet( const TName& aEventName ) + { + TInt count = iStateEvents.Count(); + for( TInt i = 0; i < count; i++ ) + { + TPtrC name = iStateEvents[i]->Des(); + if( name == aEventName ) + { + // Requested state event set already + return ETrue; + } + } + return EFalse; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: CtlEventL + + Description: Callback to control events. + + Parameters: const TEventIf& aEvent: in: event information + TRequestStatus& aStatus: in: Request status + + Return Values: CTestEventController*: CTestEventController object + + Errors/Exceptions: Leaves if CtlEventL leaves + Leaves if memory allocation fails + Leaves if unset event not found from pending + state event list + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CTestEventController* CTestEngine::CtlEventL( const TEventIf& aEvent, + TRequestStatus& aStatus ) + { + __TRACE( KVerbose, ( _L( "CTestEngine::CtlEventL" ) ) ); + + aStatus = KRequestPending; + + UpdateEventL( aEvent ); + return CTestEventController::NewL( this, aEvent, &aStatus ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: UpdateEventL + + Description: Update event lists. + + Parameters: const TEventIf& aEvent: in: event information + + Return Values: None + + Errors/Exceptions: Leaves if CtlEventL leaves + Leaves if memory allocation fails + Leaves if unset event not found from pending + state event list + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::UpdateEventL( const TEventIf& aEvent ) + { + // Handle ESetEvent and EUnsetEvent for state events here + if( aEvent.EventType() == TEventIf::EState ) + { + // Find event from the list + TInt count = iStateEvents.Count(); + TInt index = 0; + const TDesC& eventName = aEvent.Name(); + for( ; index < count; index++ ) + { + TPtrC name = iStateEvents[index]->Des(); + if( name == eventName ) + { + break; + } + } + + if( aEvent.Type() == TEventIf::ESetEvent ) + { + // Check that event is not already pending + if( index < count ) + { + User::Leave( KErrAlreadyExists ); + } + + // Add set event to pending state event list + HBufC* name = aEvent.Name().AllocLC(); + User::LeaveIfError( iStateEvents.Append( name ) ); + CleanupStack::Pop( name ); + } + else if( aEvent.Type() == TEventIf::EUnsetEvent ) + { + if( index == count ) + { + // Not found from state event list + User::Leave( KErrNotFound ); + } + HBufC* tmp = iStateEvents[index]; + iStateEvents.Remove( index ); + delete tmp; + } + } + else if( aEvent.Type() == TEventIf::EUnsetEvent ) + { + // Can not give Unset for indication event + User::Leave( KErrNotSupported ); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: Logger + + Description: Return the pointer to Logger. + + Parameters: None + + Return Values: CStifLogger*: Pointer to StifLogger + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CStifLogger* CTestEngine::Logger() + { + return iTestEngineServer->Logger(); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: WriteRebootParams + + Description: Write the Reboot's state parameters. + + Parameters: TTestInfo& aTestInfo: in: Test case information. + TInt& aCode: in: Reboot related integer information. + TDesC& aName: in: Reboot related string information. + + Return Values: TInt: Symbian OS error + + Errors/Exceptions: Error code returned if Logger creation fails. + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::WriteRebootParams( TTestInfo& aTestInfo, + TInt& aCode, + TDesC& aName ) + { + __TRACE( KVerbose, ( _L( "WriteRebootParams() starts..." ) ) ); + + // Logger's setting definitions + TLoggerSettings loggerSettings; + + loggerSettings.iCreateLogDirectories = ETrue; + loggerSettings.iOverwrite = ETrue; + loggerSettings.iTimeStamp = EFalse; + loggerSettings.iLineBreak = EFalse; + loggerSettings.iEventRanking = EFalse; + loggerSettings.iThreadId = EFalse; + // EData format because now we don't have to check file type when + // parsing this. + loggerSettings.iHardwareFormat = CStifLogger::EData; + loggerSettings.iHardwareOutput = CStifLogger::EFile; + loggerSettings.iEmulatorFormat = CStifLogger::EData; + loggerSettings.iEmulatorOutput = CStifLogger::EFile; + loggerSettings.iUnicode = EFalse; + loggerSettings.iAddTestCaseTitle = EFalse; + + // Use default setting if path or filename are not set by SetAttribute() + if( iRebootPath == NULL ) + { + iRebootPath= iRebootDefaultPath.Alloc(); + } + if( iRebootFilename == NULL ) + { + iRebootFilename= iRebootDefaultFilename.Alloc(); + } + + CStifLogger* logger = NULL; + TRAPD( ret, logger = CStifLogger::NewL( *iRebootPath, + *iRebootFilename, + loggerSettings ) ); + if( ret != KErrNone ) + { + __TRACE( KError, ( _L( "WriteRebootParams() Logger creation fails with error: " ), ret ) ); + delete logger; + return ret; + } + + // Write reboot parameters + // Because logging format is EData we need add line breaks by hand. + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "This is TestFramework's file which includes Reboot related informations" ) ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "Reboot case's related information:" ) ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "%S %S" ), &KTestModule, &aTestInfo.iModuleName ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "%S %S" ), &KTestCaseFile, &aTestInfo.iConfig ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "%S %d" ), &KTestCaseNumber, aTestInfo.iTestCaseInfo.iCaseNumber ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "%S %S" ), &KTestCaseTitle, &aTestInfo.iTestCaseInfo.iTitle ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "%S %d" ), &KStateCode, aCode ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "%S " ), &KStateName ); + logger->Log( aName ); + logger->Log( _L( "\r\n" ) ); + logger->Log( _L( "\r\n" ) ); + + delete logger; + + __TRACE( KVerbose, ( _L( "WriteRebootParams() ends" ) ) ); + + return KErrNone; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: ReadRebootParams + + Description: Read the Reboot parameters. + + Parameters: TTestInfo& aTestInfo: in: Test case information. + + Return Values: TInt: Symbian OS error + + Errors/Exceptions: Error code returned if Parser creation fails. + Error code returned if section creation fails. + Error code returned if item creation fails. + Error code returned if parsing operation fails. + KErrArgument returned if parsed values and test case + values are different. + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::ReadRebootParams( TTestInfo& aTestInfo, + TDes& aStateDes, + TInt& aState ) + { + __TRACE( KVerbose, ( _L( "ReadRebootParams() starts..." ) ) ); + + if( iRebootParams == NULL ) + { + __TRACE( KVerbose, ( _L( "ReadRebootParams(): Reboot not done" )) ); + return KErrNotFound; + } + + // --.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.-- + // Checks parsed values and test case values + // --.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.-- + if( iRebootParams->iTestModule != aTestInfo.iModuleName || + iRebootParams->iTestCaseFile != aTestInfo.iConfig || + iRebootParams->iCaseNumber != aTestInfo.iTestCaseInfo.iCaseNumber ) + { + __TRACE( KVerbose, + ( _L( "ReadRebootParams(): Reboot not done by %S" ), + &aTestInfo.iModuleName) ); + return KErrArgument; + } + + aStateDes.Copy( iRebootParams->iStateName ); + aState = iRebootParams->iStateCode; + + // delete reboot params, to ensure that same test case + // does not get indication about reboot again + delete iRebootParams; + iRebootParams = 0; + + __TRACE( KVerbose, ( _L("ReadRebootParams() ends" ) ) ); + + return KErrNone; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: ParseRebootParamsL + + Description: Parse the Reboot parameters. + + Parameters: None + + Return Values: TInt: Symbian OS error + + Errors/Exceptions: Error code returned if Parser creation fails. + Error code returned if section creation fails. + Error code returned if item creation fails. + Error code returned if parsing operation fails. + KErrArgument returned if parsed values and test case + values are different. + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::ParseRebootParamsL() + { + __TRACE( KVerbose, ( _L( "ParseRebootParamsL() starts..." ) ) ); + + TInt ret_parsing( 0 ); + TPtrC tmp; + + // Use default setting if path or filename are not set by SetAttribute() + if( iRebootPath == NULL ) + { + iRebootPath= iRebootDefaultPath.Alloc(); + } + if( iRebootFilename == NULL ) + { + iRebootFilename= iRebootDefaultFilename.Alloc(); + } + + // Create parser object + CStifParser* parser = NULL; + TRAPD( ret, parser = CStifParser::NewL( *iRebootPath, + *iRebootFilename ) ); + if( ret != KErrNone ) + { + __TRACE( KError, ( _L( "ReadRebootParams(): Reboot file not found" )) ); + return ret; + } + CleanupStack::PushL( parser ); + + // Create section object + CStifSectionParser* section = parser->SectionL( KNullDesC, KNullDesC ); + CleanupStack::PushL( section ); + + // Delete old reboot params + delete iRebootParams; + iRebootParams = 0; + iRebootParams = CRebootParams::NewL(); + + // ----------------------Test module parsing + CStifItemParser* item = section->GetItemLineL( KTestModule ); + CleanupStack::PushL( item ); + + // Parsing integer + ret_parsing = item->GetString( KTestModule, tmp ); + if( ret_parsing == KErrNone || ret_parsing == KErrNotFound ) + { + __TRACE( KVerbose, ( _L("ReadRebootParams(): TestModule: %S" ), &tmp ) ); + } + else + { + __TRACE( KError, + ( _L("ReadRebootParams(): TestModule parsing fails with error: " ), + ret_parsing ) ); + User::Leave( ret_parsing ); + } + iRebootParams->SetTestModuleNameL( tmp ); + CleanupStack::PopAndDestroy( item ); + + // ----------------------Testcase parsing + item = section->GetItemLineL( KTestCaseFile ); + CleanupStack::PushL( item ); + + // Parsing string + ret_parsing = item->GetString( KTestCaseFile, tmp ); + if( ret_parsing == KErrNone ) + { + __TRACE( KVerbose, ( _L("ReadRebootParams(): TestCaseFile: %S" ), &tmp ) ); + iRebootParams->SetTestCaseFileNameL( tmp ); + } + else if( ret_parsing == KErrNotFound ) + { + __TRACE( KVerbose, + ( _L("ReadRebootParams(): No testcasefile defined for test module" )) ); + } + else + { + __TRACE( KError, + ( _L("ReadRebootParams(): TestCaseFile parsing fails with error: %d " ), + ret_parsing ) ); + User::Leave( ret_parsing ); + } + CleanupStack::PopAndDestroy( item ); + + // ----------------------Testcase number parsing + item = section->GetItemLineL( KTestCaseNumber ); + CleanupStack::PushL( item ); + + // Parsing integer + ret_parsing = item->GetInt( KTestCaseNumber, iRebootParams->iCaseNumber ); + if( ret_parsing == KErrNone || ret_parsing == KErrNotFound ) + { + __TRACE( KVerbose, ( _L("ReadRebootParams(): TestCaseNumber: %d" ), + iRebootParams->iCaseNumber ) ); + } + else + { + __TRACE( KError, + ( _L("ReadRebootParams(): TestCaseNumber parsing fails with error: %d " ), + ret_parsing ) ); + User::Leave( ret_parsing ); + } + CleanupStack::PopAndDestroy( item ); + + // --.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.-- + // --.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.-- + // Next state code and name parsing if no error found + // --.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.--.-- + + // ----------------------State code parsing + item = section->GetItemLineL( KStateCode ); + CleanupStack::PushL( item ); + + // Parsing integer + ret_parsing = item->GetInt( KStateCode, iRebootParams->iStateCode ); + if( ret_parsing == KErrNone || ret_parsing == KErrNotFound ) + { + __TRACE( KVerbose, ( _L("ReadRebootParams(): StateCode: %d" ), + iRebootParams->iStateCode ) ); + } + else + { + __TRACE( KError, + ( _L("ReadRebootParams(): StateCode parsing fails with error: %d " ), + ret_parsing ) ); + User::Leave( ret_parsing ); + } + CleanupStack::PopAndDestroy( item ); + + // ----------------------State name parsing + ret_parsing = section->GetLine( KStateName, tmp, ENoTag ); + if( ret_parsing != KErrNone ) + { + __TRACE( KError, + ( _L("ReadRebootParams(): State name parsing fails with error: %d " ), + ret_parsing ) ); + User::Leave( ret_parsing ); + } + + iRebootParams->SetTestCaseStateL( tmp ); + + __TRACE( KVerbose, ( _L("ReadRebootParams() ends" ) ) ); + + CleanupStack::PopAndDestroy( section ); + CleanupStack::PopAndDestroy( parser ); + + // Delete file + RFs rf; + TInt retVal = rf.Connect(); + if( retVal != KErrNone ) + { + User::Leave( retVal ); + } + + TFileName file( *iRebootPath ); + file.Append( *iRebootFilename ); + rf.Delete( file ); + rf.Close(); + + return KErrNone; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: PauseAllTestCases + + Description: Pause all test case(s) which are/is running. + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Draft + +------------------------------------------------------------------------------- +*/ +void CTestEngine::PauseAllTestCases() + { + __TRACE( KVerbose, ( _L( "CTestEngine::PauseAllTestCases()" ) ) ); + + TInt count( 0 ); + count = iTestCaseArray.Count(); + + for( TInt a = 0; a < count; a++ ) + { + // Pause test case + iTestCaseArray[a]->Pause(); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: FlushAtsLogger + + Description: Flush ATS logger's + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Draft + +------------------------------------------------------------------------------- +*/ +void CTestEngine::FlushAtsLogger() + { + __TRACE( KVerbose, ( _L( "CTestEngine::FlushAtsLogger()" ) ) ); + + TInt count( 0 ); + count = iModules.Count(); + + for( TInt a = 0; a < count; a++ ) + { + // Pause test case + iModules[a]->AtsLogger().SaveForRebootL(); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: GetDeviceResetDllName + + Description: Get device reset module's DLL name. + + Parameters: None + + Return Values: TPtrC + + Errors/Exceptions: None + + Status: Draft + +------------------------------------------------------------------------------- +*/ +TPtrC CTestEngine::GetDeviceResetDllName() + { + __TRACE( KVerbose, ( _L( "CTestEngine::GetDeviceResetDllName()" ) ) ); + + return iDeviceResetDllName->Des(); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: EnableStifMeasurement + + Description: Set measurements related information, enable measurement. + + Parameters: const TName& aInfoType: in: Enabled measurement type + + Return Values: TInt: Symbian error code + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::EnableStifMeasurement( const TDesC& aInfoType ) + { + __TRACE( KInit, ( _L( "Measurement [%S] enabled" ), &aInfoType ) ); + + if( aInfoType == KStifMeasurement01 ) + { + iDisableMeasurement &= ~EMeasurement01; + } + else if( aInfoType == KStifMeasurement02 ) + { + iDisableMeasurement &= ~EMeasurement02; + } + else if( aInfoType == KStifMeasurement03 ) + { + iDisableMeasurement &= ~EMeasurement03; + } + else if( aInfoType == KStifMeasurement04 ) + { + iDisableMeasurement &= ~EMeasurement04; + } + else if( aInfoType == KStifMeasurement05 ) + { + iDisableMeasurement &= ~EMeasurement05; + } + else if( aInfoType == KStifMeasurementBappea ) + { + iDisableMeasurement &= ~EBappea; + } + else if( aInfoType == KStifMeasurementDisableAll ) + { + __TRACE( KInit, ( _L( "All measurements are disabled" ) ) ); + iDisableMeasurement &= EDisableAll; // Does change anything !!! + } + else if( aInfoType == KStifMeasurementEnableAll ) + { + __TRACE( KInit, ( _L( "All measurements types are enabled" ) ) ); + iDisableMeasurement &= EEnableAll; + } + else + { + __TRACE( KInit, ( _L( "Measurement [%S] not recognized" ), &aInfoType ) ); + return KErrArgument; + } + + return KErrNone; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: DisableStifMeasurement + + Description: Set measurements related information, disable measurement. + + Parameters: const TName& aInfoType: in: Disabled measurement type + + Return Values: TInt: Symbian error code + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::DisableStifMeasurement( const TDesC& aInfoType ) + { + __TRACE( KInit, ( _L( "Measurement [%S] disabled" ), &aInfoType ) ); + + if( aInfoType == KStifMeasurement01 ) + { + iDisableMeasurement |= EMeasurement01; + } + else if( aInfoType == KStifMeasurement02 ) + { + iDisableMeasurement |= EMeasurement02; + } + else if( aInfoType == KStifMeasurement03 ) + { + iDisableMeasurement |= EMeasurement03; + } + else if( aInfoType == KStifMeasurement04 ) + { + iDisableMeasurement |= EMeasurement04; + } + else if( aInfoType == KStifMeasurement05 ) + { + iDisableMeasurement |= EMeasurement05; + } + else if( aInfoType == KStifMeasurementBappea ) + { + iDisableMeasurement |= EBappea; + } + else if( aInfoType == KStifMeasurementDisableAll ) + { + __TRACE( KInit, ( _L( "All measurements are disabled" ) ) ); + iDisableMeasurement |= EDisableAll; + } + else if( aInfoType == KStifMeasurementEnableAll ) + { + __TRACE( KInit, ( _L( "All measurements types are enabled" ) ) ); + iDisableMeasurement |= EEnableAll; // Does change anything !!! + } + // This option can be defined in TestFramework.ini file + else if( aInfoType == KStifMeasurementDisableNone ) + { + __TRACE( KInit, ( _L( "All measurements types are enabled" ) ) ); + iDisableMeasurement = EEnableAll; // Sets to 0 + } + else + { + __TRACE( KInit, ( _L( "Measurement [%S] not recognized" ), &aInfoType ) ); + return KErrArgument; + } + + return KErrNone; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: StifMeasurement + + Description: Get measurements related information. Returns is measurement + disable. + + Parameters: None + + Return Values: TInt: Indication what measurement types is/are disabled. + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::StifMeasurement() + { + return iDisableMeasurement; + + } +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: TestModuleCrash + + Description: This method is called only when test module crashed + with KErrServerTerminated (-15). + Clones new TestModuleController: + - Find crashed testmodulecontroller + - Creates new copy of that testmodulecontroller + - Replaces old crashed testmodulecontroller with this new one + + Parameters: CTestModuleController* aTestModuleController: in: TestModuleController + Return Values: None + + Errors/Exceptions: Leaves if error happens when adding clone to the list + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::TestModuleCrash(CTestModuleController* aTestModuleController) + { + TName crashModuleName = aTestModuleController->ModuleName(KNullDesC); + __TRACE(KInit, (_L("Handling crashed test module [%S]"), &crashModuleName)); + TBool isTestScripter(EFalse); + + // Find crashed test module controller + CTestScripterController* testScripterController = aTestModuleController->iTestScripterController; + if(testScripterController) + { + isTestScripter = ETrue; + } + + // If UITestingSupport or SeparateProcesses is enabled, there is no need + // to create clone of Test Module Controller, because it will be created + // automatically when needed. + if(iUITestingSupport && crashModuleName.Find(KTestScripterName) == 0 + || iSeparateProcesses + || (crashModuleName.Find(KPythonScripter) == 0) + ) + { + __TRACE(KInit, (_L("Handling crashed test module with enabled UITestingSupport or SeparateProcesses is not needed"))); + aTestModuleController->iTestModuleCrashDetected = ETrue; + return; + } + + // Clone crashed module + TBool afterReset = EFalse; + if(iRebootParams && iRebootParams->iTestModule == crashModuleName) + { + afterReset = ETrue; + } + + CTestModuleController* clone; + clone = aTestModuleController->CloneL(aTestModuleController, afterReset, testScripterController); + + // Replaces crashed testmodulecontroller with this new one + // Note: Old Testmodulecontroller is deleted in CTestModuleController::CaseFinished + // that is called from CTestCase::~CTestCase() + + TInt index = KErrNotFound; + if(isTestScripter) + { + index = testScripterController->iTestScripter.Find(aTestModuleController); + __TRACE(KInit, (_L("Crashed module index [%d]"), index)); + if(index != KErrNotFound) + { + testScripterController->iTestScripter.Remove(index); + } + testScripterController->iTestScripter.Append(clone); + } + else + { + index = iModules.Find(aTestModuleController); + __TRACE(KInit, (_L("Crashed module index [%d]"), index)); + if(index != KErrNotFound) + { + iModules.Remove(index); + } + iModules.Append(clone); + } + __TRACE(KInit, (_L("End of handling crashed test module"))); + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: ExecuteCommandL + + Description: Executes command received from test case. + The method was created to allow test case to kill itself. + + Parameters: aTestCaseHandle: handler to test case + Return Values: None + + Errors/Exceptions: Leaves if error happens when adding clone to the list + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestEngine::ExecuteCommandL(TCommand aCommand, TDesC8& aParamsPckg) + { + TInt testCaseHandle = 0; + // Get params + switch(aCommand) + { + case EStopExecution: + { + //Unpack received parameters + TStopExecutionCommandParams par; + TStopExecutionCommandParamsPckg parPack(par); + parPack.Copy(aParamsPckg); + + __TRACE(KInit, (_L("CTestEngine::ExecuteCommandL received command [%d] type [%d] code [%d] test handle [%d]"), TInt(aCommand), TInt(par.iType), TInt(par.iCode), par.iTestCaseHandle)); + + //Get test case handle + testCaseHandle = par.iTestCaseHandle; + + break; + } + case ESendTestModuleVersion: + { + TSendTestModuleVesionCommandParams par; + TSendTestModuleVesionCommandParamsPckg parPack(par); + parPack.Copy(aParamsPckg); + + TTestModuleVersionInfo testModuleVersionInfo; + testModuleVersionInfo.iMajor = par.iMajor; + testModuleVersionInfo.iMinor = par.iMinor; + testModuleVersionInfo.iBuild = par.iBuild; + testModuleVersionInfo.iTestModuleName = par.iTestModuleName; + if( RetrieveTestReport() ) + { + iTestReport->AddTestModuleVersion(testModuleVersionInfo); + } + + return; + } + default: + __TRACE(KError, (_L("CTestEngine::ExecuteCommandL Unknown command [%d]"), TInt(aCommand))); + return; + } + + // Get test case from container + CTestCase* testCase = (CTestCase*)iTestCases->At(testCaseHandle); + + // Log some info if invalid handle + if(testCase == NULL) + { + __TRACE(KInit, ( _L( "CTestEngine::ExecuteCommandL - invalid handle. Unable to get test case to execute command [%d]"), TInt(aCommand))); + return; + } + + testCase->ExecuteCommandL(aCommand, aParamsPckg); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: GetIndexForNewTestModuleController + + Description: Returns new index for test module controller. + This number is appended to module controller name. + This method is used when option to run every test case in + separate process is set to on. + + Parameters: aTestCaseHandle: handler to test case + Return Values: None + + Errors/Exceptions: Leaves if error happens when adding clone to the list + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::GetIndexForNewTestModuleController(void) + { + return iIndexTestModuleControllers++; + } + +/* +------------------------------------------------------------------------------- + + Class: CTestEngine + + Method: AddTestCaseToTestReport + + Description: Get parameters from message and add test case to test report. + + Parameters: aMessage: message + Return Values: error id + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TInt CTestEngine::AddTestCaseToTestReport(const RMessage2& aMessage) + { + if( RetrieveTestReport() ) + { + // Read test data + TTestInfo testInfo; + TTestInfoPckg testInfoPckg(testInfo); + + TFullTestResult fullTestResult; + TFullTestResultPckg fullTestResultPckg(fullTestResult); + + TRAPD(err, aMessage.ReadL(0, testInfoPckg)); + if(err) + { + __TRACE(KError, (_L("Leave when reading TTestInfo in AddTestCaseToTestReport [%d]"), err)); + return err; + } + + TRAP(err, aMessage.ReadL(1, fullTestResultPckg)); + if(err) + { + __TRACE(KError, (_L("Leave when reading TFullTestResult in AddTestCaseToTestReport [%d]"), err)); + return err; + } + + TRAP( err, iTestReport->AddTestCaseResultL(testInfo, fullTestResult, aMessage.Int2())); + if( err ) + { + __TRACE(KError, (_L("Leave from test report in AddTestCaseToTestReport [%d]"), err)); + return err; + } + } + else + { + __TRACE(KError, (_L("TestReport not initialized in AddTestCaseToTestReport"))); + return KErrNotReady; + } + + return KErrNone; + } + +TBool CTestEngine::UITesting() + { + return iUITestingSupport; + } + +TBool CTestEngine::SeparateProcesses() + { + return iSeparateProcesses; + } + +CTestReport* CTestEngine::RetrieveTestReport() + { + if(iTestReport==NULL) + { + // Create Test Reporter if allowed + if ( iTestReportSettings->iCreateTestReport ) + { + TRAPD(err, iTestReport = + CTestReport::NewL( *iTestReportSettings, ( CTestReport::TTestReportMode ) iReportMode )); + if(err!=KErrNone) + { + iTestReport = NULL; + __TRACE( KInit,( CStifLogger::ERed, _L( "Test report creation failed with error: %d, test report not created." ), err ) ); + __TRACE( KInit,( CStifLogger::ERed, _L( "Check your testreport settings from testframework.ini file (e.g. TestReportFilePath)." ) ) ); + __TRACE( KInit,( CStifLogger::ERed, _L( "Also check if testreport is not used by other testengine session. If it is change testreport " ) ) ); + __TRACE( KInit,( CStifLogger::ERed, _L( "name in TestFramework.ini." ) ) ); + } + } + } + return iTestReport; + } + +/* +------------------------------------------------------------------------------- + + DESCRIPTION + + This module contains implementation of CTestEngineSubSession class member functions. + +------------------------------------------------------------------------------- +*/ + +// ================= MEMBER FUNCTIONS ========================================= + +/* +------------------------------------------------------------------------------- + + DESCRIPTION + + This module contains implementation of CTestCase class member functions. + +------------------------------------------------------------------------------- +*/ + +// ================= MEMBER FUNCTIONS ========================================= + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: CTestCase + + Description: Default constructor + + C++ default constructor can NOT contain any code, that + might leave. + + Parameters: CTestEngine* aEngine: in: Pointer to Test Engine + CTestModuleController* aModuleController: in: Pointer to + Module Controller + TTestInfo& aTestInfo: in: Test info for this test case + CTestModuleController* aRealModuleController: in: Pointer to + module controller used inside in scripter controller + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +CTestCase::CTestCase( CTestEngine* aEngine, + CTestModuleController* aModuleController, + TTestInfo& aTestInfo, + CTestModuleController* aRealModuleController ) : + iTestEngine( aEngine ), + iTestModule( aModuleController ), + iRealModuleController (aRealModuleController) + { + + // This method must be called to find out how + // many testcases are currently ongoing by increasing iTestCaseCounter. + // This is a part of the implementation for + // supporting test module crashing with -15 + iTestModule->CaseCreated(); + + // Store handle to RTestServer + //If test scripter is used (it uses internally module controllers) + //then use it (real module controller). + if(iRealModuleController) + { + iTestServer = iRealModuleController->Server(aTestInfo); + } + else + { + iTestServer = iTestModule->Server( aTestInfo ); + } + + //If real test module controller is provided, increase test case count + if(iRealModuleController) + { + iRealModuleController->CaseCreated(); + } + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: ConstructL + + Description: Symbian OS second phase constructor + + Symbian OS default constructor can leave. + + Parameters: CTestReport* aTestReport: in: Pointer to Test Report + TTestInfo& aTestInfo: in: Test Info for this test case + + Return Values: None + + Errors/Exceptions: Leaves if RTestExecution::Open returns error + Leaves if some of called leaving methods leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::ConstructL( CTestReport* aTestReport, + TTestInfo& aTestInfo ) + { + __TRACE( KVerbose, ( _L( "CTestCase::ConstructL" ) ) ); + + // Open handle to RTestExecution + User::LeaveIfError( iTestExecution.Open( iTestServer, + aTestInfo.iTestCaseInfo.iCaseNumber, aTestInfo.iConfig ) ); + + // Make new test case runner + iTestCaseController = CTestCaseController::NewL( iTestEngine, + aTestReport, iTestModule->AtsLogger(), iTestExecution, aTestInfo ); + + // Make new test case printer + iTestCasePrint = CTestProgressNotifier::NewL( iTestEngine, + iTestExecution ); + + iTestCaseEvent = CTestEventNotifier::NewL( iTestEngine, iTestExecution ); + + iTestCaseRemoteCmd = CTestRemoteCmdNotifier::NewL( iTestEngine, + iTestExecution, + iTestCaseController, + iTestModule->AtsLogger() ); + + iTestCaseCommand = CTestCommandNotifier::NewL(iTestEngine, iTestExecution); + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: NewL + + Description: Two-phased constructor. + + Parameters: CTestEngine* aEngine: in: Pointer to Test Engine + CTestModuleController* aModuleController: in: Pointer to + Module Controller + CTestReport* aTestReport: in: Pointer to Test Report + TTestInfo& aTestInfo: in: Test Info for this test case + + Return Values: CTestCase* : pointer to created CTestCase object + + Errors/Exceptions: Leaves if ConstructL leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CTestCase* CTestCase::NewL( CTestEngine* aEngine, + CTestModuleController* aModuleController, + CTestReport* aTestReport, + TTestInfo& aTestInfo, + CTestModuleController* aRealModuleController ) + { + CTestCase* self = new ( ELeave ) CTestCase( aEngine, aModuleController, aTestInfo, aRealModuleController ); + CleanupClosePushL( *self ); + self->ConstructL( aTestReport, aTestInfo ); + CleanupStack::Pop(); + return self; + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: ~CTestCase + + Description: Destructor + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CTestCase::~CTestCase() + { + CloseTestCase(); + + // This added method call is a part of the implementation for + // supporting test module crashing with -15. + // It checks that can old Testmodulecontroller be deletd or not + if( iTestModule != NULL ) + { + iTestModule->CaseFinished(); + } + + //If real test module controller is provided, decrease test case count + if( iRealModuleController != NULL ) + { + iRealModuleController->CaseFinished(); + } + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: CloseTestCase + + Description: Close session + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::CloseTestCase() + { + __TRACE( KVerbose, ( _L( "CTestCase::CloseTestCase" ) ) ); + + // Free allocated resources + delete iTestCaseController; + iTestCaseController = NULL; + delete iTestCasePrint; + iTestCasePrint = NULL; + delete iTestCaseRemoteCmd; + iTestCaseRemoteCmd = NULL; + + delete iTestCaseEvent; + iTestCaseEvent = NULL; + + delete iTestCaseCommand; + iTestCaseCommand = NULL; + + iTestExecution.Close(); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: RunTestCaseL + + Description: Enumerates test cases + + Parameters: const RMessage& aMessage: in: Server Message + + Return Values: None + + Errors/Exceptions: Leaves if some of called leaving methods leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::RunTestCaseL( const RMessage2& aMessage ) + { + __TRACE( KVerbose, ( _L( "CTestCase::RunTestCaseL" ) ) ); + // Start active objects for running test case + iTestCaseController->StartL( aMessage ); + iTestCaseEvent->Start(); + iTestCaseCommand->Start(); + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: Pause + + Description: Suspend the test case execution + + Parameters: None + + Return Values: TInt: Return value from RTestExecution::Pause + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TInt CTestCase::Pause() + { + __TRACE( KVerbose, ( _L( "CTestCase::Pause" ) ) ); + + return iTestExecution.Pause(); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: Resume + + Description: Resume the suspended test case execution + + Parameters: None + + Return Values: TInt: Return value from RTestExecution::Resume + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TInt CTestCase::Resume() + { + __TRACE( KVerbose, ( _L( "CTestCase::Resume" ) ) ); + + return iTestExecution.Resume(); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: NotifyProgressL + + Description: Notifies progresses from Test Module + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Leaves if called StartL method leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::NotifyProgressL( const RMessage2& aMessage ) + { + __TRACE( KVerbose, ( _L( "CTestCase::NotifyProgressL" ) ) ); + iTestCasePrint->StartL( aMessage ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: NotifyRemoteTypeL + + Description: Notifies remote commands from Test Module + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Leaves if called StartL method leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::NotifyRemoteTypeL( const RMessage2& aMessage ) + { + + __TRACE( KVerbose, ( _L( "CTestCase::NotifyRemoteTypeL" ) ) ); + iTestCaseRemoteCmd->EnableReceive( aMessage ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: NotifyRemoteMsgL + + Description: Notifies remote commands from Test Module + + Parameters: const RMessage& aMessage: in: Server message + + Return Values: None + + Errors/Exceptions: Leaves if called StartL method leaves + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::NotifyRemoteMsgL( const RMessage2& aMessage ) + { + + __TRACE( KVerbose, ( _L( "CTestCase::NotifyRemoteMsgL" ) ) ); + switch( aMessage.Int1() ) + { + case EStifCmdSend: + { + iTestCaseRemoteCmd->GetReceivedMsg( aMessage ); + } + break; + case EStifCmdReceive: + { + TInt len = aMessage.Int2(); + if( len <= 0 ) + { + User::Leave( KErrGeneral ); + } + HBufC8* buf = HBufC8::NewLC( len ); + + TPtr8 tmp = buf->Des(); + aMessage.ReadL( 0, tmp ); + + TInt ret = iTestExecution.ReadRemoteCmdInfo( tmp, EStifCmdReceive ); + + CleanupStack::PopAndDestroy( buf ); + + aMessage.Complete( ret ); + } + break; + case EStifCmdRebootProceed: + { + TInt value = 0; + TPckg tmp( value ); + aMessage.ReadL( 0, tmp ); + + TInt ret = iTestExecution.ReadRemoteCmdInfo( tmp, + EStifCmdRebootProceed, + value ); + aMessage.Complete( ret ); + } + break; + default: + { + User::Leave( KErrGeneral ); + } + } + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: CancelAsyncRequest + + Description: Asynchronous requests are canceled by this function. + + Parameters: const RMessage aMessage + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::CancelAsyncRequest( const RMessage2& aMessage ) + { + switch ( aMessage.Int0() ) + { + case ETestCaseRunTestCase: + { + iTestCaseController->Cancel(); + iTestCaseEvent->Cancel(); + break; + } + case ETestCaseNotifyProgress: + { + iTestCasePrint->Cancel(); + break; + } + case ETestCaseNotifyRemoteType: + { + iTestCaseRemoteCmd->CancelReq(); + break; + } + case ETestCaseNotifyCommand: + { + iTestCaseCommand->Cancel(); + break; + } + default: + iTestEngine->PanicClient( EBadRequest, aMessage ); + break; + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: ModuleName + + Description: Return the name of Test Module. + + Parameters: None + + Return Values: const TFileName& : Test Module owning this test case + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +const TDesC& CTestCase::ModuleName() + { + return iTestModule->ModuleName( KNullDesC ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: CtlEvent + + Description: Control events + + Parameters: const TEventIf& aEvent: in: Event + TRequestStatus& aStatus: in: Request status + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::CtlEvent( const TEventIf& aEvent, TRequestStatus& aStatus ) + { + __ASSERT_ALWAYS( iTestCaseEvent, User::Panic( _L( "TestEngine event panic" ), KErrArgument ) ); + + iTestCaseEvent->CtlEvent( aEvent, aStatus ); + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: CheckCtlEvent + + Description: Check if CtlEvent should be called + + Parameters: const TEventIf& aEvent: in: Event + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +TBool CTestCase::CheckCtlEvent( const TEventIf& aEvent ) + { + return iTestCaseEvent->CheckCtlEvent( aEvent ); + } + + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: Logger + + Description: Return the pointer to Logger. + + Parameters: None + + Return Values: CStifLogger*: Pointer to StifLogger + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CStifLogger* CTestCase::Logger() + { + return iTestEngine->Logger(); + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: ExecuteCommaandL + + Description: Executes command received from test case. + + Parameters: aStifCommand command to be executed + aParam1 parameter to command + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::ExecuteCommandL(TCommand aCommand, TDesC8& aParamsPckg) + { + switch(aCommand) + { + case EStopExecution: + { + //Unpack received parameters + TStopExecutionCommandParams par; + TStopExecutionCommandParamsPckg parPack(par); + parPack.Copy(aParamsPckg); + + __TRACE(KVerbose, (_L("CTestCase::ExecuteCommandL command [%d] type [%d] code [%d]"), TInt(aCommand), TInt(par.iType), par.iCode)); + + iTestCaseController->Suicide(par.iType, par.iCode); + break; + } + default: + __TRACE(KVerbose, (_L("CTestCase::ExecuteCommandL unknown command [%d]"), TInt(aCommand))); + return; + } + + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: GetModuleControllers + + Description: Return module controller and real module controller + + Parameters: aRealModuleController: out: real module controller + + Return Values: module controller + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +CTestModuleController* CTestCase::GetModuleControllers(CTestModuleController** aRealModuleController) + { + *aRealModuleController = iRealModuleController; + return iTestModule; + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: ResetModuleController + + Description: Set new module controller for test case (only in case when + original controller crashed) + + Parameters: aModuleController: in: new module controller + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::ResetModuleController(CTestModuleController* aModuleController) + { + iTestModule = aModuleController; + } + +/* +------------------------------------------------------------------------------- + + Class: CTestCase + + Method: ResetRealModuleController + + Description: Set new real module controller for test case (only in case + when original controller crashed). + + Parameters: aRealModuleController: in: new real module controller + + Return Values: None + + Errors/Exceptions: None + + Status: Approved + +------------------------------------------------------------------------------- +*/ +void CTestCase::ResetRealModuleController(CTestModuleController* aRealModuleController) + { + iRealModuleController = aRealModuleController; + } + +/* +------------------------------------------------------------------------------- + + DESCRIPTION + + Default constructor + +------------------------------------------------------------------------------- +*/ +CTestReportSettings::CTestReportSettings() + { + iCreateTestReport = ETrue; + iPath = NULL; + iName = NULL; + iFormat = CStifLogger::ETxt; + iOutput = CStifLogger::EFile; + iOverwrite = ETrue; + iXML = EFalse; + } + +/* +------------------------------------------------------------------------------- + + DESCRIPTION + + Two-phased constructor. + +------------------------------------------------------------------------------- +*/ +CTestReportSettings* CTestReportSettings::NewL() + { + CTestReportSettings* self = new ( ELeave ) CTestReportSettings(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +/* +------------------------------------------------------------------------------- + + DESCRIPTION + + Symbian OS second phase constructor + +------------------------------------------------------------------------------- +*/ +void CTestReportSettings::ConstructL() + { + + } +/* +------------------------------------------------------------------------------- + + DESCRIPTION + + Destructor + +------------------------------------------------------------------------------- +*/ +CTestReportSettings::~CTestReportSettings() + { + delete iPath; + iPath = NULL; + delete iName; + iName = NULL; + } + + +/* +------------------------------------------------------------------------------- + + DESCRIPTION + + This module contains implementation of CRebootParams class member functions. + +------------------------------------------------------------------------------- +*/ + +// ================= MEMBER FUNCTIONS ========================================= + +/* +------------------------------------------------------------------------------- + + Class: CRebootParams + + Method: CRebootParams + + Description: Default constructor + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Draft + +------------------------------------------------------------------------------- +*/ +CRebootParams::CRebootParams() + { + } + +/* +------------------------------------------------------------------------------- + + Class: CRebootParams + + Method: ConstructL + + Description: Symbian OS second phase constructor + + + Parameters: None + + Return Values: None + + Errors/Exceptions: Leaves if RTestExecution::Open returns error + Leaves if some of called leaving methods leaves + + Status: Draft + +------------------------------------------------------------------------------- +*/ +void CRebootParams::ConstructL() + { + } + +/* +------------------------------------------------------------------------------- + + Class: CRebootParams + + Method: NewL + + Description: Two-phased constructor. + + Parameters: none + + Return Values: CRebootParams* : pointer to created CRebootParams object + + Errors/Exceptions: Leaves if ConstructL leaves + + Status: Draft + +------------------------------------------------------------------------------- +*/ +CRebootParams* CRebootParams::NewL() + { + + CRebootParams* self = new ( ELeave ) CRebootParams(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + return self; + + } + +/* +------------------------------------------------------------------------------- + + Class: CRebootParams + + Method: ~CRebootParams + + Description: Destructor + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Draft + +------------------------------------------------------------------------------- +*/ +CRebootParams::~CRebootParams() + { + + delete iTestModuleBuf; + iTestModuleBuf = 0; + delete iTestCaseFileBuf; + iTestCaseFileBuf = 0; + delete iTestCaseTitleBuf; + iTestCaseTitleBuf = 0; + delete iStateNameBuf; + iStateNameBuf = 0; + + } + + +/* +------------------------------------------------------------------------------- + + Class: CRebootParams + + Method: SetTestModuleNameL + + Description: Setter + + Parameters: const TDesC& aName: in: name to set + + Return Values: None + + Errors/Exceptions: Leaves if memory allocation fails + + Status: Draft + +------------------------------------------------------------------------------- +*/ +void CRebootParams::SetTestModuleNameL( const TDesC& aName ) + { + + delete iTestModuleBuf; + iTestModuleBuf = 0; + iTestModuleBuf = aName.AllocLC(); + iTestModule.Set( iTestModuleBuf->Des() ); + CleanupStack::Pop( iTestModuleBuf ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CRebootParams + + Method: SetTestModuleNameL + + Description: Setter + + Parameters: const TDesC& aName: in: name to set + + Return Values: None + + Errors/Exceptions: Leaves if memory allocation fails + + Status: Draft + +------------------------------------------------------------------------------- +*/ +void CRebootParams::SetTestCaseFileNameL( const TDesC& aName ) + { + + delete iTestCaseFileBuf; + iTestCaseFileBuf = 0; + iTestCaseFileBuf = aName.AllocLC(); + iTestCaseFile.Set( iTestCaseFileBuf->Des() ); + CleanupStack::Pop( iTestCaseFileBuf ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CRebootParams + + Method: SetTestModuleNameL + + Description: Setter + + Parameters: const TDesC& aName: in: name to set + + Return Values: None + + Errors/Exceptions: Leaves if memory allocation fails + + Status: Draft + +------------------------------------------------------------------------------- +*/ +void CRebootParams::SetTestCaseTitleL( const TDesC& aName ) + { + + delete iTestCaseTitleBuf; + iTestCaseTitleBuf = 0; + iTestCaseTitleBuf = aName.AllocLC(); + iTestCaseTitle.Set( iTestCaseTitleBuf->Des() ); + CleanupStack::Pop( iTestCaseTitleBuf ); + + } + +/* +------------------------------------------------------------------------------- + + Class: CRebootParams + + Method: SetTestModuleNameL + + Description: Setter + + Parameters: const TDesC& aName: in: name to set + + Return Values: None + + Errors/Exceptions: Leaves if memory allocation fails + + Status: Draft + +------------------------------------------------------------------------------- +*/ +void CRebootParams::SetTestCaseStateL( const TDesC& aName ) + { + + delete iStateNameBuf; + iStateNameBuf = 0; + iStateNameBuf = aName.AllocLC(); + iStateName.Set( iStateNameBuf->Des() ); + CleanupStack::Pop( iStateNameBuf ); + + } + + +/* +------------------------------------------------------------------------------- + + DESCRIPTION + + This module contains implementation of TEventMsg class member functions. + +------------------------------------------------------------------------------- +*/ + +// ================= MEMBER FUNCTIONS ========================================= + +/* +------------------------------------------------------------------------------- + + Class: TEventMsg + + Method: TEventMsg + + Description: Default constructor + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +TEventMsg::TEventMsg(): + TEventIf(), + iWaitPending(EFalse), + iStateEventPending(EFalse), + iStatus( NULL ) + { + } + +/* +------------------------------------------------------------------------------- + + Class: TEventMsg + + Method: ~TEventMsg + + Description: Destructor + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +TEventMsg::~TEventMsg() + { + if( iWaitPending ) + { + iWaitMsg.Complete( KErrCancel ); + iWaitPending = EFalse; + } + + if( iStatus ) + { + User::RequestComplete( iStatus, KErrCancel ); + } + + } + +/* +------------------------------------------------------------------------------- + + Class: TEventMsg + + Method: Set + + Description: Set event. + + Parameters: TEventType aEventType: in: Event type + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void TEventMsg::Set( TEventType aEventType ) + { + iEventType = aEventType; + if( aEventType == EState ) + { + iStateEventPending = ETrue; + } + if( iWaitPending ) + { + TEventIf event; + event.Copy( *this ); + TEventIfPckg eventIfPckg( event ); + iWaitMsg.WriteL( 0, eventIfPckg ); + + iWaitMsg.Complete( KErrNone ); + iWaitPending = EFalse; + } + } + +/* +------------------------------------------------------------------------------- + + Class: TEventMsg + + Method: Wait + + Description: Wait event. + + Parameters: const RMessage& aMessage: in: Message + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void TEventMsg::Wait( const RMessage2& aMessage ) + { + if( iStateEventPending ) + { + TEventIf event; + event.Copy( *this ); + TEventIfPckg eventIfPckg( event ); + aMessage.WriteL( 0, eventIfPckg ); + aMessage.Complete( KErrNone ); + } + else + { + iWaitMsg = aMessage; + iWaitPending = ETrue; + } + } + +/* +------------------------------------------------------------------------------- + + Class: TEventMsg + + Method: CancelWait + + Description: Cancel pending Wait + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void TEventMsg::CancelWait() + { + if( iWaitPending ) + { + iWaitMsg.Complete( KErrCancel ); + iWaitPending = EFalse; + } + } + +/* +------------------------------------------------------------------------------- + + Class: TEventMsg + + Method: Release + + Description: Release event. Unset released. + + Parameters: None + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void TEventMsg::Release() + { + + if( iStatus ) + { + User::RequestComplete( iStatus, KErrNone ); + } + + } +/* +------------------------------------------------------------------------------- + + Class: TEventMsg + + Method: Unset + + Description: Unset event. Blocks until Release is called. + + Parameters: TRequestStatus& aStatus: in: Status + + Return Values: None + + Errors/Exceptions: None + + Status: Proposal + +------------------------------------------------------------------------------- +*/ +void TEventMsg::Unset( TRequestStatus& aStatus ) + { + + iStatus = &aStatus; + + } + + +// End of File