/*
* 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 file contains TestScripter implementation.
*
*/
// INCLUDE FILES
#include <StifTestEventInterface.h>
#include <StifLogger.h>
#include "TestScripter.h"
#include "TestKeywords.h"
#include "Logging.h"
#include "TestEngineClient.h"
#include "SettingServerClient.h"
#include "TestScripterInternal.h"
#include "SubTestCaseRunner.h"
#include <stifinternal/TestServerClient.h>
#include <stifinternal/UiEnvProxy.h>
// EXTERNAL DATA STRUCTURES
// None
// EXTERNAL FUNCTION PROTOTYPES
// None
// CONSTANTS
// None
const TUid KPropertyCat =
{
0x101FB3DE
};
const TUint KPropertyKey = 0x00000001;
// MACROS
#ifdef LOGGER
#undef LOGGER
#endif
#define LOGGER iLog
// LOCAL CONSTANTS AND MACROS
_LIT( KExecute, "Execute");
// Printing priorities
const TInt KPrintPriExec = 400;
// MODULE DATA STRUCTURES
// None
// LOCAL FUNCTION PROTOTYPES
// None
// FORWARD DECLARATIONS
// None
// ==================== LOCAL FUNCTIONS =======================================
/*
-------------------------------------------------------------------------------
Class: -
Method: CallBack
Description: (Function pointer) Called from CScriptBase class. Generic
method for call back operations from Test Script Class to
TestScripter.
Parameters: CTestScripter* aTestScripter: in: Pointer to TestScripter
TStifTSCallBackType aCallType: in: Call back type
const TDesC& aLine: in Script line
Return Values: TInt: Symbian error code
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CallBack( CTestScripter* aTestScripter,
TStifTSCallBackType aCallType,
const TDesC& aLine )
{
TInt ret( 0 );
switch( aCallType )
{
case EStifTSCallClass:
{
ret = aTestScripter->CallTestClass( aLine );
break;
}
case EStifTSGetObject:
{
ret = aTestScripter->GetTestScriptObject( aLine );
break;
}
default:
{
ret = KErrArgument;
break;
}
}
return ret;
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of CTestScripter class
member functions.
-------------------------------------------------------------------------------
*/
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: CTestScripter
Description: Default constructor
C++ default constructor can NOT contain any code, that
might leave.
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
CTestScripter::CTestScripter() :
iObjects(NULL)
{
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: ConstructL
Description: Symbian OS second phase constructor
Symbian OS default constructor can leave.
Parameters: None
Return Values: None
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestScripter::ConstructL()
{
__TRACE( KPrint, ( _L("New TestScripter") ) );
iStdLog = CStifLogger::NewL( KTestScripterLogDir,
KTestScripterLogFile );
iLog = iStdLog;
iOOMIgnoreFailure = EFalse; // OFF for default
iCheckHeapBalance = EFalse; // No checking heap balance by default
//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);
}
// Close Setting server session
settingServer.Close();
iAddTestCaseTitleToLogName = loggerSettings.iAddTestCaseTitle;
// Initialize parser variables
iCurrentParser = NULL;
iCurrentParserReadFirstLine = EFalse;
TUint ProperKey = RProcess().Id().Id();
TInt err = RProperty::Define(KPropertyCat, ProperKey, RProperty::EInt);
iObjects = new (ELeave) RPointerArray<TScriptObject> ;
err = RProperty::Set(KPropertyCat, ProperKey, (TInt) iObjects);
User::LeaveIfError(err);
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: NewL
Description: Two-phased constructor.
Parameters: None
Return Values: CTestScripter*: new object
Errors/Exceptions: Leaves if new or ConstructL leaves.
Status: Draft
-------------------------------------------------------------------------------
*/
CTestScripter* CTestScripter::NewL()
{
CTestScripter* self = new (ELeave) CTestScripter();
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop();
return self;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: ~CTestScripter
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
CTestScripter::~CTestScripter()
{
iTestObjects.ResetAndDestroy();
iTestModules.ResetAndDestroy();
iDefinedIni.ResetAndDestroy();
iDefinedRuntime.ResetAndDestroy();
iDefinedLocal.ResetAndDestroy();
iParserStack.ResetAndDestroy();
iGlobalObjects.ResetAndDestroy();
iSharedTestModules.ResetAndDestroy();
iObjects->Reset();
iTestObjects.Close();
iTestModules.Close();
iDefinedIni.Close();
iGlobalObjects.Close();
iDefinedRuntime.Close();
iDefinedLocal.Close();
iParserStack.Close();
iObjects->Close();
iSharedTestModules.Close();
iCurrentParser = NULL;
delete iSectionParser;
delete iTestRunner;
delete iObjects;
iLog = NULL;
delete iStdLog;
iStdLog = NULL;
delete iTCLog;
iTCLog = NULL;
TUint ProperKey = RProcess().Id().Id();
TInt err = RProperty::Delete(KPropertyCat, ProperKey);
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
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 CTestScripter::InitL( TFileName& aIniFile,
TBool /*aFirstTime*/ )
{
__TRACEFUNC();
if( aIniFile.Length() > 0 )
{
// Read initialization from test case file
ReadInitializationL( aIniFile, iDefinedIni );
}
return KErrNone;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: GetTestCases
Description: GetTestCases is used to inquired test cases
Parameters: const TFileName& aConfigFile: in: Test case file
RPointerArray<RTestEngine::TTestCaseInfo>& aTestCases: out:
Array of TestCases
Return Values: KErrNone: Success
Symbian OS error code
Errors/Exceptions: Leaves if CStifParser::SectionL leaves
Leaves if CStifParser::NextSectionL leaves
Leaves if memory allocation fails
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestScripter::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;
// Open test case file
TRAPD( err,
parser = CStifParser::NewL( _L(""),
aConfigFile,
CStifParser::ECStyleComments ) );
if( err != KErrNone )
{
__TRACE( KError, (_L("Given test case script file [%S] not found"),
&aConfigFile ) );
__RDEBUG( (_L("Given test case script file [%S] not found"),
&aConfigFile ) );
return err;
}
CleanupStack::PushL( parser );
CStifSectionParser* section;
TPtrC tmp;
TInt index = 0;
TInt ret = KErrNone;
// Find first section
section = parser->SectionL( KTestStartTag, KTestEndTag );
if( section == NULL )
{
ret = KErrNotFound;
}
else
{
// Parse all sections
while( section )
{
CleanupStack::PushL( section );
// Get title line
if( section->GetLine( TTestKeywords::Keyword( TTestKeywords::ETitle ),
tmp, ENoTag ) != KErrNone )
{
__TRACE( KError, (_L("Title not given for test case")));
User::Leave( KErrNotFound );
}
else
{
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;
// Get timeout if defined
CStifItemParser* item = section->GetItemLineL(
TTestKeywords::Keyword( TTestKeywords::ETimeout ) );
if( item )
{
TInt timeout; // In milliseconds
ret = item->GetInt(
TTestKeywords::Keyword( TTestKeywords::ETimeout ),
timeout );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Illegal timeout")));
User::Leave( ret );
}
// Type cast timeout to TInt64
tc->iTimeout = TInt64( timeout ) * 1000;
__TRACE( KMessage, (_L("Timeout: %i"), tc->iTimeout.Int64() ));
}
// Get priority if defined
item = section->GetItemLineL(
TTestKeywords::Keyword( TTestKeywords::EPriority ) );
if( item )
{
// First try to interpret as integer
ret = item->GetInt(
TTestKeywords::Keyword( TTestKeywords::EPriority ),
tc->iPriority );
if( ret != KErrNone )
{
TPtrC priority;
// If priority was not given as integer, it must be
// one of the predefined values
ret = item->GetString(
TTestKeywords::Keyword( TTestKeywords::EPriority ),
priority );
if( ret != KErrNone )
{
__TRACE( KError, (_L("Illegal priority")));
User::Leave( ret );
}
switch( TTestKeywords::Parse( priority,
TTestKeywords::Priority ) )
{
case TTestKeywords::EPriHigh:
tc->iPriority = TTestCaseInfo::EPriorityHigh;
break;
case TTestKeywords::EPriNormal:
tc->iPriority = TTestCaseInfo::EPriorityNormal;
break;
case TTestKeywords::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: CTestScripter
Method: GetConstantValue
Description: Internal fuction to get const value defined in
[Define]...[Enddefine] section of script file
GetConstantValue gets const value defined in [Define]...[Enddefine]
section of script file
Parameters: const TDesC& aName: in: constant name
TDes& avalue: out: constant value
Return Values: KErrNone: Value is returned succesfully.
KErrNotFound: Constant was not found
Any other SymbianOS error
-------------------------------------------------------------------------------
*/
EXPORT_C TInt CTestScripter::GetConstantValue( const TDesC& aName, TDes& aValue )
{
__TRACEFUNC();
TInt count = iDefinedLocal.Count();
for(TInt i = 0; i < count; i++)
{
if(iDefinedLocal[i]->Name() == aName)
{
aValue.Copy(iDefinedLocal[i]->Value());
return KErrNone;
}
}
count = iDefinedIni.Count();
for( TInt i = 0; i < count; i++ )
{
if( iDefinedIni[i]->Name() == aName )
{
aValue.Copy( iDefinedIni[i]->Value() );
return KErrNone;
}
}
count = iDefinedRuntime.Count();
for( TInt i = 0; i < count; i++ )
{
if( iDefinedRuntime[i]->Name() == aName )
{
aValue.Copy( iDefinedRuntime[i]->Value() );
return KErrNone;
}
}
return KErrNotFound;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: RunTestCaseL
Description: Run a specified testcase.
RunTestCaseL is used to run an individual test case.
Parameters: const TInt aCaseNumber: in: Testcase number
const TFileName& aConfig: in: Test case file
TTestResult& aResult: out: test case result
Return Values: KErrNone: Test case started succesfully.
KErrNotFound: Testcase not found
KErrUnknown: Unknown TestScripter error
Any other SymbianOS error
Errors/Exceptions: Leaves if GetTestCaseL leaves
Leaves if RunTestL leaves
Leaves if memory allocation fails
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestScripter::RunTestCaseL( const TInt aCaseNumber,
const TFileName& aConfig,
TTestResult& aResult )
{
// Heap is checked by test server
//__UHEAP_MARK;
__TRACEFUNC();
//Open new log file with test case title in file name
if(iAddTestCaseTitleToLogName)
{
//Delete test case logger if exists
if(iTCLog)
{
delete iTCLog;
iTCLog = NULL;
}
TFileName logFileName;
TName title;
TestModuleIf().GetTestCaseTitleL(title);
logFileName.Format(KTestScripterLogFileWithTitle, &title);
iTCLog = CStifLogger::NewL(KTestScripterLogDir, logFileName);
iLog = iTCLog;
}
__TRACE( KMessage, (_L("\n\n***Testcase started***")));
// Remove locally defined variables
iDefinedLocal.ResetAndDestroy();
// Remove existing function parsers (there shouldn't be any)
iParserStack.ResetAndDestroy();
// Keep file name of config file
iConfig = aConfig;
// Read initialization from test case file
ReadInitializationL( aConfig, iDefinedRuntime );
// Get case from test case file
iSectionParser = GetTestCaseL( aCaseNumber, aConfig );
iCurrentParser = iSectionParser;
iCurrentParserReadFirstLine = EFalse;
// Check parsing result
if( iSectionParser == NULL )
{
__TRACE( KError, (_L("***Parsing testcase failed***\n\n")));
// Delete runtime defines
iDefinedRuntime.ResetAndDestroy();
//__UHEAP_MARKEND;
return KErrNotFound;
}
// When option is set in cfg file, on EKA2 env memory leaking is enabled
TInt memCellsBef = 0; //memory in current thread allocated before the test case is run
TInt memCellsAft = 0; //memory in current thread allocated after the test case has run
memCellsBef = User::Heap().Count();
__TRACE(KMessage, (_L("Allocated memory cells before the test case: %d"), memCellsBef));
__TRACE(KMessage, (_L("Memory usage in global objects before the execution:")));
TInt beforeGlobalMemCells = TraceGlobalObjectsMemoryUsage();
CActiveScheduler* activeScheduler =
new ( ELeave ) CActiveScheduler();
CleanupStack::PushL( activeScheduler );
if ( CActiveScheduler::Current() == NULL )
{
CActiveScheduler::Install( activeScheduler );
}
// Run the given testcase described in iSectionParser section
RunTestL();
iTestObjects.ResetAndDestroy();
iTestModules.ResetAndDestroy();
iObjects->Reset();
// TestScripter must stop Active Scheduler after test
// object is destroyed. Otherwise if unexpected error occurs
// handling is erronous.
CleanupStack::PopAndDestroy( activeScheduler );
// Check for memory leak.
// It is reported in log always, but result of test case is changed only
// when option in cfg file is enabled.
memCellsAft = User::Heap().Count();
__TRACE(KMessage, (_L("Allocated memory cells after the test case: %d"), memCellsAft));
__TRACE(KMessage, (_L("Memory usage in global objects after the execution:")));
TInt afterGlobalMemCells = TraceGlobalObjectsMemoryUsage();
memCellsAft = memCellsAft - afterGlobalMemCells + beforeGlobalMemCells;
// if there is a difference report memory leak
if(memCellsAft != memCellsBef)
{
__TRACE(KError, (_L("Memory leak, %d cell(s) is missing"), memCellsAft - memCellsBef));
if(iCheckHeapBalance)
{
// Memory leaks detection is disabled for UI components testing
if ( !( TestModuleIf().UITesting() ) )
{
UpdateTestCaseResult(KErrGeneral, _L("Memory leak has occured"));
}
}
}
// Delete parser and set current parser to NULL
iCurrentParser = NULL;
delete iSectionParser;
iSectionParser = NULL;
// Erase config file name
iConfig = KNullDesC;
// Return result
aResult = iResult;
if( iResult.iResult == KErrNone )
{
__TRACE( KPrint, (_L("***Testcase PASSED***\n\n")));
TestModuleIf().Printf( KPrintPriNorm, _L("TestScripter"),
_L("***Testcase PASSED***\n\n"));
}
else
{
__TRACE( KPrint, (_L("***Testcase FAILED***\n\n")));
TestModuleIf().Printf( KPrintPriNorm, _L("TestScripter"),
_L("***Testcase FAILED***\n\n"));
}
User::After(300000);
// Delete runtime defines
iDefinedRuntime.ResetAndDestroy();
//__UHEAP_MARKEND;
//If log was replaced then restore it
if(iAddTestCaseTitleToLogName)
{
iLog = iStdLog;
delete iTCLog;
iTCLog = NULL;
}
return KErrNone;
}
TInt CTestScripter::TraceGlobalObjectsMemoryUsage()
{
__TRACEFUNC();
TInt moduleNumber = iSharedTestModules.Count();
TInt shareObjNumber = iGlobalObjects.Count();
__TRACE(KMessage, (_L("There are %d item(s) in shared modules list"),moduleNumber));
__TRACE(KMessage, (_L("There are %d item(s) in shared objects list"),shareObjNumber));
TInt listNumber = 0;
if(moduleNumber != 0)
{
listNumber++;
__TRACE(KMessage, (_L("Shared module list used 1 cell.")));
__TRACE(KMessage, (_L("There are %d shared module(s), they used %d cells"), moduleNumber , moduleNumber * 2));
}
if(shareObjNumber != 0)
{
listNumber++;
__TRACE(KMessage, (_L("Shared object list used 1 cell.")));
__TRACE(KMessage, (_L("There are %d shared object(s), they used %d cells"), shareObjNumber, shareObjNumber * 4));
}
TInt result = listNumber + moduleNumber * 2 + shareObjNumber * 4;
__TRACE(KMessage, (_L("There are %d cells used by shared objects and their modules."), result));
return result;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
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 CTestScripter::ReadInitializationL(
const TDesC& aIniFile,
RPointerArray<CDefinedValue>& aDefines )
{
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 ) );
CStifSectionParser* 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 = aDefines.Count();
TInt i = 0;
for( ; i < count; i++ )
{
if( aDefines[i]->Name() == name )
{
// Update existing
aDefines[i]->SetValueL( value );
__TRACE(KMessage, (_L("Update define [%S]: [%S]"), &name, &value));
break;
}
}
if( i == count)
{
// New define, store it
CDefinedValue* define = CDefinedValue::NewL( name, value );
CleanupStack::PushL( define );
User::LeaveIfError( aDefines.Append( define ) );
CleanupStack::Pop( define );
}
CleanupStack::PopAndDestroy( item );
item = section->GetNextItemLineL();
}
CleanupStack::PopAndDestroy( section );
section = parser->NextSectionL(KDefineStartTag, KDefineEndTag);
}
//Read StifSettings section and find value for CheckHeapBalance.
//(In cfg file in settings section User may also set CapsModifier
// option. This is handled in TestServerClient.cpp in
// RTestServer::GetCapsModifier method).
section = parser->SectionL(KStifSettingsStartTag, KStifSettingsEndTag);
if(section)
{
CleanupStack::PushL(section);
__TRACE(KMessage, (_L("Read stif settings")));
TPtrC value;
CStifItemParser* item = section->GetItemLineL(_L(""));
while(item)
{
CleanupStack::PushL(item);
__TRACE( KMessage, (_L("Got settings line")));
if(item->GetString(_L("CheckHeapBalance="), value) == KErrNone)
{
__TRACE(KMessage, (_L("Got CheckHeapBalance item, value=%S"), &value));
if(value.Compare(_L("off")) == 0)
{
iCheckHeapBalance = EFalse;
}
else if(value.Compare(_L("on")) == 0)
{
iCheckHeapBalance = ETrue;
}
else
{
__TRACE(KError, (_L("Value '%S' for CheckHeapBalance setting is not supported. Aborting"), &value));
User::Leave(KErrNotSupported);
}
}
CleanupStack::PopAndDestroy(item);
item = section->GetNextItemLineL();
}
CleanupStack::PopAndDestroy(section);
}
//Read data section
section = parser->SectionL(KDataStartTag, KDataEndTag);
if(section)
{
CleanupStack::PushL(section);
__TRACE(KMessage, (_L("Read data section")));
CStifItemParser* item = section->GetItemLineL(_L(""));
while(item)
{
CleanupStack::PushL(item);
__TRACE( KMessage, (_L("Got data section line")));
TPtrC inifile;
TPtrC inisection;
if(item->GetString(_L("File"), inifile) == KErrNone)
{
__TRACE(KMessage, (_L("Got ini file name: %S"), &inifile));
iCurrentFile.Zero();
if(inifile.Find(_L("\\"))==KErrNotFound)
{
iCurrentFile.Append(_L("c:\\TestFramework\\"));
}
iCurrentFile.Append(inifile);
TPtrC alias;
err=item->GetNextString(alias);
__TRACE(KMessage, (_L("Got ini file alias: %S"), &alias));
iCurrentFileAlias.Zero();
if(err==KErrNone)
{
iCurrentFileAlias.Copy(alias);
}
else
{
TParsePtr filespec(iCurrentFile);
iCurrentFileAlias.Copy(filespec.NameAndExt());
}
}
else if(item->GetString(_L("Section"), inisection) == KErrNone)
{
__TRACE(KMessage, (_L("Got Section name: %S"), &inisection));
iCurrentSection.Zero();
iCurrentSection.Copy(inisection);
TPtrC alias;
TInt err=item->GetNextString(alias);
__TRACE(KMessage, (_L("Got Section alias: %S"), &alias));
iCurrentSectionFileAlias.Zero();
if(err==KErrNone)
{
iCurrentSectionFileAlias.Copy(alias);
}
else
{
iCurrentSectionFileAlias.Copy(iCurrentSection);
}
TParsePtr filespec(iCurrentFile);
CStifParser* parser=CStifParser::NewL(filespec.DriveAndPath(),filespec.NameAndExt());
TBuf<KMaxFileName> section;
section.Append(_L("["));
section.Append(iCurrentSection);
section.Append(_L("]"));
CStifSectionParser* sectionparser=parser->SectionL(section,KNullDesC,1,EFalse);
CStifItemParser* itemparser=sectionparser->GetItemLineL(KNullDesC);
while(itemparser)
{
itemparser->SetParsingType(CStifItemParser::EQuoteStyleParsing);
TPtrC temp;
itemparser->Remainder(temp);
__TRACE(KMessage, (_L("Got item string: %S"), &temp));
iCurrentKey.Zero();
iCurrentKey.Append(KFileFlag);
iCurrentKey.Append(iCurrentFileAlias);
iCurrentKey.Append(KSectionFlag);
iCurrentKey.Append(iCurrentSectionFileAlias);
iCurrentKey.Append(KKeyFlag);
TBuf<KMaxFileName> tempkey;
TBuf<KMaxFileName> tempvalue;
TLex lex(temp);
TChar ch;
while((ch = lex.Get()) != 0 )
{
while ((ch = lex.Peek()) != '=')
lex.Inc();
tempkey.Append(lex.MarkedToken());
lex.Inc();
lex.Mark();
break;
}
tempkey.TrimAll();
iCurrentKey.Append(tempkey);
iKeys.Append(iCurrentKey);
tempvalue.Append(lex.Remainder());
tempvalue.TrimAll();
iCurrentvalues.Zero();
iCurrentvalues.Copy(tempvalue);
iValues.Append(iCurrentvalues);
delete itemparser;
itemparser=NULL;
itemparser=sectionparser->GetNextItemLineL();
}
delete sectionparser;
delete parser;
}
CleanupStack::PopAndDestroy(item);
item = section->GetNextItemLineL();
}
CleanupStack::PopAndDestroy(section);
}
CleanupStack::PopAndDestroy( parser );
}
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
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: CStifSectionParser*: pointer to test case section
Errors/Exceptions: Leaves if CStifParser::NewL leaves
Leaves if CStifParser::SectionL leaves
Leaves if memory allocation fails
Status: Draft
-------------------------------------------------------------------------------
*/
CStifSectionParser* CTestScripter::GetTestCaseL( const TInt aCaseNumber,
const TFileName& aConfig )
{
__TRACEFUNC();
CStifParser* parser = NULL;
TRAPD( err,
parser = CStifParser::NewL( _L(""),
aConfig,
CStifParser::ECStyleComments ); );
if( err != KErrNone )
{
__TRACE( KError, (_L("Test case file [%S] not found"), &aConfig ));
User::Leave( err );
}
CleanupStack::PushL( parser );
CStifSectionParser* section = NULL;
TRAP( err,
section =parser->SectionL( KTestStartTag, KTestEndTag, aCaseNumber ););
if( err != KErrNone )
{
__TRACE( KError,
(_L("Section [%S/%d] not found"), &aConfig, aCaseNumber ));
User::Leave( err );
}
CleanupStack::PopAndDestroy( parser );
return section;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: GetSubL
Description: Get specified function (sub) from stored config file.
Parameters: const TDesC& aSubName: in: function name
Return Values: CStifSectionParser*: pointer to test function section
Errors/Exceptions: Leaves if CStifParser::NewL leaves
Leaves if CStifParser::SectionL leaves
Leaves if memory allocation fails
Status: Draft
-------------------------------------------------------------------------------
*/
CStifSectionParser* CTestScripter::GetSubL(const TDesC& aSubName)
{
__TRACE(KMessage, (_L("Searching sub [%S]."), &aSubName));
// Check if config file is set
if(iConfig.Length() == 0)
{
__TRACE(KError, (_L("Searching sub [%S]. Config file is not set."), &aSubName));
User::Leave(KErrBadName);
}
// Create parser
CStifParser* parser = NULL;
CStifSectionParser* section = NULL;
TRAPD(err,
parser = CStifParser::NewL(_L(""), iConfig, CStifParser::ECStyleComments);
);
if(err != KErrNone)
{
__TRACE(KError, (_L("Searching sub [%S]. Error [%d] when loading config file [%S]."), &aSubName, err, &iConfig));
User::Leave(err);
}
CleanupStack::PushL(parser);
// Set section tags
_LIT(KEndSubTag, "[EndSub]");
TName startSubTag;
startSubTag.Copy(_L("[Sub "));
startSubTag.Append(aSubName);
startSubTag.Append(_L("]"));
// Load section
TRAP(err,
section = parser->SectionL(startSubTag, KEndSubTag, 1);
);
if(err != KErrNone)
{
__TRACE(KError, (_L("Searching sub [%S]. Searching section %S%S ended with error [%d]."), &aSubName, &startSubTag, &KEndSubTag, err));
User::Leave(err);
}
if(!section)
{
__TRACE(KError, (_L("Searching sub [%S]. Section %S%S not found."), &aSubName, &startSubTag, &KEndSubTag));
User::Leave(err);
}
else
{
__TRACE(KMessage, (_L("Searching sub [%S]. Section %S%S found."), &aSubName, &startSubTag, &KEndSubTag));
}
CleanupStack::PopAndDestroy(parser);
return section;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
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: Draft
-------------------------------------------------------------------------------
*/
void CTestScripter::RunTestL()
{
__TRACEFUNC();
iResult.iResult = KErrNone;
iResult.iResultDes.Zero();
// "title" keyword must be in the first line
TPtrC title;
if( iCurrentParser->GetLine(
TTestKeywords::Keyword( TTestKeywords::ETitle ), title, ENoTag )
!= KErrNone )
{
__TRACE( KError, (_L("title not found from section")));
User::Leave( KErrNotFound );
}
iCurrentParserReadFirstLine = ETrue;
__TRACE( KMessage, (_L("RunTest: %S"), &title ));
iTestRunner = CTestRunner::NewL( this );
TestModuleIf().Printf( KPrintPriNorm, _L("RunTest"), _L("%S"), &title );
// Rest of the job is done by test runner
iTestRunner->SetRunnerActive();
// Start activeScheduler looping testcase lines
__TRACE( KMessage, (_L("Start CActiveScheduler")));
CActiveScheduler::Current()->Start();
if ( iTestRunner->IsFailedSubTestCaseReported() && !(iPassLimitNotMet) )
{
TFullTestResult testResult = iTestRunner->GetFailedSubTestCaseResult();
const CStartInfo* startInfo = iTestRunner->GetFailedSubTestCaseInfo();
if( testResult.iCaseExecutionResultType == TFullTestResult::ECaseExecuted )
{
iResult.iResult = testResult.iTestResult.iResult;
}
else
{
iResult.iResult = testResult.iCaseExecutionResultCode;
}
iResult.iResultDes.Format( _L("Sub test case \"%S\" execution failed. "), &startInfo->GetTitle() );
iResult.iResultDes.AppendFormat( _L("Result [%d], expected result [%d]"), iResult.iResult, startInfo->GetExpectedResult() );
}
delete iTestRunner;
iTestRunner = NULL;
__TRACE( KMessage, ( _L("RunTestL: Done")));
// Destroy locally defined variables
iDefinedLocal.ResetAndDestroy();
// Destroy function parsers (there shouldn't be any)
iParserStack.ResetAndDestroy();
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
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
Return Values: CTCTestModule*: pointer to testmodules description
Errors/Exceptions: Leaves if CTCTestModule::NewL leaves
Leaves if RPointerArray::Append fails
Status: Draft
-------------------------------------------------------------------------------
*/
TTestModule* CTestScripter::LoadTestModuleL( TDesC& aModule )
{
__TRACEFUNC();
TInt count = iTestModules.Count();
for( TInt i=0; i < count; i++ )
{
if( iTestModules[i]->ModuleName() == aModule )
{
// Found test module, return description
__TRACE( KMessage,
(_L("GetTestModuleL: Use already loaded TestModule (%S)"),
&aModule ));
return iTestModules[i];
}
}
__TRACE( KMessage, (_L("GetTestModuleL: Load new TestModule (%S)"),
&aModule ));
TTestModule* module = new (ELeave) TTestModule();
CleanupStack::PushL( module );
module->ModuleName() = aModule;
User::LeaveIfError( iTestModules.Append( module ) );
CleanupStack::Pop( module );
TInt ret = module->iLibrary.Load ( aModule );
if( ret != KErrNone )
{
__TRACE( KMessage, (_L("GetTestModuleL: %S loading failed"),
&aModule ));
TestModuleIf().Printf( KMessage, _L("Load dll"), _L("%S failed"),
&aModule );
User::Leave( ret );
}
// Get pointer to first exported function
module->iLibEntry = (CInterfaceFactory) module->iLibrary.Lookup(1);
return module;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: LoadSharedTestModuleL
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
Return Values: CTCTestModule*: pointer to testmodules description
Errors/Exceptions: Leaves if CTCTestModule::NewL leaves
Leaves if RPointerArray::Append fails
Status: Draft
-------------------------------------------------------------------------------
*/
TTestModule* CTestScripter::LoadSharedTestModuleL(TDesC& aModule)
{
__TRACEFUNC();
TInt count = iSharedTestModules.Count();
for (TInt i = 0; i < count; i++)
{
if (iSharedTestModules[i]->ModuleName() == aModule)
{
// Found test module, return description
__TRACE( KMessage,
(_L("GetTestModuleL: Use already loaded TestModule (%S)"),
&aModule ));
return iSharedTestModules[i]->Get();
}
}
__TRACE( KMessage, (_L("GetTestModuleL: Load new TestModule (%S)"),
&aModule ));
TTestModule* module = new (ELeave) TTestModule();
CleanupStack::PushL(module);
module->ModuleName() = aModule;
User::LeaveIfError(iSharedTestModules.Append(
new (ELeave) TSharedTestModule(module)));
CleanupStack::Pop(module);
TInt ret = module->iLibrary.Load(aModule);
TestModuleIf().iNumberInGlbDict++;
if (ret != KErrNone)
{
__TRACE( KMessage, (_L("GetTestModuleL: %S loading failed"),
&aModule ));
TestModuleIf().Printf(KMessage, _L("Load dll"), _L("%S failed"),
&aModule);
User::Leave(ret);
}
// Get pointer to first exported function
module->iLibEntry = (CInterfaceFactory) module->iLibrary.Lookup(1);
return module;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: CreateObjectL
Description: Load testmodule if not already loaded, otherwise return
description of the loaded testmodule.
Parameters: TDesC& aModule: in: module name
TDesC& aObjectId: in: object id name
Return Values: None
Errors/Exceptions: Leaves on error
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestScripter::CreateObjectL( TDesC& aModule, TDesC& aObjectId )
{
__TRACEFUNC();
// Load module and get pointer
TTestModule* module = LoadTestModuleL( aModule );
TTestObject* object = new (ELeave) TTestObject();
CleanupStack::PushL( object );
object->ObjectId() = aObjectId;
object->iModule.Copy(aModule);
User::LeaveIfError( iTestObjects.Append( object ) );
CleanupStack::Pop( object );
// Create object
object->iScript = module->iLibEntry( TestModuleIf() );
//User::LeaveIfNull ( object->iScript );
if( object->iScript == NULL )
{
User::Leave( KErrGeneral );
}
// Create continue callback
object->iContinue = CTestContinue::NewL( this, object );
// Create function pointer operation to possible
object->iScript->SetScripter( &CallBack, this );
TestModuleIf().AddTestObjToCaseDictL(object);
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: CreateShareObjectL
Description: Load testmodule if not already loaded, otherwise return
description of the loaded testmodule.
Parameters: TDesC& aModule: in: module name
TDesC& aObjectId: in: object id name
Return Values: None
Errors/Exceptions: Leaves on error
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestScripter::CreateShareObjectL( TDesC& aModule, TDesC& aObjectId )
{
__TRACEFUNC();
// Load module and get pointer
TTestModule* module = LoadSharedTestModuleL(aModule);
TTestObject* object = new (ELeave) TTestObject();
CleanupStack::PushL( object );
object->ObjectId() = aObjectId;
CleanupStack::Pop( object );
object->iModule.Copy(aModule);
// Create object
object->iScript = module->iLibEntry( TestModuleIf() );
//User::LeaveIfNull ( object->iScript );
if( object->iScript == NULL )
{
User::Leave( KErrGeneral );
}
TestModuleIf().AddTestObjToCaseDictL(object);
AddTestObjToScripterDictL(object);
TestModuleIf().iNumberInGlbDict++;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: RestoreShareObjectL
Description: Load testmodule if not already loaded, otherwise return
description of the loaded testmodule.
Parameters: TDesC& aModule: in: module name
TDesC& aObjectId: in: object id name
Return Values: None
Errors/Exceptions: Leaves on error
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestScripter::RestoreShareObjectL( TDesC& aObjectId )
{
__TRACEFUNC();
TTestObject* object = NULL;
object = (TTestObject*)GetTestObjFromScripterDict( aObjectId );
if( NULL == object )
{
User::Leave( KErrGeneral );
}
//User::LeaveIfNull ( object->iScript );
if( object->iScript == NULL )
{
User::Leave( KErrGeneral );
}
TestModuleIf().AddTestObjToCaseDictL(object);
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: CreateKernelObjectL
Description: Load testdriver if not already loaded, otherwise return
description of the loaded testdriver.
Parameters: TDesC& aDriver: in: driver name
TDesC& aObjectId: in: object id name
Return Values: None
Errors/Exceptions: Leaves on error
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestScripter::CreateKernelObjectL( TDesC& aDriver, TDesC& aObjectId )
{
__TRACEFUNC();
if( ( aDriver.Length() > KMaxName ) ||
( aObjectId.Length() > KMaxName ) )
{
__TRACE( KError, (_L("CreateKernelObjectL: Max lenght exceeded") ) );
User::Leave( KErrArgument );
}
TInt ret = User::LoadLogicalDevice( aDriver );
if( ( ret != KErrNone ) && ( ret != KErrAlreadyExists ) )
{
__TRACE( KError,
(_L("CreateKernelObjectL: User::LoadLogicalDevice failed %d"),
ret ) );
User::Leave( ret );
}
TTestObjectKernel* object = new (ELeave) TTestObjectKernel();
CleanupStack::PushL( object );
object->ObjectId() = aObjectId;
object->LddName().Copy( aDriver );
ret = object->KernelTestClass().Open(
object->KernelTestClass().VersionRequired(),
aDriver );
if( ret != KErrNone )
{
__TRACE( KError,
(_L("CreateKernelObjectL: KernelTestClass().Open failed %d"),
ret ) );
User::Leave( ret );
}
User::LeaveIfError( iTestObjects.Append( object ) );
CleanupStack::Pop( object );
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
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
Return Values: CTCTestModule*: pointer to testmodules description
Errors/Exceptions: Leaves if CTCTestModule::NewL leaves
Leaves if RPointerArray::Append fails
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestScripter::DeleteObjectL( TDesC& aObjectId )
{
__TRACEFUNC();
TestModuleIf().DelTestObjFromCaseDict(aObjectId);
TInt count = iTestObjects.Count();
for( TInt i=0; i < count; i++ )
{
if( iTestObjects[i]->ObjectId() == aObjectId )
{
TTestObjectBase* object = iTestObjects[i];
iTestObjects.Remove( i );
delete object;
return KErrNone;
}
}
return KErrNone;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: DeleteGlobalObjectL
Description: Delete test object from dictionary
Parameters: TDesC& aObjectId: in: object name
Return Values: void
Errors/Exceptions: Leaves if CTCTestModule::NewL leaves
Leaves if RPointerArray::Append fails
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestScripter::DeleteScripterObjectL( TDesC& aObjectId )
{
__TRACEFUNC();
TScriptObject* obj = TestModuleIf().GetTestObjFromCaseDict(aObjectId);
if(obj == NULL)
{
return KErrNotFound;
}
TestModuleIf().DelTestObjFromCaseDict(aObjectId);
DelTestObjFromScripterDict(aObjectId);
return KErrNone;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
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: Draft
-------------------------------------------------------------------------------
*/
TTestObjectBase* CTestScripter::GetObject( const TDesC& aObjectId )
{
__TRACEFUNC();
TInt count = iTestObjects.Count();
for( TInt i=0; i < count; i++ )
{
if( iTestObjects[i]->ObjectId() == aObjectId )
{
// Found testcase with specified TestId
return iTestObjects[i];
}
}
TTestObject* object = NULL;
object = (TTestObject*)TestModuleIf().GetTestObjFromCaseDict( aObjectId );
return object;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: CallTestClass
Description: For sub classing operations.
Parameters: const TDesC& aLine: in: script line
Return Values: TInt: Symbian error code
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestScripter::CallTestClass( const TDesC& aLine )
{
CStifItemParser* item = CStifItemParser::NewL( aLine, 0, aLine.Length() );
CleanupStack::PushL( item );
TPtrC objectName;
TInt ret( KErrNone );
ret = item->GetString( _L( "" ), objectName );
if( ret != KErrNone )
{
CleanupStack::PopAndDestroy( item);
return ret;
}
TTestObjectBase* obj = GetObject( objectName );
if( obj == NULL )
{
CleanupStack::PopAndDestroy(item );
return KErrNotFound;
}
TRAPD( commandResult, commandResult = obj->RunMethodL( *item ) );
CleanupStack::PopAndDestroy(item );
return commandResult;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: GetTestScriptObject
Description: Get object address.
Parameters: const TDesC& aObjectName: in: object name
Return Values: TInt: Symbian error code
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestScripter::GetTestScriptObject( const TDesC& aObjectName )
{
TTestObjectBase* objBase = GetObject( aObjectName );
if( ( objBase == NULL ) ||
( objBase->ObjectType() != TTestObjectBase::EObjectNormal ) )
{
return KErrNotFound;
}
TTestObject* object = ( TTestObject* )objBase;
return (TInt) object->iScript;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: UpdateTestCaseResult
Description: Updates result of test case. If there is already some
description stored, it is put in the [] brackets.
Parameters: const TInt aResult: in: error code
const TDesC& aDescr: in: description
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestScripter::UpdateTestCaseResult(const TInt aResult, const TDesC& aDescr)
{
// Create buffer
RBuf buf;
TInt ret = buf.Create(iResult.iResultDes.Length() + aDescr.Length() + 5);
if(ret != KErrNone)
{
__TRACE(KError, (_L("UpdateResultDescription: descriptor creation failed [%d]"), ret));
return;
}
CleanupClosePushL(buf);
// Update result
iResult.iResult = aResult;
if(iResult.iResultDes.Length() > 0)
{
buf.Format(_L("%S [%S]"), &aDescr, &iResult.iResultDes);
}
else
{
buf.Copy(aDescr);
}
SetResultDescription(buf);
// Close buffer
CleanupStack::PopAndDestroy(&buf);
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: SetResultDescription
Description: Sets result description of test case.
Parameters: const TDesC& aDescr: in: new description
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
EXPORT_C void CTestScripter::SetResultDescription(const TDesC& aDescr)
{
if(aDescr.Length() > KStifMaxResultDes)
{
iResult.iResultDes.Copy(aDescr.Mid(0, KStifMaxResultDes));
}
else
{
iResult.iResultDes.Copy(aDescr);
}
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: SetLocalValue
Description: Internal fuction to set value of local variable defined in script
Parameters: const TDesC& aName: in: local variable name
const TDesC& avalue: in: local variable value
Return Values: KErrNone: Value is returned succesfully.
KErrNotFound: Variable was not found
Any other SymbianOS error
-------------------------------------------------------------------------------
*/
EXPORT_C TInt CTestScripter::SetLocalValue(const TDesC& aName, const TDesC& aValue)
{
__TRACEFUNC();
TInt count = iDefinedLocal.Count();
for(TInt i = 0; i < count; i++)
{
if(iDefinedLocal[i]->Name() == aName)
{
iDefinedLocal[i]->SetValueL(const_cast<TDesC&>(aValue));
return KErrNone;
}
}
return KErrNotFound;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: GetLocalValue
Description: Internal fuction to get value of local variable
Parameters: const TDesC& aName: in: local variable name
const TDesC& avalue: in: local variable value
Return Values: KErrNone: Value is returned succesfully.
KErrNotFound: Variable was not found
Any other SymbianOS error
-------------------------------------------------------------------------------
*/
EXPORT_C TInt CTestScripter::GetLocalValue(const TDesC& aName, TDes& aValue)
{
__TRACEFUNC();
TInt count = iDefinedLocal.Count();
for(TInt i = 0; i < count; i++)
{
if(iDefinedLocal[i]->Name() == aName)
{
aValue.Copy(iDefinedLocal[i]->Value());
return KErrNone;
}
}
return KErrNotFound;
}
TBool CompareTBuf(const TBuf<KMaxFileName>& aLeft,const TBuf<KMaxFileName>& aRight)
{
return aLeft.Compare(aRight) == 0 ? ETrue : EFalse;
}
void CTestScripter::Substitute(const TDesC& aSrc,TDes& aDest)
{
TIdentityRelation<TBuf<KMaxFileName> > relation(CompareTBuf);
TInt fileindex=aSrc.Find(KFileFlag);
TInt sectionindex=aSrc.Find(KSectionFlag);
TInt keyindex=aSrc.Find(KKeyFlag);
TBuf<KMaxFileName> srcbuf;
if(fileindex==KErrNotFound&§ionindex==KErrNotFound&&keyindex!=KErrNotFound)
{
srcbuf.Append(KFileFlag);
srcbuf.Append(iCurrentFileAlias);
srcbuf.Append(KSectionFlag);
srcbuf.Append(iCurrentSectionFileAlias);
srcbuf.Append(aSrc);
}
else if(fileindex==KErrNotFound&§ionindex!=KErrNotFound&&keyindex!=KErrNotFound)
{
srcbuf.Append(KFileFlag);
srcbuf.Append(iCurrentFileAlias);
srcbuf.Append(aSrc);
}
else
{
srcbuf.Append(aSrc);
}
TInt index=iKeys.Find(srcbuf,relation);
if(index==KErrNotFound)
{
aDest.Append(aSrc);
}
else
{
aDest.Append(iValues[index]);
}
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: AddTestObjToDictL
Description: Add Test Object to dictionary
Parameters: TTestObject* aObject: in: test object
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestScripter::AddTestObjToScripterDictL(TTestObject* aObject)
{
__TRACEFUNC();
User::LeaveIfNull( (TAny*)aObject );
TInt count = iGlobalObjects.Count();
for (TInt i = 0; i < count; i++)
{
if (iGlobalObjects[i]->ObjectId() == aObject->ObjectId())
{
// Found testcase with specified TestId
return;
}
}
User::LeaveIfError( iGlobalObjects.Append(aObject) );
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: DelTestObjFromDict
Description: delete Test Object from dictionary
Parameters: const TDesC& aObjectId: in: id
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestScripter::DelTestObjFromScripterDict(const TDesC& aObjectId)
{
__TRACEFUNC();
TInt count = iGlobalObjects.Count();
for (TInt i = 0; i < count; i++)
{
if (iGlobalObjects[i]->ObjectId() == aObjectId)
{
// Found testcase with specified TestId
TTestObject *object = (TTestObject*) iGlobalObjects[i];
iGlobalObjects.Remove(i);
TInt count2 = iSharedTestModules.Count();
for (TInt j = 0; j < count2; j++)
{
if (iSharedTestModules[j]->ModuleName() == object->iModule)
{
delete object;
TestModuleIf().iNumberInGlbDict--;
iSharedTestModules[j]->Del();
if (iSharedTestModules[j]->RefCount() <= 0)
{
TestModuleIf().iNumberInGlbDict--;
}
delete iSharedTestModules[j];
iSharedTestModules.Remove(j);
break;
}
}
if(iSharedTestModules.Count() == 0)
{
iSharedTestModules.Reset();
}
if(iGlobalObjects.Count() == 0)
{
iGlobalObjects.Reset();
}
return;
}
}
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
Method: GetTestObjFromDict
Description: delete Test Object from dictionary
Parameters: const TDesC& aObjectId: in: id
Return Values: TTestObject* : pointer to TTestObject
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TTestObject* CTestScripter::GetTestObjFromScripterDict(const TDesC& aObjectId) const
{
__TRACEFUNC();
TInt count = iGlobalObjects.Count();
for (TInt i = 0; i < count; i++)
{
if (iGlobalObjects[i]->ObjectId() == aObjectId)
{
// Found testcase with specified TestId
return iGlobalObjects[i];
}
}
return NULL;
}
/*
-------------------------------------------------------------------------------
Class: CTestScripter
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 CTestScripter::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);
}
}
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of CTestRunner class
member functions. CTestRunner is used to execute TestScripter testcase by
CTestScripter.
-------------------------------------------------------------------------------
*/
// MACROS
#ifdef LOGGER
#undef LOGGER
#endif
#define LOGGER iTestScripter->iLog
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: CTestRunner
Description: Default constructor
C++ default constructor can NOT contain any code, that
might leave.
Parameters: CTestScripter* aTestScripter: in: Backpointer to CTestScripter
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
CTestRunner::CTestRunner( CTestScripter* aTestScripter ):
CActive( CActive::EPriorityHigh ), // Executed with highest priority
iState( ERunnerIdle ),
iInternalStateForSubTestCases( EISNotStarted ),
iTestScripter( aTestScripter ),
iRemainingTimeValue( 0 )
{
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: Draft
-------------------------------------------------------------------------------
*/
void CTestRunner::ConstructL()
{
iPauseTimer.CreateLocal();
// Initiaze all OOM related variables to default.
OOMHeapToNormal();
iLoopHelper = CLoopHelper::NewL( this );
iSlavesManager = CSlavesManager::NewL( this, iTestScripter->TestModuleIf() );
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: NewL
Description: Two-phased constructor.
Parameters: CTestScripter* aTestScripter: in: Backpointer to CTestScripter
Return Values: CTestRunner*: new object
Errors/Exceptions: Leaves if new or ConstructL leaves
Status: Draft
-------------------------------------------------------------------------------
*/
CTestRunner* CTestRunner::NewL( CTestScripter* aTestScripter )
{
CTestRunner* self = new (ELeave) CTestRunner( aTestScripter );
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();
iPauseTimer.Close();
delete iLine;
iLine = NULL;
delete iLoopHelper;
iLoopHelper = NULL;
iSubTestCases.ResetAndDestroy();
iSubTestCases.Close();
delete iTestIdForComplete;
iTestIdForComplete = NULL;
delete iFailedSubTestCaseInfo;
iFailedSubTestCaseInfo = NULL;
TInt count = iEventArray.Count();
TEventIf event( TEventIf::ERelEvent );
for( TInt i = 0; i < count; i++ )
{
HBufC* tmp = iEventArray[0];
event.SetName( iEventArray[0]->Des() );
iEventArray.Remove(0);
if( iTestScripter != NULL )
{
iTestScripter->TestModuleIf().Event( event );
}
delete tmp;
}
iTestCaseResults.Reset();
iEventArray.ResetAndDestroy();
iTestCaseResults.Close();
iEventArray.Close();
delete iSlavesManager;
iSlavesManager = NULL;
// Reset test case allow result to CTestModuleIf side too. This is
// used in TAL-TA5L macro handling.
if( iTestScripter != NULL )
{
User::LeaveIfError(
iTestScripter->TestModuleIf().ResetAllowResult() );
}
// Stop all remaining interference object
TInt count_inter = iTestInterferenceArray.Count();
for( TInt a = 0; a < count_inter; a++ )
{
if( iTestInterferenceArray[a] != NULL )
{
iTestInterferenceArray[a]->iInterference->Stop();
}
}
iTestInterferenceArray.ResetAndDestroy();
iTestInterferenceArray.Close();
// Stop all remaining measurement modules
const TInt count_meas = iTestMeasurementArray.Count();
for( TInt b = 0; b < count_meas; b++ )
{
if( iTestMeasurementArray[b] != NULL )
{
iTestMeasurementArray[b]->iMeasurement->Stop();
}
}
iTestMeasurementArray.ResetAndDestroy();
iTestMeasurementArray.Close();
iPlugins.ResetAndDestroy();
iPlugins.Close();
iPluginnames.ResetAndDestroy();
iPluginnames.Close();
iLibrary.Close();
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: RunL
Description: Derived from CActive, handles testcase execution.
Parameters: None.
Return Values: None.
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestRunner::RunL()
{
__TRACEFUNC();
__TRACE( KMessage, (_L("CTestRunner::RunL: [%d] "), iStatus.Int() ));
if ( iInternalStateForSubTestCases == EISNotStarted )
{
iInternalStateForSubTestCases = EISRuning;
}
// Check if we need to Pause test case again
if( iStatus == KErrNone && iRemainingTimeValue > 0 )
{
// Maximum time for one RTimer::After request
TInt maximumTime = KMaxTInt / 1000;
__TRACE( KMessage, (_L("CTestRunner::RunL: Going to reissue After request ") ) );
__TRACE( KMessage, (_L("CTestRunner::RunL: iRemainingTimeValue = %d"), iRemainingTimeValue ) );
if( iRemainingTimeValue < maximumTime )
{
iPauseTimer.After( iStatus, ( iRemainingTimeValue * 1000 ) );
iRemainingTimeValue = 0;
}
else
{
iRemainingTimeValue -= maximumTime;
iPauseTimer.After( iStatus, ( maximumTime * 1000 ) );
}
SetActive();
}
else
{
TBool continueTask = EFalse;
User::LeaveIfError( iStatus.Int() );
if( ( iTestScripter == NULL ) ||
( iTestScripter->iCurrentParser == NULL ) )
{
__TRACE( KError, (_L("CTestRunner invalid arguments")));
User::Leave( KErrGeneral );
}
iState = ERunnerIdle;
// Get next execution line from configuration section
TPtrC line;
// If current parser already has read the first line, then read next line.
// Otherwise read the first line.
if(iTestScripter->iCurrentParserReadFirstLine && iTestScripter->iCurrentParser->GetNextLine(line) == KErrNone
|| !iTestScripter->iCurrentParserReadFirstLine && iTestScripter->iCurrentParser->GetLine(KNullDesC, line) == KErrNone)
{
iTestScripter->iCurrentParserReadFirstLine = ETrue;
// Got new execution line
__TRACE( KMessage, (_L("Executing line [%S]"), &line));
CStifItemParser* item = PreprocessLineL( line );
CleanupStack::PushL( item );
TPtrC keyword;
// Get first word from line, i.e. keyword
User::LeaveIfError( item->GetString( _L(""), keyword ) );
__TRACE( KMessage, (_L("CTestRunner execute %S"), &keyword ));
// Execute script line
continueTask = ExecuteLineL( keyword, item );
__TRACE( KMessage, (_L("CTestRunner %S executed"), &keyword ));
if( continueTask )
{
__TRACE( KMessage, (_L("RunL: continueTask")));
// Set CTestRunner active again to perform
// next execution line
// from testcase section
SetRunnerActive();
}
CleanupStack::PopAndDestroy( item );
}
else // Stop execution if end of test case
{
__TRACE( KMessage, (_L("Executing line: no more lines from this section")));
// There is no more lines in current parser, but it needs to be
// checked if the parser is not taken for function (sub).
// If this is true, then we have to get back to the parser which
// has called the function.
TInt lastParserIndex = iTestScripter->iParserStack.Count() - 1;
if(lastParserIndex >= 0)
{
// Delete current (the last one) parser
delete iTestScripter->iParserStack[lastParserIndex];
iTestScripter->iParserStack.Remove(lastParserIndex);
if(lastParserIndex >= 1) //There is some other parser on the stack
{
iTestScripter->iCurrentParser = iTestScripter->iParserStack[lastParserIndex - 1];
}
else //The parser stack is empty
{
iTestScripter->iCurrentParser = iTestScripter->iSectionParser;
}
__TRACE(KMessage, (_L("Returning to calling parser stored on section stack")));
// Continue with the test case
__TRACE(KMessage, (_L("RunL: continueTask (end of Sub reached)")));
SetRunnerActive();
return;
}
// No more execution lines in testcase section
// Check if there are running test cases
if ( iSubTestCases.Count() > 0 )
{
if ( iInternalStateForSubTestCases != EISFinishedWaitingForSubTestCases )
{
iInternalStateForSubTestCases = EISFinishedWaitingForSubTestCases;
}
// Continue with the test case
// proper sub test case runner should activate test runner
return;
}
iInternalStateForSubTestCases = EISFinished;
// Release remote resources
RPointerArray<CSlave>& slaves = iSlavesManager->GetSlaves();
while ( slaves.Count() > 0 )
{
slaves[ 0 ]->WaitForSubTestCasesL();
RPointerArray<TEventTS>& slaveEvents = slaves[ 0 ]->GetEvents();
for ( TInt k = 0; k < slaveEvents.Count(); k++ )
{
iSlavesManager->EventReleaseL( slaves[ 0 ], slaveEvents[ k ]->Name() );
}
slaveEvents.ResetAndDestroy();
iSlavesManager->SlaveFreeL( slaves[ 0 ]->GetName() );
}
__TRACE( KMessage,
(_L("CTestRunner::RunL: Testcase script done") ));
iTestScripter->TestModuleIf().Printf( KPrintPriLow,
_L("RunL"), _L("Script done"));
__TRACE( KMessage,
(_L("RunL: All TestCases done, stop CActiveScheduler")));
CActiveScheduler::Current()->Stop();
// Now testcase section is executed,
// so CTestRunner has done its job and stops
}
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: DoCancel
Description: Derived from CActive handles the Cancel
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestRunner::DoCancel()
{
__TRACEFUNC();
__TRACE( KMessage, (_L("CTestRunner::DoCancel")));
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Runner"), _L("DoCancel"));
iPauseTimer.Cancel();
CActiveScheduler::Current()->Stop();
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: Draft
-------------------------------------------------------------------------------
*/
TInt CTestRunner::RunError( TInt aError )
{
__TRACEFUNC();
__TRACE( KMessage, (_L("CTestRunner::RunError %d"), aError));
if ( iRunErrorMessage.Length() != 0 )
{
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("RunError : %S"), &iRunErrorMessage );
iRunErrorMessage = KNullDesC;
}
else
{
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("RunError"));
}
iState = ERunnerError;
// Return error from here, if none given from execution
if( iTestScripter->iResult.iResult == KErrNone )
{
iTestScripter->UpdateTestCaseResult(aError, _L("CTestRunner::RunError"));
}
CActiveScheduler::Current()->Stop();
return KErrNone;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: GetLogger
Description: Returns TestScripter logger
Parameters: None
Return Values: Pointer to TestScripter logger.
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
CStifLogger* CTestRunner::GetLogger()
{
return iTestScripter->iLog;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: PreprocessLineL
Description: Preprocesses script line
Parameters: TPtrC& line: in: script line
CStifItemParser*& aItem: out: New CItemParser 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;
TInt ret = 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;
HBufC* sourceLine = line.AllocL();
CleanupStack::PushL(sourceLine);
//Check for local variable definitions
item = CStifItemParser::NewL(sourceLine->Des(), 0, sourceLine->Length());
CleanupStack::PushL(item);
ret = item->GetString(KNullDesC, tmp);
TBool isVarDefinition = (tmp == TTestKeywords::Keyword(TTestKeywords::EVar));
if(!isVarDefinition)
{
while( ret == KErrNone )
{
len += CheckDefinedLocals(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);
ret = item->GetNextString(tmp);
if(ret == KErrNone)
{
// Add space only if we got new string
parsedLine.Append(_L(" "));
}
}
CleanupStack::PopAndDestroy(item);
item = NULL;
CleanupStack::PopAndDestroy(sourceLine);
sourceLine = NULL;
//Prepare data for checking for defines
sourceLine = parsedLine.AllocL();
CleanupStack::PushL(sourceLine);
parsedLine.Zero();
item = CStifItemParser::NewL(sourceLine->Des(), 0, sourceLine->Length());
CleanupStack::PushL(item);
ret = item->GetString(KNullDesC, tmp);
}
//Check for defines
while(ret == KErrNone)
{
if(!isVarDefinition)
{
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);
ret = item->GetNextString(tmp);
if( ret == KErrNone )
{
// Add space only if we got new string
parsedLine.Append(_L(" "));
}
}
//Cleaning...
CleanupStack::PopAndDestroy(item);
item = NULL;
CleanupStack::PopAndDestroy(sourceLine);
sourceLine = NULL;
__TRACE(KMessage, (_L("Preprocessed line [%S]"), &parsedLine));
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 diference between new and old word
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestRunner::CheckDefined( TPtrC& aWord )
{
TInt len = 0;
TInt i = 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;
}
// First, check values defined in test case file
TInt count = iTestScripter->iDefinedRuntime.Count();
for( i = 0; i < count; i++ )
{
if( iTestScripter->iDefinedRuntime[i]->Name() == aWord )
{
len = iTestScripter->iDefinedRuntime[i]->Value().Length() - aWord.Length();
aWord.Set( iTestScripter->iDefinedRuntime[i]->Value() );
return len;
}
}
// Second, check values defined in test module initialization file
count = iTestScripter->iDefinedIni.Count();
for( i = 0; i < count; i++ )
{
if( iTestScripter->iDefinedIni[i]->Name() == aWord )
{
len = iTestScripter->iDefinedIni[i]->Value().Length() - aWord.Length();
aWord.Set( iTestScripter->iDefinedIni[i]->Value() );
return len;
}
}
return len;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: CheckDefinedLocals
Description: Check if aWord is a local variable
Parameters: TPtrC& aWord: inout: Parsed word, defined or original returned
Return Values: TInt: length diference between new and old word
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestRunner::CheckDefinedLocals( TPtrC& aWord )
{
TInt len = 0;
TInt i = 0;
TInt count = iTestScripter->iDefinedLocal.Count();
for(i = 0; i < count; i++)
{
if(iTestScripter->iDefinedLocal[i]->Name() == aWord)
{
len = iTestScripter->iDefinedLocal[i]->Value().Length() - aWord.Length();
aWord.Set(iTestScripter->iDefinedLocal[i]->Value());
return len;
}
}
return len;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteLineL
Description: Executes script line
Parameters: TDesC& aKeyword: in: keyword string
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::ExecuteLineL( TDesC& aKeyword,
CStifItemParser* aItem )
{
_LIT( KErrMsgDeleteNoParam, "Delete: Name of object is not defined" );
_LIT( KErrMsgDeleteObjNotFound, "Delete: Can't delete object %S. Object does not exists." );
_LIT( KErrMsgPauseTimeoutNotDefined, "Pause: No timeout value given or value has invalid format" );
_LIT( KErrMsgPauseTimeoutNotPositive, "Pause: Timeout value can't be <0" );
_LIT( KErrMsgCreateTestModeleNotDefined, "Create: Name of test module is not defined" );
_LIT( KErrMsgCreateObjectIdNotDefined, "Create: Name of test module object is not defined" );
_LIT( KErrMsgCreateKernelDriverNotDefined, "CreateKernel: Kernel driver name is not defined" );
_LIT( KErrMsgCreateKernelObjectNameNotDefined, "CreateKernel: Kernel driver object name is not defined" );
_LIT( KErrMsgCreateKernelFailed, "CreateKernel: Can't creeate kernel driver %S" );
_LIT( KErrMsgWaitTestClassNameNotDefined, "WaitTestClass: Test class object name is not defined" );
_LIT( KErrMsgWaitTestClassObjNotFound, "WaitTestClass: Test class object %S does not exists" );
_LIT( KErrMsgBringToForegroundNotSupported, "BringToForeground: BringToForeground is not supported in non s60 environment" );
_LIT( KErrMsgSendToBackgroundNotSupported, "SendToBackground: SendToBackground is not supported in non s60 environment" );
_LIT( KErrMsgPressKeyNotSupported, "PressKey: PressKey is not supported in non s60 environment. Check if .cfg file name contains ui_ prefix and UITestingSupport= YES entry is defined in TestFrameworkd.ini" );
_LIT( KErrMsgTypeTextNotSupported, "TypeText: TypeText is not supported in non s60 environment. Check if .cfg file name contains ui_ prefix and UITestingSupport= YES entry is defined in TestFrameworkd.ini" );
_LIT( KErrMsgSendPointerEventNotSupported, "SendPointerEvent: SendPointerEvent is not supported in non s60 environment. Check if .cfg file name contains ui_ prefix and UITestingSupport= YES entry is defined in TestFrameworkd.ini" );
_LIT( KErrVarNameError, "Variable: Could not get variable name");
_LIT( KErrVarValueError, "Variable: Value too long");
_LIT( KErrSubNameError, "Sub: Could not get name of Sub to be called");
_LIT( KErrSubGetError, "Sub: Could not get Sub section");
TPtrC temp;
RBuf buf;
buf.Create(512);
CleanupClosePushL(buf);
buf.Append(aKeyword);
buf.Append(_L(" "));
while(aItem->GetNextString(temp)==KErrNone)
{
RBuf tempbuf;
tempbuf.Create(512);
iTestScripter->Substitute(temp,tempbuf);
buf.Append(tempbuf);
buf.Append(_L(" "));
tempbuf.Close();
}
delete aItem;
aItem=NULL;
temp.Set((TUint16 *)buf.Ptr(),buf.Length());
aItem=CStifItemParser::NewL(temp,0,temp.Length());
aItem->GetString(KNullDesC,temp);
iRunErrorMessage = KNullDesC;
TBool continueTask = ETrue;
TInt key = TTestKeywords::Parse( aKeyword, TTestKeywords::Keyword );
switch( key )
{
// Test case execution control cases
case TTestKeywords::ECreate:
case TTestKeywords::ECreateX:
case TTestKeywords::ECreateShareObj:
{
TPtrC tmp;
TName module;
// Testmodule name
TInt ret = aItem->GetNextString( tmp );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgCreateTestModeleNotDefined;
User::Leave( KErrArgument );
}
TParse p;
p.Set( tmp, NULL, NULL );
// Check if exists in module name
if( p.ExtPresent() )
{
module.Copy( tmp );
}
else
{
// No extension in module name, add it here
_LIT( KDllExtension, ".dll");
module.Copy( tmp );
module.Append( KDllExtension );
}
// objectid
ret = aItem->GetNextString( tmp );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgCreateObjectIdNotDefined;
User::Leave( KErrArgument );
}
__TRACE( KMessage, (_L("%S %S"), &aKeyword, &tmp));
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("%S %S"), &aKeyword, &tmp);
if( TTestKeywords::ECreateShareObj == key )
{
iTestScripter->CreateShareObjectL( module, tmp );
}
else
{
iTestScripter->CreateObjectL( module, tmp );
}
}
break;
case TTestKeywords::ERestoreShareObj:
{
TPtrC tmp;
// objectid
TInt ret = aItem->GetNextString( tmp );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgCreateObjectIdNotDefined;
User::Leave( KErrArgument );
}
__TRACE( KMessage, (_L("%S %S"), &aKeyword, &tmp));
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("%S %S"), &aKeyword, &tmp);
iTestScripter->RestoreShareObjectL( tmp );
}
break;
case TTestKeywords::ECreateKernel:
{
TPtrC obj;
TPtrC driver;
// Testdriver name
TInt ret = aItem->GetNextString( driver );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgCreateKernelDriverNotDefined;
User::Leave( ret );
}
// objectid
ret = aItem->GetNextString( obj );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgCreateKernelObjectNameNotDefined;
User::Leave( ret );
}
__TRACE( KMessage, (_L("%S %S"), &aKeyword, &obj));
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("%S %S"), &aKeyword, &obj);
TInt leaveErr = KErrNone;
TRAP( leaveErr, iTestScripter->CreateKernelObjectL( driver, obj ));
if ( leaveErr != KErrNone )
{
iRunErrorMessage.Format( KErrMsgCreateKernelFailed, &driver );
User::Leave( leaveErr );
}
}
break;
case TTestKeywords::EDelete:
{
TPtrC tmp;
// objectid
TInt ret = aItem->GetNextString( tmp );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgDeleteNoParam;
User::Leave( ret );
}
__TRACE( KMessage, (_L("%S %S"), &aKeyword, &tmp));
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("%S %S"), &aKeyword, &tmp);
ret = iTestScripter->DeleteObjectL( tmp );
if ( ret != KErrNone )
{
iRunErrorMessage.Format( KErrMsgDeleteObjNotFound, &tmp );
User::Leave( ret );
}
}
break;
case TTestKeywords::EDeleteShareObj:
{
TPtrC tmp;
// objectid
TInt ret = aItem->GetNextString( tmp );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgDeleteNoParam;
User::Leave( ret );
}
__TRACE( KMessage, (_L("%S %S"), &aKeyword, &tmp));
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("%S %S"), &aKeyword, &tmp);
ret = iTestScripter->DeleteScripterObjectL( tmp );
if(ret)
{
iRunErrorMessage.Format( KErrMsgDeleteObjNotFound, &tmp );
User::Leave( ret );
}
}
break;
case TTestKeywords::ERun:
continueTask = ExecuteRunL( aItem );
break;
case TTestKeywords::ECancelIfError:
iCancelIfError = ETrue;
break;
case TTestKeywords::EComplete:
continueTask = ExecuteCompleteL( aItem );
break;
case TTestKeywords::EPauseTest:
continueTask = ControlSubTestCaseL( TTestKeywords::EPauseTest, aItem );
break;
case TTestKeywords::EResume:
continueTask = ControlSubTestCaseL( TTestKeywords::EResume, aItem );
break;
case TTestKeywords::ECancel:
continueTask = ControlSubTestCaseL( TTestKeywords::ECancel, aItem );
break;
case TTestKeywords::ERequest:
case TTestKeywords::EWait:
case TTestKeywords::ERelease:
case TTestKeywords::ESet:
case TTestKeywords::EUnset:
continueTask = ExecuteEventL( aKeyword, aItem );
break;
case TTestKeywords::EPrint:
{
__TRACE( KMessage, (_L("%S"), &aKeyword));
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Runner"),
_L("%S"), &aKeyword );
RBuf buf;
buf.CreateL(1024);
CleanupClosePushL(buf);
TPtrC tmp;
while( aItem->GetNextString( tmp ) == KErrNone )
{
if( buf.Length() + tmp.Length() >= buf.MaxLength() )
{
buf.ReAllocL(buf.MaxLength() + tmp.Length() * 10);
}
buf.Append( tmp );
buf.Append( _L(" ") );
}
iTestScripter->TestModuleIf().Printf( KPrintPriNorm,
_L("Test"),
_L("%S"), &buf);
RDebug::Print( _L("Print : Test : %S"), &buf );
CleanupStack::PopAndDestroy(&buf);
}
break;
case TTestKeywords::EAllowNextResult:
{
AddTestCaseResultL( aItem );
}
break;
case TTestKeywords::EExpectedPanic:
{
AddTestCasePanicL( aItem );
}
break;
case TTestKeywords::EWaitTestClass:
{
// Just stop script running, continue event is signaled
// from test class with specified object name
TPtrC objectName;
// Get Object name
TInt ret = aItem->GetNextString( objectName );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgWaitTestClassNameNotDefined;
User::Leave( ret );
}
TTestObjectBase* obj = iTestScripter->GetObject ( objectName );
//User::LeaveIfNull( obj );
if( obj == NULL )
{
iRunErrorMessage.Format( KErrMsgWaitTestClassObjNotFound, &objectName );
User::Leave( KErrGeneral );
}
continueTask = obj->Wait();
if( continueTask )
{
// If OOM testing is ongoing ignore result check(given by user)
if( !iTestScripter->iOOMIgnoreFailure )
{
if( iTestCaseResults.Count() == 0 )
{
// KErrNone is the default result expected
// if nothing else is given
User::LeaveIfError( iTestCaseResults.Append(
KErrNone ) );
}
if( iTestCaseResults.Find( obj->iAsyncResult ) < 0 )
{
__TRACE( KError, ( _L("Command for [%S] failed (%d)"),
&objectName, obj->iAsyncResult ));
iTestScripter->UpdateTestCaseResult(obj->iAsyncResult, _L("CTestRunner::ExecuteLineL: asynchronous method returned error"));
// Stops execution from CTestRunner::RunError
User::Leave( KErrGeneral );
}
}
else
{
__TRACE( KMessage, (
_L( "OOM test: 'oomignorefailure' is ON, test case result will reset" ) ) );
}
iTestCaseResults.Reset();
// Reset test case allow result to CTestModuleIf side too. This is
// used in TAL-TA5L macro handling.
User::LeaveIfError(
iTestScripter->TestModuleIf().ResetAllowResult() );
}
}
break;
case TTestKeywords::EPause:
{
// Maximum time for one RTimer::After request
TInt maximumTime = KMaxTInt / 1000;
// Set iRemainingTimeValue to zero
iRemainingTimeValue = 0;
TInt timeout;
// Read valid results to timeout
if( aItem->GetNextInt( timeout ) != KErrNone )
{
__TRACE( KError, (_L("CTestRunner::ExecuteLineL: No timeout value given for pause")));
iRunErrorMessage = KErrMsgPauseTimeoutNotDefined;
User::Leave( KErrArgument );
}
// Test case file parsing was success
__TRACE( KMessage, (_L("CTestRunner::ExecuteLineL: Pause for %d milliseconds"), timeout));
if( timeout < 0 )
{
__TRACE( KError, (_L("CTestRunner::ExecuteLineL: Given pause value < 0")));
iRunErrorMessage = KErrMsgPauseTimeoutNotPositive;
User::Leave( KErrArgument );
}
else
{
// Check is pause value suitable for RTimer::After
if( timeout < maximumTime )
{
iPauseTimer.After( iStatus, ( timeout * 1000 ) );
}
else
{
// Given pause value after multiplication with 1000 is
// larger than KMaxTInt, so we need to split it and
// re-request After with remaining value from RunL
iRemainingTimeValue = timeout - maximumTime;
iPauseTimer.After( iStatus, maximumTime * 1000 );
}
SetActive();
// Stop execution after paused for given timeout
continueTask = EFalse;
}
}
break;
case TTestKeywords::EAllocate:
continueTask = ExecuteAllocateL( aItem );
break;
case TTestKeywords::EFree:
continueTask = ExecuteFreeL( aItem );
break;
case TTestKeywords::ERemote:
continueTask = ExecuteRemoteL( aItem );
break;
case TTestKeywords::ELoop:
continueTask = ExecuteLoopL( aItem );
break;
case TTestKeywords::EEndLoop:
continueTask = ExecuteEndLoopL( aItem );
break;
case TTestKeywords::ETimeout:
case TTestKeywords::EPriority:
// not used here
break;
case TTestKeywords::EOOMIgnoreFailure:
{
OOMIgnoreFailureL( aItem ); // Handle parsing
break;
}
case TTestKeywords::EOOMHeapFailNext:
{
OOMHeapFailNextL( aItem ); // Handle parsing
break;
}
case TTestKeywords::EOOMHeapSetFail:
{
OOMHeapSetFailL( aItem ); // Handle parsing
break;
}
case TTestKeywords::EOOMHeapToNormal:
{
// Initialize all OOM related variables back to default.
OOMHeapToNormal();
__TRACE( KMessage, (
_L( "'oomheaptonormal' called, OOM initialization or ending OOM test") ) );
break;
}
case TTestKeywords::ETestInterference:
{
TestInterferenceL( aItem ); // Handle parsing
break;
}
case TTestKeywords::EMeasurement:
{
MeasurementL( aItem ); // Handle parsing
break;
}
case TTestKeywords::EAllowErrorCodes:
{
// Check is KErrNone already appended to iTestCaseResults array.
if( iTestCaseResults.Find( KErrNone ) < 0 )
{
// 'allowerrorcodes' keyword sets KErrNone as a default
User::LeaveIfError( iTestCaseResults.Append( KErrNone ) );
// Set test case allow result to CTestModuleIf side too. This
// is used in TAL-TA5L macro handling.
User::LeaveIfError(
iTestScripter->TestModuleIf().SetAllowResult( KErrNone ) );
}
// Set user given specific error code to be allowed.
AddTestCaseResultL( aItem );
}
break;
case TTestKeywords::EBringToForeground:
{
if ( iTestScripter->TestModuleIf().UITesting() == true )
{
iTestScripter->TestModuleIf().GetUiEnvProxy()->BringToForeground();
}
else
{
__TRACE( KError, (_L("ExecuteLineL: Can't execute bringtoforeground in non s60 environment. Check if .cfg file name contains ui_ prefix and UITestingSupport= YES entry is defined in TestFrameworkd.ini")));
iRunErrorMessage = KErrMsgBringToForegroundNotSupported;
User::Leave( KErrNotSupported );
}
}
break;
case TTestKeywords::ESendToBackground:
{
if ( iTestScripter->TestModuleIf().UITesting() == true )
{
iTestScripter->TestModuleIf().GetUiEnvProxy()->SendToBackground();
}
else
{
__TRACE( KError, (_L("ExecuteLineL: Can't execute sendtobackground in non s60 environment. Check if .cfg file name contains ui_ prefix and UITestingSupport= YES entry is defined in TestFrameworkd.ini")));
iRunErrorMessage = KErrMsgSendToBackgroundNotSupported;
User::Leave( KErrNotSupported );
}
}
break;
case TTestKeywords::EPressKey:
{
if ( iTestScripter->TestModuleIf().UITesting() == true )
{
continueTask = PressKeyL( aItem );
}
else
{
__TRACE( KError, (_L("ExecuteLineL: Can't execute presskey in non s60 environment. Check if .cfg file name contains ui_ prefix and UITestingSupport= YES entry is defined in TestFrameworkd.ini")));
iRunErrorMessage = KErrMsgPressKeyNotSupported;
User::Leave( KErrNotSupported );
}
// Check if it was global or local presskey
if ( !continueTask )
{
// Stop execution after key is pressed and wait until it is handled
SetActive();
}
}
break;
case TTestKeywords::ETypeText:
{
if ( iTestScripter->TestModuleIf().UITesting() == true )
{
continueTask = TypeTextL( aItem );
}
else
{
__TRACE( KError, (_L("ExecuteLineL: Can't execute typetext in non s60 environment. Check if .cfg file name contains ui_ prefix and UITestingSupport= YES entry is defined in TestFrameworkd.ini")));
iRunErrorMessage = KErrMsgTypeTextNotSupported;
User::Leave( KErrNotSupported );
}
// Check if it was global or local typetext
if ( !continueTask )
{
// Stop execution after key is pressed and wait until it is handled
SetActive();
}
}
break;
case TTestKeywords::EVar:
{
TName name;
TName buf;
TPtrC tmp;
//Get variable name
if(aItem->GetNextString(tmp) == KErrNone)
{
name.Copy(tmp);
}
else
{
//Error when getting variable name
__TRACE(KError, (_L("ExecuteLineL: Could not read variable name")));
iRunErrorMessage = KErrVarNameError;
User::Leave(KErrArgument);
}
//Get value for variable
while(aItem->GetNextString(tmp) == KErrNone)
{
if(buf.Length() + tmp.Length() >= buf.MaxLength())
{
//Error when getting variable name
__TRACE(KError, (_L("ExecuteLineL: Variable value too long")));
iRunErrorMessage = KErrVarValueError;
User::Leave(KErrArgument);
}
buf.Append(tmp);
buf.Append(_L(" "));
}
//Remove last space
if(buf.Length() > 0)
{
buf.SetLength(buf.Length() - 1);
}
//Store local variable
TInt count = iTestScripter->iDefinedLocal.Count();
TInt i;
for(i = 0; i < count; i++)
{
if(iTestScripter->iDefinedLocal[i]->Name() == name)
{
// Update existing
iTestScripter->iDefinedLocal[i]->SetValueL(buf);
__TRACE(KMessage, (_L("Update local variable [%S]: [%S]"), &name, &buf));
break;
}
}
if(i == count)
{
// New define, store it
CDefinedValue* define = CDefinedValue::NewL(name, buf);
CleanupStack::PushL(define);
User::LeaveIfError(iTestScripter->iDefinedLocal.Append(define));
CleanupStack::Pop(define);
__TRACE(KMessage, (_L("Add local variable [%S]: [%S]"), &name, &buf));
}
}
break;
case TTestKeywords::ECallSub:
{
// Get sub name
TPtrC subName;
//Get sub name
TInt err = aItem->GetNextString(subName);
if(err != KErrNone)
{
//Error when getting sub name
__TRACE(KError, (_L("ExecuteLineL: Could not read sub name [%d]"), err));
iRunErrorMessage = KErrSubNameError;
User::Leave(KErrArgument);
}
// Load section
CStifSectionParser* subSection = NULL;
TRAP(err,
subSection = iTestScripter->GetSubL(subName);
);
if((err != KErrNone) || (!subSection))
{
//Error when getting sub name
if(err == KErrNone)
{
err = KErrArgument;
}
__TRACE(KError, (_L("ExecuteLineL: Could not get section for sub [%d]"), err));
iRunErrorMessage = KErrSubGetError;
User::Leave(err);
}
// Handle new section parser
CleanupStack::PushL(subSection);
iTestScripter->iParserStack.AppendL(subSection);
__TRACE(KMessage, (_L("ExecuteLineL: Section for sub [%S] appended to section stack"), &subName));
CleanupStack::Pop(subSection);
iTestScripter->iCurrentParser = subSection;
iTestScripter->iCurrentParserReadFirstLine = EFalse; //Change it to false, becaue subSection is a new parser and it has nothing read
}
break;
case TTestKeywords::ESetResultDescription:
{
__TRACE(KMessage, (_L("%S"), &aKeyword));
iTestScripter->TestModuleIf().Printf(KPrintPriLow, _L("Runner"), _L("%S"), &aKeyword);
TName buf;
TPtrC tmp;
while(aItem->GetNextString(tmp) == KErrNone)
{
if(buf.Length() + tmp.Length() >= buf.MaxLength())
{
break;
}
if(buf.Length() > 0)
{
buf.Append(_L(" "));
}
buf.Append(tmp);
}
iTestScripter->SetResultDescription(buf);
RDebug::Print( _L("SetDescription to [%S]"), &buf );
}
break;
case TTestKeywords::ESendPointerEvent:
{
if ( iTestScripter->TestModuleIf().UITesting() == true )
{
continueTask = SendPointerEventL( aItem );
}
else
{
__TRACE( KError, (_L("ExecuteLineL: Can't execute sendpointerevent in non s60 environment. Check if .cfg file name contains ui_ prefix and UITestingSupport= YES entry is defined in TestFrameworkd.ini")));
iRunErrorMessage = KErrMsgSendPointerEventNotSupported;
User::Leave( KErrNotSupported );
}
// Check if it was global or local sendpointerevent
if ( !continueTask )
{
// Stop execution after pointer event is send and wait until it is handled
SetActive();
}
}
break;
case TTestKeywords::EUsing:
{
TInt err;
TPtrC dll;
err=aItem->GetNextString(dll);
err=iLibrary.Load(dll);
User::LeaveIfError(err);
TLibraryFunction LibEntryL=iLibrary.Lookup(1);
iPlugins.Append((CStfTestLibPlugin*)LibEntryL());
TPtrC temp;
err=aItem->GetNextString(temp);
HBufC* alias=HBufC::NewL(temp.Length());
alias->Des().Copy(temp);
iPluginnames.Append(alias);
break;
}
default:
{
if(ExecuteLibL(aKeyword, aItem))
{
}
else
{
continueTask = ExecuteCommandL( aKeyword, aItem );
}
}
break;
}
__TRACE( KMessage, (_L("ExecuteLineL: TestCase line executed")));
CleanupStack::PopAndDestroy(&buf);
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")));
iTestScripter->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->GetModuleName(), startInfo->GetTestCaseNumber() );
CSubTestCaseRunner* subTestCaseRunner = CLocalSubTestCaseRunner::NewLC( this );
__TRACE( KMessage, ( _L( "Executing sub test case: module=%S cfg=%S tcnum=%d id=%S" ),
&startInfo->GetModuleName(), &startInfo->GetConfig(),
startInfo->GetTestCaseNumber(), &startInfo->GetTestId()) );
RDebug::Print( _L( "Executing sub test case: module=%S cfg=%S tcnum=%d id=%S" ),
&startInfo->GetModuleName(), &startInfo->GetConfig(),
startInfo->GetTestCaseNumber(), &startInfo->GetTestId() );
subTestCaseRunner->RunSubTestCaseL( *startInfo );
iSubTestCases.AppendL( subTestCaseRunner );
if ( iLoopHelper->LoopInProgress() )
{
iLoopHelper->RegisterInLoopSubTestCaseL( subTestCaseRunner );
}
CleanupStack::Pop( subTestCaseRunner );
iRunErrorMessage = KNullDesC;
CleanupStack::PopAndDestroy( startInfo );
return ETrue;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteCompleteL
Description: Executes complete 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::ExecuteCompleteL( CStifItemParser* aItem )
{
_LIT( KErrMsgTestIdNotDefined, "%S : testid is not defined" );
TPtrC testId;
TInt ret = KErrNone;
TPtrC keywordStr = TTestKeywords::Keyword( TTestKeywords::EComplete );
// Parse testid
ret = aItem->GetNextString( testId );
if( ret != KErrNone )
{
iRunErrorMessage.Format( KErrMsgTestIdNotDefined, &keywordStr );
User::Leave( ret );
}
for ( TInt i = 0; i < iSubTestCases.Count(); i++ )
{
if ( iSubTestCases[ i ]->GetStartInfo()->GetTestId() == testId )
{
delete iTestIdForComplete;
iTestIdForComplete = testId.AllocL();
iInternalStateForSubTestCases = EISWaitingForComplete;
return EFalse;
}
}
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.GetModuleName() ));
// 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.GetConfig() ));
// Check is TestScripter
if( aStartInfo.GetModuleName().Find( KTestScripterName ) != KErrNotFound )
{
// TestScripter name is format: 'testscripter_testcasefilename'
TParse parse;
parse.Set( aStartInfo.GetConfig(), 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.SetModuleNameL( testScripterAndTestCaseFile );
}
// Testcase number
TInt testCaseNumber;
ret = aItem->GetInt( tmp, testCaseNumber );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgRunTestcaseNumberNotDefined;
User::Leave( ret );
}
aStartInfo.SetTestCaseNumber( testCaseNumber );
__TRACE( KMessage, (_L("testcasenum: %d"), testCaseNumber ) );
// 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( TTestKeywords::Parse( arg, TTestKeywords::RunOptArg ) )
{
case TTestKeywords::EExpect:
{
TLex ptr( val );
TInt expectedResult;
ret = ptr.Val( expectedResult );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgRunInvalidExpectValue;
User::Leave( ret );
}
aStartInfo.SetExpectedResult( expectedResult );
__TRACE( KMessage, (_L("expect=%d"), expectedResult ));
}
break;
case TTestKeywords::ETestid:
{
aStartInfo.SetTestIdL( val );
__TRACE( KMessage, (_L("TestId=%S"), &val));
}
break;
case TTestKeywords::EIni:
{
__TRACE( KMessage, (_L("ini=%S"), &val));
TFileName iniFileName( val );
TStifUtil::CorrectFilePathL( iniFileName );
aStartInfo.SetIniFileL( iniFileName );
}
break;
case TTestKeywords::ECategory:
{
__TRACE( KMessage, (_L("category=%S"), &val));
aStartInfo.SetExpectedResultCategory( TTestKeywords::GetResultCategory( val ) );
if( aStartInfo.GetExpectedResultCategory() == TFullTestResult::ECaseOngoing )
{
__TRACE( KError, (_L("Unknown or illegal result category")));
//Unknown or illegal category
iRunErrorMessage = KErrMsgRunUnknownOrIllegalCategory;
User::Leave( KErrGeneral );
}
}
break;
case TTestKeywords::ECaseTimeout:
{
TInt timeout;
TLex ptr( val );
ret = ptr.Val( timeout );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgRunInvalidTimeoutValue;
User::Leave( ret );
}
aStartInfo.SetTimeout( timeout );
__TRACE( KMessage, (_L("timeout=%d"), timeout ) );
}
break;
case TTestKeywords::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: 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 );
}
TBool CompareTDesC(const TDesC8& aLeft,const TDesC8& aRight)
{
return aLeft.Compare(aRight) == 0 ? ETrue : EFalse;
}
/**
* Executes method call to object script line.
*/
TBool CTestRunner::ExecuteLibL( TDesC& lib,
CStifItemParser* aItem )
{
TBool result=EFalse;
TIdentityRelation<TDesC8 > relation(CompareTDesC);
TInt count=iPluginnames.Count();
TInt index;
for( index=0;index<count;index++)
{
HBufC* temp=iPluginnames[index];
TPtr tempptr=temp->Des();
if(tempptr==lib)
{
TPtrC partcommand;
TBuf<300> commandline;
TBuf<100> command;
result=ETrue;
TInt i=0;
while(aItem->GetNextString(partcommand)==KErrNone)
{
if(i==0)
{
command.Append(partcommand);
}
commandline.Append(partcommand);
commandline.Append(_L(" "));
i++;
}
commandline.TrimAll();
if(iPlugins[index]->IsCommandSupported(command))
{
iPlugins[index]->ExecuteCommandL(commandline);
}
break;
}
}
return result;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: PressKeyL
Description: Send key press event to AppUi
Parameters: CStifItemParser* aItem: in: script line
Return Values: None
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::PressKeyL( CStifItemParser* aItem )
{
_LIT( KErrMsgSendKeyEventInvalidParameterValue, "PressKey: Invalid parameter %s value " );
_LIT( KErrMsgSendKeyEventInvalidParameter, "PressKey: Invalid parameter %s" );
_LIT( KKeyCodeParameter, "keycode=" );
_LIT( KKeyScanCodeParameter, "keyscancode=" );
_LIT( KModifierParameter, "modifier=" );
_LIT( KRepeatsParameter, "repeats=" );
_LIT( KModeGlobal, "global" );
_LIT( KModeLocal, "local" );
TBool globalMode = EFalse;
TUint keyCode = 0;
TInt keyScanCode = 0;
TUint keyModifiers = 0;
TInt keyRepeats = 0;
TPtrC parameter;
CUiEnvProxy* uiEnvProxy = iTestScripter->TestModuleIf().GetUiEnvProxy();
while( aItem->GetNextString( parameter ) == KErrNone )
{
if ( parameter.Find( KKeyCodeParameter ) == 0 )
{
TPtrC parameterValue = parameter.Right( parameter.Length() - KKeyCodeParameter().Length() );
TLex parameterValueParser( parameterValue );
if ( parameterValueParser.Val( keyCode ) != KErrNone )
{
if ( uiEnvProxy->ParseKeyCode( parameterValue, keyCode ) != KErrNone )
{
__TRACE( KError, (_L("SendKeyEvent: Invalid parameter value")));
TBuf<128> errMsg;
errMsg.Format( KErrMsgSendKeyEventInvalidParameterValue, &KKeyCodeParameter() );
iRunErrorMessage = errMsg;
User::Leave( KErrArgument );
}
}
}
else if ( parameter.Find( KKeyScanCodeParameter ) == 0 )
{
TPtrC parameterValue = parameter.Right( parameter.Length() - KKeyScanCodeParameter().Length() );
TLex parameterValueParser( parameterValue );
if ( parameterValueParser.Val( keyScanCode ) != KErrNone )
{
if ( uiEnvProxy->ParseKeyScanCode( parameterValue, keyScanCode ) != KErrNone )
{
__TRACE( KError, (_L("SendKeyEvent: Invalid parameter value")));
TBuf<128> errMsg;
errMsg.Format( KErrMsgSendKeyEventInvalidParameterValue, &KKeyCodeParameter() );
iRunErrorMessage = errMsg;
User::Leave( KErrArgument );
}
}
}
else if ( parameter.Find( KModifierParameter ) == 0 )
{
TPtrC parameterValue = parameter.Right( parameter.Length() - KModifierParameter().Length() );
TLex parameterValueParser( parameterValue );
if ( parameterValueParser.Val( keyModifiers ) != KErrNone )
{
if ( uiEnvProxy->ParseModifier( parameterValue, keyModifiers ) != KErrNone )
{
__TRACE( KError, (_L("SendKeyEvent: Invalid parameter value")));
TBuf<128> errMsg;
errMsg.Format( KErrMsgSendKeyEventInvalidParameterValue, &KModifierParameter() );
iRunErrorMessage = errMsg;
User::Leave( KErrArgument );
}
}
}
else if ( parameter.Find( KRepeatsParameter ) == 0 )
{
TPtrC parameterValue = parameter.Right( parameter.Length() - KRepeatsParameter().Length() );
TLex parameterValueParser( parameterValue );
if ( parameterValueParser.Val( keyRepeats ) != KErrNone )
{
__TRACE( KError, (_L("SendKeyEvent: Invalid parameter value")));
TBuf<128> errMsg;
errMsg.Format( KErrMsgSendKeyEventInvalidParameterValue, &KRepeatsParameter() );
iRunErrorMessage = errMsg;
User::Leave( KErrArgument );
}
}
else if ( parameter == KModeGlobal )
{
globalMode = ETrue;
}
else if ( parameter == KModeLocal )
{
globalMode = EFalse;
}
else if ( uiEnvProxy->ParseKeyCode( parameter, keyCode ) == KErrNone )
{
}
else if ( parameter.Length() == 1 )
{
keyCode = parameter[ 0 ];
}
else
{
__TRACE( KError, (_L("PressKey: Invalid parameter")));
TBuf<128> errMsg;
errMsg.Format( KErrMsgSendKeyEventInvalidParameter, ¶meter );
iRunErrorMessage = errMsg;
User::Leave( KErrArgument );
}
}
if ( globalMode )
{
uiEnvProxy->PressKeyL( keyCode, keyScanCode, keyModifiers, keyRepeats );
}
else
{
uiEnvProxy->PressKeyL( &iStatus, keyCode, keyScanCode, keyModifiers, keyRepeats );
}
return globalMode;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: TypeTextL
Description: Sends text to AppUi
Parameters: CStifItemParser* aItem: in: script line
Return Values: None
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::TypeTextL( CStifItemParser* aItem )
{
_LIT( KErrMsgTypeTextInvalidParameter, "TypeText: Invalid parameter %S" );
_LIT( KErrMsgTypeTextNotEnoughParameters, "TypeText: Not enough parameters" );
TBool globalMode = EFalse;
TPtrC command;
TPtrC text;
aItem->SetParsingType( CStifItemParser::EQuoteStyleParsing );
// Read first parameter
TInt ret = aItem->GetNextString( command );
if ( ret != KErrNone )
{
__TRACE( KError, (_L("TypeText: Not enough parameters")));
iRunErrorMessage = KErrMsgTypeTextNotEnoughParameters;
User::Leave( ret );
}
// Read second parameter
ret = aItem->GetNextString( text );
// Check if second can be read. if yes then check if first parameters is
// 'global' parameter
if ( ret != KErrNone )
{
// normal type text
text.Set( command );
iTestScripter->TestModuleIf().GetUiEnvProxy()->TypeTextL( &iStatus, text );
globalMode = EFalse;
}
else if ( command == _L("global") )
{
iTestScripter->TestModuleIf().GetUiEnvProxy()->TypeTextL( text );
globalMode = ETrue;
}
else
{
__TRACE( KError, (_L("TypeText: Invalid parameter")));
TBuf<128> errMsg;
errMsg.Format( KErrMsgTypeTextInvalidParameter, &command );
iRunErrorMessage = errMsg;
User::Leave( KErrNotSupported );
}
return globalMode;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: SendPointerEventL
Description: Send key press event to AppUi
Parameters: CStifItemParser* aItem: in: script line
Return Values: None
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
TBool CTestRunner::SendPointerEventL( CStifItemParser* aItem )
{
// Error messages
_LIT( KErrMsgNotEnoughParameters, "SendPointerEvent: Not enough parameters" );
_LIT( KErrMsgPointerEventTypeNotDefined, "SendPointerEvent: Pointer event type not defined" );
_LIT( KErrMsgInvalidUnknownPointerEventType, "SendPointerEvent: Invalid/Unknown pointer event type %S" );
_LIT( KErrMsgPositionXNotDefined, "SendPointerEvent: x co-ordinate is not defined" );
_LIT( KErrMsgPositionYNotDefined, "SendPointerEvent: y co-ordinate is not defined" );
_LIT( KErrMsgPositionXInvalidValue, "SendPointerEvent: Invalid value of x co-ordinate" );
_LIT( KErrMsgPositionYInvalidValue, "SendPointerEvent: Invalid value of y co-ordinate" );
// Parameters keywords
_LIT( KModeGlobal, "global" );
_LIT( KModeLocal, "local" );
TBool globalMode = EFalse;
TUint eventType = 0;
TPoint position( 0, 0 );
TPoint parentPosition( 0, 0 );
TPtrC parameter;
CUiEnvProxy* uiEnvProxy = iTestScripter->TestModuleIf().GetUiEnvProxy();
// Get first parameter
if ( aItem->GetNextString( parameter ) != KErrNone )
{
__TRACE( KError, (_L("SendPointerEvent: Not enough parameters")));
iRunErrorMessage = KErrMsgNotEnoughParameters;
User::Leave( KErrArgument );
}
else
{
TBool modeSelected = EFalse;
// Check if global/local mode is defined
if ( parameter == KModeLocal )
{
globalMode = false;
modeSelected = ETrue;
}
else if ( parameter == KModeGlobal )
{
globalMode = true;
modeSelected = ETrue;
}
if ( modeSelected )
{
// First parameter was mode so we need get next parameter which should
// contain event type
if ( aItem->GetNextString( parameter ) != KErrNone )
{
__TRACE( KError, (_L("SendPointerEvent: Pointer event type not defined")));
iRunErrorMessage = KErrMsgPointerEventTypeNotDefined;
User::Leave( KErrArgument );
}
}
}
// Parse event type
if ( uiEnvProxy->ParsePointerEventType( parameter, eventType ) != KErrNone )
{
__TRACE( KError, (_L("PressKey: Invalid/Unknown pointer event type %S"), ¶meter ));
iRunErrorMessage.Format( KErrMsgInvalidUnknownPointerEventType, ¶meter );
User::Leave( KErrArgument );
}
if ( aItem->GetNextString( parameter ) != KErrNone )
{
__TRACE( KError, (_L("SendPointerEvent: x co-ordinate is not defined")));
iRunErrorMessage = KErrMsgPositionXNotDefined;
User::Leave( KErrArgument );
}
TLex parameterParser( parameter );
if ( parameterParser.Val( position.iX ) != KErrNone )
{
__TRACE( KError, (_L("SendPointerEvent: Invalid value of x co-ordinate")));
iRunErrorMessage = KErrMsgPositionXInvalidValue;
User::Leave( KErrArgument );
}
if ( aItem->GetNextString( parameter ) != KErrNone )
{
__TRACE( KError, (_L("SendPointerEvent: y co-ordinate is not defined")));
iRunErrorMessage = KErrMsgPositionYNotDefined;
User::Leave( KErrArgument );
}
parameterParser.Assign( parameter );
if ( parameterParser.Val( position.iY ) != KErrNone )
{
__TRACE( KError, (_L("SendPointerEvent: Invalid value of y co-ordinate")));
iRunErrorMessage = KErrMsgPositionYInvalidValue;
User::Leave( KErrArgument );
}
// Send pointer event
if ( globalMode )
{
uiEnvProxy->SendPointerEventL( eventType, position );
}
else
{
uiEnvProxy->SendPointerEventL( &iStatus, eventType, position );
}
return globalMode;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteEventL
Description: Executes event command script line
Parameters: TDesC& aKeyword: in: keyword string
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::ExecuteEventL( TDesC& aKeyword,
CStifItemParser* aItem )
{
_LIT( KErrMsgEventNameNotDefined, "%S : Event name not defined" );
_LIT( KErrMsgUnknowKeyword, "Unknow keyword %S" );
TInt ret = KErrNone;
TInt key = TTestKeywords::Parse( aKeyword, TTestKeywords::Keyword );
TBool continueTask = ETrue;
TPtrC eventName;
// read eventname
ret = aItem->GetNextString( eventName );
if ( ret != KErrNone )
{
iRunErrorMessage.Format( KErrMsgEventNameNotDefined, &aKeyword );
User::Leave( ret );
}
TEventIf event;
event.SetName( eventName );
__TRACE( KMessage, (_L("%S %S"), &aKeyword, &eventName));
iTestScripter->TestModuleIf().Printf( KPrintPriLow, _L("Event"),
_L("%S %S"), &aKeyword, &eventName);
switch( key )
{
case TTestKeywords::ERequest:
{
HBufC* eName = eventName.AllocLC();
User::LeaveIfError( iEventArray.Append( eName ) );
CleanupStack::Pop( eName );
event.SetType( TEventIf::EReqEvent );
ret = iTestScripter->TestModuleIf().Event( event );
}
break;
case TTestKeywords::EWait:
{
event.SetType( TEventIf::EWaitEvent );
iTestScripter->TestModuleIf().Event( event, iStatus );
SetActive();
continueTask = EFalse;
}
break;
case TTestKeywords::ERelease:
{
event.SetType( TEventIf::ERelEvent );
ret = iTestScripter->TestModuleIf().Event( event );
if( ret == KErrNone )
{
TPtrC eName;
TInt count = iEventArray.Count();
for( TInt i = 0; i < count; i++ )
{
eName.Set( iEventArray[i]->Des() );
if( eName == eventName )
{
HBufC* tmp = iEventArray[i];
iEventArray.Remove(i);
delete tmp;
break;
}
}
}
}
break;
case TTestKeywords::ESet:
{
event.SetType( TEventIf::ESetEvent );
TPtrC tmp;
// Get optional set argument
if( aItem->GetNextString( tmp ) == KErrNone )
{
// Parse optional set argument
if( tmp == _L("state") )
{
__TRACE( KMessage, (_L("State event")));
event.SetEventType( TEventIf::EState );
}
else
{
__TRACE( KError,
(_L("Unknown argument for set %S"),
&tmp));
}
}
ret = iTestScripter->TestModuleIf().Event( event );
}
break;
case TTestKeywords::EUnset:
{
event.SetType( TEventIf::EUnsetEvent );
event.SetEventType( TEventIf::EState );
ret = iTestScripter->TestModuleIf().Event( event );
}
break;
default:
__TRACE( KError, (_L("Unknown keyword %S"), &aKeyword));
iRunErrorMessage.Format( KErrMsgUnknowKeyword, &aKeyword );
User::Leave( KErrGeneral );
break;
}
if( ret != KErrNone )
{
TName resultDescr;
resultDescr.Format(_L("Event %S returned error: %d"), &aKeyword, ret);
iTestScripter->UpdateTestCaseResult(ret, resultDescr);
// Stops execution from CTestRunner::RunError
User::Leave( KErrGeneral );
}
return continueTask;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteCommandL
Description: Executes script line
Parameters: TDesC& aObject: in: object name
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::ExecuteCommandL( TDesC& aObject, CStifItemParser* aItem)
{
_LIT( KErrMsgUnknownObjOrKeyword, "Unknow keyword/object %S" );
TTestObjectBase* obj = iTestScripter->GetObject ( aObject );
if( obj == NULL )
{
iRunErrorMessage.Format( KErrMsgUnknownObjOrKeyword, &aObject );
User::Leave( KErrGeneral );
}
if( iTestCaseResults.Count() == 0 )
{
// KErrNone is the default result expected if nothing else is given
User::LeaveIfError( iTestCaseResults.Append( KErrNone ) );
}
// OOM heap testing with FAILNEXT
if( iHeapFailNext > 0 )
{
__TRACE( KPrint, (
_L( "OOM FAILNEXT is used with count value: %d " ),
iHeapFailNext) );
User::__DbgSetAllocFail( RHeap::EUser, RHeap::EFailNext, iHeapFailNext );
}
// OOM heap testing with SETFAIL
if( iHeapSetFailValue > 0 )
{
__TRACE( KPrint, (
_L("OOM SETFAIL is used with type:[%d] and value(rate):[%d]"),
iHeapSetFailType, iHeapSetFailValue ) );
User::__DbgSetAllocFail( RHeap::EUser, iHeapSetFailType, iHeapSetFailValue );
}
TInt commandResult = KErrNone;
TRAP( commandResult, commandResult = obj->RunMethodL( *aItem ) );
// Reset OOM macro immediately(Otherwise other allocations
// will be blocked)
User::__DbgSetAllocFail( RHeap::EUser, RHeap::ENone, 1 );
// OOM test class's build block handling
if( iTestScripter->iOOMIgnoreFailure )
{
__TRACE( KPrint, (
_L( "----------< OOM related test information >----------" ) ) );
if( iHeapFailNext > 0 )
{
__TRACE( KPrint, (
_L( "'oomignorefailure' is:[ON] and 'failnextvalue' count is:[%d]" ),
iHeapFailNext ) );
}
if( iHeapSetFailValue > 0 )
{
__TRACE( KPrint, (
_L( "'oomignorefailure' is:[ON], 'setfailtype' type is:[%d] and value is:[%d]" ),
iHeapSetFailType, iHeapSetFailValue ) );
}
__TRACE( KPrint, (
_L( "Test class build block execution with result:[%d]" ),
commandResult ) );
__TRACE( KPrint, (
_L( "----------------------------------------------------" ) ) );
// Continue testing, despite the memory error situations
iTestCaseResults.Reset();
return ETrue; // Continue script executions
}
// Normal test class's build block handling
if( iTestCaseResults.Find( commandResult ) < 0 )
{
__TRACE( KError, ( _L("Command for [%S] failed (%d)"),
&aObject, commandResult ));
// Added more logging for this special case
if( commandResult == KErrNone )
{
__TRACE( KError, (_L("Test fails with result KErrGeneral, because execution result was KErrNone and expected results given with 'allownextresult' were Symbian's error codes (<0)")));
}
iTestScripter->UpdateTestCaseResult(commandResult, _L("CTestRunner::ExecuteCommandL returned error"));
// Stops execution from CTestRunner::RunError
User::Leave( KErrGeneral );
}
iTestCaseResults.Reset();
// Reset test case allow result to CTestModuleIf side too. This is
// used in TAL-TA5L macro handling.
User::LeaveIfError(
iTestScripter->TestModuleIf().ResetAllowResult() );
return ETrue;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: SetRunnerActive
Description: Set CTestRunner active and complete.
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestRunner::SetRunnerActive()
{
__TRACEFUNC();
// Update state
iState = ERunnerRunning;
iStatus = KRequestPending;
TRequestStatus* rs = &iStatus;
SetActive();
User::RequestComplete( rs, KErrNone );
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: OOMIgnoreFailure
Description: Handles 'oomignorefailure' keyword parsing.
Parameters: CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestRunner::OOMIgnoreFailureL( CStifItemParser* aItem )
{
_LIT( KerrMsgOOMIgnoreFailureUnknownArgument, "OOMIgnoreFailure : Invalid argument %S" );
_LIT( KerrMsgOOMIgnoreFailureNoArgument, "OOMIgnoreFailure : Parameter not defined" );
__TRACEFUNC();
TPtrC tmp;
// Get result
if( aItem->GetNextString( tmp ) == KErrNone )
{
if( tmp == _L("ON") || tmp == _L("on") )
{
__TRACE( KMessage, (_L("OOM related 'oomignorefailure': ON")));
iTestScripter->iOOMIgnoreFailure = ETrue;
}
else if( tmp == _L("OFF") || tmp == _L("off") )
{
__TRACE( KMessage, (_L("OOM related 'oomignorefailure': OFF")));
iTestScripter->iOOMIgnoreFailure = EFalse;
}
else
{
__TRACE( KError,
(_L("Unknown argument for 'oomignorefailure': [%S]"),
&tmp));
iRunErrorMessage.Format( KerrMsgOOMIgnoreFailureUnknownArgument, &tmp );
User::Leave( KErrArgument );
}
}
else
{
__TRACE( KError, ( _L( "Unknown argument for 'oomignorefailure'" ) ) );
iRunErrorMessage = KerrMsgOOMIgnoreFailureNoArgument;
User::Leave( KErrArgument );
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: OOMHeapFailNext
Description: Handles 'oomheapfailnext' keyword parsing.
Parameters: CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestRunner::OOMHeapFailNextL( CStifItemParser* aItem )
{
_LIT( KErrMsgHeapFailNextNoArgument, "HeapFailNext : Parameters is not defined or has invalid value" );
_LIT( KErrMsgHeapFailNextInvalidValue, "HeapFailNext : Argument value can't be <0" );
__TRACEFUNC();
TInt heapfailNext( 0 );
// If LOOP_COUNTER is used the GetNextInt returns a correct
// value(Because of the LOOP_COUNTER implementation).
if( aItem->GetNextInt( heapfailNext ) == KErrNone )
{
if( heapfailNext < 0 )
{
__TRACE( KError, ( _L( "Argument value must be >0" ) ) );
iRunErrorMessage = KErrMsgHeapFailNextInvalidValue;
User::Leave( KErrArgument );
}
// OOM heap's FAILNEXT range is from 1 to n
iHeapFailNext = heapfailNext + 1;
__TRACE( KMessage, ( _L( "'oomheapfailnext' count value(rate): %d" ),
iHeapFailNext ) );
}
else
{
__TRACE( KError, ( _L( "Unknown argument for 'oomheapfailnext'" ) ) );
iRunErrorMessage = KErrMsgHeapFailNextNoArgument;
User::Leave( KErrArgument );
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: OOMHeapSetFail
Description: Handles 'oomheapsetfail' keyword parsing.
Parameters: CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestRunner::OOMHeapSetFailL( CStifItemParser* aItem )
{
_LIT( KErrMsgOOMHeapSetFailTypeNotDefined, "OOMHeapSetFail : Parameter type is not defined" );
_LIT( KErrMsgOOMHeapSetFailRateNotDefined, "OOMHeapSetFail : Parameter rate is not defined" );
_LIT( KErrMsgOOMHeapSetFailTypeInvalidValue, "OOMHeapSetFail : Parameter type has invalid value" );
_LIT( KErrMsgOOMHeapSetFailRateInvalidValue, "OOMHeapSetFail : Parameter rate can't be <0" );
__TRACEFUNC();
_LIT( KRandom, "random");
_LIT( KTrueRandom, "truerandom");
_LIT( KDeterministic, "deterministic");
_LIT( KNone, "none");
_LIT( KFailNext, "failnext");
TPtrC type;
TInt value( 0 );
// NOTE: If error in type or value parsing => return without changing
// iHeapSetFailType or iHeapSetFailValue variables.
// Get type
if( aItem->GetNextString( type ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'oomheapsetfail' type" ) ) );
iRunErrorMessage = KErrMsgOOMHeapSetFailTypeNotDefined;
User::Leave( KErrArgument );
}
// Get value(rate)
if( aItem->GetNextInt( value ) != KErrNone )
{
if(type == KNone)
{
value = 0;
}
else
{
__TRACE( KError, (_L( "Unknown argument for 'oomheapsetfail' value(rate)" ) ) );
iRunErrorMessage = KErrMsgOOMHeapSetFailRateNotDefined;
User::Leave( KErrArgument );
}
}
// All parsing operations are passed, get type and value
// Get type
if(type == KRandom)
{
__TRACE( KMessage, (_L("'oomheapsetfail' type: random")));
iHeapSetFailType = RHeap::ERandom;
}
else if(type == KTrueRandom)
{
__TRACE( KMessage, (_L("'oomheapsetfail' type: truerandom")));
iHeapSetFailType = RHeap::ETrueRandom;
}
else if(type == KDeterministic)
{
__TRACE( KMessage, (_L("'oomheapsetfail' type: deterministic")));
iHeapSetFailType = RHeap::EDeterministic;
}
else if(type == KNone)
{
__TRACE( KMessage, (_L("'oomheapsetfail' type: none")));
iHeapSetFailType = RHeap::ENone;
}
else if(type == KFailNext)
{
__TRACE( KMessage, (_L("'oomheapsetfail' type: failnext")));
iHeapSetFailType = RHeap::EFailNext;
}
else
{
__TRACE( KError,
( _L( "Unknown argument for 'oomheapsetfail' type: [%S]" ),
&type ) );
iRunErrorMessage = KErrMsgOOMHeapSetFailTypeInvalidValue;
User::Leave( KErrArgument );
}
if( value < 0 )
{
__TRACE( KError, _L( "'oomheapsetfail' value(rate) can't be <0" ) );
iRunErrorMessage = KErrMsgOOMHeapSetFailRateInvalidValue;
User::Leave( KErrArgument );
}
// Get value
// OOM heap's SETFAIL range is from 1 to n
iHeapSetFailValue = value + 1;
__TRACE(KMessage, (_L( "'oomheapsetfail' value(rate): [%d]" ), iHeapSetFailValue));
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: OOMHeapToNormal
Description: Initialize all OOM related variables.
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestRunner::OOMHeapToNormal()
{
__TRACEFUNC();
if( iTestScripter )
{
// This should initialize also
iTestScripter->iOOMIgnoreFailure = EFalse;
}
iHeapFailNext = 0;
iHeapSetFailType = RHeap::ENone;
iHeapSetFailValue = 0;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: TestInterference
Description: Starts test interference.
Parameters: CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::TestInterferenceL( CStifItemParser* aItem )
{
_LIT( KErrMsgTestInterferenceNameNotDefined, "TestInterference : Parameter name is not defined" );
_LIT( KErrMsgTestInterferenceCommandNotDefined, "TestInterference : Parameter command is not defined" );
_LIT( KErrMsgTestInterferenceCommandInvalidValue, "TestInterference : Parameter command has invalid value" );
__TRACEFUNC();
TPtrC name;
TPtrC command;
// Get name
if( aItem->GetNextString( name ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' name" ) ) );
iRunErrorMessage = KErrMsgTestInterferenceNameNotDefined;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
// Get command
if( aItem->GetNextString( command ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' command" ) ) );
iRunErrorMessage = KErrMsgTestInterferenceCommandNotDefined;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
if( command == _L( "start" ) )
{
__TRACE( KMessage, ( _L( "'testinterference' called, starts test interference") ) );
StartInterferenceL( name, aItem );
}
else if( command == _L( "stop" ) )
{
__TRACE( KMessage, ( _L( "'testinterference' called, stops and releases test interference") ) );
StopInterferenceL( name );
}
else
{
__TRACE( KError, (
_L( "Unknown command for 'testinterference'[%S]" ), &command ) );
iRunErrorMessage = KErrMsgTestInterferenceCommandInvalidValue;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: StartInterference
Description:
Parameters: CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::StartInterferenceL( TDesC& aName, CStifItemParser* aItem )
{
_LIT( KErrMsgStartInterferenceCategoryNotDefined, "TestInterference : Parameter category is not defined" );
_LIT( KErrMsgStartInterferenceCategoryInvalidValue, "TestInterference : Parameter category has invalid value" );
_LIT( KErrMsgStartInterferenceTypeNotDefined, "TestInterference : Parameter type is not defined" );
_LIT( KErrMsgStartInterferenceTypeInvalidValue, "TestInterference : Parameter type has invalid value" );
_LIT( KErrMsgStartInterferenceIdleNotDefined, "TestInterference : Parameter idle is not defined or has invalid value" );
_LIT( KErrMsgStartInterferenceIdleInvalidValue, "TestInterference : Parameter idle has invalid value" );
_LIT( KErrMsgStartInterferenceActiveNotDefined, "TestInterference : Parameter active is not defined or has invalid value" );
_LIT( KErrMsgStartInterferenceActiveInvalidValue, "TestInterference : Parameter active has invalid value" );
__TRACEFUNC();
TPtrC category;
TPtrC type;
TInt idle( 0 );
TInt active( 0 );
TInt priority( 0 );
// Get category
if( aItem->GetNextString( category ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' category" ) ) );
iRunErrorMessage = KErrMsgStartInterferenceCategoryNotDefined;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
// Get type
if( aItem->GetNextString( type ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' type" ) ) );
iRunErrorMessage = KErrMsgStartInterferenceTypeNotDefined;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
TPtrC timeStr;
TReal time;
// Get idle time
if( aItem->GetNextString( timeStr ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' idle" ) ) );
iRunErrorMessage = KErrMsgStartInterferenceIdleNotDefined;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
if ( TLex( timeStr ).Val( time, '.' ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' idle" ) ) );
iRunErrorMessage = KErrMsgStartInterferenceIdleNotDefined;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
// Convert idle time from milli to micro seconds
idle = time * 1000.0;
if( idle < 0 )
{
__TRACE( KError, (
_L( "Argument 'testinterference' idle can't be <0" ) ) );
iRunErrorMessage = KErrMsgStartInterferenceIdleInvalidValue;
User::Leave( KErrArgument );
}
// Get active time
if( aItem->GetNextString( timeStr ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' active" ) ) );
iRunErrorMessage = KErrMsgStartInterferenceActiveNotDefined;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
if ( TLex( timeStr ).Val( time, '.' ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' idle" ) ) );
iRunErrorMessage = KErrMsgStartInterferenceIdleNotDefined;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
// Convert active time from milli to micro seconds
active = time * 1000.0;
if( active < 0 )
{
__TRACE( KError, (
_L( "Argument 'testinterference' active can't be <0" ) ) );
iRunErrorMessage = KErrMsgStartInterferenceActiveInvalidValue;
User::Leave( KErrArgument );
}
// Get priority
if( aItem->GetNextInt( priority ) != KErrNone )
{
// Log information only do not return. Priority value is optional.
__TRACE( KInit, (
_L( "Unknown argument for 'testinterference' priority or value not given, default priority will be used" ) ) );
}
MSTIFTestInterference* interference = NULL;
// Get category
if( category == _L("activeobject") )
{
interference = MSTIFTestInterference::NewL( iTestScripter,
MSTIFTestInterference::EActiveObject );
}
else if( category == _L("thread") )
{
interference = MSTIFTestInterference::NewL( iTestScripter,
MSTIFTestInterference::EThread );
}
else
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' category[%S]" ), &category ) );
iRunErrorMessage = KErrMsgStartInterferenceCategoryInvalidValue;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
// Create object that include test interference information and append this
// to array.
TTestInterference* object = new (ELeave) TTestInterference();
object->iName = aName;
object->iInterference = interference;
// Array for handling test interference between different objects
TInt ret = iTestInterferenceArray.Append( object );
if( ret != KErrNone )
{
delete object;
__TRACE( KError, (
_L( "CTestRunner::StartInterference: iTestInterferenceArray.Append fails:[%d]" ), ret ) );
User::Leave( ret );
}
// Set priority if user given
if( priority != 0 )
{
interference->SetPriority( priority );
}
// Get type
if( type == _L("cpuload") )
{
interference->StartL( MSTIFTestInterference::ECpuLoadMicroSeconds, idle , active );
}
else if( type == _L("filesystemreadc") )
{
interference->StartL( MSTIFTestInterference::EFileSystemReadCMicroSeconds, idle , active );
}
else if( type == _L("filesystemreadd") )
{
interference->StartL( MSTIFTestInterference::EFileSystemReadDMicroSeconds, idle , active );
}
else if( type == _L("filesystemreade") )
{
interference->StartL( MSTIFTestInterference::EFileSystemReadEMicroSeconds, idle , active );
}
else if( type == _L("filesystemreadz") )
{
interference->StartL( MSTIFTestInterference::EFileSystemReadZMicroSeconds, idle , active );
}
else if( type == _L("filesystemwritec") )
{
interference->StartL( MSTIFTestInterference::EFileSystemWriteCMicroSeconds, idle , active );
}
else if( type == _L("filesystemwrited") )
{
interference->StartL( MSTIFTestInterference::EFileSystemWriteDMicroSeconds, idle , active );
}
else if( type == _L("filesystemwritee") )
{
interference->StartL( MSTIFTestInterference::EFileSystemWriteEMicroSeconds, idle , active );
}
else if( type == _L("filesystemfillandemptyc") )
{
interference->StartL( MSTIFTestInterference::EFileSystemFillAndEmptyCMicroSeconds, idle , active );
}
else if( type == _L("filesystemfillandemptyd") )
{
interference->StartL( MSTIFTestInterference::EFileSystemFillAndEmptyDMicroSeconds, idle , active );
}
else if( type == _L("filesystemfillandemptye") )
{
interference->StartL( MSTIFTestInterference::EFileSystemFillAndEmptyEMicroSeconds, idle , active );
}
else
{
__TRACE( KError, (
_L( "Unknown argument for 'testinterference' type[%S]" ), &type ) );
iRunErrorMessage = KErrMsgStartInterferenceTypeInvalidValue;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: StopInterference
Description: Stops test interference.
Parameters: TDesC& aName: in: Indicates right test interference object.
Return Values: None.
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::StopInterferenceL( TDesC& aName )
{
_LIT( KErrMsgStopInterference, "TestInterference : testinterference %S was not start" );
__TRACEFUNC();
TInt count = iTestInterferenceArray.Count();
for( TInt i = 0; i < count; i++ )
{
if( iTestInterferenceArray[i]->iName == aName )
{
// Found test module, return description
iTestInterferenceArray[i]->iInterference->Stop();
// Delete data
delete iTestInterferenceArray[i];
// Remove pointer to deleted data(Append())
iTestInterferenceArray.Remove( i );
// iTestMeasurementArray can contain only one type of measurement
// so we can break when type is removed.
return;
}
}
__TRACE( KError, (
_L( "'testinterference' type[%S] was not start" ), &aName ) );
iRunErrorMessage.Format( KErrMsgStopInterference, &aName );
User::Leave( KErrArgument ); // Error in parsing => Leave
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: MeasurementL
Description: Starts test measurement.
Parameters: CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: Leaves if StartBappeaMeasurementL() fails.
Leaves if StopBappeaMeasurementL() fails.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::MeasurementL( CStifItemParser* aItem )
{
_LIT( KErrMsgMeasurementCommandNotDefined, "TestMeasurement : Parameter command is not defined" );
_LIT( KErrMsgMeasurementTypeNotDefined, "TestMeasurement : Parameter type is not defined" );
_LIT( KErrMsgMeasurementUnknownType, "TestMeasurement : Unknown measurement type %S" );
_LIT( KErrMsgMeasurementUnknownCommand, "TestMeasurement : Unknown command %S" );
__TRACEFUNC();
TPtrC type;
TPtrC command;
// Get command
if( aItem->GetNextString( command ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'measurement' command" ) ) );
iRunErrorMessage = KErrMsgMeasurementCommandNotDefined;
User::Leave( KErrArgument ); // Error in parsing => Leave
}
// Get name
if( aItem->GetNextString( type ) != KErrNone )
{
__TRACE( KError, (
_L( "Unknown argument for 'measurement' type" ) ) );
iRunErrorMessage = KErrMsgMeasurementTypeNotDefined;
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 ) );
iRunErrorMessage.Format( KErrMsgMeasurementUnknownType, &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 ) );
iRunErrorMessage.Format( KErrMsgMeasurementUnknownCommand, &command );
User::Leave( KErrArgument ); // Error in commands => Leave
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: StartMeasurementL
Description: Start measurement
Parameters: const TDesC& aType: in: Plugin type.
CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: Leaves is measurement operation fails.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::StartMeasurementL( const TDesC& aType,
CStifItemParser* aItem )
{
_LIT( KErrMsgMeasurementUnknownPlugin, "Measurement : Unknown measurement plugin %S" );
_LIT( KErrMsgMeasurementStartFail, "Measurement : Measurement start fails" );
__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(
iTestScripter,
CSTIFTestMeasurement::KStifMeasurementPlugin01,
configurationInfo );
}
else if( aType == KParamMeasurement02 )
{
testMeasurement = CSTIFTestMeasurement::NewL(
iTestScripter,
CSTIFTestMeasurement::KStifMeasurementPlugin02,
configurationInfo );
}
else if( aType == KParamMeasurement03 )
{
testMeasurement = CSTIFTestMeasurement::NewL(
iTestScripter,
CSTIFTestMeasurement::KStifMeasurementPlugin03,
configurationInfo );
}
else if( aType == KParamMeasurement04 )
{
testMeasurement = CSTIFTestMeasurement::NewL(
iTestScripter,
CSTIFTestMeasurement::KStifMeasurementPlugin04,
configurationInfo );
}
else if( aType == KParamMeasurement05 )
{
testMeasurement = CSTIFTestMeasurement::NewL(
iTestScripter,
CSTIFTestMeasurement::KStifMeasurementPlugin05,
configurationInfo );
}
else if( aType == KParamMeasurementBappea )
{
testMeasurement = CSTIFTestMeasurement::NewL(
iTestScripter,
CSTIFTestMeasurement::KStifMeasurementBappeaProfiler,
configurationInfo );
}
else
{
__TRACE( KError, ( _L( "Unknown plugin[%S] for 'measurement'" ), &aType ) );
iRunErrorMessage.Format( KErrMsgMeasurementUnknownPlugin, &aType );
User::Leave( KErrArgument );
}
// Start test measurement
TInt start_ret( KErrNone );
start_ret = testMeasurement->Start();
if( start_ret != KErrNone )
{
delete testMeasurement;
//CleanupStack::PopAndDestroy( setting_buf );
__TRACE( KError, (
_L( "CTestRunner::StartMeasurementL(): Measurement Start() fails:[%d]" ), start_ret ) );
iRunErrorMessage = KErrMsgMeasurementStartFail;
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( "CTestRunner::StartMeasurementL(): iTestMeasurementArray.Append fails:[%d]" ), ret ) );
User::Leave( ret );
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: StopMeasurementL
Description: Stops test measurement.
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::StopMeasurementL( const TDesC& aType )
{
_LIT( KErrMsgMeasurementNotStarted, "Measurement : Measurement %S was not start" );
__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.
return;
}
}
__TRACE( KError, (
_L( "CTestRunner::StopMeasurementL(): Measurement %S was not start" ), &aType ) );
iRunErrorMessage.Format( KErrMsgMeasurementNotStarted, &aType );
User::Leave( KErrArgument );
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: AddTestCaseResultL
Description: Adds new test case result. Used with 'allownextresult'
and 'allowerrorcodes' keywords.
Parameters: CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: Leaves if iTestCaseResults.Append fails.
Leaves if aItem->GetNextInt() fails.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::AddTestCaseResultL( CStifItemParser* aItem )
{
_LIT( KErrMsgAllowNextResultInvalidValue, "No expected result value given or value has invalid format" );
TInt result;
TPtrC codeBuf;
TBool found = EFalse;
while( aItem->GetNextString( codeBuf ) == KErrNone )
{
TLex codeParser( codeBuf );
if ( codeParser.Val( result ) != KErrNone )
{
__TRACE( KError, (_L("ExecuteLineL: No expected result value given")));
iRunErrorMessage = KErrMsgAllowNextResultInvalidValue;
User::Leave( KErrArgument );
}
else
{
User::LeaveIfError( iTestCaseResults.Append( result ) );
// Set test case allow result to CTestModuleIf side too. This is
// used in TAL-TA5L macro handling.
User::LeaveIfError(
iTestScripter->TestModuleIf().SetAllowResult( result ) );
found = ETrue;
}
}
if ( !found )
{
__TRACE( KError, (_L("ExecuteLineL: No expected result value given")));
iRunErrorMessage = KErrMsgAllowNextResultInvalidValue;
User::Leave( KErrArgument );
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: AddTestCasePanicL
Description: Adds new test case result. Used with 'allowpanic'
and 'allowerrorcodes' keywords.
Parameters: CStifItemParser* aItem: in: Item object for parsing.
Return Values: None.
Errors/Exceptions: Leaves if iTestCaseResults.Append fails.
Leaves if aItem->GetNextInt() fails.
Status: Approved
-------------------------------------------------------------------------------
*/
void CTestRunner::AddTestCasePanicL( CStifItemParser* aItem )
{
_LIT( KErrMsgAllowNextPanicInvalidValue, "No expected panic value given or value has invalid format" );
TInt panic;
TPtrC codeBuf;
while( aItem->GetNextString( codeBuf ) == KErrNone )
{
TLex codeParser( codeBuf );
if ( codeParser.Val( panic ) != KErrNone )
{
__TRACE( KError, (_L("ExecuteLineL: No expected panic value given")));
iRunErrorMessage = KErrMsgAllowNextPanicInvalidValue;
User::Leave( KErrArgument );
}
else
{
//do not add panic result to allowed result of case.
//User::LeaveIfError( iTestCaseResults.Append( panic ) );
// Set test case allow result to CTestModuleIf side too. This is
// used in TAL-TA5L macro handling.
iTestScripter->TestModuleIf().SetExitReason( CTestModuleIf::EPanic, panic );
break;
}
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: SubTestCaseFinishedL
Description: Recieves and handles notification about finished sub test
\ case execution.
Parameters: CSubTestCaseRunner* aSubTestCaseRunner: in: sub test case
runner used to run test case.
Return Values: None
Errors/Exceptions: Leaves on error situations.
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestRunner::SubTestCaseFinishedL( CSubTestCaseRunner* aSubTestCaseRunner )
{
if ( iInternalStateForSubTestCases == EISFinished )
{
if ( aSubTestCaseRunner->GetTestCaseResult().iCaseExecutionResultCode == KErrCancel )
{
// Test was canceled. Do nothing.
return;
}
else
{
User::Leave( KErrGeneral );
}
}
TInt index = iSubTestCases.Find( aSubTestCaseRunner );
if ( index < 0 )
{
// Debug info
return;
}
CSubTestCaseRunner* subTestCaseRunner = iSubTestCases[ index ];
iSubTestCases.Remove( index );
CleanupStack::PushL( subTestCaseRunner );
TInt runResult = subTestCaseRunner->GetRunResult();
TFullTestResult testCaseResult = subTestCaseRunner->GetTestCaseResult();
const CStartInfo* startInfo = subTestCaseRunner->GetStartInfo();
__TRACE( KMessage, ( _L( "Sub test case execution finished: module=%S cfg=%S tcnum=%d id=%S" ),
&startInfo->GetModuleName(), &startInfo->GetConfig(),
startInfo->GetTestCaseNumber(), &startInfo->GetTestId()) );
__TRACE( KMessage, ( _L( "Sub test case execution result: execution_result=%d, test_result=%d, des=%S" ),
testCaseResult.iCaseExecutionResultCode, testCaseResult.iTestResult.iResult,
&testCaseResult.iTestResult.iResultDes ) );
RDebug::Print( _L( "Sub test case execution finished: module=%S cfg=%S tcnum=%d id=%S" ),
&startInfo->GetModuleName(), &startInfo->GetConfig(),
startInfo->GetTestCaseNumber(), &startInfo->GetTestId() );
RDebug::Print( _L( "Sub test case execution result: execution_result=%d, test_result=%d, des=%S" ),
testCaseResult.iCaseExecutionResultCode, testCaseResult.iTestResult.iResult,
&testCaseResult.iTestResult.iResultDes );
// Check expected execution result type
TBool reportFailedSubTestCase = EFalse;
if( testCaseResult.iCaseExecutionResultType != startInfo->GetExpectedResultCategory() )
{
reportFailedSubTestCase = true;
}
else
{
if( startInfo->GetExpectedResultCategory() == TFullTestResult::ECaseExecuted )
{
if ( startInfo->GetExpectedResult() != testCaseResult.iTestResult.iResult )
{
reportFailedSubTestCase = true;
}
}
else
{
if ( startInfo->GetExpectedResult() != testCaseResult.iCaseExecutionResultCode )
{
reportFailedSubTestCase = true;
}
}
}
if ( reportFailedSubTestCase )
{
// Only remember first failed sub test case
if ( iFailedSubTestCaseReported == EFalse )
{
// If passlimit is enabled and loop is in progress ignore sub test case fail.
// Fail will be reported only if passlimit is not met.
// It is done in ReportLoopEndResultL
if ( !( iLoopHelper->LoopInProgress() && iPasslimitEnabled ) || iCancelIfError )
{
iFailedSubTestCaseReported = true;
iFailedSubTestCaseResult = testCaseResult;
iFailedSubTestCaseInfo = CStartInfo::NewL();
iFailedSubTestCaseInfo->CopyL( *startInfo );
}
}
}
switch( iInternalStateForSubTestCases )
{
case EISRuning:
// Do noting
if ( iLoopHelper->LoopInProgress() )
{
iLoopHelper->NotifySubTestCaseEndL( subTestCaseRunner, !reportFailedSubTestCase );
}
break;
case EISWaitingForComplete:
if ( iLoopHelper->LoopInProgress() )
{
iLoopHelper->NotifySubTestCaseEndL( subTestCaseRunner, !reportFailedSubTestCase );
}
// Do noting
if ( subTestCaseRunner->GetStartInfo()->GetTestId() == *iTestIdForComplete )
{
delete iTestIdForComplete;
iTestIdForComplete = NULL;
SetRunnerActive(); // Continue test case execution after complete
iInternalStateForSubTestCases = EISRuning;
}
break;
case EISFinishedWaitingForSubTestCases:
if ( iSubTestCases.Count() <= 0 )
{
SetRunnerActive();
}
break;
default:
break;
}
CleanupStack::PopAndDestroy( subTestCaseRunner );
if ( iCancelIfError && iFailedSubTestCaseReported )
{
// Make sure that DoCancel will be executed
if ( !IsActive() )
{
SetRunnerActive();
}
// Stop Test Case execution
Cancel();
}
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ReportLoopEndResultL
Description: Recives report from CLoopHelper about result of loop execution
Parameters: TInt aPassedIterations: in: number of passed loop iterations
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
void CTestRunner::ReportLoopEndResultL( TInt aPassedIterations )
{
//If passlimit was given and number of passed test is less then expected, stop execution of scripter's test case
if( iPasslimitEnabled && ( aPassedIterations < iPasslimit ) )
{
__TRACE( KMessage, ( _L( "Loop has failed (passlimit). Finishing with KErrCompletion." ) ) );
iTestScripter->iPassLimitNotMet = ETrue;
iTestScripter->iResult.iResult = KErrCompletion;
iTestScripter->iResult.iResultDes = _L("Loop has not reached passlimit requirement.");
Cancel();
}
else if( iPasslimitEnabled && ( aPassedIterations >= iPasslimit ) )
{
__TRACE( KMessage, ( _L( "Loop has passed (passlimit)" ) ) );
}
iPasslimit = 0;
iPasslimitEnabled = EFalse;
}
void CTestRunner::ReleaseRemoteResourcesAllocatedInLoopL()
{
RPointerArray<CSlave>& inLoopSlaves = iLoopHelper->GetRegisteredInLoopSlaves();
for ( TInt i = 0; i < inLoopSlaves.Count(); i++ )
{
inLoopSlaves[ i ]->WaitForSubTestCasesL();
RPointerArray<TEventTS>& slaveEvents = inLoopSlaves[ i ]->GetEvents();
for ( TInt k = 0; k < slaveEvents.Count(); k++ )
{
iSlavesManager->EventReleaseL( inLoopSlaves[ i ], slaveEvents[ k ]->Name() );
}
slaveEvents.ResetAndDestroy();
iSlavesManager->SlaveFreeL( inLoopSlaves[ i ]->GetName() );
}
inLoopSlaves.Reset();
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: IsFailedSubTestCaseReported
Description: Gets information if there was reported executed sub test
case which failed.
Parameters: None
Return Values: ETrue: test case was reported
EFalse: test case was not reported
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
TBool CTestRunner::IsFailedSubTestCaseReported() const
{
return iFailedSubTestCaseReported;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: GetFailedSubTestCaseResult
Description: Returns first failed sub test case result.
Parameters: None
Return Values: First failed sub test case result.
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
TFullTestResult CTestRunner::GetFailedSubTestCaseResult() const
{
return iFailedSubTestCaseResult;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: GetFailedSubTestCaseInfo
Description: Returns first failed sub test case info.
Parameters: None
Return Values: First failed sub test case info.
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
const CStartInfo* CTestRunner::GetFailedSubTestCaseInfo() const
{
return iFailedSubTestCaseInfo;
}
void CTestRunner::HandleRemoteReceiveError( TInt aError, const TDesC& aErrorDescription )
{
iTestScripter->UpdateTestCaseResult( aError, aErrorDescription );
CActiveScheduler::Current()->Stop();
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ControlSubTestCaseL
Description: Controls sub test case execution
Parameters: Sub test case id
Return Values: ETrue: continue script file execution
EFalse: stop script file execution
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ControlSubTestCaseL( TTestKeywords::TKeywords aOperation, CStifItemParser* aItem )
{
_LIT( KErrMsgInvalidTestId, "testid is not specified or it has invalid value" );
_LIT( KErrMsgUnknownCall, "Unknown operation call on sub test case" );
TPtrC subTestId;
TInt ret = aItem->GetNextString( subTestId );
if ( ret != KErrNone )
{
iRunErrorMessage = KErrMsgInvalidTestId;
User::Leave( KErrArgument );
}
TInt subTestCasesCount = iSubTestCases.Count();
for ( TInt i = 0; i < subTestCasesCount; i++ )
{
if ( iSubTestCases[ i ]->GetStartInfo()->GetTestId() == subTestId )
{
switch ( aOperation )
{
case TTestKeywords::EPauseTest:
{
__TRACE( KMessage, ( _L( "Pause sub test case testid=%S" ), &subTestId ) );
iSubTestCases[ i ]->PauseSubTestCaseL();
}
break;
case TTestKeywords::EResume:
{
__TRACE( KMessage, ( _L( "Reasume sub test case testid=%S" ), &subTestId ) );
iSubTestCases[ i ]->ResumeSubTestCaseL();
}
break;
case TTestKeywords::ECancel:
{
__TRACE( KMessage, ( _L( "Cancel sub test case testid=%S" ), &subTestId ) );
CSubTestCaseRunner* subTestCaseRunner = iSubTestCases[ i ];
subTestCaseRunner->CancelSubTestCaseL();
if ( subTestCaseRunner->GetType() == CSubTestCaseRunner::ESTTRemote )
{
CRemoteSubTestCaseRunner* remoteSubTestCaseRunner =
(CRemoteSubTestCaseRunner*)subTestCaseRunner;
CSlave* slave = remoteSubTestCaseRunner->GetSlave();
slave->UnregisterSubTestCaseL( remoteSubTestCaseRunner );
}
if ( iLoopHelper->LoopInProgress() )
{
iLoopHelper->UnregisterInLoopSubTestCaseL( subTestCaseRunner );
}
delete iSubTestCases[ i ];
iSubTestCases.Remove( i );
}
break;
default:
{
iRunErrorMessage = KErrMsgUnknownCall;
User::Leave( KErrArgument );
}
break;
}
return true;
}
}
__TRACE( KMessage, ( _L( "Sub test case testid=%S not found" ), &subTestId ) );
RDebug::Print( _L( "Sub test case testid=%S not found" ), &subTestId );
return true;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteLoopL
Description: Executes loop keyword
Parameters: CStifItemParser* aItem: in: script line
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteLoopL( CStifItemParser* aItem )
{
_LIT( KErrMsgLoopNested, "Loop: Nested loop are not supported" );
_LIT( KErrMsgLoopNoParam, "Loop: No loop iterations count given or value has invalid format" );
_LIT( KErrMsgLoopInvalidParam, "Loop: Loop count must be >0" );
_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" );
if( iLoopTimes > 0 )
{
__TRACE( KError, (_L("ExecuteLineL: Nested loop are not supported")));
iRunErrorMessage = KErrMsgLoopNested;
User::Leave( KErrNotSupported );
}
iLoopTimes = 0;
iLoopCounter = 0;
iTimedLoop = EFalse;
if( aItem->GetNextInt( iLoopTimes ) != KErrNone )
{
__TRACE( KError, (_L("ExecuteLineL: No loop count value given for loop")));
iRunErrorMessage = KErrMsgLoopNoParam;
User::Leave( KErrArgument );
}
if( iLoopTimes < 1 )
{
__TRACE( KError, (_L("ExecuteLineL: Loop count must be >0")));
iRunErrorMessage = KErrMsgLoopInvalidParam;
User::Leave( KErrArgument );
}
__TRACE( KMessage, (_L("ExecuteLineL: 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("ExecuteLineL: 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("ExecuteLineL: Unknown or unexpected loop option [%S]"), &option));
iRunErrorMessage = KErrMsgLoopUnknownUnexpectedOption;
User::Leave( KErrNotSupported );
}
iLoopStartPos = iTestScripter->iCurrentParser->GetPosition();
iLoopHelper->LoopStartL();
return ETrue;
}
/*
-------------------------------------------------------------------------------
Class: CTestRunner
Method: ExecuteEndLoopL
Description: Executes endloop keyword
Parameters: CStifItemParser* aItem: in: script line
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
TBool CTestRunner::ExecuteEndLoopL( CStifItemParser* /*aItem*/ )
{
_LIT( KErrMsgEndLoopNotOpened, "Endloop: Can't execute endloop. No opened loop exists" );
if( iLoopTimes == 0 )
{
__TRACE( KError, (_L("ExecuteLineL: Can't execute endloop. No opened loop exists")));
iRunErrorMessage = KErrMsgEndLoopNotOpened;
User::Leave( KErrNotFound );
}
iLoopCounter++;
__TRACE( KMessage,
(_L("ExecuteLineL: Loop executed for %d times" ),
iLoopCounter ) );
TTime currTime;
currTime.HomeTime();
if(((!iTimedLoop) && (iLoopCounter < iLoopTimes)) //Normal loop
||
iTimedLoop && (currTime.MicroSecondsFrom(iStartTime) < iExpectedLoopTime)) //Timed loop
{
// Go to beginning of the loop
User::LeaveIfError(
iTestScripter->iCurrentParser->SetPosition( iLoopStartPos ));
iLoopHelper->IterationEndStartNextIterationL();
}
else
{
// End looping
iLoopCounter = 0;
iLoopTimes = 0;
iLoopStartPos = 0;
iLoopHelper->LoopEndL();
}
// iLoopHelper will activate runner in proper moment
return EFalse;
}
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 );
}
iTestScripter->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("Allocate %S"), &name );
__TRACE( KMessage, (_L("Allocate %S [name: %S]"), &type, &name));
if( iSlavesManager->GetSlave( name ) )
{
__TRACE( KError, (_L("Slave with name %S already allocated"),
&name ) );
iRunErrorMessage.Format( KErrMsgAllocateSlaveAlreadyAllocated, &name );
User::Leave( KErrAlreadyExists );
}
iSlavesManager->SlaveAllocateL( name, type );
if ( iLoopHelper->LoopInProgress() )
{
CSlave* slave = iSlavesManager->GetSlave( name );
iLoopHelper->RegisterInLoopSlaveL( slave );
}
return ETrue;
}
TBool CTestRunner::ExecuteFreeL( CStifItemParser* aItem )
{
_LIT( KErrMsgFreeSlaveNameNotDefined, "Free : Slave name is not defined" );
_LIT( KErrMsgFreeSlaveNotFound, "Free : Slave %S not found" );
__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 );
}
iTestScripter->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("Free %S"), &name );
__TRACE( KMessage, (_L("Free %S"), &name ) );
CSlave* slave = iSlavesManager->GetSlave( name );
if( slave == NULL )
{
__TRACE( KError, (_L("Slave %S not found"), &name ));
iRunErrorMessage.Format( KErrMsgFreeSlaveNotFound, &name );
User::Leave( KErrNotFound );
}
if ( iLoopHelper->LoopInProgress() )
{
iLoopHelper->UnregisterInLoopSlaveL( slave );
}
if ( slave->HasRunningTestCases() )
{
slave->WaitForSubTestCasesL();
}
iSlavesManager->SlaveFreeL( name );
return ETrue;
}
TBool CTestRunner::ExecuteRemoteL( CStifItemParser* aItem )
{
_LIT( KErrMsgRemoteSlaveNameNotDefined, "Remote : Slave name is not defined" );
_LIT( KErrMsgRemoteSlaveNotFound, "Remore : Slave %S not found" );
_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));
CSlave* slave = iSlavesManager->GetSlave( name );
if( slave == NULL )
{
__TRACE( KError, (_L("Slave %S not found"), &name ));
iRunErrorMessage.Format( KErrMsgRemoteSlaveNotFound, &name );
User::Leave( KErrArgument );
}
// 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 );
}
iTestScripter->TestModuleIf().Printf( KPrintPriExec, KExecute,
_L("remote %S %S"), &name, &command );
__TRACE( KPrint, (_L("remote %S %S"), &name, &command ) );
// Parse command name
TInt key = TTestKeywords::Parse( command, TTestKeywords::Keyword );
TBool continueTask = ETrue;
switch( key )
{
// Test case starting
case TTestKeywords::ERun:
continueTask = ExecuteRemoteRunL( aItem, slave );
break;
// Event control cases
case TTestKeywords::ERequest:
case TTestKeywords::EWait:
case TTestKeywords::ERelease:
case TTestKeywords::ESet:
case TTestKeywords::EUnset:
continueTask = ExecuteRemoteEventCtlL( aItem, slave, key );
break;
// asynchronous 'sendreceive'
case TTestKeywords::ESendReceive:
continueTask = ExecuteRemoteSendReceiveL( aItem, slave );
break;
default:
// Some unknown remote command, forward as such
continueTask = ExecuteRemoteUnknownL( aItem, slave, command );
break;
}
return continueTask;
}
TBool CTestRunner::ExecuteRemoteRunL( CStifItemParser* aItem, CSlave* aSlave,
HBufC *aSetUnsetEvent,
TInt aCaseNumber )
{
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->SetTestCaseNumber( aCaseNumber );
}
else
{
ParseRunParamsL( aItem, *startInfo );
}
CRemoteSubTestCaseRunner* remoteSubTestCase = CRemoteSubTestCaseRunner::NewL(
this,
aSlave,
iSlavesManager->GetRemoteCallsProxy() );
CleanupStack::PushL( remoteSubTestCase );
__TRACE( KMessage, ( _L( "Executing sub test case: module=%S cfg=%S tcnum=%d id=%S" ),
&startInfo->GetModuleName(), &startInfo->GetConfig(),
startInfo->GetTestCaseNumber(), &startInfo->GetTestId()) );
RDebug::Print( _L( "Executing sub test case: module=%S cfg=%S tcnum=%d id=%S" ),
&startInfo->GetModuleName(), &startInfo->GetConfig(),
startInfo->GetTestCaseNumber(), &startInfo->GetTestId() );
remoteSubTestCase->RunSubTestCaseL( *startInfo );
iSubTestCases.AppendL( remoteSubTestCase );
if ( iLoopHelper->LoopInProgress() )
{
iLoopHelper->RegisterInLoopSubTestCaseL( remoteSubTestCase );
}
CleanupStack::Pop( remoteSubTestCase );
iRunErrorMessage = KNullDesC;
CleanupStack::PopAndDestroy( startInfo );
return ETrue;
}
TBool CTestRunner::ExecuteRemoteEventCtlL( CStifItemParser* aItem,
CSlave* 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 );
}
TBool continueTask = ETrue;
switch( aCmd )
{
// Event control cases
case TTestKeywords::ERequest:
{
TEventTS* event = aSlave->GetEvent( eventName );
if( event != NULL )
{
__TRACE( KError, (_L("Event %S already requested"),
&eventName ) );
User::Leave( KErrNotFound );
}
event = new( ELeave ) TEventTS( (TName&)eventName );
CleanupStack::PushL( event );
iSlavesManager->EventRequestL( aSlave, event );
aSlave->AddEventL( event );
CleanupStack::Pop( event );
}
break;
case TTestKeywords::ERelease:
{
TEventTS* event = aSlave->GetEvent( eventName );
if( event == NULL )
{
__TRACE( KError, (_L("Event not found %S"),
&eventName ) );
User::Leave( KErrNotFound );
}
aSlave->RemoveEventL( event );
delete event;
// Release event
iSlavesManager->EventReleaseL( aSlave, eventName );
}
break;
case TTestKeywords::EWait:
{
TEventTS* 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
continueTask = EFalse;
}
break;
case TTestKeywords::ESet:
{
TPtrC optParam;
ret = aItem->GetNextString( optParam );
TEventIf::TEventType eventType = TEventIf::EIndication;
if( ret == KErrNone )
{
if ( optParam != _L("state") )
{
__TRACE( KError, (_L("Invalid optional argument")));
User::Leave( KErrArgument );
}
eventType = TEventIf::EState;
}
iSlavesManager->EventSetL( aSlave, eventName, eventType );
}
break;
case TTestKeywords::EUnset:
{
iSlavesManager->EventUnsetL( aSlave, eventName );
}
break;
default:
// Should never come here
User::Leave( KErrGeneral );
}
return continueTask;
}
TBool CTestRunner::ExecuteRemoteSendReceiveL( CStifItemParser* aItem,
CSlave* aSlave )
{
TPtrC message;
aItem->Remainder( message );
iSlavesManager->SendReceiveL( aSlave, message );
return ETrue;
}
TBool CTestRunner::ExecuteRemoteUnknownL( CStifItemParser* aItem,
CSlave* aSlave,
TDesC& aCommand )
{
TPtrC message;
aItem->Remainder( message );
iSlavesManager->SendUnknownL( aSlave, aCommand, message );
return ETrue;
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of CTestContinue class
member functions. CTestContinue handles ContinueScript calls from
TestScripter.
-------------------------------------------------------------------------------
*/
// MACROS
#ifdef LOGGER
#undef LOGGER
#endif
#define LOGGER iTestScripter->iLog
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: CTestContinue
Method: CTestContinue
Description: Default constructor
Parameters: CTestRunner* aTestRunner: in: Backpointer to CTestRunner
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
CTestContinue::CTestContinue( CTestScripter* aTestScripter,
TTestObject* aObject ):
// Executed with lowest priority, must be lower than CTesRunner priority
CActive( CActive::EPriorityLow ),
iTestScripter( aTestScripter ),
iObject( aObject )
{
CActiveScheduler::Add( this );
__TRACEFUNC();
}
/*
-------------------------------------------------------------------------------
Class: CTestContinue
Method: ConstructL
Description: Symbian OS second phase constructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestContinue::ConstructL()
{
iObject->iScript->EnableSignal( iStatus );
SetActive();
}
/*
-------------------------------------------------------------------------------
Class: CTestContinue
Method: NewL
Description: Two-phased constructor.
Parameters: CTestRunner* aTestRunner: in: Backpointer to CTestRunner
Return Values: CTestContinue*: new object
Errors/Exceptions: Leaves if new or ConstructL leaves
Status: Draft
-------------------------------------------------------------------------------
*/
CTestContinue* CTestContinue::NewL( CTestScripter* aTestScripter,
TTestObject* aObject )
{
CTestContinue* self =
new (ELeave) CTestContinue( aTestScripter, aObject );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop();
return self;
}
/*
-------------------------------------------------------------------------------
Class: CTestContinue
Method: ~CTestContinue
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
CTestContinue::~CTestContinue()
{
__TRACEFUNC();
Cancel();
}
/*
-------------------------------------------------------------------------------
Class: CTestContinue
Method: RunL
Description: Derived from CActive, handles testcase execution.
Parameters: None.
Return Values: None.
Errors/Exceptions: Leaves on error situations.
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestContinue::RunL()
{
__TRACEFUNC();
__TRACE( KMessage, (_L("CTestContinue::RunL: [%d] "), iStatus.Int() ));
if( iObject->Signal() )
{
// If OOM testing is ongoing ignore result check(given by user).
if( !iTestScripter->iOOMIgnoreFailure )
{
// Erronous case RunError will called and test handling continue
// from there.
if( iTestScripter->TestRunner().TestCaseResults().Count() == 0 )
{
// KErrNone is the default result expected
// if nothing else is given
User::LeaveIfError( iTestScripter->TestRunner().
TestCaseResults().Append( KErrNone ) );
}
if( iTestScripter->TestRunner().TestCaseResults().
Find( iStatus.Int() ) < 0 )
{
__TRACE( KError, ( _L("Command for [%S] failed (%d)"),
&iObject->ObjectId(), iStatus.Int() ));
if( iStatus.Int() == KErrNone )
{
User::Leave( KErrGeneral );
}
else
{
User::Leave( iStatus.Int() );
}
}
}
else
{
__TRACE( KMessage, (
_L( "OOM test: 'oomignorefailure' is ON, signal result[%d] ignored" ),
iStatus.Int() ));
}
iTestScripter->TestRunner().TestCaseResults().Reset();
__TRACE( KMessage, (_L("CTestContinue::RunL: Set runner active ")));
iTestScripter->iTestRunner->SetRunnerActive();
}
else
{
// Signal called from test side but 'waittestclass' not yet processed
iObject->iAsyncResult = iStatus.Int();
}
iObject->iScript->EnableSignal( iStatus );
SetActive();
}
/*
-------------------------------------------------------------------------------
Class: CTestContinue
Method: DoCancel
Description: Derived from CActive handles the Cancel
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
void CTestContinue::DoCancel()
{
__TRACEFUNC();
__TRACE( KMessage, (_L("CTestContinue::DoCancel")));
iObject->iScript->CancelSignal();
}
/*
-------------------------------------------------------------------------------
Class: CTestContinue
Method: RunError
Description: Derived from CActive handles the Cancel
Parameters: None.
Return Values: None.
Errors/Exceptions: None.
Status: Draft
-------------------------------------------------------------------------------
*/
TInt CTestContinue::RunError( TInt aError )
{
// Return error from here, if none given from execution
if( iTestScripter->iResult.iResult == KErrNone )
{
iTestScripter->UpdateTestCaseResult(aError, _L("CTestContinue::RunError"));
}
CActiveScheduler::Current()->Stop();
return KErrNone;
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of CDefinedValue class
member functions.
-------------------------------------------------------------------------------
*/
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: CDefinedValue
Method: CDefinedValue
Description: Default constructor
C++ default constructor can NOT contain any code, that
might leave.
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
CDefinedValue::CDefinedValue()
{
}
/*
-------------------------------------------------------------------------------
Class: CDefinedValue
Method: ConstructL
Description: Symbian OS second phase constructor
Symbian OS default constructor can leave.
Parameters: TDesC& aName: in: Define name
TDesC& aValue: in: Define value
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
void CDefinedValue::ConstructL( TDesC& aName, TDesC& aValue )
{
iNameBuf = aName.AllocLC();
iName.Set( iNameBuf->Des() );
iValueBuf = aValue.AllocLC();
iValue.Set( iValueBuf->Des() );
CleanupStack::Pop( iValueBuf );
CleanupStack::Pop( iNameBuf );
}
/*
-------------------------------------------------------------------------------
Class: CDefinedValue
Method: NewL
Description: Two-phased constructor.
Parameters: TDesC& aName: in: Define name
TDesC& aValue: in: Define value
Return Values: CDefinedValue*: new object
Errors/Exceptions: Leaves if new or ConstructL leaves.
Status: Draft
-------------------------------------------------------------------------------
*/
CDefinedValue* CDefinedValue::NewL( TDesC& aName, TDesC& aValue )
{
CDefinedValue* self = new (ELeave) CDefinedValue();
CleanupStack::PushL( self );
self->ConstructL( aName, aValue );
CleanupStack::Pop();
return self;
}
/*
-------------------------------------------------------------------------------
Class: CDefinedValue
Method: ~CDefinedValue
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
CDefinedValue::~CDefinedValue()
{
delete iValueBuf;
delete iNameBuf;
}
/*
-------------------------------------------------------------------------------
Class: CDefinedValue
Method: SetValueL
Description: Set new define value
Parameters: TDesC& aValue: in: Define value
Return Values: None
Errors/Exceptions: Leaves on error.
Status: Draft
-------------------------------------------------------------------------------
*/
void CDefinedValue::SetValueL( TDesC& aValue )
{
delete iValueBuf;
iValueBuf = 0;
iValueBuf = aValue.AllocLC();
iValue.Set( iValueBuf->Des() );
CleanupStack::Pop( iValueBuf );
}
/*
-------------------------------------------------------------------------------
Class: CDefinedValue
Method: Name
Description: Returns define name.
Parameters: None
Return Values: TDesC: Define name
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TDesC& CDefinedValue::Name()
{
return iName;
}
/*
-------------------------------------------------------------------------------
Class: CDefinedValue
Method: Value
Description: Returns define value.
Parameters: None
Return Values: TDesC: Define value
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TDesC& CDefinedValue::Value()
{
return iValue;
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of TTestObjectBase class
member functions.
-------------------------------------------------------------------------------
*/
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: TTestObjectBase
Method: TTestObjectBase
Description: Constructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TTestObjectBase::TTestObjectBase( TObjectType aType ) :
iAsyncResult( KErrNone ),
iType( aType )
{
RDebug::Print( _L("TTestObjectBase::TTestObjectBase") );
iName.Zero();
}
/*
-------------------------------------------------------------------------------
Class: TTestObjectBase
Method: ~TTestObjectBase
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TTestObjectBase::~TTestObjectBase()
{
RDebug::Print( _L("TTestObjectBase::~TTestObjectBase") );
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of TTestObject class
member functions.
-------------------------------------------------------------------------------
*/
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: TTestObject
Method: TTestObject
Description: Constructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TTestObject::TTestObject() :
TTestObjectBase( EObjectNormal ),
iContinue(0),
iCount(0)
{
iScript = 0;
RDebug::Print( _L("TTestObject::TTestObject") );
}
/*
-------------------------------------------------------------------------------
Class: TTestObject
Method: ~TTestObject
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TTestObject::~TTestObject()
{
RDebug::Print( _L("TTestObject::~TTestObject") );
delete iContinue;
iContinue = 0;
}
/*
-------------------------------------------------------------------------------
Class: TTestObject
Method: RunMethodL
Description: Run specified method from testclass.
Parameters: CStifItemParser* aItem: in: itemparser
Return Values: Symbian OS error code
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TInt TTestObject::RunMethodL( CStifItemParser& aItem )
{
return iScript->RunMethodL( aItem );
}
/*
-------------------------------------------------------------------------------
DESCRIPTION
This module contains the implementation of TTestObjectKernel class
member functions.
-------------------------------------------------------------------------------
*/
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: TTestObjectKernel
Method: TTestObjectKernel
Description: Constructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TTestObjectKernel::TTestObjectKernel() :
TTestObjectBase( EObjectKernel )
{
RDebug::Print( _L("TTestObjectKernel::TTestObjectKernel") );
}
/*
-------------------------------------------------------------------------------
Class: TTestObjectKernel
Method: ~TTestObjectKernel
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TTestObjectKernel::~TTestObjectKernel()
{
RDebug::Print( _L("TTestObjectKernel::~TTestObjectKernel") );
iTestClass.Close();
User::FreeLogicalDevice( iLddName );
}
/*
-------------------------------------------------------------------------------
Class: TTestObjectKernel
Method: RunMethodL
Description: Run specified method from kernel testclass.
Parameters: CStifItemParser& aItem: in: itemparser
Return Values: Symbian OS error code
Errors/Exceptions: None
Status: Draft
-------------------------------------------------------------------------------
*/
TInt TTestObjectKernel::RunMethodL( CStifItemParser& aItem )
{
TPtrC method;
TPtrC params;
User::LeaveIfError( aItem.GetNextString( method ) );
aItem.Remainder( params );
TInt result;
TMethodResultDes resultDes;
// Need to change descriptors from 16bit to 8bit for EKA2 kernel
// because STIF Parser doesn't support 8bit parsing
HBufC8 * myBuf1 = HBufC8::NewL( method.Length() );
TPtr8 met8 = myBuf1->Des();
met8.Copy( method );
HBufC8 * myBuf2 = HBufC8::NewL( params.Length() );
TPtr8 par8 = myBuf2->Des();
par8.Copy( params );
TInt ret = iTestClass.RunMethod( met8, par8, result, resultDes );
delete myBuf1;
delete myBuf2;
if( ret != KErrNone )
{
return ret;
}
return result;
};
// ================= OTHER EXPORTED FUNCTIONS =================================
/*
-------------------------------------------------------------------------------
Function: LibEntryL
Description: Polymorphic Dll Entry Point
Parameters: None.
Return Values: CTestScripter*: pointer to new CTestScripter
Errors/Exceptions: Leaves if NewL leaves.
Status: Draft
-------------------------------------------------------------------------------
*/
EXPORT_C CTestScripter* LibEntryL()
{
return CTestScripter::NewL();
}
// End of File