/*
* 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: CATSInterface: This object executes test cases from
* STIF Test Framework.
*
*/
// INCLUDE FILES
#include <e32base.h>
#include <e32cons.h>
#include <e32svr.h>
#include "ATSInterface.h"
#include "ATSInterfaceRunner.h"
#include "StifTestInterface.h"
// EXTERNAL DATA STRUCTURES
// None
// EXTERNAL FUNCTION PROTOTYPES
// None
// CONSTANTS
// None
// MACROS
// None
// LOCAL CONSTANTS AND MACROS
// None
// MODULE DATA STRUCTURES
// None
// LOCAL FUNCTION PROTOTYPES
// None
// FORWARD DECLARATIONS
// None
// ==================== LOCAL FUNCTIONS =======================================
// None
// ================= MEMBER FUNCTIONS =========================================
// ================= MEMBER FUNCTIONS =========================================
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: CATSInterface
Description: Default constructor
C++ default constructor can NOT contain any code, that
might leave.
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
CATSInterface::CATSInterface()
{
// Initialize buffers to zero
iEngineIniFile.Zero();
iModuleIniFile.Zero();
iConfigFile.Zero();
iTestModule.Zero();
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: ConstructL
Description: Symbian OS second phase constructor
Symbian OS default constructor can leave.
Parameters: None
Return Values: None
Errors/Exceptions: Leaves if some of called leaving functions leaves
Leaves each time the LogErrorAndLeaveL is called
Status: Proposal
-------------------------------------------------------------------------------
*/
void CATSInterface::ConstructL()
{
RDebug::Print(_L("Creating module list object"));
TRAPD(err, iModuleList = CTestModuleList::NewL(NULL));
if(err != KErrNone)
{
LogErrorAndLeaveL(_L("CATSInterface::ConstructL"), _L("CTestModuleList::NewL"), err);
return;
}
if(!iModuleList)
{
LogErrorAndLeaveL(_L("CATSInterface::ConstructL"), _L("CTestModuleList::NewL - iModuleList is NULL"), KErrGeneral);
return;
}
// Read command line
ParseCommandLineL();
// Add to module list info about module taken from command line
RDebug::Print(_L("Adding command line module to list"));
TName moduleName;
moduleName.Copy(iTestModule);
moduleName.LowerCase();
err = iModuleList->AddTestModule(moduleName);
if(err != KErrNone && err != KErrAlreadyExists)
{
LogErrorAndLeaveL(_L("CATSInterface::ConstructL"), _L("CTestModuleList::AddTestModule - Could not add module to list of modules"), err);
return;
}
//Get added module
CTestModuleInfo* moduleInfo = iModuleList->GetModule(moduleName);
if(!moduleInfo)
{
LogErrorAndLeaveL(_L("CATSInterface::ConstructL"), _L("CTestModuleList::GetModule - Could not add get module info from list"), KErrGeneral);
return;
}
//Add ini file if given
if(iModuleIniFile.Length() > 0)
{
TFileName filename;
filename.Copy(iModuleIniFile);
filename.LowerCase();
moduleInfo->SetIniFile(filename);
}
//Add config file if given
if(iConfigFile.Length() > 0)
{
TFileName filename;
filename.Copy(iConfigFile);
filename.LowerCase();
moduleInfo->AddCfgFile(filename);
}
//Now check all config files if there are included modules
_LIT(KIncludeModuleStart, "[New_Include_Module]");
_LIT(KIncludeModuleEnd, "[End_Include_Module]");
RDebug::Print(_L("Start parsing included modules"));
CTestCaseFileInfo* finfo = iModuleList->GetUncheckedCfgFile();
while(finfo)
{
TFileName fname;
finfo->GetCfgFileName(fname);
RDebug::Print(_L("Checking file: '%S'"), &fname);
finfo->SetChecked();
CStifParser* parser = NULL;
TRAP(err, parser = CStifParser::NewL(_L(""), fname));
if(err != KErrNone)
{
LogErrorAndLeaveL(_L("CATSInterface::ConstructL"), _L("CStifParser::NewL - Could not create parser"), err);
return;
}
CleanupStack::PushL(parser);
ParseTestModulesL(parser, iModuleList, KIncludeModuleStart, KIncludeModuleEnd);
CleanupStack::PopAndDestroy(parser);
finfo = iModuleList->GetUncheckedCfgFile();
}
RDebug::Print(_L("End parsing included modules"));
// Create Test Engine
RDebug::Print(_L("Creating test engine"));
TInt ret = iTestEngineServ.Connect();
if ( ret != KErrNone )
{
// Log error
LogErrorAndLeaveL( _L("CATSInterface::ConstructL"), _L("iTestEngineServ.Connect"), ret );
return;
}
ret = iTestEngine.Open( iTestEngineServ, iEngineIniFile );
if ( ret != KErrNone )
{
// Log error
LogErrorAndLeaveL( _L("CATSInterface::ConstructL"), _L("iTestEngine.Open"), ret );
return;
}
/*
// Add test module
ret = iTestEngine.AddTestModule( iTestModule, iModuleIniFile );
if ( ret != KErrNone && ret != KErrAlreadyExists )
{
// Log error
LogErrorAndLeaveL( _L("CATSInterface::ConstructL"), _L("iTestEngine.AddTestModule"), ret );
return;
}
*/
// Add all test modules and config files
RDebug::Print(_L("Start creating test modules"));
moduleInfo = NULL;
TInt i;
TInt modCnt = iModuleList->Count();
for(i = 0; i < modCnt; i++)
{
RDebug::Print(_L("Processing module"));
// Get module
moduleInfo = iModuleList->GetModule(i);
if(!moduleInfo)
{
RDebug::Print(_L("Could not get module info at index %d"), i);
continue;
}
// Get module name
TName moduleName;
moduleInfo->GetModuleName(moduleName);
RDebug::Print(_L("module name: '%S'"), &moduleName);
// Get ini file, if exists
TFileName ini;
moduleInfo->GetIniFileName(ini);
if(ini.Length() == 0)
{
RDebug::Print(_L("ini file not found"));
}
else
{
RDebug::Print(_L("ini file: '%S'"), &ini);
}
// Create test module
RDebug::Print(_L("Adding module to test engine"));
ret = iTestEngine.AddTestModule(moduleName, ini);
if(ret != KErrNone && ret != KErrAlreadyExists)
{
LogErrorAndLeaveL(_L("CATSInterface::ConstructL"), _L("iTestEngine.AddTestModule"), ret);
return;
}
//Add test case files
TInt cfgCnt = moduleInfo->CountCfgFiles();
TInt j;
TFileName cfgFile;
for(j = 0; j < cfgCnt; j++)
{
moduleInfo->GetCfgFileName(j, cfgFile);
if(cfgFile.Length() > 0)
{
RDebug::Print(_L("config file: '%S'"), &cfgFile);
ret = iTestEngine.AddConfigFile(moduleName, cfgFile);
if(ret != KErrNone && ret != KErrAlreadyExists)
{
// Log error
LogErrorAndLeaveL(_L("CATSInterface::ConstructL"), _L("RTestEngine::AddConfigFile"), ret);
return;
}
}
else
{
RDebug::Print(_L("Got empty cfg file"));
}
}
if(cfgCnt == 0)
{
RDebug::Print(_L("cfg file not found"));
}
RDebug::Print(_L("Module '%S' processed correctly"), &moduleName);
}
RDebug::Print(_L("End creating test modules"));
// Create console screen
iConsole = Console::NewL(
iTestModule, TSize( KConsFullScreen, KConsFullScreen ) );
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: NewL
Description: Two-phased constructor.
Parameters: None
Return Values: CATSInterface* : pointer to created CATSInterface object
Errors/Exceptions: Leaves if memory allocation for CATSInterface fails
Leaves if ConstructL leaves
Status: Approved
-------------------------------------------------------------------------------
*/
CATSInterface* CATSInterface::NewL()
{
// Create CATSInterface and return it
CATSInterface* self = new ( ELeave ) CATSInterface();
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop();
return self;
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: ~CATSInterface
Description: Destructor
Parameters: None
Return Values: None
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
CATSInterface::~CATSInterface()
{
// Close Test Engine
iTestEngine.Close();
iTestEngineServ.Close();
delete iModuleList;
delete iConsole;
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: ParseTestModulesL
Description: Parse and search for module info and fill list of modules.
Parameters: CStifParser* aParser: in: CStifParser object
CTestModuleList* aModuleList: in: list of modules
TPtrC& aSectionStart: in: descriptor with start of section string
TPTrC& aSectionEnd: in: descriptor with end of section string
Return Values: None
Errors/Exceptions: Leaves if some of called leaving methods leaves
Status: Approved
-------------------------------------------------------------------------------
*/
void CATSInterface::ParseTestModulesL(CStifParser* aParser, CTestModuleList* aModuleList, const TDesC& aSectionStart, const TDesC& aSectionEnd)
{
//First let's find all modules given in Stif's ini file and store that info in CTestModuleList object
CStifSectionParser* sectionParser = NULL;
CStifItemParser* item = NULL;
sectionParser = aParser->SectionL(aSectionStart, aSectionEnd);
while(sectionParser)
{
RDebug::Print(_L("Found '%S' and '%S' sections"), &aSectionStart, &aSectionEnd);
CleanupStack::PushL(sectionParser);
RDebug::Print(_L("Starting to read module information"));
// Get name of module
_LIT(KModuleName, "ModuleName=");
item = sectionParser->GetItemLineL(KModuleName);
CleanupStack::PushL(item);
if(!item)
{
CleanupStack::PopAndDestroy(item);
LogErrorAndLeaveL(_L("CATSInterface::ParseTestModulesL"), _L("CStifItemParser::GetItemLineL - line not found from module section"), KErrNotFound);
return;
}
else
{
RDebug::Print(_L("'%S' found"), &KModuleName);
}
TPtrC name;
TName moduleName;
TInt ret(KErrNone);
ret = item->GetString(KModuleName, name);
if(ret != KErrNone)
{
CleanupStack::PopAndDestroy(item);
LogErrorAndLeaveL(_L("CATSInterface::ParseTestModulesL"), _L("CStifItemParser::GetString - Module name parsing left with error"), ret);
return;
}
else
{
RDebug::Print(_L("Module '%S' found from ini-file"), &name);
moduleName.Copy(name);
moduleName.LowerCase();
ret = aModuleList->AddTestModule(moduleName);
if(ret != KErrNone && ret != KErrAlreadyExists)
{
LogErrorAndLeaveL(_L("CATSInterface::ParseTestModulesL"), _L("CTestModuleList::AddTestModule - Could not add module to list of modules"), ret);
return;
}
}
CleanupStack::PopAndDestroy(item);
//Get pointer to added module
CTestModuleInfo* moduleInfo = aModuleList->GetModule(moduleName);
if(!moduleInfo)
{
LogErrorAndLeaveL(_L("CATSInterface::ParseTestModulesL"), _L("CTestModuleList::GetModule - Could not add get module info from list"), KErrNotFound);
return;
}
// Get ini file, if it exists
RDebug::Print(_L("Start parsing ini file"));
_LIT(KIniFile, "IniFile=");
item = sectionParser->GetItemLineL(KIniFile);
if(item)
{
RDebug::Print(_L("'%S' found"), &KIniFile);
CleanupStack::PushL(item);
TPtrC iniFile;
ret = item->GetString(KIniFile, iniFile);
if(ret == KErrNone)
{
RDebug::Print(_L("Initialization file '%S' found, file can be empty"), &iniFile);
TFileName filename;
filename.Copy(iniFile);
filename.LowerCase();
TStifUtil::CorrectFilePathL( filename );
moduleInfo->SetIniFile(filename);
}
else
{
RDebug::Print(_L("Initialization file not found"));
}
CleanupStack::PopAndDestroy(item);
}
else
{
RDebug::Print(_L("'%S' not found"), &KIniFile);
}
// Get config (testcase) file
RDebug::Print(_L("Start parsing cfg files"));
TPtrC cfgTag;
for(TInt i = 0; i < 2; i++)
{
//Set tag for config files
if(i == 0)
{
cfgTag.Set(_L("ConfigFile="));
}
else
{
cfgTag.Set(_L("TestCaseFile="));
}
//Read data
item = sectionParser->GetItemLineL(cfgTag);
while(item)
{
CleanupStack::PushL(item);
RDebug::Print(_L("Item '%S' found"), &cfgTag);
TPtrC cfgFile;
ret = item->GetString(cfgTag, cfgFile);
if(ret == KErrNone)
{
TFileName ifile;
ifile.Copy(cfgFile);
ifile.LowerCase();
TStifUtil::CorrectFilePathL( ifile );
RDebug::Print(_L("Configuration file '%S' found"), &ifile);
moduleInfo->AddCfgFile(ifile);
}
else
{
RDebug::Print(_L("Configuration file not found"));
}
CleanupStack::PopAndDestroy(item);
item = sectionParser->GetNextItemLineL(cfgTag);
}
}
RDebug::Print(_L("Module '%S' information read correctly"), &moduleName);
// Get next section
CleanupStack::PopAndDestroy(sectionParser);
sectionParser = aParser->NextSectionL(aSectionStart, aSectionEnd);
}
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: ParseCommandLineL
Description: Parse command line parameters
Parameters: None
Return Values: None
Errors/Exceptions: Leaves if module name not found from command line
Status: Approved
-------------------------------------------------------------------------------
*/
void CATSInterface::ParseCommandLineL()
{
// Command line params
_LIT( KTestModule, "-testmodule" );
_LIT( KConfigFile, "-config" );
_LIT( KEngineIniFile, "-engineini" );
_LIT( KModuleIniFile, "-moduleini" );
const TInt length = User::CommandLineLength();
HBufC* cmdLine = HBufC::NewLC( length );
TPtr ptr = cmdLine->Des();
User::CommandLine( ptr );
TBool moduleFound( EFalse );
TLex lex( ptr );
// Parse the command line
while ( !lex.Eos() )
{
TPtrC tmpPtr = lex.NextToken();
// Check the test module name
if ( tmpPtr == KTestModule )
{
TPtrC module = lex.NextToken();
if ( module.Ptr() )
{
iTestModule.Copy( module );
moduleFound = ETrue;
}
}
// Check the module's config file
else if ( tmpPtr == KConfigFile )
{
TPtrC config = lex.NextToken();
if ( config.Ptr() )
{
iConfigFile.Copy( config );
TStifUtil::CorrectFilePathL( iConfigFile );
}
}
// Check the engine's ini file
else if ( tmpPtr == KEngineIniFile )
{
TPtrC iniFile = lex.NextToken();
if ( iniFile.Ptr() )
{
iEngineIniFile.Copy( iniFile );
TStifUtil::CorrectFilePathL( iEngineIniFile );
}
}
// Check the module's ini file
else if ( tmpPtr == KModuleIniFile )
{
TPtrC iniFile = lex.NextToken();
if ( iniFile.Ptr() )
{
iModuleIniFile.Copy( iniFile );
TStifUtil::CorrectFilePathL( iModuleIniFile );
}
}
else
{
// Skip unknown commands
}
} // while
// Destroy command line buffer
CleanupStack::PopAndDestroy( cmdLine );
// Module name has to exists
if ( !moduleFound )
{
User::Leave( KErrArgument );
}
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: RunTestsL
Description: Starts testing
Parameters: None
Return Values: None
Errors/Exceptions: Leaves if RunAllTestCasesL leaves
Leaves if RemoveTestModule returns error
Status: Approved
-------------------------------------------------------------------------------
*/
void CATSInterface::RunTestsL()
{
// Run all test cases
RunAllTestCasesL();
/*
// Remove test module
User::LeaveIfError( iTestEngine.RemoveTestModule( iTestModule ) );
*/
RDebug::Print(_L("Start removing test modules"));
CTestModuleInfo* moduleInfo = NULL;
TInt i;
TInt modCnt = iModuleList->Count();
for(i = 0; i < modCnt; i++)
{
RDebug::Print(_L("Processing module"));
// Get module
moduleInfo = iModuleList->GetModule(i);
if(!moduleInfo)
{
RDebug::Print(_L("Could not get module info at index %d"), i);
continue;
}
// Get module name
TName moduleName;
moduleInfo->GetModuleName(moduleName);
RDebug::Print(_L("module name: '%S'"), &moduleName);
// Remove test module
User::LeaveIfError(iTestEngine.RemoveTestModule(moduleName));
RDebug::Print(_L("Module '%S' removed"), &moduleName);
}
RDebug::Print(_L("End removing test modules"));
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: RunAllTestCasesL
Description: Run all test cases from test module.
Parameters: None
Return Values: None
Errors/Exceptions: Leaves if some of called leaving methods leaves
Status: Proposal
-------------------------------------------------------------------------------
*/
void CATSInterface::RunAllTestCasesL()
{
TInt ret( KErrNone );
/*
// Add given config file to test module
if ( iConfigFile.Length() > 0 )
{
ret = iTestEngine.AddConfigFile( iTestModule, iConfigFile );
if ( ret != KErrNone && ret != KErrAlreadyExists )
{
// Log error
LogErrorAndLeaveL( _L("CATSInterface::RunAllTestCasesL"), _L("iTestEngine.AddConfigFile"), ret );
return;
}
}
*/
// Enumerate test cases
TCaseCount caseCount;
TRequestStatus status;
iTestEngine.EnumerateTestCases( caseCount, status );
User::WaitForRequest( status );
// Check that enumerate succeeded
if ( status != KErrNone )
{
// Log error
LogErrorAndLeaveL( _L("CATSInterface::RunAllTestCasesL"), _L("iTestEngine.EnumerateTestCases"), status.Int() );
return;
}
// Get test cases to buffer
CFixedFlatArray<TTestInfo>* testCases =
CFixedFlatArray<TTestInfo>::NewL( caseCount() );
CleanupStack::PushL( testCases );
ret = iTestEngine.GetTestCases( *testCases );
if ( ret != KErrNone )
{
// Log error
LogErrorAndLeaveL( _L("CATSInterface::RunAllTestCasesL"), _L("iTestEngine.GetTestCases"), status.Int() );
return;
}
//variables used to get version of STIF
TInt majorV;
TInt minorV;
TInt buildV;
TBuf<30> relDate;
TStifUtil::STIFVersion(majorV, minorV, buildV, relDate);
TBuf<50> version;
version.Format(_L("STIF v%d.%d.%d - "), majorV, minorV, buildV);
version.Append(relDate);
version.Append(_L("\n"));
iConsole->Printf(version); //printing STIF version information (version and release date)
iConsole->Printf( _L("Test case count: [%d]\n\n"), testCases->Count() );
// Loop through all test cases in buffer and run them
const TInt count = testCases->Count();
for ( TInt i = 0; i < count; i++ )
{
#ifdef _DEBUG
RDebug::Print( ( *testCases)[i].iTestCaseInfo.iTitle );
#endif
iConsole->Printf( _L("Now running test case: [%d] [%S] "), i+1,
&( *testCases )[i].iTestCaseInfo.iTitle );
// Run test case
RunTestCaseL( ( *testCases )[i] );
}
// End test set
CleanupStack::PopAndDestroy( testCases );
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: RunTestCaseL
Description: Run test case
Parameters: TTestInfo& aTestInfo: in: TTestInfo: Test info
Return Values: None
Errors/Exceptions: Leaves if some of called leaving methods leaves
Status: Proposal
-------------------------------------------------------------------------------
*/
void CATSInterface::RunTestCaseL( TTestInfo& aTestInfo )
{
TInt testResult( KErrNone );
CATSInterfaceRunner* runner;
// Trap to catch errors from test case executing
TRAPD( trapError,
runner = CATSInterfaceRunner::NewL( this, aTestInfo );
CleanupStack::PushL( runner );
testResult = RunATestCaseL( runner );
CleanupStack::PopAndDestroy( runner );
);
if ( trapError != KErrNone )
{
testResult = trapError;
}
if ( testResult != KErrNone ) // Test case is FAILED
{
// Test case failed, print out the error
iConsole->Printf( _L("\nTest case FAILED! err=[%d]\n"), testResult );
}
else // Test case is PASSED
{
iConsole->Printf( _L("\nTest case PASSED!\n") );
testResult = KErrNone;
}
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: RunATestCaseL
Description: Run a test case
Parameters: CATSInterfaceRunner* aTestCase: in: Pointer to test case runner
Return Values: TInt KErrNone: Test case passed
other error code: Test case failed or cannot be executed
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
TInt CATSInterface::RunATestCaseL( CATSInterfaceRunner* aTestCase )
{
iTestCompletedError = KErrNone;
// Create timer
CActiveTimer* timer = CActiveTimer::NewL( iConsole );
CleanupStack::PushL( timer );
// Start test case and timer
aTestCase->StartTestL();
timer->StartL();
// Wait for test case completed
CActiveScheduler::Start();
timer->Cancel();
CleanupStack::PopAndDestroy( timer );
// test completion error is set in TestCompleted method
return iTestCompletedError;
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: TestEngineServer
Description: Return handle to Test Engine Server.
Parameters: None
Return Values: RTestEngineServer&: Reference to RTestEngineServer handle
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
RTestEngineServer& CATSInterface::TestEngineServer()
{
return iTestEngineServ;
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: TestEngine
Description: Return handle to Test Engine.
Parameters: None
Return Values: RTestEngine&: reference to RTestEngine handle
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
RTestEngine& CATSInterface::TestEngine()
{
return iTestEngine;
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: TestCompleted
Description: Test case completed
This method is called when test case is completed or error occurred
during the test.
Parameters: TInt aError: in: Symbian OS error: Test result
Return Values: None
Errors/Exceptions: None
Status: Approved
-------------------------------------------------------------------------------
*/
void CATSInterface::TestCompleted( TInt aError )
{
// Store completion error
iTestCompletedError = aError;
// Stop the scheduler
CActiveScheduler::Stop();
}
/*
-------------------------------------------------------------------------------
Class: CATSInterface
Method: LogErrorAndLeaveL
Description: Write error Logger and leave.
This function is called if some function returns error and the error cannot
be logged another way Logger, e.g. RTestEngineServer and
RTestEngine methods.
Parameters: const TDesC& aFunction: in: any string: Function where the error
occurred
const TDesC& aDescription: in: any string: Description for error
const TInt aError: in: Symbian OS error: Test result
Return Values: None
Errors/Exceptions: None
Status: Proposal
-------------------------------------------------------------------------------
*/
void CATSInterface::LogErrorAndLeaveL( const TDesC& aFunction,
const TDesC& aDescription,
const TInt aError )
{
RDebug::Print( _L("%S: %S [%d]"), &aFunction, &aDescription, aError );
User::Leave( aError );
}
// ================= OTHER EXPORTED FUNCTIONS =================================
/*
-------------------------------------------------------------------------------
Function: E32Main
Description: Main function called by E32.
Parameters: None
Return Values: TInt: KErrNone :No errors occurred
TInt: Other Symbian OS Error :Error catch by TRAP
Errors/Exceptions: TRAP is used to catch errors from leaving methods.
Status: Approved
-------------------------------------------------------------------------------
*/
GLDEF_C TInt E32Main()
{
TInt processHandleCountBefore;
TInt threadHandleCountBefore;
RThread().HandleCount( processHandleCountBefore, threadHandleCountBefore );
TInt reqsBefore = RThread().RequestCount();
TInt processHandleCountAfter;
TInt threadHandleCountAfter;
TInt reqsAfter;
__UHEAP_MARK;
CTrapCleanup* cleanup = CTrapCleanup::New();
if ( cleanup == NULL )
{
__UHEAP_MARKEND;
return KErrNoMemory;
}
CActiveScheduler* activeScheduler = new CActiveScheduler;
if ( activeScheduler == NULL )
{
delete cleanup;
__UHEAP_MARKEND;
return KErrNoMemory;
}
CActiveScheduler::Install( activeScheduler );
// Construct the test client
CATSInterface* test = NULL;
TRAPD( err, test = CATSInterface::NewL() );
if ( err != KErrNone )
{
#ifdef _DEBUG
RDebug::Print(_L("ATSInterface construction failed %d: "), err );
#endif
delete cleanup;
delete activeScheduler;
__UHEAP_MARKEND;
return err;
}
// Run tests
TRAP( err, test->RunTestsL() );
if ( err != KErrNone )
{
#ifdef _DEBUG
RDebug::Print(_L("RunTestsL left with %d: "), err );
#endif
}
// Deallocate resources
delete test;
delete activeScheduler;
delete cleanup;
reqsAfter = RThread().RequestCount();
RThread().HandleCount( processHandleCountAfter, threadHandleCountAfter );
if ( reqsAfter != reqsBefore )
{
#ifdef _DEBUG
RDebug::Print(_L("Request count not matching! %d vs. %d: "),
reqsBefore, reqsAfter );
#endif
}
if ( threadHandleCountAfter != threadHandleCountBefore )
{
#ifdef _DEBUG
RDebug::Print(_L("Handle count not matching! %d vs. %d: "),
threadHandleCountBefore, threadHandleCountAfter );
#endif
}
__UHEAP_MARKEND;
return err;
}
// End of File
// End of File