/*
* 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 the implementation of
* CTestCombiner class member functions.
*
*/
// INCLUDE FILES
#include <StifTestEventInterface.h>
#include <StifLogger.h>
#include "TestCombiner.h"
#include "TestKeywords.h"
#include "TestCase.h"
#include "TestCombinerEvent.h"
#include "Logging.h"
//--PYTHON-- begin
#include "StifPython.h"
#include "StifPythonFunComb.h"
//--PYTHON-- end
#include "SettingServerClient.h"
// EXTERNAL DATA STRUCTURES
// None
// EXTERNAL FUNCTION PROTOTYPES
// None
// CONSTANTS
_LIT( KTestRunner, "CTestRunner" );
_LIT( KRemoteTimer, "CRemoteTimer" );
_LIT( KRemoteReceiver, "CRemoteReceiver" );
// MACROS
#ifdef LOGGER
#undef LOGGER
#endif
#define LOGGER iLog
// LOCAL CONSTANTS AND MACROS
_LIT(KTitle, "title");
_LIT(KTimeout, "timeout");
_LIT(KPriority, "priority");
//printing macros
_LIT( KExecute, "Execute");
// MODULE DATA STRUCTURES
// None
// LOCAL FUNCTION PROTOTYPES
// None
// FORWARD DECLARATIONS
// None
// ==================== LOCAL FUNCTIONS =======================================
// None
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: CTestCombiner
Description: Default constructor
C++ default constructor can NOT contain any code, that
might leave.
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
CTestCombiner::CTestCombiner():
iSchedulerActive( EFalse ),
iRunningTests( 0 ),
iResult( KErrNone ),
iEventPckg( iEvent ),
iRemoteTimeout( KRemoteProtocolTimeout ),
iCancelIfError( EFalse ),
iFailedTestCase( 0 ),
iLoopIsUsed( EFalse )
{
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: ConstructL
Description: Symbian OS second phase constructor
Symbian OS default constructor can leave.
Parameters: None
Return Values: None
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestCombiner::ConstructL()
{
// TRAPed to avoid crashing if logfile creation fails,
// so we can run test without logging to file
TRAPD( err, iStdLog = CStifLogger::NewL( KTestCombinerLogDir,
KTestCombinerLogFile );
);
if( err != KErrNone )
{
iStdLog = NULL;
__RDEBUG( (_L("Creating logfile failed") ) );
}
iLog = iStdLog;
//Read logger settings to check whether test case name is to be
//appended to log file name.
RSettingServer settingServer;
TInt ret = settingServer.Connect();
if(ret != KErrNone)
{
User::Leave(ret);
}
// Struct to StifLogger settigs.
TLoggerSettings loggerSettings;
// Parse StifLogger defaults from STIF initialization file.
ret = settingServer.GetLoggerSettings(loggerSettings);
if(ret != KErrNone)
{
User::Leave(ret);
}
// Get engine settings
TEngineSettings engineSettings;
ret = settingServer.GetEngineSettings(engineSettings);
if(ret != KErrNone)
{
__TRACE(KError, (_L("Could not retrieve engine settings from SettingServer [%d]"), ret));
iUITestingSupport = EFalse;
iSeparateProcesses = EFalse;
}
else
{
iUITestingSupport = engineSettings.iUITestingSupport;
iSeparateProcesses = engineSettings.iSeparateProcesses;
__TRACE(KMessage, (_L("Engine settings retrieved from SettingServer. UITestingSupport [%d] SeparateProcesses [%d]"), iUITestingSupport, iSeparateProcesses));
}
// Close Setting server session
settingServer.Close();
iAddTestCaseTitleToLogName = loggerSettings.iAddTestCaseTitle;
iIndexTestModuleControllers = 1;
__TRACE( KPrint, ( _L("New TestCombiner") ) );
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: NewL
Description: Two-phased constructor.
Parameters: None
Return Values: CTestCombiner*: new object
Errors/Exceptions: Leaves if new or ConstructL leaves.
Status: Approved
-------------------------------------------------------------------------------
*/
CTestCombiner* CTestCombiner::NewL()
{
CTestCombiner* self = new (ELeave) CTestCombiner();
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop();
return self;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: ~CTestCombiner
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
CTestCombiner::~CTestCombiner()
{
iLoopAllocationArray.Reset();
iLoopAllocationArray.Close();
iLoopIsUsed = EFalse;
iTestCases.ResetAndDestroy();
iTestModules.ResetAndDestroy();
iEventArray.ResetAndDestroy();
iSlaveArray.ResetAndDestroy();
iSendReceive.ResetAndDestroy();
iTestCases.Close();
iTestModules.Close();
iEventArray.Close();
iSlaveArray.Close();
iSendReceive.Close();
// Stop all remaining measurement modules
const TInt count_meas = iTestMeasurementArray.Count();
for( TInt b = 0; b < count_meas; b++ )
{
iTestMeasurementArray[b]->iMeasurement->Stop();
}
iTestMeasurementArray.ResetAndDestroy();
iTestMeasurementArray.Close();
delete iSectionParser;
delete iRemoteReceiver;
delete iTestRunner;
iLog = NULL;
delete iStdLog;
iStdLog = NULL;
delete iTCLog;
iTCLog = NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: InitL
Description: InitL is used to initialize the Test Module.
Parameters: const TFileName& aIniFile: in: Initialization file
TBool aFirstTime: in: First time flag
Return Values: Symbian OS error code
Errors/Exceptions: Leaves if ReadInitializationL leaves
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestCombiner::InitL( TFileName& aIniFile,
TBool /*aFirstTime*/ )
{
__TRACEFUNC();
if( aIniFile.Length() > 0 )
{
// Read initialization from test case file
ReadInitializationL( aIniFile );
}
return KErrNone;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetTestCases
Description: GetTestCases is used to inquired test cases
Parameters: const TFileName& aConfigFile: in: Config file name
RPointerArray<RTestEngine::TTestCaseInfo>& aTestCases: out:
Array of TestCases
Return Values: KErrNone: Success
KErrNotFound: Testcases not found
Errors/Exceptions: Leaves if CStifParser::NewL leaves
Leaves if CStifParser::SectionL leaves
Leaves if CStifParser::NextSectionL leaves
Leaves if memory allocation fails
Status: Approved
-------------------------------------------------------------------------------
*/
TInt CTestCombiner::GetTestCasesL( const TFileName& aConfigFile,
RPointerArray<TTestCaseInfo>& aTestCases )
{
__TRACEFUNC();
if( aConfigFile.Length() == 0 )
{
__TRACE( KError, (_L("No test case script file given") ) );
__RDEBUG( (_L("No test case script file given") ) );
return KErrNotFound;
}
CStifParser* parser = NULL;
TRAPD( err, parser =
CStifParser::NewL( _L(""), aConfigFile, CStifParser::ECStyleComments ) );
if( err != KErrNone )
{
__TRACE( KError, (_L("Test case script file not found") ) );
__RDEBUG( (_L("Test case script file not found") ) );
return KErrNotFound;
}
CleanupStack::PushL( parser );
CStifSectionParser* section;
TPtrC tmp;
TInt index = 0;
TInt ret = KErrNone;
section = parser->SectionL( KTestStartTag, KTestEndTag );
if( section == NULL )
{
ret = KErrNotFound;
}
else
{
while( section )
{
CleanupStack::PushL( section );
if( section->GetLine( KTitle, tmp, ENoTag ) == KErrNone )
{
if( tmp.Length() > KMaxName )
{
tmp.Set( tmp.Left( KMaxName ) );
}
TTestCaseInfo* tc = new ( ELeave ) TTestCaseInfo();
CleanupStack::PushL( tc );
__TRACE( KVerbose, (_L("TestCase: %S"), &tmp));
tc->iTitle.Copy( tmp );
tc->iCaseNumber = ++index;
CStifItemParser* item = section->GetItemLineL( KTimeout );
if( item )
{
TInt timeout; // In milliseconds
ret = item->GetInt( KTimeout, timeout );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Illegal timeout")));
User::Leave( ret );
}
tc->iTimeout = (TInt64)timeout*1000;
__TRACE( KMessage, (_L("Timeout: %i"), tc->iTimeout.Int64() ));
}
item = section->GetItemLineL( KPriority );
if( item )
{
ret = item->GetInt( KPriority, tc->iPriority );
if( ret != KErrNone )
{
TPtrC priority;
ret = item->GetString( KPriority, priority );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Illegal priority")));
User::Leave( ret );
}
switch( TTCKeywords::Parse( priority,
TTCKeywords::Priority ) )
{
case TTCKeywords::EPriHigh:
tc->iPriority = TTestCaseInfo::EPriorityHigh;
break;
case TTCKeywords::EPriNormal:
tc->iPriority = TTestCaseInfo::EPriorityNormal;
break;
case TTCKeywords::EPriLow:
tc->iPriority = TTestCaseInfo::EPriorityLow;
break;
default:
__TRACE( KError, (_L("Illegal priority")));
User::Leave( KErrArgument );
}
}
__TRACE( KMessage, (_L("Priority: %i"), tc->iPriority ));
}
aTestCases.Append(tc);
CleanupStack::Pop( tc );
}
CleanupStack::PopAndDestroy( section );
section = parser->NextSectionL( KTestStartTag, KTestEndTag );
}
}
CleanupStack::PopAndDestroy( parser );
__TRACE( KPrint, ( _L( "Configfile '%S', testcases %d" ),
&aConfigFile, index ));
return ret;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: RunTestCaseL
Description: Run a specified testcase.
RunTestCaseL is used to run an individual test case specified
by aTestCase.
Parameters: const TInt aCaseNumber: in: Testcase number
const TFileName& aConfig: in: Configuration file name
TTestResult& aResult: out; test case result
Return Values: KErrNone: Test case started succesfully.
KErrNotFound: Testcase not found
KErrUnknown: Unknown TestCombiner error
Any other SymbianOS error
Errors/Exceptions: Leaves if GetTestCaseL leaves
Leaves if RunTestL leaves
Leaves if memory allocation fails
Status: Approved
-------------------------------------------------------------------------------
*/
TInt CTestCombiner::RunTestCaseL( const TInt aCaseNumber,
const TFileName& aConfig,
TTestResult& aResult )
{
__TRACEFUNC();
__TRACE( KMessage, (_L("***Testcase started***")));
//Open new log file with test case title in file name
if(iAddTestCaseTitleToLogName)
{
//Close test case log if exists
if(iTCLog)
{
delete iTCLog;
iTCLog = NULL;
}
TFileName logFileName;
TName title;
TestModuleIf().GetTestCaseTitleL(title);
logFileName.Format(KTestCombinerLogFileWithTitle, &title);
iTCLog = CStifLogger::NewL(KTestCombinerLogDir, logFileName);
iLog = iTCLog;
}
/*
* Allow memory leaks, because Defines are leaved untouched
* after test case execution. Real memory leaks are detected with
* UHEAP macros.
*/
TestModuleIf().SetBehavior( CTestModuleIf::ETestLeaksMem );
// Read initialization from test case file
ReadInitializationL( aConfig );
__UHEAP_MARK;
iSectionParser = GetTestCaseL( aCaseNumber, aConfig );
// Check parsing result
if( iSectionParser == NULL )
{
__TRACE( KError, (_L("***Parsing testcase failed***")));
__UHEAP_MARKEND;
return KErrNotFound;
}
CActiveScheduler* activeScheduler =
new ( ELeave ) CActiveScheduler();
CleanupStack::PushL( activeScheduler );
CActiveScheduler::Install( activeScheduler );
// Resetting these variables to normal state @js
iFailedTestCase = 0;
iCancelIfError = EFalse;
iScriptFailed = KErrNone;
iScriptFailedDescription.Copy(KNullDesC);
// Run the given testcase described in iSectionParser section
RunTestL();
CleanupStack::PopAndDestroy( activeScheduler );
delete iSectionParser;
iSectionParser = NULL;
TInt ret = KErrNone;
// Check if test case starting failed
if( iResult != KErrNone )
{
TestModuleIf().Printf( KPrintPriHigh, _L("Result"), _L("Starting FAILED"));
__TRACE( KError, (_L("***Starting testcase FAILED***")));
ret = iResult;
aResult.iResult = -2;
aResult.iResultDes = _L("Testcase script execution failed");
}
else if(iScriptFailed != KErrNone)
{
TestModuleIf().Printf( KPrintPriHigh, _L("Result"), _L("Script execution FAILED"));
__TRACE( KError, (_L("***Sscript execution FAILED***")));
aResult.iResult = iScriptFailed;
if(iScriptFailedDescription != KNullDesC)
{
aResult.iResultDes.Copy(iScriptFailedDescription);
}
else
{
aResult.iResultDes = _L("Testcase script execution failed");
}
}
else
{
__TRACE( KPrint, (_L("***Testcase completed***")));
// Testcombiner succeeded to start all testcases,
// check individual testcase results
TInt count = iTestCases.Count();
TInt i = iFailedTestCase;
// iFailedTestCase is either 0 or the number of failed test case if
// canceliferror was given and a test case has failed
for(; i < count; i++ )
{
// All cases should be completed now
if( iTestCases[i]->State() != CTCTestCase::ETestCaseCompleted )
{
// This is some unknown internal TestCombiner error
// Should not happen
__TRACE( KError, (_L("TestCase (%S) not completed"),
&iTestCases[i]->TestId() ));
ret = KErrUnknown;
break;
}
// Interpret execution result type from returned result
TInt executionResult = TFullTestResult::ECaseExecuted; // Ok
if( iTestCases[i]->iResult.iCaseExecutionResultType >=
TFullTestResult::ECaseLeave )
{
// Some abnormal execution result type
executionResult = iTestCases[i]->iResult.iCaseExecutionResultType;
}
// Check expected execution result type
if( executionResult != iTestCases[i]->ExpectedResultCategory() )
{
// expected and returned result types differ
aResult.iResult = KErrGeneral;
aResult.iResultDes.Copy( _L("Test case completed with ") );
aResult.iResultDes.Append(
TTCKeywords::ResultCategory(
iTestCases[i]->iResult.iCaseExecutionResultType ));
aResult.iResultDes.Append( _L(" and expected was ") );
aResult.iResultDes.Append(
TTCKeywords::ResultCategory(
iTestCases[i]->ExpectedResultCategory() ));
AppendTestResultToResultDes(aResult.iResultDes, iTestCases[i]->iResult.iTestResult.iResultDes);
__TRACE( KPrint, ( _L( "%S"), &aResult.iResultDes ) );
break;
}
// Check normal test result
if( iTestCases[i]->ExpectedResultCategory() ==
TFullTestResult:: ECaseExecuted )
{
// Normal completion, check result
if( iTestCases[i]->iResult.iTestResult.iResult !=
iTestCases[i]->ExpectedResult() )
{
__TRACE( KPrint, ( _L( "Test failed, expect(%d) != result(%d)"),
iTestCases[i]->ExpectedResult(),
iTestCases[i]->iResult.iTestResult.iResult ));
// We return the first error result as aResult
if( iTestCases[i]->iResult.iTestResult.iResult != KErrNone )
{
aResult = iTestCases[i]->iResult.iTestResult;
}
else
{
aResult.iResult = KErrGeneral;
aResult.iResultDes.Copy( _L("Test case completed with KErrNone and expected "));
aResult.iResultDes.AppendNum( iTestCases[i]->ExpectedResult() );
AppendTestResultToResultDes(aResult.iResultDes, iTestCases[i]->iResult.iTestResult.iResultDes);
}
break;
}
}
else
{
// Abnormal completion, i.e. panic, leave, exception or timeout
if( iTestCases[i]->iResult.iCaseExecutionResultCode !=
iTestCases[i]->ExpectedResult() )
{
__TRACE( KPrint, ( _L( "Test failed, expect errorcode(%d) != result(%d)"),
iTestCases[i]->ExpectedResult(),
iTestCases[i]->iResult.iCaseExecutionResultCode ) );
// We return the first error result as aResult
aResult = iTestCases[i]->iResult.iTestResult;
// override result with real error code
aResult.iResult = iTestCases[i]->iResult.iCaseExecutionResultCode;
break;
}
}
}
if( i == count )
{
TestModuleIf().Printf( KPrintPriHigh, _L("Result"), _L("PASSED"));
__TRACE( KPrint, (_L("***Test case result: PASSED***")));
aResult.iResult = KErrNone;
aResult.iResultDes.Copy( _L("Test case succeeded") );
}
else
{
TestModuleIf().Printf( KPrintPriHigh, _L("Result"), _L("FAILED"));
__TRACE( KPrint, (_L("***Test case result: FAILED***")));
}
}
// Release all pending event requests
TEventIf event( TEventIf::ERelEvent );
TInt eventCount = iEventArray.Count();
for( TInt ind=0; ind < eventCount; ind++ )
{
event.SetName( iEventArray[ind]->Name() );
TestModuleIf().Event( event );
}
iLoopAllocationArray.Reset();
iLoopAllocationArray.Close();
iLoopIsUsed = EFalse;
// Delete all completed and checked testcases
// Do not change the deletion order of events and test cases!!!
iEventArray.ResetAndDestroy();
iTestCases.ResetAndDestroy();
iTestModules.ResetAndDestroy();
iSlaveArray.ResetAndDestroy();
iSendReceive.ResetAndDestroy();
// Stop all remaining measurement modules
const TInt count_meas = iTestMeasurementArray.Count();
for( TInt b = 0; b < count_meas; b++ )
{
iTestMeasurementArray[b]->iMeasurement->Stop();
}
iTestMeasurementArray.ResetAndDestroy();
iTestMeasurementArray.Close();
__UHEAP_MARKEND;
//If log was replaced then restore it
if(iAddTestCaseTitleToLogName)
{
iLog = iStdLog;
delete iTCLog;
iTCLog = NULL;
}
return ret;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetTestCaseL
Description: Get specified test case section from configfile.
Parameters: const TInt aCaseNumber: in: Test case number
const TFileName& aConfig: in: Configfile name
Return Values: CSectionParser*: pointer to test case section
Errors/Exceptions: Leaves if CStifParser::NewL leaves
Leaves if CStifParser::SectionL leaves
Leaves if memory allocation fails
Status: Approved
-------------------------------------------------------------------------------
*/
CStifSectionParser* CTestCombiner::GetTestCaseL( const TInt aCaseNumber,
const TFileName& aConfig )
{
__TRACEFUNC();
CStifParser* parser =
CStifParser::NewL( _L(""), aConfig, CStifParser::ECStyleComments );
CleanupStack::PushL( parser );
CStifSectionParser* section =
parser->SectionL( KTestStartTag, KTestEndTag, aCaseNumber );
CleanupStack::PopAndDestroy( parser );
return section;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: ReadInitializationL
Description: Read initialization from file.
Parameters: const TDesC& aIniFile: in: File that contains initialization
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestCombiner::ReadInitializationL( const TDesC& aIniFile )
{
CStifParser* parser = NULL;
// Open file
TRAPD( err, parser =
CStifParser::NewL( _L(""), aIniFile, CStifParser::ECStyleComments ) );
if( ( err == KErrNone ) && parser )
{
CleanupStack::PushL( parser );
__TRACE( KMessage, (_L("Read initialization from [%S]"),
&aIniFile ) );
// Read initialization parameters
CStifSectionParser* section = parser->SectionL( KInitStartTag,
KInitEndTag );
if( section )
{
CleanupStack::PushL( section );
__TRACE( KMessage, (_L("Read initializations")) );
// Read RCP timeout
CStifItemParser* item = section->GetItemLineL( KInitRcpTimeout );
if( item != NULL )
{
__TRACE( KMessage, (_L("Got RCP timeout definition")) );
CleanupStack::PushL( item );
TInt value;
if( item->GetInt( KInitRcpTimeout, value )
!= KErrNone )
{
__TRACE( KError, (_L("No RCP timeout value given")) );
User::Leave( KErrGeneral );
}
// Change from seconds to milliseconds
iRemoteTimeout = value*1000*1000;
CleanupStack::PopAndDestroy( item );
}
CleanupStack::PopAndDestroy( section );
}
// Read defines
section = parser->SectionL( KDefineStartTag, KDefineEndTag );
while(section)
{
CleanupStack::PushL( section );
__TRACE( KMessage, (_L("Read defines")) );
TPtrC name;
TPtrC value;
CStifItemParser* item = section->GetItemLineL( _L("") );
while( item )
{
CleanupStack::PushL( item );
if( item->GetString( _L(""), name ) != KErrNone )
{
__TRACE( KError, (_L("No define name given")) );
User::Leave( KErrGeneral );
}
if( item->Remainder( value ) != KErrNone )
{
__TRACE( KError, (_L("No define value given")) );
User::Leave( KErrGeneral );
}
TInt count = iDefined.Count();
TInt i = 0;
for( ; i < count; i++ )
{
if( iDefined[i]->Name() == name )
{
__TRACE( KMessage, (_L("Update define %S:%S"), &name, &value ) );
// Update existing
iDefined[i]->SetValueL( value );
break;
}
}
if( i == count)
{
// New define, store it
CDefinedValue* define = CDefinedValue::NewL( name, value );
CleanupStack::PushL( define );
User::LeaveIfError( iDefined.Append( define ) );
CleanupStack::Pop( define );
}
CleanupStack::PopAndDestroy( item );
item = section->GetNextItemLineL();
}
CleanupStack::PopAndDestroy( section );
section = parser->NextSectionL(KDefineStartTag, KDefineEndTag);
}
CleanupStack::PopAndDestroy( parser );
}
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: RunTestL
Description: Run a testcase specified by iSectionParser.
Parameters: None
Return Values: None.
Errors/Exceptions: Leaves if CSectionParser::GetItemLineL leaves
Leaves if CTestRunner::NewL leaves
Leaves if memory allocation fails
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestCombiner::RunTestL()
{
__TRACEFUNC();
iResult = KErrNone;
TPtrC line;
// "title" keyword must be in the first line
User::LeaveIfError( iSectionParser->GetLine( KTitle, line, ENoTag ) );
iTestRunner = CTestRunner::NewL( this );
iRemoteReceiver = CRemoteReceiver::NewL( this );
iRemoteReceiver->Start();
__TRACE( KMessage, (_L("Run: %S"), &line));
TestModuleIf().Printf( KPrintPriNorm, _L("Run"), _L("%S"), &line);
// Rest of the job is done by test runner
iTestRunner->SetRunnerActive();
// Start activeScheduler looping testcase lines
iSchedulerActive = ETrue;
__TRACE( KMessage, (_L("Start CActiveScheduler")));
CActiveScheduler::Current()->Start();
TestModuleIf().Printf( KPrintPriNorm, _L("Executed"), _L("%S"), &line);
__TRACE( KMessage, (_L("Executed: %S"), &line));
delete iRemoteReceiver;
iRemoteReceiver = NULL;
delete iTestRunner;
iTestRunner = NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetTestModuleL
Description: Load testmodule if not already loaded, otherwise return
description of the loaded testmodule.
Parameters: TDesC& aModule: in: Module name.
TDesC& aIniFile: in: Ini file name.
const TDesC& aConfigFile: in: Test case(config) file name.
Return Values: CTCTestModule*: pointer to testmodules description
Errors/Exceptions: Leaves if CTCTestModule::NewL leaves
Leaves if RPointerArray::Append fails
Status: Proposal
-------------------------------------------------------------------------------
*/
CTCTestModule* CTestCombiner::GetTestModuleL( TDesC& aModule,
TDesC& aIniFile,
const TDesC& aConfigFile )
{
__TRACEFUNC();
TInt count = iTestModules.Count();
TInt i, j;
TInt counttc;
TInt running;
TBool newWay = EFalse;
__TRACE(KMessage, (_L("Find test module for [%S]"), &aModule));
//Name for new module controller
TName newModuleName = aModule;
//Check if it is python case or UITestingSupport or SeparateProcesses mode
newWay = (aModule.Find(KPythonScripter) == 0)
|| (iUITestingSupport && aModule.Find(KTestScripterName) == 0)
|| (iSeparateProcesses);
if(newWay)
{
__TRACE(KMessage, (_L("TCTestModule operating mode: exclusive")));
//Find module of given name
__TRACE(KMessage, (_L("Looking for module [%S]"), &aModule));
if(iUITestingSupport && aModule.Find(KTestScripterName) == 0)
{
__TRACE(KMessage, (_L("UITestingSupport option is on. New module controller will be created always")));
}
else
{
for(i = 0; i < count; i++)
{
TPtrC modName = iTestModules[i]->ModuleName();
if(modName.Find(aModule) == 0)
{
//Check if there is running test case
counttc = iTestCases.Count();
running = 0;
for(j = 0; j < counttc; j++)
{
if(iTestCases[j]->TestModule() == iTestModules[i] && iTestCases[j]->State() != CTestCase::ETestCaseCompleted)
{
//We have found at least one running test case. There is no reason to find any more,
//because there shouldn't be because test module may run only one python scripter test case.
running++;
__TRACE(KMessage, (_L("Module controller found [%S], but it has running test cases"), &modName));
break;
}
}
if(running == 0)
{
__TRACE(KMessage, (_L("Free module controller has been found [%S]"), &modName));
return iTestModules[i];
}
}
}
}
//Update name of new module to be created
newModuleName.AppendFormat(_L("@%d_"), GetIndexForNewTestModuleController());
newModuleName.LowerCase();
}
else
{
__TRACE(KMessage, (_L("TCTestModule operating mode: normal")));
for(i = 0; i < count; i++)
{
if(iTestModules[i]->ModuleName() == aModule)
{
// Found test module, return description
__TRACE(KMessage, (_L("Module controller [%S] found"), &aModule));
return iTestModules[i];
}
}
}
__TRACE(KMessage, (_L("Creating new test module controller [%S] with ini [%S]"), &newModuleName, &aIniFile));
CTCTestModule* module = CTCTestModule::NewL(this, newModuleName, aIniFile, aConfigFile);
CleanupStack::PushL(module);
//Enumerate test cases
module->GetTestCasesForCombiner(aConfigFile);
//Append new module to list
User::LeaveIfError(iTestModules.Append(module));
CleanupStack::Pop(module);
//Log some info
if(newWay)
{
__TRACE(KMessage, (_L("Module [%S] added to list. Currently there are following controllers of [%S] type:"), &newModuleName, &aModule));
j = 1;
for(i = 0; i < iTestModules.Count(); i++)
{
if(iTestModules[i]->ModuleName().Find(aModule) == 0)
{
__TRACE(KMessage, (_L(" %d. [%S]"), j, &iTestModules[i]->ModuleName()));
j++;
}
}
}
if( iLoopIsUsed )
{
User::LeaveIfError( iLoopAllocationArray.Append( module ) );
}
return module;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetTest
Description: Get test case from testcase array.
Parameters: TDesC& aTestId: in: TestId for testcase
Return Values: CTCTestCase*: running/runned testcase
NULL: Testcase with aTestId not running/runned
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
CTestCase* CTestCombiner::GetTest( TDesC& aTestId )
{
__TRACEFUNC();
// TestId is not mandatory, so length may be zero
if( aTestId.Length() == 0 )
{
return NULL;
}
TInt count = iTestCases.Count();
for( TInt i=0; i < count; i++ )
{
if( iTestCases[i]->TestId() == aTestId )
{
// Found testcase with specified TestId
return iTestCases[i];
}
}
// Test case with aTestId not found
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetRunningTest
Description: Get running test case.
Parameters: TDesC& aTestId: in: TestId for testcase
Return Values: CTCTestCase*: running testcase
NULL: Testcase with aTestId not running
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
CTestCase* CTestCombiner::GetRunningTest( TDesC& aTestId )
{
__TRACEFUNC();
CTestCase* test = GetTest( aTestId );
if( test )
{
if( test->State() == CTestCase::ETestCaseRunning )
{
return test;
}
else
{
__TRACE( KMessage, (_L("GetTest: Searched task (%S) not running (%i)"),
&aTestId, test->State() ));
}
}
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetLocalTest
Description: Get local test case from testcase array.
Parameters: TDesC& aTestId: in: TestId for testcase
Return Values: CTCTestCase*: running/runned testcase
NULL: Testcase with aTestId not running/runned
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CTCTestCase* CTestCombiner::GetLocalTest( TDesC& aTestId )
{
__TRACEFUNC();
CTestCase* testCase = GetTest( aTestId );
if( testCase )
{
if( testCase->Type() != CTestCase::ECaseLocal )
{
__TRACE( KMessage, (_L("GetLocalTest: Searched task (%S) not local"),
&aTestId ));
return NULL;
}
}
return ( CTCTestCase* ) testCase;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetLocalRunningTest
Description: Get local running test case.
Parameters: TDesC& aTestId: in: TestId for testcase
Return Values: CTCTestCase*: running/runned testcase
NULL: Testcase with aTestId not running/runned
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CTCTestCase* CTestCombiner::GetLocalRunningTest( TDesC& aTestId )
{
__TRACEFUNC();
CTestCase* testCase = GetRunningTest( aTestId );
if( testCase )
{
if( testCase->Type() != CTestCase::ECaseLocal )
{
__TRACE( KMessage, (_L("GetLocalRunningTest: Searched task (%S) not local"),
&aTestId ));
return NULL;
}
}
return ( CTCTestCase* ) testCase;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetRemoteTest
Description: Get local test case from testcase array.
Parameters: TDesC& aTestId: in: TestId for testcase
Return Values: CTCTestCase*: running/runned testcase
NULL: Testcase with aTestId not running/runned
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteTestCase* CTestCombiner::GetRemoteTest( TDesC& aTestId )
{
__TRACEFUNC();
CTestCase* testCase = GetTest( aTestId );
if( testCase )
{
if( testCase->Type() != CTestCase::ECaseRemote )
{
__TRACE( KMessage, (_L("GetRemoteTest: Searched task (%S) not remote"),
&aTestId ));
return NULL;
}
}
return ( CRemoteTestCase* ) testCase;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetRemoteTest
Description: Get remote test case from slave array.
Parameters: TUint32 aSlaveId: in: Slave id for testcase
Return Values: TCaseInfo*: running/runned testcase
NULL: Testcase with aTestId not running/runned
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteTestCase* CTestCombiner::GetRemoteTest( TUint32 aSlaveId )
{
__TRACEFUNC();
// Check all remote testcases
TInt caseCount = iTestCases.Count();
CRemoteTestCase* testCase = NULL;
for( TInt caseInd = 0; caseInd < caseCount; caseInd++ )
{
if( iTestCases[caseInd]->Type() == CTestCase::ECaseRemote )
{
testCase = ( CRemoteTestCase* )iTestCases[caseInd];
if( testCase->iSlaveId == aSlaveId )
{
return testCase;
}
}
}
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetRemoteTestRunSent
Description: Get remote test case from slave array
Parameters: TUint32 aSlaveId: in: Slave id for testcase
Return Values: TCaseInfo*: running/runned testcase
NULL: Testcase with aTestId not running/runned
Errors/Exceptions: None
Status: Draft @js
-------------------------------------------------------------------------------
*/
CRemoteTestCase* CTestCombiner::GetRemoteTestRunSent( TUint32 aSlaveId )
{
__TRACEFUNC();
// Check all remote testcases
TInt caseCount = iTestCases.Count();
CRemoteTestCase* testCase = NULL;
for( TInt caseInd = 0; caseInd < caseCount; caseInd++ )
{
if( iTestCases[caseInd]->Type() == CTestCase::ECaseRemote )
{
testCase = ( CRemoteTestCase* )iTestCases[caseInd];
if( testCase->iRemoteState != CRemoteTestCase::ECaseRunSent )
{
continue;
}
if( testCase->iSlaveId == aSlaveId )
{
return testCase;
}
}
}
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetRemoteTest
Description: Get remote test case from slave array.
Parameters: TUint32 aSlaveId: in: Slave id for testcase
Return Values: TCaseInfo*: running/runned testcase
NULL: Testcase with aTestId not running/runned
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteTestCase* CTestCombiner::GetRunningRemoteTest( TUint32 aSlaveId )
{
__TRACEFUNC();
// Check all remote testcases
TInt caseCount = iTestCases.Count();
CRemoteTestCase* testCase = NULL;
for( TInt caseInd = 0; caseInd < caseCount; caseInd++ )
{
if( ( iTestCases[caseInd]->Type() == CTestCase::ECaseRemote ) &&
( iTestCases[caseInd]->State() == CTestCase::ETestCaseRunning ) )
{
testCase = ( CRemoteTestCase* )iTestCases[caseInd];
if( ( testCase->iRemoteState != CRemoteTestCase::ECaseRunSent ) &&
( testCase->iRemoteState != CRemoteTestCase::ECaseRunning ) &&
( testCase->iRemoteState != CRemoteTestCase::ECaseCancelled ))
{
//User::Leave( KErrGeneral );
continue;
}
if( testCase->iSlaveId == aSlaveId )
{
return testCase;
}
}
}
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetRemoteTestSlave
Description: Get remote test case running on slave
Parameters: TUint32 aSlaveDevId: in: Slave id for testcase
Return Values: CRemoteTestCase*: running/runned testcase
NULL: Testcase with aTestId not running/runned
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteTestCase* CTestCombiner::GetRemoteRunningTestOnSlave(
TUint32 aSlaveDevId )
{
__TRACEFUNC();
// Check all remote testcases
TInt caseCount = iTestCases.Count();
CRemoteTestCase* testCase = NULL;
for( TInt caseInd = 0; caseInd < caseCount; caseInd++ )
{
if( ( iTestCases[caseInd]->Type() == CTestCase::ECaseRemote ) &&
( iTestCases[caseInd]->State() == CTestCase::ETestCaseRunning ) )
{
testCase = ( CRemoteTestCase* )iTestCases[caseInd];
if( DEVID( testCase->iSlaveId ) == DEVID( aSlaveDevId ) )
{
return testCase;
}
}
}
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetRemoteTestSlave
Description: Gets a correct CRemoteSendReceive object on slave with
aSlaveId.
Parameters: TUint32 aSlaveId: in: Slave id CRemoteSendReceive object
Return Values: CRemoteSendReceive*: Current CRemoteSendReceive object.
NULL: CRemoteSendReceive object do not exist or found.
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteSendReceive* CTestCombiner::GetRemoteSendReceive( TUint32 aSlaveId )
{
__TRACEFUNC();
for( TInt sr = 0; sr < iSendReceive.Count(); sr++ )
{
if( iSendReceive[sr]->iSlaveId == aSlaveId )
{
return iSendReceive[sr];
}
}
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetSlave
Description: Get remote slave.
Parameters: TUint32 aSlaveId: in: Slave id
Return Values: CSlaveInfo*: reserved slave
NULL: slave with aSlaveId not reserved
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CSlaveInfo* CTestCombiner::GetSlave( TUint32 aSlaveId )
{
__TRACEFUNC();
TInt count = iSlaveArray.Count();
for( TInt index = 0; index < count; index++ )
{
if( DEVID( iSlaveArray[index]->iSlaveDevId ) == DEVID( aSlaveId) )
{
return iSlaveArray[index];
}
}
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: GetSlave
Description: Get remote slave.
Parameters: TDesC& aSlaveName: in: Slave name
Return Values: CSlaveInfo*: reserved slave
NULL: slave with aSlaveId not reserved
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CSlaveInfo* CTestCombiner::GetSlave( TDesC& aSlaveName )
{
__TRACEFUNC();
TInt count = iSlaveArray.Count();
for( TInt index = 0; index < count; index++ )
{
if( iSlaveArray[index]->iName == aSlaveName )
{
return iSlaveArray[index];
}
}
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: StartTestL
Description: Start specified test case from testmodule.
Parameters: CStartInfo& aStartInfo: in: Test case information
Return Values: KErrNone: Testcase started
KErrAlreadyExists: testcase with same aTestId is already
running
Any other SymbianOS errorcode
Errors/Exceptions: Leaves if CTCTestCase::NewL leaves
Leaves if arguments are illegal
Leaves if GetTestModuleL leaves
Leaves if CTestExecution::Open fails
Leaves if CTCTestCase::StartL leaves
Leaves if RPointerArray::Append fails
Status: Proposal
-------------------------------------------------------------------------------
*/
TInt CTestCombiner::StartTestL( CStartInfo& aStartInfo )
{
__TRACEFUNC();
// Check that TestId is unique.
if( GetTest( aStartInfo.iTestId ) != NULL )
{
// If loop testing is ongoing, allow already defined testid.
if( iLoopIsUsed )
{
__TRACE( KVerbose, ( _L("StartTestL: TestId (%S) already in use. Loop allows already defined TestId"),
&aStartInfo.iTestId ));
}
else
{
__TRACE( KError, ( _L("StartTestL: TestId (%S) already in use"),
&aStartInfo.iTestId ));
return KErrAlreadyExists;
}
}
__ASSERT_ALWAYS( aStartInfo.iModule.Length() < KMaxFileName,
User::Leave( KErrArgument ) );
__ASSERT_ALWAYS( aStartInfo.iIniFile.Length() < KMaxFileName,
User::Leave( KErrArgument ) );
__ASSERT_ALWAYS( aStartInfo.iConfig.Length() < KMaxFileName,
User::Leave( KErrArgument ) );
__ASSERT_ALWAYS( aStartInfo.iTestId.Length() < KMaxName,
User::Leave( KErrArgument ) );
__TRACE( KMessage, ( _L("Call GetTestModuleL") ));
// Load Test Module
CTCTestModule* module = NULL;
if( (aStartInfo.iModule.Find( KTestScripterName ) != KErrNotFound)
|| (aStartInfo.iModule.Find( KPythonScripter ) != KErrNotFound)
|| (aStartInfo.iModule.Find( KTestCombinerName ) != KErrNotFound)
)
{
// TestScripter in use. Give config file for parsing STIF Settings.
module = GetTestModuleL( aStartInfo.iModule,
aStartInfo.iIniFile,
aStartInfo.iConfig );
}
else
{
module = GetTestModuleL( aStartInfo.iModule,
aStartInfo.iIniFile,
KNullDesC );
}
__TRACE( KMessage, ( _L("Create CTCTestCase") ));
CTCTestCase* tc =
CTCTestCase::NewL( this,
aStartInfo.iModule,
aStartInfo.iTestId,
aStartInfo.iExpectedResult,
aStartInfo.iCategory,
module ); //--PYTHON--
CleanupStack::PushL( tc );
//If name of testcase was given, find testcase number
if(aStartInfo.iTitle != KNullDesC)
{
__TRACE(KMessage, (_L("Trying to find test case entitled \"%S\""), &aStartInfo.iTitle));
aStartInfo.iCaseNum = -1;
TInt ret = module->GetCaseNumByTitle(aStartInfo.iTitle, aStartInfo.iCaseNum);
if(ret != KErrNone)
{
__TRACE(KError, (_L("Couldn't find test case entitled \"%S\". Error %d"), &aStartInfo.iTitle, ret));
}
else
{
__TRACE(KMessage, (_L("Found test case entitled \"%S\". Case num %d"), &aStartInfo.iTitle, aStartInfo.iCaseNum));
}
}
__TRACE( KMessage, ( _L("Open TestExecution") ));
User::LeaveIfError( tc->TestExecution().Open( module->TestServer(),
aStartInfo.iCaseNum,
aStartInfo.iConfig ) );
__TRACE( KMessage, ( _L("Start testcase runner") ));
// Enable testcase control before calling RunTestCase
tc->StartL();
__TRACE( KMessage,
( _L("Start: testid(%S), module(%S), ini(%S), config(%S), case(%d), expect(%d/%d), timeout(%d)"),
&aStartInfo.iTestId, &aStartInfo.iModule, &aStartInfo.iIniFile,
&aStartInfo.iConfig, aStartInfo.iCaseNum, aStartInfo.iExpectedResult,
aStartInfo.iCategory, aStartInfo.iTimeout ));
TestModuleIf().Printf( KPrintPriLow, _L("Start"),
_L("testid(%S), module(%S), ini(%S), config(%S), case(%d), expect(%d)"),
&aStartInfo.iTestId, &aStartInfo.iModule, &aStartInfo.iIniFile,
&aStartInfo.iConfig, aStartInfo.iCaseNum, aStartInfo.iExpectedResult );
tc->TestExecution().RunTestCase( tc->iResultPckg, tc->iStatus );
iRunningTests++;
User::LeaveIfError( iTestCases.Append( tc ) );
if( iLoopIsUsed )
{
User::LeaveIfError( iLoopAllocationArray.Append( tc ) );
}
CleanupStack::Pop( tc );
return KErrNone;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: Complete
Description: Handle completed test case.
Parameters: CTCTestCase* aTestCase: in: Test case to complete
Return Values: None.
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestCombiner::Complete( CTestCase* aTestCase, TInt aError )
{
__TRACEFUNC();
if( aError != KErrNone )
{
iResult = aError;
}
TInt count = iTestCases.Count();
TInt i = 0;
for(; i < count; i++ )
{
if( iTestCases[i] == aTestCase )
{
// Test Case completed
__TRACE( KPrint, ( _L( "Complete: %S result: %d, execution result: %d, expected: %d"),
&aTestCase->TestId(), aTestCase->iResult.iTestResult.iResult,
aTestCase->iResult.iCaseExecutionResultCode, aTestCase->ExpectedResult() ));
TestModuleIf().Printf( KPrintPriLow, _L("Complete"),
_L( "%S results: test(%d) exe(%d) expect(%d)"),
&aTestCase->TestId(), aTestCase->iResult.iTestResult.iResult,
aTestCase->iResult.iCaseExecutionResultCode, aTestCase->ExpectedResult() );
iRunningTests--;
break;
}
}
if( i == count )
{
__TRACE( KError, (_L("CTestCombiner::Complete: Test case not found!!")));
}
// Check if we were waiting this case to complete
if( ( iWaitTestCase.Length() > 0 ) &&
( iWaitTestCase == aTestCase->TestId() ) )
{
// We were waiting this case to complete
// Now we can proceed executing the testcase
__TRACE( KMessage, (_L("TestCase was waiting, set runner active")));
iTestRunner->SetRunnerActive();
iWaitTestCase.Zero();
//return; - return removed due to STIF-509 CancelIfError won't work when used together with complete command
}
else if( aTestCase->Type() == CTestCase::ECaseRemote )
{
__TRACE( KMessage, (_L("CTestCombiner::Complete: Remote case complete")));
// Completed testcase was remote case,
// check if slave should be freed
CRemoteTestCase* remote = ( CRemoteTestCase* )aTestCase;
if( remote->iFreeSlave )
{
CSlaveInfo* slave = GetSlave( remote->iSlaveId );
if( slave )
{
// Free slave now
TRAPD( err, iTestRunner->ExecuteFreeL( slave ) );
// Continue if freeing fails
if( err == KErrNone )
{
__TRACE( KMessage, (_L("Complete: Freeing slave")));
return;
}
else
{
__TRACE( KError, (_L("Complete: Freeing slave failed")));
}
}
else
{
__TRACE( KError, (_L("Complete: Slave not found")));
}
}
}
// If running test is 0, active scheduler is active and CTestRunner is
// ready then stop active scheduler.(Operations continue from
// CTestCombiner::RunTestL() after active scheduler start).
if( ( iRunningTests == 0 ) &&
iSchedulerActive &&
( iTestRunner->iState == CTestRunner::ERunnerReady ) )
{
// This was last running testcase, so we can stop
// activescheduler
__TRACE( KMessage, (_L("All TestCases completed, stop CActiveScheduler")));
CActiveScheduler::Current()->Stop();
iSchedulerActive = EFalse;
}
else
{
__TRACE( KMessage,
(_L("CTestCombiner::Complete: %d test cases running"), iRunningTests ));
__TRACE( KMessage,
(_L("CTestCombiner::Complete: active %d"), iSchedulerActive ));
if(iSchedulerActive)
{
__TRACE( KMessage,
(_L("CTestCombiner::Complete: state %d"), iTestRunner->iState ));
}
}
// Checking if user wants to skip the rest of the execution in case of error @js
if(iCancelIfError && iSchedulerActive)
{
// Interpret execution result type from returned result
TInt executionResult = TFullTestResult::ECaseExecuted; // Ok
if( (aTestCase->iResult.iCaseExecutionResultType >=
TFullTestResult::ECaseLeave ))
{
__TRACE( KMessage, (_L("The test case ended with error!")));
// Some abnormal execution result type
executionResult = iTestCases[i]->iResult.iCaseExecutionResultType;
}
// Check expected execution result type
if( executionResult != aTestCase->ExpectedResultCategory() )
{
// expected and returned result types differ
__TRACE( KMessage, (_L("The test case has wrong result category!")));
// There was an error and we must stop test case execution
iFailedTestCase = i;
iRunningTests--;
__TRACE( KMessage, (_L("Stopping the CActiveScheduler.")));
CActiveScheduler::Current()->Stop();
iSchedulerActive = EFalse;
}
// Check normal test result if activescheduler is still up & running
if( iSchedulerActive )
{
if( aTestCase->ExpectedResultCategory() ==
TFullTestResult:: ECaseExecuted)
{
// Normal completion, check result
if( iTestCases[i]->iResult.iTestResult.iResult !=
iTestCases[i]->ExpectedResult() )
{
__TRACE( KMessage, (_L("Result category is not what was expected!")));
// There was an error and we must stop test case execution
iFailedTestCase = i;
iRunningTests = 0; //The whole test is stopped. Reset value of running tests.
//This line caused that variable value to be -1. Test could not finish. //iRunningTests--;
__TRACE( KMessage, (_L("Stopping the CActiveScheduler.")));
CActiveScheduler::Current()->Stop();
iSchedulerActive = EFalse;
}
}
else
{
// Abnormal completion, i.e. panic, leave, exception or timeout
if( aTestCase->iResult.iCaseExecutionResultCode !=
aTestCase->ExpectedResult())
{
__TRACE( KMessage, (_L("The test case has abnormal completion!")));
// There was an error and we must stop test case execution
iFailedTestCase = i;
iRunningTests--;
__TRACE( KMessage, (_L("Stopping the CActiveScheduler.")));
CActiveScheduler::Current()->Stop();
iSchedulerActive = EFalse;
}
}
}
}
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: NotifyEvent
Description: Asynchronous event command interface
Check requested events and send unset to first requested
Parameters: TEventIf& aEvent: in: Event command
TRequestStatus& aStatus: in: TRequestStatus used in
asynchronous command
Return Values: ETrue: asynchronous command given
EFalse: asyncronous command not given
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
TBool CTestCombiner::UnsetEvent( TEventIf& aEvent,
TRequestStatus& aStatus )
{
__TRACE( KMessage, ( _L("CTestCombiner::NotifyEvent")));
// First check TestCombiner events
TInt eventCount = iEventArray.Count();
for( TInt i = 0; i < eventCount; i++ )
{
if( aEvent.Name() == iEventArray[i]->Name() )
{
__TRACE( KMessage, (
_L( "Set unset pending for testcombiner's %S event"),
&aEvent.Name() ));
iEventArray[i]->SetRequestStatus( &aStatus );
return ETrue;
}
}
// Check all local testcases
TInt caseCount = iTestCases.Count();
TInt eventInd;
CTCTestCase* testCase = NULL;
for( TInt caseInd = 0; caseInd < caseCount; caseInd++ )
{
if( iTestCases[caseInd]->Type() == CTestCase::ECaseLocal )
{
testCase = ( CTCTestCase* )iTestCases[caseInd];
eventCount = testCase->EventArray().Count();
// Check all requested events
for( eventInd = 0; eventInd < eventCount; eventInd++)
{
const TName& eventName =
testCase->EventArray()[eventInd]->Event().Name();
if( eventName == aEvent.Name() )
{
// Event request is pending, send control command
iEvent.Copy( aEvent );
__TRACE( KMessage, (
_L( "Set unset pending for client's %S event"),
&aEvent.Name() ));
testCase->TestExecution().NotifyEvent( iEventPckg,
aStatus );
return ETrue;
}
}
}
}
return EFalse;
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: ReceiveResponse
Description: Handles responce received from slave
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestCombiner::ReceiveResponse( TDesC& aMsg )
{
__TRACEFUNC();
TBool continueTask = ETrue;
TRAPD( err, continueTask = iTestRunner->ReceiveResponseL( aMsg ) );
// We start receiver again, even in error situation
iRemoteReceiver->Start();
if( err != KErrNone )
{
__TRACE( KError, ( _L("CTestCombiner::ReceiveResponse ERROR")));
iResult = err;
if( iTestRunner->IsActive() )
{
iTestRunner->Cancel();
}
else
{
iTestRunner->CancelTestCases();
}
return;
}
if( continueTask && !iTestRunner->IsActive() )
{
iTestRunner->SetRunnerActive();
}
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: RemoteTimeout
Description: Handles timeouts.
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestCombiner::RemoteTimeout()
{
__TRACEFUNC();
iResult = KErrTimedOut;
if( iTestRunner->IsActive() )
{
__TRACE( KError, (_L("Remote timeout, Cancel runner")));
iTestRunner->Cancel();
}
else
{
__TRACE( KError, (_L("Remote timeout, Cancel test cases")));
iTestRunner->CancelTestCases();
}
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: ExecuteMeasurementL
Description: Executes measurement script line.
Parameters: CStifItemParser* aItem: in: parsed line
Return Values: TBool: in no error ETrue returned
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestCombiner::ExecuteMeasurementL( CStifItemParser* aItem )
{
__TRACEFUNC();
__TRACEFUNC();
TPtrC type;
TPtrC command;
// Get command
if( aItem->GetNextString( command ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'measurement' command" ) ) );
User::Leave( KErrArgument ); // Error in parsing => Leave
}
// Get name
if( aItem->GetNextString( type ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'measurement' type" ) ) );
User::Leave( KErrArgument ); // Error in parsing => Leave
}
// Verify measurement type
if( !( type == KParamMeasurement01 ||
type == KParamMeasurement02 ||
type == KParamMeasurement03 ||
type == KParamMeasurement04 ||
type == KParamMeasurement05 ||
type == KParamMeasurementBappea ) )
{
__TRACE( KError, (
_L( "Unknown measurement type:[%S]" ), &type ) );
User::Leave( KErrArgument ); // Error in types => Leave
}
// Verify command
if( command == _L( "start" ) )
{
// START measurement's process
__TRACE( KMessage, ( _L( "Start 'measurement' with '%S'"), &type ) );
StartMeasurementL( type, aItem );
}
else if( command == _L( "stop" ) )
{
// STOP measurement's process
__TRACE( KMessage, ( _L( "'Stop 'measurement' with '%S'"), &type ) );
StopMeasurementL( type );
}
else
{
__TRACE( KError, (
_L( "Unknown command for 'measurement' command:[%S] or type:[%S]" ), &command, &type ) );
User::Leave( KErrArgument ); // Error in commands => Leave
}
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: StartMeasurementL
Description:
Parameters: const TDesC& aType: in: Plugin type.
CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: Leaves is bappea start or timed operation fails.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestCombiner::StartMeasurementL( const TDesC& aType,
CStifItemParser* aItem )
{
__TRACEFUNC();
CSTIFTestMeasurement* testMeasurement = NULL;
// Get Measurement configuration info
TPtrC configurationInfo( KNullDesC() );
if( aItem->Remainder( configurationInfo ) != KErrNone )
{
__TRACE( KInit, (
_L( "Using default path and file name for measurement configure" ) ) );
}
if( aType == KParamMeasurement01 )
{
testMeasurement = CSTIFTestMeasurement::NewL(
this,
CSTIFTestMeasurement::KStifMeasurementPlugin01,
configurationInfo );
}
else if( aType == KParamMeasurement02 )
{
testMeasurement = CSTIFTestMeasurement::NewL(
this,
CSTIFTestMeasurement::KStifMeasurementPlugin02,
configurationInfo );
}
else if( aType == KParamMeasurement03 )
{
testMeasurement = CSTIFTestMeasurement::NewL(
this,
CSTIFTestMeasurement::KStifMeasurementPlugin03,
configurationInfo );
}
else if( aType == KParamMeasurement04 )
{
testMeasurement = CSTIFTestMeasurement::NewL(
this,
CSTIFTestMeasurement::KStifMeasurementPlugin04,
configurationInfo );
}
else if( aType == KParamMeasurement05 )
{
testMeasurement = CSTIFTestMeasurement::NewL(
this,
CSTIFTestMeasurement::KStifMeasurementPlugin05,
configurationInfo );
}
else if( aType == KParamMeasurementBappea )
{
testMeasurement = CSTIFTestMeasurement::NewL(
this,
CSTIFTestMeasurement::KStifMeasurementBappeaProfiler,
configurationInfo );
}
else
{
__TRACE( KError, ( _L( "Unknown plugin[%S] for 'measurement'" ), &aType ) );
User::Leave( KErrArgument );
}
// Start test measurement
TInt start_ret( KErrNone );
start_ret = testMeasurement->Start();
if( start_ret != KErrNone )
{
delete testMeasurement;
__TRACE( KError, (
_L( "CTestCombiner::StartMeasurementL(): Measurement Start() fails:[%d]" ), start_ret ) );
User::Leave( start_ret );
}
TTestMeasurement* object = new (ELeave) TTestMeasurement();
object->iName = aType;
object->iMeasurement = testMeasurement;
// Array for handling test measurement between different objects
TInt ret = iTestMeasurementArray.Append( object );
if( ret != KErrNone )
{
delete object;
__TRACE( KError, (
_L( "CTestCombiner::StartMeasurementL(): iTestMeasurementArray.Append fails:[%d]" ), ret ) );
User::Leave( ret );
}
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: StopMeasurementL
Description: Stops test measurement.
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestCombiner::StopMeasurementL( const TDesC& aType )
{
__TRACEFUNC();
TInt count = iTestMeasurementArray.Count();
for( TInt i = 0; i < count; i++ )
{
if( iTestMeasurementArray[i]->iName == aType )
{
// Found measurement module, stop
iTestMeasurementArray[i]->iMeasurement->Stop();
// Delete data
delete iTestMeasurementArray[i];
// Remove pointer to deleted data(Append())
iTestMeasurementArray.Remove( i );
// iTestMeasurementArray can contain only one type of measurement
// so we can break when type is removed.
break;
}
}
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
Method: AppendTestResultToResultDes
Description: Append to TC's result description (if possible due to length)
limitation provided text in [] brackets.
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestCombiner::AppendTestResultToResultDes(TDes& aResultDescr, const TDesC& aTestCaseResultDescr)
{
if(aTestCaseResultDescr != KNullDesC)
{
_LIT(KAdditionalInfo, " [%S]");
TInt len = aResultDescr.Length() + KAdditionalInfo().Length() + aTestCaseResultDescr.Length();
if(len > KStifMaxResultDes)
{
len = KStifMaxResultDes - aResultDescr.Length() - KAdditionalInfo().Length();
if(len > 0)
{
TPtrC descr = aTestCaseResultDescr.Mid(0, len);
aResultDescr.AppendFormat(KAdditionalInfo, &descr);
}
}
else
{
aResultDescr.AppendFormat(KAdditionalInfo, &aTestCaseResultDescr);
}
}
}
/*
-------------------------------------------------------------------------------
Class: CTestCombiner
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: None
Return Values: None
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
TInt CTestCombiner::GetIndexForNewTestModuleController(void)
{
return iIndexTestModuleControllers++;
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of CTestRunner class
member functions. CTestRunner is used to execute TestCombiner testcase by
CTestCombiner.
-------------------------------------------------------------------------------
*/
// MACROS
#ifdef LOGGER
#undef LOGGER
#endif
#define LOGGER iTestCombiner->iLog
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: CTestRunner
Description: Default constructor
C++ default constructor can NOT contain any code, that
might leave.
Parameters: CTestCombiner* aTestCombiner: in: Backpointer to CTestCombiner
Return Values: None
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
CTestRunner::CTestRunner( CTestCombiner* aTestCombiner ):
CActive( CActive::EPriorityLow ), // Executed with lowest priority
iState( ERunnerIdle ),
iTestCombiner( aTestCombiner )
{
CActiveScheduler::Add( this );
__TRACEFUNC();
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ConstructL
Description: Symbian OS second phase constructor
Symbian OS default constructor can leave.
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::ConstructL()
{
iPauseTimer.CreateLocal();
iRemoteTimer = CRemoteTimer::NewL( iTestCombiner );
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: NewL
Description: Two-phased constructor.
Parameters: CTestCombiner* aTestCombiner: in: Backpointer to CTestCombiner
Return Values: CTestRunner*: new object
Errors/Exceptions: Leaves if new or ConstructL leaves
Status: Approved
-------------------------------------------------------------------------------
*/
CTestRunner* CTestRunner::NewL( CTestCombiner* aTestCombiner )
{
CTestRunner* self = new (ELeave) CTestRunner( aTestCombiner );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop();
return self;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ~CTestRunner
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
CTestRunner::~CTestRunner()
{
__TRACEFUNC();
Cancel();
delete iRemoteTimer;
iRemoteTimer = 0;
delete iLine;
iLine = 0;
iPauseTimer.Close();
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: RunL
Description: Derived from CActive, handles testcase execution.
Parameters: None.
Return Values: None.
Errors/Exceptions: Leaves on error situations.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::RunL()
{
__TRACEFUNC();
__TRACE( KMessage, (_L("CTestRunner::RunL: [%d] "), iStatus.Int() ));
User::LeaveIfError( iStatus.Int() );
if( ( iTestCombiner == NULL ) ||
( iTestCombiner->iSectionParser == NULL ) )
{
User::Leave( KErrGeneral );
}
TBool continueTask = EFalse;
switch( iState )
{
case ERunnerWaitTimeout:
{
__TRACE( KMessage, (_L("Resume %S"), &iPausedTestCase));
iTestCombiner->TestModuleIf().Printf( KPrintPriExec,
KExecute, _L("Resume %S"), &iPausedTestCase);
// Get running testcase identified with testid
CTestCase* testCase = iTestCombiner->GetRunningTest( iPausedTestCase );
if( testCase == NULL ) User::Leave( KErrNotFound );
iPausedTestCase.Zero();
if( testCase->Type() == CTestCase::ECaseLocal )
{
CTCTestCase* localTestCase = ( CTCTestCase* )testCase;
// Resume execution
User::LeaveIfError( localTestCase->TestExecution().Resume() );
continueTask = ETrue;
}
else // ECaseRemote
{
CRemoteTestCase* remoteTestCase = ( CRemoteTestCase* )testCase;
// Resume execution
if( ExecuteRemoteTestCtlL( NULL,
remoteTestCase,
TTCKeywords::EResume ) )
{
continueTask = ETrue;
}
}
}
break;
case ERunnerWaitUnset:
iState = ERunnerIdle;
// Check Unset event
if( !CheckUnsetEvent() )
{
// Got event and unset has not completed
// Should never come here
User::Panic( KTestRunner, KErrGeneral );
}
break;
case ERunnerRunning:
{
iState = ERunnerIdle;
// Get next execution line from configuration section
iEndLoopStartPos = iTestCombiner->iSectionParser->GetPosition();
TPtrC line;
if( iTestCombiner->iSectionParser->GetNextLine( line ) == KErrNone )
{
// Got new execution line
__TRACE( KMessage, (_L("CTestRunner got line")));
CStifItemParser* item = PreprocessLineL( line );
if( item )
{
// Got new execution line
CleanupStack::PushL( item );
// Execute script line
if( ExecuteLineL( item ) )
{
__TRACE( KMessage, (_L("RunL: continueTask")));
// Set CTestRunner active again to perform
// next execution line
// from testcase section
continueTask = ETrue;
}
CleanupStack::PopAndDestroy( item );
}
}
else
{
// No more execution lines in testcase section
__TRACE( KMessage,
(_L("CTestRunner::RunL: Testcase script done (%d running)"),
iTestCombiner->iRunningTests));
if( ( iTestCombiner->iRunningTests == 0 ) &&
iTestCombiner->iSchedulerActive )
{
__TRACE( KMessage,
(_L("RunL: All TestCases done, stop CActiveScheduler")));
CActiveScheduler::Current()->Stop();
iTestCombiner->iSchedulerActive = EFalse;
}
// Now testcase section is executed,
// so CTestRunner has done its job and stops
iState = ERunnerReady;
//If we're inside loop, then we have error
if(iTestCombiner->iLoopIsUsed)
{
__TRACE(KError, (_L("Endloop keyword not found. Cannot finish test case properly.")));
iTestCombiner->iResult = KErrGeneral;
}
}
}
break;
case ERunnerAllocate:
case ERunnerFree:
case ERunnerRemote:
default:
__TRACE( KError,
(_L("CTestRunner::RunL: Entered in illegal state(%d)"), iState ));
User::Panic( KTestRunner, KErrGeneral );
break;
}
if( continueTask )
{
SetRunnerActive();
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: DoCancel
Description: Derived from CActive handles the Cancel
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::DoCancel()
{
__TRACEFUNC();
__TRACE( KMessage, (_L("CTestRunner::DoCancel")));
iTestCombiner->TestModuleIf().Printf( KPrintPriLow, _L("Runner"), _L("DoCancel"));
switch( iState )
{
case ERunnerWaitTimeout:
iPauseTimer.Cancel();
break;
case ERunnerWaitUnset:
break;
case ERunnerRunning:
break;
case ERunnerAllocate:
case ERunnerFree:
case ERunnerRemote:
// Cancel remote test cases
break;
default:
__TRACE( KError,
(_L("CTestRunner::DoCancel: Entered in illegal state(%d)"), iState ));
User::Panic( KTestRunner, KErrGeneral );
break;
}
// Cancel all testcases
CancelTestCases();
iState = ERunnerCancel;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: RunError
Description: Derived from CActive handles errors from active handler.
Parameters: TInt aError: in: error from CActive
Return Values: KErrNone: success
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
TInt CTestRunner::RunError( TInt aError )
{
__TRACEFUNC();
__TRACE( KMessage, (_L("CTestRunner::RunError %d"), aError));
if ( iRunErrorMessage.Length() != 0 )
{
iTestCombiner->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("RunError : %S"), &iRunErrorMessage );
iRunErrorMessage = KNullDesC;
}
else
{
iTestCombiner->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("RunError"));
}
iState = ERunnerError;
// Return error from here
iTestCombiner->iResult = aError;
CancelTestCases();
return KErrNone;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: PreprocessLineL
Description: Preprocesses script line
Parameters: TPtrC& line: in: script line
CStifItemParser*& aItem: out: New CStifItemParser for script
line.
Return Values: HBufC* pointer if new memory that has been allocated
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
CStifItemParser* CTestRunner::PreprocessLineL( TDesC& line )
{
CStifItemParser* item = NULL;
TPtrC tmp;
TInt len = 0;
// Decide how long buffer should be allocated
if( line.Length() < KMaxName/2 )
{
len = KMaxName;
}
else
{
len = line.Length() + KMaxName;
}
delete iLine;
iLine = 0;
iLine = HBufC::NewL( len );
TPtr parsedLine( iLine->Des() );
len = 0;
item = CStifItemParser::NewL( line, 0, line.Length() );
CleanupStack::PushL( item);
TInt ret = item->GetString( _L(""), tmp );
while( ret == KErrNone )
{
len += CheckDefined( tmp );
if( ( parsedLine.Length() + tmp.Length() + 1 ) > parsedLine.MaxLength() )
{
// Allocate bigger buffer
HBufC* tmpBuf = HBufC::NewL( parsedLine.MaxLength() + KMaxName );
CleanupStack::PushL( tmpBuf );
TPtrC ptr( iLine->Des() );
parsedLine.Set( tmpBuf->Des() );
parsedLine.Copy( ptr );
delete iLine;
iLine = tmpBuf;
CleanupStack::Pop( tmpBuf );
}
parsedLine.Append( tmp );
parsedLine.Append( _L(" ") );
ret = item->GetNextString( tmp );
}
CleanupStack::PopAndDestroy( item );
item = CStifItemParser::NewL( parsedLine, 0, parsedLine.Length() );
return item;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: CheckDefined
Description: Check if aWord is some defined word
Parameters: TPtrC& aWord: inout: Parsed word, defined or original returned
Return Values: TInt: Length difference between new and old word
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
TInt CTestRunner::CheckDefined( TPtrC& aWord )
{
TInt len = 0;
// KLoopCounter word changing to current loop count value.
if( aWord == KLoopCounter )
{
iLoopCounterDes.Zero();
iLoopCounterDes.AppendNum( iLoopCounter );
len = iLoopCounterDes.Length() - aWord.Length();
aWord.Set( iLoopCounterDes );
return len;
}
TInt count = iTestCombiner->iDefined.Count();
for( TInt i = 0; i < count; i++ )
{
if( iTestCombiner->iDefined[i]->Name() == aWord )
{
len = iTestCombiner->iDefined[i]->Value().Length() - aWord.Length();
aWord.Set( iTestCombiner->iDefined[i]->Value() );
break;
}
}
return len;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteLineL
Description: Executes script line
Parameters: CStifItemParser* aItem: in: script line
TTCKeywords::TKeywords aKeyword: in: keyword index
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Approved
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteLineL( CStifItemParser* aItem )
{
_LIT( KErrMsgUnknownKeyword, "Unknown or illegal keyword %S" );
_LIT( KErrMsgMeasurementInvalidArgument, "Measurement : Invalid argument" );
TBool continueTask = ETrue;
TPtrC tmp;
TPtrC keywordItem;
// Get first word from line, i.e. keyword
User::LeaveIfError( aItem->GetString( _L(""), keywordItem ) );
// Parse keyword
TInt keyword = TTCKeywords::Parse( keywordItem, TTCKeywords::Keyword );
switch( keyword )
{
// Test case execution control cases
case TTCKeywords::EPauseCombiner:
continueTask = ExecuteCombinerPauseL( aItem );
break;
case TTCKeywords::ERun:
continueTask = ExecuteRunL( aItem );
break;
case TTCKeywords::EPause:
case TTCKeywords::EComplete:
case TTCKeywords::ECancel:
case TTCKeywords::EResume:
continueTask = ExecuteTestCtlL( aItem, (TTCKeywords::TKeywords)keyword );
break;
// Event control cases
case TTCKeywords::ESet:
continueTask = ExecuteEventSetL( aItem );
break;
case TTCKeywords::EUnset:
continueTask = ExecuteEventUnsetL( aItem );
break;
case TTCKeywords::ERequest:
case TTCKeywords::EWait:
case TTCKeywords::ERelease:
continueTask = ExecuteEventCtlL( aItem, (TTCKeywords::TKeywords)keyword );
break;
case TTCKeywords::EPrint:
{
TName buf;
while( aItem->GetNextString( tmp ) == KErrNone )
{
if( buf.Length() + tmp.Length() >= buf.MaxLength() )
{
break;
}
buf.Append( tmp );
buf.Append( _L(" ") );
}
__TRACE( KMessage, (_L("Test: %S"), &buf ));
iTestCombiner->TestModuleIf().Printf( KPrintPriHigh,
_L("Test"),
_L("%S"), &buf);
}
break;
case TTCKeywords::EAllocate:
continueTask = ExecuteAllocateL( aItem );
break;
case TTCKeywords::EFree:
continueTask = ExecuteFreeL( aItem );
break;
case TTCKeywords::ERemote:
continueTask = ExecuteRemoteL( aItem );
break;
case TTCKeywords::ETimeout:
case TTCKeywords::EPriority:
// not used here
break;
case TTCKeywords::ECancelIfError:
// @js
iTestCombiner->iCancelIfError = ETrue;
break;
case TTCKeywords::EMeasurement:
TRAPD( retErr, iTestCombiner->ExecuteMeasurementL( aItem ) );
if ( retErr == KErrArgument )
{
iRunErrorMessage = KErrMsgMeasurementInvalidArgument;
}
if ( retErr != KErrNone )
{
User::Leave( retErr );
}
break;
case TTCKeywords::ELoop:
ExecuteLoopL( aItem );
iTestCombiner->iLoopIsUsed = ETrue;
break;
case TTCKeywords::EEndLoop:
continueTask = ExecuteEndLoopL();
break;
case TTCKeywords::ETitle:
// title has been handled already, this is duplicate
default:
{
__TRACE( KError, (_L("Unknown or illegal keyword") ) );
// Unknown or illegal keyword
iRunErrorMessage.Format( KErrMsgUnknownKeyword, &keywordItem );
User::Leave( KErrGeneral );
}
break;
}
__TRACE( KMessage, (_L("RunL: TestCase line executed")));
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteRunL
Description: Executes run line
Parameters: CStifItemParser* aItem: in: script line
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Proposal
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteRunL( CStifItemParser* aItem )
{
_LIT( KErrMsgCaseRunError, "Run : %S[case=%d] run error" );
__TRACE( KMessage, (_L("Run")));
iTestCombiner->TestModuleIf().Printf( KPrintPriExec, KExecute, _L("Run"));
CStartInfo* startInfo = CStartInfo::NewL();
CleanupStack::PushL( startInfo );
ParseRunParamsL( aItem, *startInfo );
// Start new case with configurations parsed above
iRunErrorMessage.Format( KErrMsgCaseRunError, &startInfo->iModule, startInfo->iCaseNum );
User::LeaveIfError(
iTestCombiner->StartTestL( *startInfo ) );
iRunErrorMessage = KNullDesC;
CleanupStack::PopAndDestroy( startInfo );
return ETrue;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ParseRunParamsL
Description: Parses run parameters
Parameters: CStifItemParser* aItem: in: script line
CStartInfo& aStartInfo: out: Parsed information
Return Values: None
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestRunner::ParseRunParamsL( CStifItemParser* aItem,
CStartInfo& aStartInfo )
{
_LIT( KErrMsgRunTestmoduleNameNotDefined, "Run : Testmodule name is not defined " );
_LIT( KErrMsgRunCfgFileNotDefined, "Run : Testmodule configuration file is not defined" );
_LIT( KErrMsgRunTestcaseNumberNotDefined, "Run : Testcase number is not defined or has invalid value" );
_LIT( KErrMsgRunCfgFileNameToLong, "Run : TestScripter test case file(config)'s name is too long. Current length[%d], allowed max length[%d]. Cannot continue" );
_LIT( KErrMsgRunInvalidExpectValue, "Run : Invalid expected result value" );
_LIT( KErrMsgRunUnknownOrIllegalCategory, "Run : Unknown or illegal result category" );
_LIT( KErrMsgRunInvalidTimeoutValue, "Run: Invalid testcase timeout value" );
_LIT( KErrMsgRunUnknowOrIllegalKeyword, "Run: Unknown or illegal keyword %S" );
TPtrC tmp;
TInt ret = KErrNone;
// Get mandatory run arguments
// Testmodule name
ret = aItem->GetNextString( tmp );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgRunTestmoduleNameNotDefined;
User::Leave( ret );
}
aStartInfo.SetModuleNameL( tmp );
__TRACE( KMessage, (_L("module: %S"), &aStartInfo.iModule ));
// Configuration file
ret = aItem->GetNextString( tmp );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgRunCfgFileNotDefined;
User::Leave( ret );
}
TFileName cfgFileName( tmp );
TStifUtil::CorrectFilePathL( cfgFileName );
aStartInfo.SetConfigL( cfgFileName );
__TRACE( KMessage, (_L("config: %S"), &aStartInfo.iConfig ));
// Check is TestScripter
if( aStartInfo.iModule.Find( KTestScripterName ) != KErrNotFound )
{
// TestScripter name is format: 'testscripter_testcasefilename'
TParse parse;
parse.Set( aStartInfo.iConfig, NULL, NULL );
// Maximum length of TestScripter's name(Max limitation from
// CTestModuleController creation)
TInt maximumLength = KMaxName - ( KTestScripterNameLength + 1 );
TFileName testScripterAndTestCaseFile; // InitL() takes TFileName
testScripterAndTestCaseFile.Copy( KTestScripterName );
testScripterAndTestCaseFile.Append( _L( "_" ) );
if( parse.Name().Length() < maximumLength )
{
testScripterAndTestCaseFile.Append( parse.Name() );
}
else
{
__TRACE( KInit, ( CStifLogger::ERed,
_L( "TestScripter test case file(config)'s name is too long. Current length[%d], allowed max length[%d]. Cannot continue" ),
parse.Name().Length(), maximumLength ) );
iRunErrorMessage.Format( KErrMsgRunCfgFileNameToLong, parse.Name().Length(), maximumLength );
User::Leave( KErrArgument );
}
// ----
aStartInfo.DeleteModuleName(); // Delete old name buffer for new one
aStartInfo.SetModuleNameL( testScripterAndTestCaseFile );
}
// Testcase number
ret = aItem->GetInt( tmp, aStartInfo.iCaseNum );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgRunTestcaseNumberNotDefined;
User::Leave( ret );
}
__TRACE( KMessage, (_L("testcasenum: %d"), aStartInfo.iCaseNum ) );
// Set mode of item parser to be able to read titles with spaces inside
aItem->SetParsingType(CStifItemParser::EQuoteStyleParsing);
// Get optional run arguments
while( aItem->GetNextString( tmp ) == KErrNone )
{
TPtrC val;
TPtrC arg;
ParseOptArgL( tmp, arg, val );
CheckDefined( val );
// Parse optional argument
switch( TTCKeywords::Parse( arg, TTCKeywords::RunOptArg ) )
{
case TTCKeywords::EExpect:
{
TLex ptr( val );
ret = ptr.Val( aStartInfo.iExpectedResult );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgRunInvalidExpectValue;
User::Leave( ret );
}
__TRACE( KMessage, (_L("expect=%d"), aStartInfo.iExpectedResult));
}
break;
case TTCKeywords::ETestid:
{
aStartInfo.SetTestIdL( val );
__TRACE( KMessage, (_L("TestId=%S"), &val));
}
break;
case TTCKeywords::EIni:
{
__TRACE( KMessage, (_L("ini=%S"), &val));
TFileName iniFileName( val );
TStifUtil::CorrectFilePathL( iniFileName );
aStartInfo.SetIniFileL( iniFileName );
}
break;
case TTCKeywords::ECategory:
{
__TRACE( KMessage, (_L("category=%S"), &val));
aStartInfo.iCategory = TTCKeywords::GetResultCategory( val );
if( aStartInfo.iCategory == TFullTestResult::ECaseOngoing )
{
__TRACE( KError, (_L("Unknown or illegal result category")));
//Unknown or illegal category
iRunErrorMessage = KErrMsgRunUnknownOrIllegalCategory;
User::Leave( KErrGeneral );
}
}
break;
case TTCKeywords::ECaseTimeout:
{
TLex ptr( val );
ret = ptr.Val( aStartInfo.iTimeout );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgRunInvalidTimeoutValue;
User::Leave( ret );
}
__TRACE( KMessage, (_L("timeout=%d"), aStartInfo.iTimeout ) );
}
break;
case TTCKeywords::ECaseTitle:
{
__TRACE( KMessage, (_L("case title=%S"), &val));
aStartInfo.SetTitleL(val);
break;
}
default:
{
__TRACE( KError, (_L("Unknown or illegal keyword")));
//Unknown or illegal keyword
iRunErrorMessage.Format( KErrMsgRunUnknowOrIllegalKeyword, &arg );
User::Leave( KErrGeneral );
}
}
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteTestCtlL
Description: Executes script line
Parameters: CStifItemParser* aItem: in: script line
TTCKeywords::TKeywords aKeyword: in: keyword index
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Approved
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteTestCtlL( CStifItemParser* aItem,
TTCKeywords::TKeywords aKeyword )
{
_LIT( KErrMsgTestIdNotDefined, "%S : testid is not defined" );
_LIT( KErrMsgTestCaseNotFound, "%S : Test case %S not found" );
TBool continueTask = ETrue;
TPtrC tmp;
TInt ret = KErrNone;
TPtrC keywordStr = TTCKeywords::Keyword( aKeyword );
// Parse testid
ret = aItem->GetNextString( tmp );
if( ret != KErrNone )
{
iRunErrorMessage.Format( KErrMsgTestIdNotDefined, &keywordStr );
User::Leave( ret );
}
// Get testcase identified with testid
CTestCase* testCase = iTestCombiner->GetTest( tmp );
if( testCase == NULL )
{
__TRACE( KError, (_L("ExecuteTestCtlL: Test case %S not found"),
&tmp));
iRunErrorMessage.Format( KErrMsgTestCaseNotFound, &keywordStr, &tmp );
User::Leave( KErrNotFound );
}
switch( aKeyword )
{
// Test case execution control cases
case TTCKeywords::EPause:
continueTask = ExecutePauseL( aItem, testCase );
break;
case TTCKeywords::EComplete:
continueTask = ExecuteCompleteL( aItem, testCase );
break;
case TTCKeywords::ECancel:
__TRACE( KMessage, (_L("Cancel %S"), &tmp));
iTestCombiner->TestModuleIf().Printf( KPrintPriExec,
KExecute, _L("Cancel %S"), &tmp);
if( testCase->Type() == CTestCase::ECaseRemote )
{
continueTask =
ExecuteRemoteTestCtlL( aItem, testCase, aKeyword );
}
else
{
if( testCase->State() != CTestCase::ETestCaseRunning )
{
__TRACE( KMessage, (_L("Cancelled task (%S) not running (%i)"),
&tmp, testCase->State() ));
User::Leave( KErrNotFound );
}
CTCTestCase* test = ( CTCTestCase* )testCase;
// Cancel local testcase
test->TestExecution().CancelAsyncRequest( ETestExecutionRunTestCase );
}
break;
case TTCKeywords::EResume:
{
__TRACE( KMessage, (_L("Resume %S"), &tmp));
iTestCombiner->TestModuleIf().Printf( KPrintPriExec,
KExecute, _L("Resume %S"), &tmp);
if( testCase->Type() == CTestCase::ECaseRemote )
{
continueTask =
ExecuteRemoteTestCtlL( aItem, testCase, aKeyword );
}
else
{
if( testCase->State() != CTestCase::ETestCaseRunning )
{
__TRACE( KMessage, (_L("Resumed task (%S) not running (%i)"),
&tmp, testCase->State() ));
User::Leave( KErrNotFound );
}
CTCTestCase* test = ( CTCTestCase* )testCase;
// Resume execution
User::LeaveIfError( test->TestExecution().Resume() );
}
}
break;
default:
// Should never come here
User::Leave( KErrGeneral );
break;
}
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteCombinerPauseL
Description: Executes causes pause in TestCombiner
Parameters: CStifItemParser* aItem: in: script line
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Proposal
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteCombinerPauseL( CStifItemParser* aItem )
{
_LIT( KErrMsgPauseTimeoutNotDefined, "PauseCombiner : No timeout value given or value has invalid format" );
_LIT( KErrMsgPauseTimeoutNotPositive, "PauseCombiner : Timeout value can't be <0" );
TBool continueTask = ETrue;
TInt pauseTime;
TInt ret = KErrNone;
// Parse testid
ret = aItem->GetNextInt( pauseTime );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgPauseTimeoutNotDefined;
User::Leave( ret );
}
if( pauseTime < 0 )
{
__TRACE( KError, (_L("CTestRunner::ExecuteCombinerPauseL: Given pause value < 0")));
iRunErrorMessage = KErrMsgPauseTimeoutNotPositive;
User::Leave( KErrArgument );
}
//Time given by End User should be given in miliseconds
pauseTime*=1000;
__TRACE( KMessage, (_L("time=%d"), pauseTime ) );
User::After( pauseTime );
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecutePauseL
Description: Executes pause line
Parameters: CStifItemParser* aItem: in: script line
CTestCase* aTestcase: in: test case
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Approved
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecutePauseL( CStifItemParser* aItem,
CTestCase* aTestcase )
{
_LIT( KErrMsgPauseUnknownKeyword, "Pause : Unknown or illegal keyword %S" );
_LIT( KErrMsgPauseTimeInvalidValue, "Pause : Pause time is not defined or has invalid value" );
_LIT( KErrMsgPauseTimeNotPositive, "Pause : Pause time can't be <0" );
TBool continueTask = ETrue;
// Get optional pause arguments
TPtrC tmp;
iPauseTime = 0;
while( aItem->GetNextString( tmp ) == KErrNone )
{
TPtrC val;
TPtrC arg;
ParseOptArgL( tmp, arg, val );
CheckDefined( val );
// Parse optional argument
switch( TTCKeywords::Parse( arg, TTCKeywords::PauseOptArg ) )
{
case TTCKeywords::ETime:
{
TLex ptr( val );
TInt ret = KErrNone;
ret = ptr.Val( iPauseTime );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgPauseTimeInvalidValue;
User::Leave( ret );
}
if ( iPauseTime < 0 )
{
iRunErrorMessage = KErrMsgPauseTimeNotPositive;
User::Leave( KErrArgument );
}
__TRACE( KMessage, (_L("time=%d"), iPauseTime ));
}
break;
default:
__TRACE( KError, (_L("Unknown or illegal keyword")));
//Unknown or illegal keyword
iRunErrorMessage.Format( KErrMsgPauseUnknownKeyword, &arg );
User::Leave( KErrGeneral );
}
}
// Store paused testcase id if timeout was given as pause argument
if( iPauseTime != 0 )
{
iPausedTestCase.Copy( aTestcase->TestId() );
}
if( aTestcase->Type() == CTestCase::ECaseRemote )
{
return ExecuteRemoteTestCtlL( aItem, aTestcase, TTCKeywords::EPause );
}
if( aTestcase->State() != CTestCase::ETestCaseRunning )
{
__TRACE( KMessage, (_L("Paused task (%S) not running (%i)"),
&aTestcase->TestId(), aTestcase->State() ));
User::Leave( KErrNotFound );
}
CTCTestCase* test = ( CTCTestCase* )aTestcase;
// Pause execution
User::LeaveIfError( test->TestExecution().Pause() );
// Resume paused case if timeout was given
if( iPauseTime != 0 )
{
continueTask = EFalse;
iState = ERunnerWaitTimeout;
iPauseTimer.After( iStatus, iPauseTime*1000 );
SetActive();
}
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteCompleteL
Description: Executes complete line
Parameters: CStifItemParser* aItem: in: script line
CTestCase* aTestcase: in: test case
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Approved
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteCompleteL( CStifItemParser* /* aItem */,
CTestCase* aTestcase )
{
TBool ret = ETrue;
if( aTestcase->State() == CTestCase::ETestCaseCompleted )
{
// Requested testcase is completed already,
// proceed testcase execution
__TRACE( KMessage, (_L("Already completed")));
}
else if( aTestcase->State() == CTCTestCase::ETestCaseRunning )
{
// Wait testcase to complete
iTestCombiner->iWaitTestCase.Copy( aTestcase->TestId() );
// Stop testcase execution until testcase completed
ret = EFalse;
iState = ERunnerWaitTestCase;
}
else
{
// This should newer happen
User::Leave( KErrGeneral );
}
return ret;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteEventSetL
Description: Executes event set line
Parameters: CStifItemParser* aItem: in: script line
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Approved
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteEventSetL( CStifItemParser* aItem )
{
_LIT( KErrMsgSetEventNameNotDefined, "Set : event name is not defined" );
_LIT( KErrMsgSetUnknownOrIllegalKeyword, "Set :Unknown or illegal keyword %S" );
_LIT( KErrMsgSetStateInvalidValue, "Set : State value is not defined or has invalid format" );
TPtrC tmp;
TPtrC eventName;
TInt ret = KErrNone;
// Get event name
ret = aItem->GetNextString( eventName );
if( ret != KErrNone )
{
iRunErrorMessage = KErrMsgSetEventNameNotDefined;
User::Leave( ret );
}
__TRACE( KMessage, (_L("Set %S"), &eventName));
iTestCombiner->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("Set %S"), &eventName);
iEvent.SetName( eventName );
iEvent.SetType( TEventIf::ESetEvent );
// Get optional set arguments
while( aItem->GetNextString( tmp ) == KErrNone )
{
TPtrC val;
TPtrC arg;
ParseOptArgL( tmp, arg, val );
CheckDefined( val );
// Parse optional set argument
switch( TTCKeywords::Parse( arg, TTCKeywords::EventOptArg ) )
{
case TTCKeywords::EState:
{
TLex ptr( val );
TInt tmpVal = 0;
ret = ptr.Val( tmpVal );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgSetStateInvalidValue;
User::Leave( ret );
}
// Only value 1 has special meaning, others are ignored
if( tmpVal == 1 )
{
__TRACE( KMessage, (_L("State event")));
iEvent.SetEventType( TEventIf::EState );
}
}
break;
default:
__TRACE( KError, (_L("Unknown or illegal keyword")));
//Unknown or illegal keyword
iRunErrorMessage.Format( KErrMsgSetUnknownOrIllegalKeyword, &arg );
User::Leave( KErrGeneral );
}
}
// Set event
iTestCombiner->TestModuleIf().Event( iEvent, iStatus );
iState = ERunnerRunning;
SetActive();
return EFalse;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteEventUnsetL
Description: Executes event unset line
Parameters: CStifItemParser* aItem: in: script line
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Approved
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteEventUnsetL( CStifItemParser* aItem )
{
_LIT( KErrMsgUnsetEventNameNotDefined, "Unset : Event name is not defined" );
TPtrC eventName;
TInt ret = KErrNone;
// Get event name
ret = aItem->GetNextString( eventName );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgUnsetEventNameNotDefined;
User::Leave( ret );
}
__TRACE( KMessage, (_L("Unset %S"), &eventName));
iTestCombiner->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("Unset %S"), &eventName);
iEvent.Set( TEventIf::EUnsetEvent, eventName, TEventIf::EState );
// Check if trying to unset an event that is requested
// by testcombiner (otherwise testcombiner would deadlock)
TInt count = iTestCombiner->iEventArray.Count();
TInt ind = 0;
for(; ind < count; ind++ )
{
if( eventName == iTestCombiner->iEventArray[ind]->Name() )
{
User::Leave( KErrInUse );
}
}
// Check if some testmodule below
// has event request pending
if( iTestCombiner->UnsetEvent( iEvent,
iStatus ) == EFalse )
{
// If they haven't requested event,
// then check others above
iTestCombiner->TestModuleIf().Event( iEvent, iStatus );
iState = ERunnerRunning;
SetActive();
}
else
{
// Some testmodule below has requested the event
// Wait unset to complete
SetActive();
__TRACE( KPrint, ( _L("Unset: Start" ) ) );
iState = ERunnerWaitUnset;
// Stop execution until unset has completed
}
return EFalse;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteLineL
Description: Executes script line
Parameters: CStifItemParser* aItem: in: script line
TTCKeywords::TKeywords aKeyword: in: keyword index
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Approved
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteEventCtlL( CStifItemParser* aItem,
TTCKeywords::TKeywords aKeyword )
{
_LIT( KErrMsgEventNameNotDefined, "%S : Event name is not defined" );
_LIT( KErrMsgEequestEventAlreadyExist, "Request : Requested event %S already exists" );
_LIT( KErrMsgWaitEventNotRequested, "Wait :Waited event %S is not requested" );
_LIT( KErrMsgReleaseEventNotRequested, "Release : Released event %S is not requested" );
TBool continueTask = ETrue;
TPtrC eventName;
TInt ret = KErrNone;
TPtrC keywordStr = TTCKeywords::Keyword( aKeyword );
// Get event name
ret = aItem->GetNextString( eventName );
if ( ret != KErrNone )
{
iRunErrorMessage.Format( KErrMsgEventNameNotDefined, &keywordStr );
User::Leave( ret );
}
TInt count = iTestCombiner->iEventArray.Count();
TInt ind = 0;
for(; ind < count; ind++ )
{
if( eventName == iTestCombiner->iEventArray[ind]->Name() )
{
break;
}
}
switch( aKeyword )
{
case TTCKeywords::ERequest:
{
__TRACE( KMessage, (_L("Request %S"), &eventName));
iTestCombiner->TestModuleIf().Printf( KPrintPriExec,
KExecute, _L("Request %S"), &eventName);
// Check that event is not already requested
if( ind < count )
{
__TRACE( KError, (_L("Requested event %S already exists"),
&eventName));
iRunErrorMessage.Format( KErrMsgEequestEventAlreadyExist, &eventName );
User::Leave( KErrAlreadyExists );
}
// Add event to event array
iEvent.SetName( eventName );
iEvent.SetType( TEventIf::EReqEvent );
TEventTc* event = new (ELeave) TEventTc( iTestCombiner->iLog );
CleanupStack::PushL( event );
event->Copy( iEvent );
User::LeaveIfError( iTestCombiner->iEventArray.Append( event ));
if( iTestCombiner->iLoopIsUsed )
{
User::LeaveIfError( iTestCombiner->iLoopAllocationArray.Append( event ) );
}
CleanupStack::Pop( event );
// Request event
iTestCombiner->TestModuleIf().Event( iEvent, iStatus );
iState = ERunnerRunning;
SetActive();
continueTask = EFalse;
}
break;
case TTCKeywords::EWait:
{
__TRACE( KMessage, (_L("Wait %S"), &eventName));
iTestCombiner->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("Wait %S"), &eventName);
// Check that event is requested
if( ind == count )
{
__TRACE( KError, (_L("Waited event %S is not requested"),
&eventName));
iRunErrorMessage.Format( KErrMsgWaitEventNotRequested, &eventName );
User::Leave( KErrNotFound );
}
iEvent.SetName( eventName );
iEvent.SetType( TEventIf::EWaitEvent );
// Wait event
iTestCombiner->TestModuleIf().Event( iEvent, iStatus );
iState = ERunnerRunning;
SetActive();
continueTask = EFalse;
}
break;
case TTCKeywords::ERelease:
{
__TRACE( KMessage, (_L("Release %S"), &eventName));
iTestCombiner->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("Release %S"), &eventName);
// Check that event is requested
if( ind == count )
{
__TRACE( KError, (_L("Released event %S is not requested"),
&eventName));
iRunErrorMessage.Format( KErrMsgReleaseEventNotRequested, &eventName );
User::Leave( KErrNotFound );
}
// Remove event from array
TEventTc* event = iTestCombiner->iEventArray[ind];
iTestCombiner->iEventArray.Remove( ind );
delete event;
iEvent.SetName( eventName );
iEvent.SetType( TEventIf::ERelEvent );
// Release event
iTestCombiner->TestModuleIf().Event( iEvent, iStatus );
iState = ERunnerRunning;
SetActive();
continueTask = EFalse;
}
break;
default:
{
__TRACE( KError, (_L("Illegal keyword") ) );
// Unknown or illegal keyword
User::Leave( KErrGeneral );
}
break;
}
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteAllocateL
Description: Executes allocate line
Parameters: CStifItemParser* aItem: in: script line
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteAllocateL( CStifItemParser* aItem )
{
_LIT( KErrMsgAllocateSlaveTypeNotDefined, "Allocate : Slave type was not given for allocate" );
_LIT( KErrMsgAllocateSlaveNameNotDefined, "Allocate : Slave name is not defined" );
_LIT( KErrMsgAllocateSlaveAlreadyAllocated, "Allocate : Slave with name %S already allocated" );
__TRACE( KMessage, (_L("Allocate")));
TPtrC type;
TPtrC name;
// Get slave type
TInt ret = aItem->GetNextString( type );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Slave type was not given for allocate")));
iRunErrorMessage = KErrMsgAllocateSlaveTypeNotDefined;
User::Leave( KErrArgument );
}
// Get slave name
ret = aItem->GetNextString( name );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Slave name was not given for allocate")));
iRunErrorMessage = KErrMsgAllocateSlaveNameNotDefined;
User::Leave( KErrArgument );
}
iTestCombiner->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("Allocate %S"), &name );
__TRACE( KMessage, (_L("Allocate %S [name: %S]"), &type, &name));
if( iTestCombiner->GetSlave( name ) )
{
__TRACE( KError, (_L("Slave with name %S already allocated"),
&name ) );
iRunErrorMessage.Format( KErrMsgAllocateSlaveAlreadyAllocated, &name );
User::Leave( KErrAlreadyExists );
}
CSlaveInfo* slave = CSlaveInfo::NewL( name, KRemoteProtocolMasterId );
CleanupStack::PushL( slave );
User::LeaveIfError( iTestCombiner->iSlaveArray.Append( slave ) );
if( iTestCombiner->iLoopIsUsed )
{
User::LeaveIfError( iTestCombiner->iLoopAllocationArray.Append( slave ) );
}
CleanupStack::Pop( slave );
CStifTFwIfProt* req = CStifTFwIfProt::NewL();
CleanupStack::PushL( req );
req->CreateL();
// Reserve message
User::LeaveIfError(
req->Append( CStifTFwIfProt::MsgType, CStifTFwIfProt::EMsgReserve ) );
// Srcid. i.e. master id
User::LeaveIfError(
req->AppendId( slave->iMasterId ) );
// DstId, broacast id
User::LeaveIfError(
req->AppendId( slave->iSlaveDevId ) );
// Slave type
User::LeaveIfError( req->Append( type ) );
User::LeaveIfError(
iTestCombiner->TestModuleIf().RemoteSend( req->Message() ) );
iState = ERunnerAllocate;
slave->iState = CSlaveInfo::ESlaveReserveSent;
// Start timer
iRemoteTimer->SetTimerActive( iTestCombiner->iRemoteTimeout );
CleanupStack::PopAndDestroy( req );
return EFalse;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteFreeL
Description: Executes free line
Parameters: CStifItemParser* aItem: in: script line
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteFreeL( CStifItemParser* aItem )
{
_LIT( KErrMsgFreeSlaveNameNotDefined, "Free : Slave name is not defined" );
_LIT( KErrMsgFreeSlaveNotFound, "Free : Slave %S not found" );
_LIT( KErrMsgFreeSlaveReserved, "Free : Slave %S in illegal state %d, cannot be released" );
__TRACE( KMessage, (_L("Free")));
TPtrC name;
// Get slave name
TInt ret = aItem->GetNextString( name );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Slave name was not given for free")));
iRunErrorMessage = KErrMsgFreeSlaveNameNotDefined;
User::Leave( KErrArgument );
}
iTestCombiner->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("Free %S"), &name );
__TRACE( KMessage, (_L("Free %S"), &name ) );
CSlaveInfo* slave = iTestCombiner->GetSlave( name );
if( slave == NULL )
{
__TRACE( KError, (_L("Slave %S not found"), &name ));
iRunErrorMessage.Format( KErrMsgFreeSlaveNotFound, &name );
User::Leave( KErrNotFound );
}
if( slave->iState != CSlaveInfo::ESlaveReserved )
{
__TRACE( KError, (_L("Slave %S in illegal state %d, cannot be released"),
&name, slave->iState ));
iRunErrorMessage.Format( KErrMsgFreeSlaveReserved, &name, slave->iState );
User::Leave( KErrGeneral );
}
ExecuteFreeL( slave );
return EFalse;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteFreeL
Description: Executes free line
Parameters: CSlaveInfo* aSlave: in: slave info
Return Values: None
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestRunner::ExecuteFreeL( CSlaveInfo* aSlave )
{
CRemoteTestCase* testCase =
iTestCombiner->GetRemoteRunningTestOnSlave( aSlave->iSlaveDevId );
if( testCase )
{
__TRACE( KMessage,
(_L("Postpone free until testcases completed")));
// Test cases still running on slave,
// Free slave after test case has completed
testCase->iFreeSlave = ETrue;
return;
}
CStifTFwIfProt* req = CStifTFwIfProt::NewL();
CleanupStack::PushL( req );
req->CreateL();
// Release message
User::LeaveIfError(
req->Append( CStifTFwIfProt::MsgType, CStifTFwIfProt::EMsgRelease ) );
// Srcid. i.e. master id
User::LeaveIfError(
req->AppendId( aSlave->iMasterId ) );
// DstId is device broadcast
User::LeaveIfError(
req->AppendId( SETID( DEVID( aSlave->iSlaveDevId ), 0 ) ) );
User::LeaveIfError(
iTestCombiner->TestModuleIf().RemoteSend( req->Message() ) );
iState = ERunnerFree;
aSlave->iState = CSlaveInfo::ESlaveReleaseSent;
// Start timer
iRemoteTimer->SetTimerActive( iTestCombiner->iRemoteTimeout );
CleanupStack::PopAndDestroy( req );
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteRemoteL
Description: Executes remote line
Parameters: CStifItemParser* aItem: in: script line
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteRemoteL( CStifItemParser* aItem )
{
_LIT( KErrMsgRemoteSlaveNameNotDefined, "Remote : Slave name is not defined" );
_LIT( KErrMsgRemoteSlaveNotFound, "Remore : Slave %S not found" );
_LIT( KErrMsgRemoteIllegalState, "Remote : Slave %S in illegal state %d, cannot send remote call" );
_LIT( KErrMsgRemoteCommandNotDefined, "Slave command name was not given for remote" );
TPtrC name;
TPtrC command;
// Get slave name
TInt ret = aItem->GetNextString( name );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Slave name was not given for remote")));
iRunErrorMessage = KErrMsgRemoteSlaveNameNotDefined;
User::Leave( KErrArgument );
}
__TRACE( KMessage, (_L("Remote command to %S"), &name));
CSlaveInfo* slave = iTestCombiner->GetSlave( name );
if( slave == NULL )
{
__TRACE( KError, (_L("Slave %S not found"), &name ));
iRunErrorMessage.Format( KErrMsgRemoteSlaveNotFound, &name );
User::Leave( KErrArgument );
}
if( slave->iState != CSlaveInfo::ESlaveReserved )
{
__TRACE( KError, (_L("Slave %S in illegal state %d, cannot send remote call"),
&name, slave->iState ));
iRunErrorMessage.Format( KErrMsgRemoteIllegalState, &name, slave->iState );
User::Leave( KErrNotReady );
}
// Get remote command name
ret = aItem->GetNextString( command );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Slave command name was not given for remote")));
iRunErrorMessage = KErrMsgRemoteCommandNotDefined;
User::Leave( KErrArgument );
}
iTestCombiner->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("remote %S %S"), &name, &command );
__TRACE( KPrint, (_L("remote %S %S"), &name, &command ) );
// Parse command name
TInt key = TTCKeywords::Parse( command, TTCKeywords::Keyword );
TBool continueTask = ETrue;
switch( key )
{
// Test case starting
case TTCKeywords::ERun:
continueTask = ExecuteRemoteRunL( aItem, slave );
break;
// Event control cases
case TTCKeywords::ERequest:
case TTCKeywords::EWait:
case TTCKeywords::ERelease:
continueTask = ExecuteRemoteEventCtlL( aItem, slave, key );
break;
case TTCKeywords::ESet:
case TTCKeywords::EUnset:
continueTask = ExecuteRemoteSetUnsetEventL(aItem, slave, key);
break;
// asynchronous 'sendreceive'
case TTCKeywords::ESendReceive:
continueTask = ExecuteRemoteSendReceiveL( aItem, slave );
break;
default:
// Some unknown remote command, forward as such
continueTask = ExecuteRemoteUnknownL( aItem, slave, command );
break;
}
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteRemoteRunL
Description: Handles remote run
Parameters: CStifItemParser* aItem: in: script line
CSlaveInfo* aSlave: in: slave info
HBufC *aSetUnsetEvent: in: data needed for startInfo
TInt aCaseNumber: in: data needed for startInfo
Return Values: ETrue: continue script file execution
EFalse: stop script file execution and wait response
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteRemoteRunL( CStifItemParser* aItem,
CSlaveInfo* aSlave,
HBufC *aSetUnsetEvent,
TInt aCaseNumber )
{
CStifTFwIfProt* req = CStifTFwIfProt::NewL();
CleanupStack::PushL( req );
req->CreateL();
CStartInfo* startInfo = CStartInfo::NewL();
CleanupStack::PushL( startInfo );
//if aSetUnsetEvent is given, then get start info from this argument
if(aSetUnsetEvent != NULL)
{
TBuf<10> tmpModuleName;
tmpModuleName.Copy(_L("suevent"));
startInfo->SetModuleNameL(tmpModuleName);
startInfo->SetConfigL(*aSetUnsetEvent);
startInfo->iCaseNum = aCaseNumber;
}
else
{
ParseRunParamsL( aItem, *startInfo );
}
if( iTestCombiner->GetTest( startInfo->iTestId ) )
{
/*
__TRACE( KError, (_L("´Slave test running already with testid %S"),
&startInfo->iTestId ) );
*/
User::Leave( KErrAlreadyExists );
}
CRemoteTestCase* remote =
CRemoteTestCase::NewL( iTestCombiner,
startInfo->iTestId,
startInfo->iExpectedResult,
startInfo->iCategory );
CleanupStack::PushL( remote );
// Remote message
User::LeaveIfError(
req->Append( CStifTFwIfProt::MsgType, CStifTFwIfProt::EMsgRemote ) );
// Srcid. i.e. master id
User::LeaveIfError( req->AppendId( aSlave->iMasterId ) );
// DstId is device broadcast
User::LeaveIfError(
req->AppendId( SETID( DEVID( aSlave->iSlaveDevId ), 0 ) ) );
// Run command
User::LeaveIfError(
req->Append( CStifTFwIfProt::CmdType, CStifTFwIfProt::ECmdRun ) );
// Run parameters
User::LeaveIfError(
req->Append( CStifTFwIfProt::RunParams,
CStifTFwIfProt::ERunModule,
startInfo->iModule ) );
User::LeaveIfError(
req->Append( CStifTFwIfProt::RunParams,
CStifTFwIfProt::ERunTestcasenum,
startInfo->iCaseNum ));
if( startInfo->iIniFile.Length() > 0 )
{
// Initialization file
__TRACE( KMessage, (_L("ini: %S"), &startInfo->iIniFile ));
User::LeaveIfError(
req->Append( CStifTFwIfProt::RunParams,
CStifTFwIfProt::ERunInifile,
startInfo->iIniFile ) );
}
if( startInfo->iConfig.Length() > 0 )
{
// Initialization file
__TRACE( KMessage, (_L("config: %S"), &startInfo->iConfig ));
User::LeaveIfError(
req->Append( CStifTFwIfProt::RunParams,
CStifTFwIfProt::ERunTestcasefile,
startInfo->iConfig ));
}
//Title (must be given between quotation marks in case of any spaces inside
if( startInfo->iTitle.Length() > 0 )
{
__TRACE(KMessage, (_L("title: %S"), &startInfo->iTitle));
TName tit;
tit.Format(_L("\"title=%S\""), &startInfo->iTitle);
User::LeaveIfError(req->Append(tit));
}
User::LeaveIfError(
iTestCombiner->TestModuleIf().RemoteSend( req->Message() ) );
remote->iRemoteState = CRemoteTestCase::ECaseRunSent;
remote->iSlaveId = aSlave->iSlaveDevId;
remote->StartL();
User::LeaveIfError( iTestCombiner->iTestCases.Append( remote ) );
if( iTestCombiner->iLoopIsUsed )
{
User::LeaveIfError( iTestCombiner->iLoopAllocationArray.Append( remote ) );
}
CleanupStack::Pop( remote );
CleanupStack::PopAndDestroy( startInfo );
iTestCombiner->iRunningTests++;
// Start timer
iRemoteTimer->SetTimerActive( iTestCombiner->iRemoteTimeout );
iState = ERunnerRemote;
CleanupStack::PopAndDestroy( req );
return EFalse;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteRemoteTestCtlL
Description: Handles remote testcase controlling
Parameters: CStifItemParser* aItem: in: script line
CTestCase* aTestCase: in: test case
TInt aCmd: in: remote command
Return Values: ETrue: continue script file execution
EFalse: stop script file execution and wait response
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteRemoteTestCtlL( CStifItemParser* /* aItem */,
CTestCase* aTestCase,
TInt aCmd )
{
CRemoteTestCase* caseInfo = ( CRemoteTestCase* ) aTestCase;
CStifTFwIfProt* req = CStifTFwIfProt::NewL();
CleanupStack::PushL( req );
req->CreateL();
// Remote message
User::LeaveIfError(
req->Append( CStifTFwIfProt::MsgType, CStifTFwIfProt::EMsgRemote ) );
// Srcid. i.e. master id
//req->AppendId( ( TUint32 ) this );
User::LeaveIfError(
req->AppendId( KRemoteProtocolMasterId ));
// DstId, i.e.slave id
User::LeaveIfError(
req->AppendId( caseInfo->iSlaveId ));
switch( aCmd )
{
case TTCKeywords::EPause:
if( caseInfo->iRemoteState != CRemoteTestCase::ECaseRunning )
{
__TRACE( KError, (_L("Test case with testid %S not running"),
&aTestCase->TestId() ));
User::Leave( KErrGeneral );
}
// Pause command
User::LeaveIfError(
req->Append( CStifTFwIfProt::CmdType, CStifTFwIfProt::ECmdPause ) );
caseInfo->iRemoteState = CRemoteTestCase::ECasePauseSent;
break;
case TTCKeywords::EResume:
if( caseInfo->iRemoteState != CRemoteTestCase::ECasePaused )
{
__TRACE( KError, (_L("Test case with testid %S not paused"),
&aTestCase->TestId() ));
User::Leave( KErrGeneral );
}
// Resume command
User::LeaveIfError(
req->Append( CStifTFwIfProt::CmdType, CStifTFwIfProt::ECmdResume ));
caseInfo->iRemoteState = CRemoteTestCase::ECaseResumeSent;
break;
case TTCKeywords::ECancel:
if( ( caseInfo->iRemoteState != CRemoteTestCase::ECaseRunning ) &&
( caseInfo->iRemoteState != CRemoteTestCase::ECasePaused ) )
{
__TRACE( KError, (_L("Test case with testid %S not running"),
&aTestCase->TestId() ));
User::Leave( KErrGeneral );
}
// Cancel command
User::LeaveIfError(
req->Append( CStifTFwIfProt::CmdType, CStifTFwIfProt::ECmdCancel ));
caseInfo->iRemoteState = CRemoteTestCase::ECaseCancelSent;
break;
case TTCKeywords::EComplete:
if( caseInfo->iRemoteState == CRemoteTestCase::ECaseCompleted )
{
__TRACE( KError, (_L("Test case with testid %S already completed"),
&aTestCase->TestId() ));
CleanupStack::PopAndDestroy( req );
return ETrue;
}
else
{
iTestCombiner->iWaitTestCase = aTestCase->TestId();
CleanupStack::PopAndDestroy( req );
return EFalse;
}
default:
// Should never come here
User::Leave( KErrGeneral );
}
User::LeaveIfError(
iTestCombiner->TestModuleIf().RemoteSend( req->Message() ) );
// Start timer
iRemoteTimer->SetTimerActive( iTestCombiner->iRemoteTimeout );
iState = ERunnerRemote;
CleanupStack::PopAndDestroy( req );
return EFalse;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteRemoteEventCtlL
Description: Handles remote event controlling
Parameters: CStifItemParser* aItem: in: script line
CSlaveInfo* aSlave: in: slave info
TInt aCmd: in: remote command
Return Values: ETrue: continue script file execution
EFalse: stop script file execution and wait response
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteRemoteEventCtlL( CStifItemParser* aItem,
CSlaveInfo* aSlave,
TInt aCmd )
{
TPtrC eventName;
// Get event name
TInt ret = aItem->GetNextString( eventName );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Event name was not given for remote")));
User::Leave( KErrArgument );
}
if( aCmd == TTCKeywords::EWait )
{
TEventTc* event = aSlave->GetEvent( eventName );
if( event == NULL )
{
__TRACE( KError, (_L("Waited event %S not requested"),
&eventName ) );
User::Leave( KErrNotFound );
}
iState = ERunnerRunning;
SetActive();
event->WaitEvent( iStatus );
// Execution continue if waited event is set or after it is set
return EFalse;
}
CStifTFwIfProt* req = CStifTFwIfProt::NewL();
CleanupStack::PushL( req );
req->CreateL();
// Remote message
User::LeaveIfError(
req->Append( CStifTFwIfProt::MsgType, CStifTFwIfProt::EMsgRemote ));
// Srcid. i.e. master id
User::LeaveIfError( req->AppendId( aSlave->iMasterId ) );
// DstId, i.e.slave device id
User::LeaveIfError( req->AppendId( aSlave->iSlaveDevId ) );
switch( aCmd )
{
// Event control cases
case TTCKeywords::ERequest:
{
TEventTc* event = aSlave->GetEvent( eventName );
if( event != NULL )
{
__TRACE( KError, (_L("Event %S already requested"),
&eventName ) );
User::Leave( KErrNotFound );
}
event = new( ELeave ) TEventTc( (TName&)eventName,
iTestCombiner->iLog );
CleanupStack::PushL( event );
User::LeaveIfError( aSlave->iEvents.Append( event ) );
CleanupStack::Pop( event );
// Request event
User::LeaveIfError(
req->Append( CStifTFwIfProt::CmdType, CStifTFwIfProt::ECmdRequest ));
}
break;
case TTCKeywords::ERelease:
{
TEventIf* event = NULL;
TInt count = aSlave->iEvents.Count();
TInt i = 0;
for( ; i < count; i++ )
{
if( aSlave->iEvents[i]->Name() == eventName )
{
event = aSlave->iEvents[i];
break;
}
}
if( event == NULL )
{
__TRACE( KError, (_L("Event not found %S"),
&eventName ) );
User::Leave( KErrNotFound );
}
aSlave->iEvents.Remove(i);
delete event;
// Release event
User::LeaveIfError(
req->Append( CStifTFwIfProt::CmdType, CStifTFwIfProt::ECmdRelease ));
}
break;
case TTCKeywords::ESet:
{
__TRACE( KPrint, (_L("JIRA51 CTestRunner::ExecuteRemoteEventCtlL case ESet")));
User::LeaveIfError(req->Append(CStifTFwIfProt::CmdType, CStifTFwIfProt::ECmdSetEvent));
break;
}
case TTCKeywords::EUnset:
{
__TRACE( KPrint, (_L("JIRA51 CTestRunner::ExecuteRemoteEventCtlL case EUnset")));
User::LeaveIfError(req->Append(CStifTFwIfProt::CmdType, CStifTFwIfProt::ECmdUnsetEvent));
break;
}
default:
// Should never come here
User::Leave( KErrGeneral );
}
// Event name
User::LeaveIfError( req->Append( eventName ) );
if(aCmd == TTCKeywords::ESet)
{
TPtrC stateEvent;
TInt ret = aItem->GetNextString(stateEvent);
if(ret == KErrNotFound) //indication event - add indicate keyword to message
{
User::LeaveIfError(req->Append(CStifTFwIfProt::EventType, TEventIf::EIndication));
}
else if(ret == KErrNone) //possibly state event
{
if(stateEvent.Compare(_L("state")) == 0) //state event - add state keyword to message
{
User::LeaveIfError(req->Append(CStifTFwIfProt::EventType, TEventIf::EState));
}
else //syntax error in the line
{
__TRACE(KError, (_L("Unknown keyword %S"), &stateEvent));
}
}
else //syntax error in the line
{
__TRACE(KError, (_L("Unknown keyword (2) %S"), &stateEvent));
}
}
User::LeaveIfError(
iTestCombiner->TestModuleIf().RemoteSend( req->Message() ) );
// Start timer
iRemoteTimer->SetTimerActive( iTestCombiner->iRemoteTimeout );
iState = ERunnerRemote;
CleanupStack::PopAndDestroy( req );
return EFalse;
}
TBool CTestRunner::ExecuteRemoteSetUnsetEventL(CStifItemParser* aItem,
CSlaveInfo* aSlave,
TInt aCmd)
{
TPtrC eventName;
// Get event name
TInt ret = aItem->GetNextString(eventName);
if(ret != KErrNone)
{
__TRACE(KError, (_L("Event name was not given for remote")));
User::Leave(KErrArgument);
}
// Check if this is a state set, indication set, or unset command
TInt caseNumber = -1;
if(aCmd == TTCKeywords::ESet)
{
TPtrC stateEvent;
TInt ret = aItem->GetNextString(stateEvent);
if(ret == KErrNotFound) //indication event - add indicate keyword to message
{
caseNumber = 1;
}
else if(ret == KErrNone) //possibly state event
{
if(stateEvent.Compare(_L("state")) == 0) //state event - add state keyword to message
{
caseNumber = 0;
}
else //syntax error in the line
{
__TRACE(KError, (_L("Unknown keyword %S"), &stateEvent));
}
}
else //syntax error in the line
{
}
}
else //TTCKeyword::EUnset
{
caseNumber = 2;
}
if(caseNumber == -1)
{
__TRACE(KError, _L("Should never occur"));
}
// Build new descriptor with command to run hardcoded suevent test case on remote phone
HBufC* cmd = HBufC::NewL(100);
CleanupStack::PushL(cmd);
TPtr cmdPtr(cmd->Des());
cmdPtr.Copy(eventName);
// Run remotely test case
RDebug::Print(_L("CTestRunner::ExecuteRemoteSetUnsetEventL calling ExecuteRemoteRun"));
TBool retval = ExecuteRemoteRunL(aItem, aSlave, cmd, caseNumber);
// Clean data
CleanupStack::PopAndDestroy(cmd);
RDebug::Print(_L("CTestRunner::ExecuteRemoteSetUnsetEventL end"));
return retval;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteRemoteSendReceiveL
Description: Handles asynchronous remote sendreceive controlling
Parameters: CStifItemParser* aItem: in: script line
CSlaveInfo* aSlave: in: slave info
Return Values: ETrue: continue script file execution
EFalse: stop script file execution and wait response
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteRemoteSendReceiveL( CStifItemParser* aItem,
CSlaveInfo* aSlave )
{
CStifTFwIfProt* req = CStifTFwIfProt::NewL();
CleanupStack::PushL( req );
// Create CRemoteSendReceive object for taking sendreceive information to
// save for later use.
CRemoteSendReceive* remoteSendReceive =
CRemoteSendReceive::NewL( iTestCombiner );
CleanupStack::PushL( remoteSendReceive );
req->CreateL();
// Remote message
User::LeaveIfError(
req->Append( CStifTFwIfProt::MsgType, CStifTFwIfProt::EMsgRemote ) );
// Srcid. i.e. master id
User::LeaveIfError( req->AppendId( aSlave->iMasterId ) );
// DstId, i.e.slave device id
User::LeaveIfError( req->AppendId( aSlave->iSlaveDevId ) );
// Run command
User::LeaveIfError( req->Append(
CStifTFwIfProt::CmdType, CStifTFwIfProt::ECmdSendReceive ) );
// asynchronous sendreceive's parameters
TPtrC tmp;
while( aItem->GetNextString( tmp ) == KErrNone )
{
// Append parameters
User::LeaveIfError( req->Append( tmp ) );
}
User::LeaveIfError(
iTestCombiner->TestModuleIf().RemoteSend( req->Message() ) );
remoteSendReceive->iRemoteState = CRemoteSendReceive::ECaseSend;
remoteSendReceive->iSlaveId = aSlave->iSlaveDevId;
// Take CRemoteSendReceive object to save in array. This can be used in
// TestCombiner when handling responses.
User::LeaveIfError(
iTestCombiner->iSendReceive.Append( remoteSendReceive ) );
if( iTestCombiner->iLoopIsUsed )
{
User::LeaveIfError(
iTestCombiner->iLoopAllocationArray.Append( remoteSendReceive ) );
}
CleanupStack::Pop( remoteSendReceive );
// Start timer
iRemoteTimer->SetTimerActive( iTestCombiner->iRemoteTimeout );
iState = ERunnerRemote;
CleanupStack::PopAndDestroy( req );
// Return EFalse=>start waiting response...
return EFalse;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteRemoteUnknownL
Description: Forwards messages as such
Parameters: CStifItemParser* aItem: in: script line
CSlaveInfo* aSlave: in: slave info
TInt aCmd: in: remote command
Return Values: ETrue: continue script file execution
EFalse: stop script file execution and wait response
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteRemoteUnknownL( CStifItemParser* aItem,
CSlaveInfo* aSlave,
TDesC& aCommand )
{
CStifTFwIfProt* req = CStifTFwIfProt::NewL();
CleanupStack::PushL( req );
req->CreateL();
// Remote message
User::LeaveIfError(
req->Append( CStifTFwIfProt::MsgType, CStifTFwIfProt::EMsgRemote ) );
// Srcid. i.e. master id
User::LeaveIfError( req->AppendId( aSlave->iMasterId ) );
// DstId, i.e.slave device id
User::LeaveIfError( req->AppendId( aSlave->iSlaveDevId ) );
// Append command name
User::LeaveIfError( req->Append( aCommand ) );
TPtrC tmp;
while( aItem->GetNextString( tmp ) == KErrNone )
{
// Append parameters
User::LeaveIfError( req->Append( tmp ) );
}
User::LeaveIfError(
iTestCombiner->TestModuleIf().RemoteSend( req->Message() ) );
// Start timer
iRemoteTimer->SetTimerActive( iTestCombiner->iRemoteTimeout );
iState = ERunnerRemote;
CleanupStack::PopAndDestroy( req );
return EFalse;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ReceiveResponseL
Description: Handles responce received from slave
Parameters: TDesC& aMsg: in: message
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ReceiveResponseL( TDesC& aMsg )
{
__TRACE( KMessage, (_L("ReceiveResponse")));
iRemoteTimer->Cancel();
CStifTFwIfProt* msg = CStifTFwIfProt::NewL();
CleanupStack::PushL( msg );
TRAPD( err, msg->SetL( aMsg ); );
if( err != KErrNone )
{
__TRACE( KError, (_L("Response parsing failed")));
User::Leave( err );
}
// Check protocol identifiers
if( ( msg->SrcDevId() == 0 ) ||
( msg->DstDevId() == 0 ) ||
( msg->DstTestId() == 0 ) )
{
__TRACE( KError, (_L("Illegal deviceid received")));
User::Leave( KErrGeneral );
}
// This is master, cannot receive anything else but responses
if( msg->iMsgType != CStifTFwIfProt::EMsgResponse )
{
__TRACE( KError, (_L("Illegal message received %d"),
msg->iMsgType ));
User::Leave( KErrGeneral );
}
TBool continueTask = ETrue;
switch( msg->iRespType )
{
case CStifTFwIfProt::EMsgReserve:
{
__TRACE( KMessage, (_L("ReceiveResponse Reserve")));
if( iState != ERunnerAllocate )
{
__TRACE( KError, (_L("Response reserve received in illegal state %d"),
iState ));
User::Leave( KErrGeneral );
}
// Check protocol Src test id
if( msg->SrcTestId() != 0 )
{
__TRACE( KError, (_L("Illegal deviceid received")));
User::Leave( KErrGeneral );
}
if( msg->iResult != KErrNone )
{
__TRACE( KError, (_L("Response with error %d"), msg->iResult ));
User::Leave( msg->iResult );
}
CSlaveInfo* slave = NULL;
TInt count = iTestCombiner->iSlaveArray.Count();
for( TInt index = 0; index < count; index++ )
{
slave = iTestCombiner->iSlaveArray[index];
if( ( slave->iSlaveDevId == 0 ) &&
( slave->iState == CSlaveInfo::ESlaveReserveSent ) )
{
break;
}
slave = NULL;
}
if( slave == NULL )
{
User::Leave( KErrNotFound );
}
slave->iSlaveDevId = msg->SrcId();
slave->iState = CSlaveInfo::ESlaveReserved;
__TRACE( KMessage, (_L("Slave allocated succesfully, continue execution")));
}
break;
case CStifTFwIfProt::EMsgRelease:
{
__TRACE( KMessage, (_L("ReceiveResponse Release")));
if( iState != ERunnerFree )
{
__TRACE( KError, (_L("Response release received in illegal state %d"),
iState ));
User::Leave( KErrGeneral );
}
// Check protocol Src test id
if( msg->SrcTestId() != 0 )
{
__TRACE( KError, (_L("Illegal deviceid received")));
User::Leave( KErrGeneral );
}
if( msg->iResult != KErrNone )
{
__TRACE( KError, (_L("Response with error %d"), msg->iResult ));
User::Leave( msg->iResult );
}
CSlaveInfo* slave = iTestCombiner->GetSlave( msg->SrcId() );
if( slave == NULL )
{
User::Leave( KErrNotFound );
}
slave->iState = CSlaveInfo::ESlaveReleased;
__TRACE( KMessage, (_L("Slave freed succesfully, continue execution")));
}
break;
case CStifTFwIfProt::EMsgRemote:
{
__TRACE( KMessage, (_L("ReceiveResponse Remote")));
switch( msg->iCmdType )
{
case CStifTFwIfProt::ECmdRun:
continueTask = ReceiveResponseRunL( *msg );
break;
case CStifTFwIfProt::ECmdPause:
case CStifTFwIfProt::ECmdResume:
case CStifTFwIfProt::ECmdCancel:
continueTask = ReceiveResponseTestCtlL( *msg );
break;
case CStifTFwIfProt::ECmdRequest:
case CStifTFwIfProt::ECmdRelease:
case CStifTFwIfProt::ECmdSetEvent:
case CStifTFwIfProt::ECmdUnsetEvent:
continueTask = ReceiveResponseEventCtlL( *msg );
break;
case CStifTFwIfProt::ECmdSendReceive:
continueTask = ReceiveResponseSendReceiveL( *msg );
break;
default:
continueTask = ReceiveResponseUnknownL( *msg );
break;
}
}
break;
default:
User::Leave( KErrGeneral );
}
CleanupStack::PopAndDestroy( msg );
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ReceiveResponseRunL
Description: Handles response for run received from slave
Parameters: CStifTFwIfProt& aMsg: in: protocol message parser
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ReceiveResponseRunL( CStifTFwIfProt& aMsg )
{
TPtrC tmp = CStifTFwIfProt::RunStatus(aMsg.iRunStatus);
__TRACE( KMessage, (_L("ReceiveResponse Remote Run %S"), &tmp ));
TBool continueTask = ETrue;
switch( aMsg.iRunStatus )
{
case CStifTFwIfProt::ERunStarted:
{
// Locate testcase
CRemoteTestCase* tcase =
iTestCombiner->GetRemoteTestRunSent( GETDEVID( aMsg.SrcId() ) );
if( tcase == NULL )
{
__TRACE( KError, (_L("Testcase not found")));
User::Leave( KErrNotFound );
}
tcase->iSlaveId = aMsg.SrcId();
tcase->iRemoteState = CRemoteTestCase::ECaseRunning;
}
break;
case CStifTFwIfProt::ERunError:
case CStifTFwIfProt::ERunReady:
{
// Locate testcase
CRemoteTestCase* tcase =
iTestCombiner->GetRunningRemoteTest( aMsg.SrcId() );
if( tcase == NULL )
{
__TRACE( KError, (_L("Testcase not found")));
User::Leave( KErrNotFound );
}
switch( aMsg.iResultCategory )
{
case CStifTFwIfProt::EResultNormal:
tcase->iResult.iCaseExecutionResultType =
TFullTestResult::ECaseExecuted;
tcase->iResult.iTestResult.iResult = aMsg.iResult;
tcase->iResult.iCaseExecutionResultCode = 0;
break;
case CStifTFwIfProt::EResultPanic:
tcase->iResult.iCaseExecutionResultType =
TFullTestResult::ECasePanic;
tcase->iResult.iTestResult.iResult = KErrGeneral;
tcase->iResult.iCaseExecutionResultCode = aMsg.iResult;
break;
case CStifTFwIfProt::EResultException:
tcase->iResult.iCaseExecutionResultType =
TFullTestResult::ECaseException;
tcase->iResult.iTestResult.iResult = KErrGeneral;
tcase->iResult.iCaseExecutionResultCode = aMsg.iResult;
break;
case CStifTFwIfProt::EResultTimeout:
tcase->iResult.iCaseExecutionResultType =
TFullTestResult::ECaseTimeout;
tcase->iResult.iTestResult.iResult = KErrGeneral;
tcase->iResult.iCaseExecutionResultCode = aMsg.iResult;
break;
case CStifTFwIfProt::EResultLeave:
tcase->iResult.iCaseExecutionResultType =
TFullTestResult::ECaseLeave;
tcase->iResult.iTestResult.iResult = KErrGeneral;
tcase->iResult.iCaseExecutionResultCode = aMsg.iResult;
break;
default:
User::Leave( KErrGeneral );
}
if( ( tcase->iRemoteState == CRemoteTestCase::ECaseCancelled ) ||
( tcase->iRemoteState == CRemoteTestCase::ECaseRunSent ) )
{
// Complete for cancelled testcase or error for run request,
// set runner active again
continueTask = ETrue;
}
else
{
// Continued from Complete in state ECaseRunning
continueTask = EFalse;
}
tcase->iRemoteState = CRemoteTestCase::ECaseCompleted;
__TRACE( KMessage, (_L("ReceiveResponse Remote Run rq comp")));
TRequestStatus* rs = &tcase->iStatus;
// Complete testcase
User::RequestComplete( rs, KErrNone );
}
break;
default:
// Should never come here
User::Leave( KErrGeneral );
}
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ReceiveResponseTestCtlL
Description: Handles responses for test control commands
received from slave
Parameters: CStifTFwIfProt& aMsg: in: protocol message parser
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ReceiveResponseTestCtlL( CStifTFwIfProt& aMsg )
{
if( aMsg.iResult != KErrNone )
{
__TRACE( KError, (_L("Response with error %d"), aMsg.iResult ));
User::Leave( aMsg.iResult );
}
// Locate testcase
CRemoteTestCase* tcase = iTestCombiner->GetRemoteTest( aMsg.SrcId() );
if( tcase == NULL )
{
__TRACE( KError, (_L("Testcase not found")));
User::Leave( KErrNotFound );
}
TBool continueTask = ETrue;
switch( aMsg.iCmdType )
{
case CStifTFwIfProt::ECmdPause:
__TRACE( KMessage, (_L("ReceiveResponse Remote Pause")));
if( tcase->iRemoteState != CRemoteTestCase::ECasePauseSent )
{
__TRACE( KError, (_L("Pause response received in illegal state")));
User::Leave( KErrGeneral );
}
tcase->iRemoteState = CRemoteTestCase::ECasePaused;
// Start pause timer if timeout was given
if( ( iPausedTestCase.Length() > 0 ) &&
( iPauseTime != 0 ) )
{
continueTask = EFalse;
iState = ERunnerWaitTimeout;
iPauseTimer.After( iStatus, iPauseTime*1000 );
SetActive();
}
break;
case CStifTFwIfProt::ECmdResume:
__TRACE( KMessage, (_L("ReceiveResponse Remote Resume")));
if( tcase->iRemoteState != CRemoteTestCase::ECaseResumeSent )
{
__TRACE( KError, (_L("Resume response received in illegal state")));
User::Leave( KErrGeneral );
}
tcase->iRemoteState = CRemoteTestCase::ECaseRunning;
break;
case CStifTFwIfProt::ECmdCancel:
__TRACE( KMessage, (_L("ReceiveResponse Remote Cancel")));
if( tcase->iRemoteState != CRemoteTestCase::ECaseCancelSent )
{
__TRACE( KError, (_L("Cancel response received in illegal state")));
User::Leave( KErrGeneral );
}
tcase->iRemoteState = CRemoteTestCase::ECaseCancelled;
// Need to wait Run response with KErrCancel
continueTask = EFalse;
// Start timer
iRemoteTimer->SetTimerActive( iTestCombiner->iRemoteTimeout );
break;
default:
// Should never come here
User::Leave( KErrGeneral );
}
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ReceiveResponseEventCtlL
Description: Handles responses for event system control commands
received from slave
Parameters: CStifTFwIfProt& aMsg: in: protocol message parser
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ReceiveResponseEventCtlL( CStifTFwIfProt& aMsg )
{
CSlaveInfo* slave = iTestCombiner->GetSlave( aMsg.SrcId() );
if( slave == NULL )
{
User::Leave( KErrNotFound );
}
TBool continueTask = ETrue;
switch( aMsg.iCmdType )
{
case CStifTFwIfProt::ECmdRequest:
{
__TRACE( KMessage, (_L("ReceiveResponse Request")));
TEventTc* event = slave->GetEvent( aMsg.iEventName );
if( event == NULL )
{
User::Leave( KErrNotFound );
}
switch( aMsg.iEventStatus )
{
case CStifTFwIfProt::EEventActive:
__TRACE( KMessage, (_L("Event %S active"), &aMsg.iEventName ));
break;
case CStifTFwIfProt::EEventSet:
__TRACE( KMessage, (_L("Event %S set"), &aMsg.iEventName ));
// Set event
event->SetEvent( aMsg.iEventType );
continueTask = EFalse;
break;
case CStifTFwIfProt::EEventError:
__TRACE( KMessage, (_L("Event %S error %d"),
&aMsg.iEventName, aMsg.iResult ));
User::Leave( aMsg.iResult );
default:
User::Leave( KErrGeneral );
}
}
break;
case CStifTFwIfProt::ECmdRelease:
__TRACE( KMessage, (_L("ReceiveResponse Release")));
if( aMsg.iResult != KErrNone )
{
__TRACE( KError, (_L("Response with error %d"), aMsg.iResult ));
User::Leave( aMsg.iResult );
}
// Everything ok, no need to do anything
break;
case CStifTFwIfProt::ECmdSetEvent:
__TRACE( KMessage, (_L("ReceiveResponse SetEvent")));
if( aMsg.iResult != KErrNone )
{
__TRACE( KError, (_L("Response with error %d"), aMsg.iResult ));
User::Leave( aMsg.iResult );
}
// Everything ok, no need to do anything
break;
case CStifTFwIfProt::ECmdUnsetEvent:
__TRACE( KMessage, (_L("ReceiveResponse Unset")));
if( aMsg.iResult != KErrNone )
{
__TRACE( KError, (_L("Response with error %d"), aMsg.iResult ));
User::Leave( aMsg.iResult );
}
// Everything ok, no need to do anything
break;
default:
// Should never come here
User::Leave( KErrGeneral );
}
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ReceiveResponseSendReceiveL
Description: Handles responses for asynchronous sendreceive commands
received from slave
Parameters: CStifTFwIfProt& aMsg: in: protocol message parser
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ReceiveResponseSendReceiveL( CStifTFwIfProt& aMsg )
{
TPtrC tmp = CStifTFwIfProt::RunStatus(aMsg.iRunStatus);
__TRACE( KMessage, (
_L("ReceiveResponseSendReceiveL asynchronous Remote SendReceive %S"),
&tmp ) );
TBool continueTask = EFalse;
switch( aMsg.iRunStatus )
{
case CStifTFwIfProt::ERunStarted:
{
// Locate CRemoteSendReceive object
CRemoteSendReceive* sendreceive =
iTestCombiner->GetRemoteSendReceive( GETDEVID(
aMsg.SrcId() ) );
if( sendreceive == NULL )
{
__TRACE( KError, (_L("CRemoteSendReceive object not found")));
User::Leave( KErrNotFound );
}
sendreceive->iRemoteState = CRemoteSendReceive::ECaseSend;
// continueTask is EFalse=>stop script file execution
break;
}
case CStifTFwIfProt::ERunError:
case CStifTFwIfProt::ERunReady:
{
if( aMsg.iResult != KErrNone )
{
__TRACE( KError, (_L("sendreceive response with error %d"), aMsg.iResult ));
User::Leave( aMsg.iResult );
}
// Locate CRemoteSendReceive object
CRemoteSendReceive* sendreceive =
iTestCombiner->GetRemoteSendReceive( aMsg.SrcId() );
if( sendreceive == NULL )
{
__TRACE( KError, (_L("CRemoteSendReceive object not found")));
User::Leave( KErrNotFound );
}
// continueTask is ETrue=>continue script file execution
continueTask = ETrue;
sendreceive->iRemoteState = CRemoteSendReceive::ECaseCompleted;
__TRACE( KMessage, (
_L( "ReceiveResponseSendReceiveL asynchronous Remote SendReceive rq comp" ) ) );
break;
}
default:
{
// Should never come here
User::Leave( KErrGeneral );
}
}
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ReceiveResponseUnknownL
Description: Handles responses for unspecified commands
Parameters: CStifTFwIfProt& aMsg: in: protocol message parser
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ReceiveResponseUnknownL( CStifTFwIfProt& aMsg )
{
CSlaveInfo* slave = iTestCombiner->GetSlave( aMsg.SrcId() );
if( slave == NULL )
{
User::Leave( KErrNotFound );
}
if( aMsg.iResult != KErrNone )
{
__TRACE( KError, (_L("Response with error %d"), aMsg.iResult ));
User::Leave( aMsg.iResult );
}
return ETrue;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ParseOptArgL
Description: Parses optional argument
Parameters: const TDesC& aOptArg: in:
argument-value pair (format arg=value)
TPtrC& aArg: out: parsed argument
TPtrC& aVal: out: parsed value
Return Values: None
Errors/Exceptions: Leaves if parsing fails.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::ParseOptArgL( const TDesC& aOptArg, TPtrC& aArg, TPtrC& aVal)
{
_LIT( KErrMsgUnknownOrIllegalKeyword, "Unknown or illegal argument %S" );
_LIT( KErrMsgValueNotDefined, "Value of optional argument %S is not defined" );
TInt length = aOptArg.Length();
for( TInt i=0; i < length; i++)
{
// find the '=' sign
if( aOptArg[i] == '=' )
{
if( i+1 >= length )
{
__TRACE( KError,
(_L("Illegal optional argument(%S), no value"),
&aOptArg ));
TPtrC tmp = aOptArg.Left( i );
iRunErrorMessage.Format( KErrMsgValueNotDefined, &tmp );
User::Leave( KErrArgument );
}
aArg.Set( aOptArg.Left( i ) );
aVal.Set( aOptArg.Mid( i+1 ) );
__TRACE( KMessage, ( _L( "arg '%S', val '%S'" ),
&aArg, &aVal ));
return;
}
}
__TRACE( KError, (_L("Illegal optional argument(%S)"), &aOptArg ));
iRunErrorMessage.Format( KErrMsgUnknownOrIllegalKeyword, &aOptArg );
User::Leave( KErrArgument );
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: CancelTestCases
Description: Cancels all running testcases
Parameters: None
Return Values: None
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::CancelTestCases()
{
__TRACEFUNC();
TInt count = iTestCombiner->iTestCases.Count();
for( TInt i=0; i < count; i++ )
{
if( iTestCombiner->iTestCases[i]->State() ==
CTCTestCase::ETestCaseRunning )
{
iTestCombiner->iTestCases[i]->Cancel();
}
}
if( ( iTestCombiner->iRunningTests == 0 ) &&
iTestCombiner->iSchedulerActive )
{
// Stop execution
CActiveScheduler::Current()->Stop();
iTestCombiner->iSchedulerActive = EFalse;
return;
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: SetRunnerActive
Description: Set CTestRunner active and complete.
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::SetRunnerActive()
{
__TRACEFUNC();
if( IsActive() )
{
__TRACE( KError, ( _L("Runner already active %d"), iState ));
User::Panic( KTestRunner, KErrInUse );
}
// Update state
iState = ERunnerRunning;
iStatus = KRequestPending;
TRequestStatus* rs = &iStatus;
SetActive();
User::RequestComplete( rs, KErrNone );
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: CheckUnsetEvent
Description: Check unset event.
Parameters: None
Return Values: ETrue: Unset event completed
EFalse: No unset event pending
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
TBool CTestRunner::CheckUnsetEvent()
{
if( iEvent.Name().Length() == 0 )
{
return EFalse;
}
__TRACE( KMessage, (_L("Unset event completed") ));
// Check if some testmodule below has still event request pending
if( iTestCombiner->UnsetEvent( iEvent, iStatus ) == EFalse )
{
// No event request pending
// then check other testmodules (may block)
TInt res = iTestCombiner->TestModuleIf().Event( iEvent );
if( res != KErrNone )
{
iTestCombiner->iResult = res;
}
__TRACE( KPrint, (_L("Unset: Complete") ) );
iEvent.SetName( _L("") );
// Proceed testcase section execution
SetRunnerActive();
}
else
{
iState = ERunnerWaitUnset;
// Wait for unset to complete
SetActive();
}
return ETrue;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteLoopL
Description: Handle the loop keyword operations.
Parameters: CStifItemParser* aItem: in: Pointer to parsed item object.
Return Values: None.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestRunner::ExecuteLoopL( CStifItemParser* aItem )
{
_LIT( KErrMsgLoopNestedLoop, "Loop: Nested loops are not supported " );
_LIT( KErrMsgLoopInvalidLoopCountParam, "Loop: No loop count value given for loop or value has invalid format" );
_LIT( KErrMsgLoopUnknownUnexpectedOption, "Loop: Unknown or unexpected loop option");
_LIT( KErrMsgLoopPasslimitInvalidValue, "Loop: No passlimit value given for loop or value has invalid format" );
_LIT( KErrMsgLoopPasslimitNotInRange, "Loop: Passlimit value is lower than 0 or higher than loop count" );
__TRACEFUNC();
if( iLoopTimes != 0 )
{
__TRACE( KError, (_L("ExecuteLoopL: Nested loop are not supported")));
iRunErrorMessage = KErrMsgLoopNestedLoop;
User::Leave( KErrNotSupported );
}
iLoopTimes = 0;
iLoopCounter = 0;
iPasslimitEnabled = EFalse;
iTimedLoop = EFalse;
if( aItem->GetNextInt( iLoopTimes ) != KErrNone )
{
__TRACE( KError, (_L("ExecuteLoopL: No loop count value given for loop")));
iRunErrorMessage = KErrMsgLoopInvalidLoopCountParam;
User::Leave( KErrArgument );
}
__TRACE( KMessage, (_L("ExecuteLoopL: Loop for %d times" ), iLoopTimes ) );
//Check loop options
TPtrC option;
TInt ret = aItem->GetNextString(option);
if(ret == KErrNone)
{
if(option.Compare(_L("msec")) == 0) //time loop option
{
iTimedLoop = ETrue;
iStartTime.HomeTime();
iExpectedLoopTime = TInt64(iLoopTimes) * TInt64(1000); //convert to micro seconds
__TRACE(KMessage, (_L("ExecuteLoopL: Timed loop for %d msec" ), iLoopTimes));
ret = aItem->GetNextString(option); //Get next option
}
}
if(ret == KErrNone)
{
if(option.Compare(_L("passlimit")) == 0) //passlimit option
{
iPasslimit = 0;
if( aItem->GetNextInt( iPasslimit ) != KErrNone )
{
__TRACE( KError, ( _L( "ExecuteLoopL: No passlimit value given for loop." ) ) );
iRunErrorMessage = KErrMsgLoopPasslimitInvalidValue;
User::Leave( KErrArgument );
}
__TRACE( KMessage, ( _L( "ExecuteLoopL: Passlimit set on %d" ), iPasslimit ) );
//Check if passlimit has valid value
if(iPasslimit < 0 || (iPasslimit > iLoopTimes && !iTimedLoop))
{
__TRACE( KError, ( _L( "ExecuteLoopL: Passlimit value is lower than 0 or higher than loop count." ) ) );
iRunErrorMessage = KErrMsgLoopPasslimitNotInRange;
User::Leave( KErrArgument );
}
iPasslimitEnabled = ETrue;
ret = aItem->GetNextString(option); //Get next option
}
}
if(ret == KErrNone)
{
__TRACE( KError, ( _L( "ExecuteLoopL: Unknown or unexpected loop option [%S]" ), &option ) );
iRunErrorMessage = KErrMsgLoopUnknownUnexpectedOption;
User::Leave( KErrNotSupported );
}
iPassedIterationCnt = 0;
iLoopStartPos = iTestCombiner->iSectionParser->GetPosition();
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteEndLoopL
Description: Handle the endloop keyword operations.
Parameters: None.
Return Values: TBool: Boolean value for indicate can testing continue.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteEndLoopL()
{
__TRACEFUNC();
// Fail test case if there was no loop started
if(iTestCombiner->iLoopIsUsed == EFalse)
{
__TRACE(KError, (_L("Encountered \'endloop\' without \'loop\'. Aborting test case.")));
iTestCombiner->iResult = KErrGeneral;
iState = ERunnerError;
CancelTestCases();
return ETrue; // Test case file parsing can be continue
}
TBool iterationFailed = EFalse; //Has last iteration failed (at least one of test cases has failed)
// First we check is all test cases that is set to run inside the loop
// completed. If not completed we wait until test case completes.
// Is some loop executions fails that is not allowed then loop execution
// will be stopped and error result is given to TestCombiner
for( TInt s = 0; s < iTestCombiner->iTestCases.Count(); s++ )
{
CTestCase* testCase = (CTestCase*)iTestCombiner->iTestCases[s];
if( testCase == NULL )
{
__TRACE( KError, (_L("ExecuteEndLoopL: CTestCase object not found") ) );
return ETrue;
}
// Check that testCase object is allocated inside the loop
TBool isLoopTestCase( EFalse );
for( TInt p = 0; p < iTestCombiner->iLoopAllocationArray.Count(); p++ )
{
if( iTestCombiner->iLoopAllocationArray[p] == testCase )
{
isLoopTestCase = ETrue;
break;
}
}
// testCase object is allocated inside loop
if( isLoopTestCase )
{
// Test case is completed
//if( testCase->State() == CTCTestCase::ETestCaseCompleted )
if(testCase->IsCompletelyFinished())
{
// Check normal test result
if( testCase->iExpectedResultCategory == TFullTestResult:: ECaseExecuted )
{
// Normal completion, check result
if( testCase->iResult.iTestResult.iResult != testCase->iExpectedResult )
{
__TRACE( KPrint, ( _L( "Test failed, expect(%d) != result(%d)"),
testCase->iExpectedResult,
testCase->iResult.iTestResult.iResult ));
//If no passlimit is provided behave in old way
if( !iPasslimitEnabled )
{
// We return the first error result as aResult
if( testCase->iResult.iTestResult.iResult != KErrNone )
{
iTestCombiner->iScriptFailed = testCase->iResult.iCaseExecutionResultCode;
iTestCombiner->iScriptFailedDescription.Copy(testCase->iResult.iTestResult.iResultDes);
}
else
{
iTestCombiner->iScriptFailed = testCase->iResult.iCaseExecutionResultCode;
iTestCombiner->iScriptFailedDescription.Copy(_L("Test case has not finished with expected result (in loop)."));
}
iState = ERunnerError;
CancelTestCases();
return ETrue; // Test case file parsing can be continue
}
else
{
// Set flag that one of test cases has failed, so whole iteration is failed
iterationFailed = ETrue;
}
}
}
// Abnormal completion, i.e. panic, leave, exception or timeout
else
{
if( testCase->iResult.iCaseExecutionResultCode != testCase->iExpectedResult )
{
__TRACE( KPrint, ( _L( "Test failed, expect errorcode(%d) != result(%d)"),
testCase->iExpectedResult,
testCase->iResult.iCaseExecutionResultCode ) );
//If no passlimit is provided behave in old way
if( !iPasslimitEnabled )
{
// We return the first error result as aResult
iTestCombiner->iScriptFailed = testCase->iResult.iCaseExecutionResultCode;
iTestCombiner->iScriptFailedDescription.Copy(_L("Test case has not finished with expected execution error (in loop)."));
iState = ERunnerError;
// Return error from here
CancelTestCases();
return ETrue; // Test case file parsing can be continue
}
else
{
// Set flag that one of test cases has failed, so whole iteration is failed
iterationFailed = ETrue;
}
}
// Requested testcase is completed already,
// proceed testcase execution
__TRACE( KMessage, (_L("Already completed")));
}
} // End "Test case is completed"
// Test case is running state, set to wait the test case complete
else if( testCase->State() == CTCTestCase::ETestCaseRunning )
{
// Wait testcase to complete. If no id there should generate
// id that test case complete will be handled correctly
if( testCase->TestId().Length() == 0 )
{
TPtrC generatedTestId( _L( "stif" ) );
delete testCase->iTestId;
testCase->iTestId = generatedTestId.Alloc();
}
iTestCombiner->iWaitTestCase.Copy( testCase->TestId() );
// Stop testcase execution until testcase completed
iState = ERunnerWaitTestCase;
// Go to beginning of the endloop
User::LeaveIfError(
iTestCombiner->iSectionParser->SetPosition( iEndLoopStartPos ));
// Testing is ongoing, test case file parsing cannot
// be continue. Next line will be run when some AO
// will be complete and allow parsing to continue
return EFalse;
}
else if(testCase->State() == CTCTestCase::ETestCaseCompleted)
{
// Go to beginning of the endloop
User::LeaveIfError(iTestCombiner->iSectionParser->SetPosition(iEndLoopStartPos));
// Testing is ongoing, test case file parsing cannot
// be continue. Next line will be run when some AO
// will be complete and allow parsing to continue
return ETrue;
}
else
{
// This should newer happen
__TRACE( KError, (_L("ExecuteEndLoopL: Illegal branch") ) );
}
}
} // end for-loop
iLoopCounter++;
__TRACE( KMessage, (_L("ExecuteLineL: Loop executed for %d times" ),
iLoopCounter ) );
//If passlimit (endurance) is enabled, we must check if any of test case in this iteration has failed
if( iPasslimitEnabled && !iterationFailed )
{
iPassedIterationCnt++;
}
TTime currTime;
currTime.HomeTime();
//if( iLoopCounter < iLoopTimes )
if(((!iTimedLoop) && (iLoopCounter < iLoopTimes)) //Normal loop
||
iTimedLoop && (currTime.MicroSecondsFrom(iStartTime) < iExpectedLoopTime)) //Timed loop
{
// Go to beginning of the loop
User::LeaveIfError(
iTestCombiner->iSectionParser->SetPosition( iLoopStartPos ));
}
else
{
// End looping
if( iPasslimitEnabled )
{
__TRACE(KMessage, (_L("ExecuteLoopL: Loop executed. Iterations: %d, passed: %d, expected: %d"), iLoopCounter, iPassedIterationCnt, iPasslimit));
}
iLoopCounter = 0;
iLoopTimes = 0;
iLoopStartPos = 0;
// Loop related initializations
iTestCombiner->iLoopIsUsed = EFalse;
//--LOOPBUG-- Do not zero counter because there could be some test cases run before the loop (Stif-83)
//--LOOPBUG-- iTestCombiner->iRunningTests = 0;
//If passlimit was given and number of passed test is less then expected, stop execution of combiner's test case
if( iPasslimitEnabled && iPassedIterationCnt < iPasslimit )
{
__TRACE( KMessage, ( _L( "ExecuteLoopL: Loop has failed (passlimit). Finishing with KErrCompletion." ) ) );
iTestCombiner->iScriptFailed = KErrCompletion;
iTestCombiner->iScriptFailedDescription = _L("Loop has not reached passlimit requirement.");
iState = ERunnerError;
CancelTestCases();
return ETrue; // Test case file parsing can be continue
}
else if( iPasslimitEnabled && iPassedIterationCnt >= iPasslimit )
{
__TRACE( KMessage, ( _L( "ExecuteLoopL: Loop has passed (passlimit)" ) ) );
}
iPassedIterationCnt = 0;
iPasslimit = 0;
iPasslimitEnabled = EFalse;
}
// Loop time is executed, free allocations that is allocated during loop
TInt a( 0 );
TInt b( 0 );
for( b = 0; b < iTestCombiner->iLoopAllocationArray.Count(); b++ )
{
//for( a = 0; a < iTestCombiner->iLoopAllocationArray.Count(); a++ )
for( a = 0; a < iTestCombiner->iTestCases.Count(); a++ )
{
if( a < iTestCombiner->iTestCases.Count() && iTestCombiner->iTestCases[a] == iTestCombiner->iLoopAllocationArray[b] )
{
delete iTestCombiner->iTestCases[a];
iTestCombiner->iTestCases.Remove( a );
}
}
}
for( b = 0; b < iTestCombiner->iLoopAllocationArray.Count(); b++ )
{
//for( a = 0; a < iTestCombiner->iLoopAllocationArray.Count(); a++ )
for( a = 0; a < iTestCombiner->iTestModules.Count(); a++ )
{
if( a < iTestCombiner->iTestModules.Count() && iTestCombiner->iTestModules[a] == iTestCombiner->iLoopAllocationArray[b] )
{
delete iTestCombiner->iTestModules[a];
iTestCombiner->iTestModules.Remove( a );
}
}
}
for( b = 0; b < iTestCombiner->iLoopAllocationArray.Count(); b++ )
{
//for( a = 0; a < iTestCombiner->iLoopAllocationArray.Count(); a++ )
for( a = 0; a < iTestCombiner->iEventArray.Count(); a++ )
{
if( a < iTestCombiner->iEventArray.Count() && iTestCombiner->iEventArray[a] == iTestCombiner->iLoopAllocationArray[b] )
{
delete iTestCombiner->iEventArray[a];
iTestCombiner->iEventArray.Remove( a );
}
}
}
for( b = 0; b < iTestCombiner->iLoopAllocationArray.Count(); b++ )
{
//for( a = 0; a < iTestCombiner->iLoopAllocationArray.Count(); a++ )
for( a = 0; a < iTestCombiner->iSlaveArray.Count(); a++ )
{
if( a < iTestCombiner->iSlaveArray.Count() && iTestCombiner->iSlaveArray[a] == iTestCombiner->iLoopAllocationArray[b] )
{
delete iTestCombiner->iSlaveArray[a];
iTestCombiner->iSlaveArray.Remove( a );
}
}
}
for( b = 0; b < iTestCombiner->iLoopAllocationArray.Count(); b++ )
{
//for( a = 0; a < iTestCombiner->iLoopAllocationArray.Count(); a++ )
for( a = 0; a < iTestCombiner->iSendReceive.Count(); a++ )
{
if( a < iTestCombiner->iSendReceive.Count() && iTestCombiner->iSendReceive[a] == iTestCombiner->iLoopAllocationArray[b] )
{
delete iTestCombiner->iSendReceive[a];
iTestCombiner->iSendReceive.Remove( a );
}
}
}
// Test operation can be continued
return ETrue; // Test case file parsing can be continue
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of CRemoteTimer class
member functions.
-------------------------------------------------------------------------------
*/
// MACROS
#ifdef LOGGER
#undef LOGGER
#endif
#define LOGGER iTestRunner->iTestCombiner->iLog
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: CRemoteTimer
Method: CRemoteTimer
Description: Default constructor
C++ default constructor can NOT contain any code, that
might leave.
Parameters: CTestRunner* aTestRunner: in: Backpointer to CTestRunner
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteTimer::CRemoteTimer( CTestCombiner* aTestCombiner ):
CActive( CActive::EPriorityLow ), // Executed with lowest priority
iState( ETimerIdle ),
iTestCombiner( aTestCombiner )
{
CActiveScheduler::Add( this );
}
/*
-------------------------------------------------------------------------------
Class: CRemoteTimer
Method: ConstructL
Description: Symbian OS second phase constructor
Symbian OS default constructor can leave.
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
void CRemoteTimer::ConstructL()
{
iTimer.CreateLocal();
}
/*
-------------------------------------------------------------------------------
Class: CRemoteTimer
Method: NewL
Description: Two-phased constructor.
Parameters: CTestCombiner* aTestCombiner: in: Backpointer to CTestCombiner
Return Values: CRemoteTimer*: new object
Errors/Exceptions: Leaves if new or ConstructL leaves
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteTimer* CRemoteTimer::NewL( CTestCombiner* aTestCombiner )
{
CRemoteTimer* self = new (ELeave) CRemoteTimer( aTestCombiner );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop();
return self;
}
/*
-------------------------------------------------------------------------------
Class: CRemoteTimer
Method: ~CRemoteTimer
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteTimer::~CRemoteTimer()
{
Cancel();
iTimer.Close();
}
/*
-------------------------------------------------------------------------------
Class: CRemoteTimer
Method: RunL
Description: Derived from CActive, handles testcase execution.
Parameters: None.
Return Values: None.
Errors/Exceptions: Leaves on error situations.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CRemoteTimer::RunL()
{
if( iState != ETimerPending )
{
User::Panic( KRemoteTimer, KErrGeneral );
}
if( iStatus.Int() != KErrNone )
{
User::Panic( KRemoteTimer, KErrDied );
}
iState = ETimerIdle;
iTestCombiner->RemoteTimeout();
}
/*
-------------------------------------------------------------------------------
Class: CRemoteTimer
Method: DoCancel
Description: Derived from CActive handles the Cancel
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
void CRemoteTimer::DoCancel()
{
iTimer.Cancel();
iState = ETimerIdle;
}
/*
-------------------------------------------------------------------------------
Class: CRemoteTimer
Method: SetTimerActive
Description: Starts timer
Parameters: TTimeIntervalMicroSeconds32 anInterval: in: Timeout
Return Values: None.
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
void CRemoteTimer::SetTimerActive( TTimeIntervalMicroSeconds32 anInterval )
{
if( iState != ETimerIdle )
{
User::Panic( KRemoteTimer, KErrGeneral );
}
iState = ETimerPending;
iTimer.After( iStatus, anInterval );
SetActive();
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of CRemoteReceiver class
member functions.
-------------------------------------------------------------------------------
*/
// MACROS
#ifdef LOGGER
#undef LOGGER
#endif
#define LOGGER iTestCombiner->iLog
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: CRemoteReceiver
Method: CRemoteReceiver
Description: Default constructor
C++ default constructor can NOT contain any code, that
might leave.
Parameters: CTestCombiner* aTestCombiner: in: Backpointer to CTestCombiner
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteReceiver::CRemoteReceiver( CTestCombiner* aTestCombiner ):
CActive( CActive::EPriorityStandard ),
iState( EReceiverIdle ),
iTestCombiner( aTestCombiner )
{
CActiveScheduler::Add( this );
__TRACEFUNC();
}
/*
-------------------------------------------------------------------------------
Class: CRemoteReceiver
Method: ConstructL
Description: Symbian OS second phase constructor
Symbian OS default constructor can leave.
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
void CRemoteReceiver::ConstructL()
{
}
/*
-------------------------------------------------------------------------------
Class: CRemoteReceiver
Method: NewL
Description: Two-phased constructor.
Parameters: CTestCombiner* aTestCombiner: in: Backpointer to CTestCombiner
Return Values: CRemoteReceiver*: new object
Errors/Exceptions: Leaves if new or ConstructL leaves
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteReceiver* CRemoteReceiver::NewL( CTestCombiner* aTestCombiner )
{
CRemoteReceiver* self = new (ELeave) CRemoteReceiver( aTestCombiner );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop();
return self;
}
/*
-------------------------------------------------------------------------------
Class: CRemoteReceiver
Method: ~CRemoteReceiver
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
CRemoteReceiver::~CRemoteReceiver()
{
__TRACEFUNC();
Cancel();
}
/*
-------------------------------------------------------------------------------
Class: CRemoteReceiver
Method: StartL
Description: Activates receiving.
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CRemoteReceiver::Start()
{
__TRACEFUNC();
__ASSERT_ALWAYS( iState == EReceiverIdle,
User::Panic( KRemoteReceiver, KErrGeneral ) );
iState = EReceiverPending;
iTestCombiner->TestModuleIf().RemoteReceive( iRemoteMsg, iStatus );
SetActive();
}
/*
-------------------------------------------------------------------------------
Class: CRemoteReceiver
Method: RunL
Description: Derived from CActive, handles testcase execution.
Parameters: None.
Return Values: None.
Errors/Exceptions: Leaves on error situations.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CRemoteReceiver::RunL()
{
__TRACEFUNC();
__ASSERT_ALWAYS( iState == EReceiverPending,
User::Panic( KRemoteReceiver, KErrGeneral ) );
iState = EReceiverIdle;
iTestCombiner->ReceiveResponse( iRemoteMsg );
}
/*
-------------------------------------------------------------------------------
Class: CRemoteReceiver
Method: DoCancel
Description: Derived from CActive handles the Cancel
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CRemoteReceiver::DoCancel()
{
__TRACEFUNC();
iTestCombiner->TestModuleIf().RemoteReceiveCancel();
}
// ================= OTHER EXPORTED FUNCTIONS =================================
/*
-------------------------------------------------------------------------------
Function: LibEntryL
Description: Polymorphic Dll Entry Point
Parameters: None.
Return Values: CTestCombiner*: pointer to new CTestCombiner
Errors/Exceptions: Leaves if NewL leaves.
Status: Approved
-------------------------------------------------------------------------------
*/
EXPORT_C CTestCombiner* LibEntryL()
{
return CTestCombiner::NewL();
}
// End of File