diff -r 7fdc9a71d314 -r 8ad140f3dd41 hti/HtiServicePlugins/HtiStifTfServicePlugin/src/HtiStifTfIf.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hti/HtiServicePlugins/HtiStifTfServicePlugin/src/HtiStifTfIf.cpp Wed Oct 13 16:17:58 2010 +0300 @@ -0,0 +1,2092 @@ +/* +* 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: Implements the functions to control STIF Test Framework +* through the STIF TF interface. +* +*/ + + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include "HtiStifTfIf.h" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +// MACROS + +// LOCAL CONSTANTS AND MACROS +const static TUid KStifTfServiceUid = { 0x10210CC3 }; + +enum TStifTfCommands + { + ECmdOpen = 0x01, + ECmdClose = 0x02, + ECmdLoadModule = 0x03, + ECmdUnloadModule = 0x04, + ECmdListCases = 0x05, + ECmdStartCase = 0x06, + ECmdCancelCase = 0x07, + ECmdPauseCase = 0x08, + ECmdResumeCase = 0x09, + ECmdAddCaseFile = 0x0A, + ECmdRemoveCaseFile = 0x0B, + ECmdCaseMsg = 0x0C, + ECmdSetDevId = 0x0D, + ECmdTestCompleted = 0x0E, + ECmdAtsMessage = 0x0F, + ECmdSetAttribute = 0x10 + }; + +_LIT8( KParameterDelimiter, "|" ); + +// NOTE: Max length for error description is defined +// in HtiDispatcherInterface.h (currently 118). +_LIT8( KErrorStifTfNotOpen, "ERROR: STIF TF is not open" ); +_LIT8( KErrorOpen, "ERROR: Failed to open STIF TF" ); +_LIT8( KErrorAlreadyOpen, "ERROR: STIF TF is already open" ); +_LIT8( KErrorClose, "ERROR: Failed to close STIF TF" ); +_LIT8( KErrorUnknownCmd, "ERROR: Unknown STIF TF command" ); +_LIT8( KErrorNoCmd, "ERROR: No command given" ); +_LIT8( KErrorParameterMissing, "ERROR: Mandatory parameter missing" ); +_LIT8( KErrorParameterTooLong, "ERROR: Parameter too long" ); +_LIT8( KErrorTooManyParameters, "ERROR: Too many parameters" ); +_LIT8( KErrorNoMemory, "ERROR: Memory allocation failure" ); +_LIT8( KErrorLoadModule, "ERROR: Load Module failed" ); +_LIT8( KErrorUnloadModule, "ERROR: Unload Module failed" ); +_LIT8( KErrorInvalidCaseNumber, "ERROR: Invalid test case number parameter" ); +_LIT8( KErrorModuleNotLoaded, "ERROR: Given test module is not loaded" ); +_LIT8( KErrorGetTestCases, "ERROR: Failed to get test cases from module" ); +_LIT8( KErrorGetTestCaseInfos, "ERROR: Failed to get test case infos" ); +_LIT8( KErrorStartTestCase, "ERROR: Failed to start test case" ); +_LIT8( KErrorCancelTestCase, "ERROR: Failed to cancel test case" ); +_LIT8( KErrorPauseTestCase, "ERROR: Failed to pause test case" ); +_LIT8( KErrorResumeTestCase, "ERROR: Failed to resume test case" ); +_LIT8( KErrorInvalidDeviceId, "ERROR: Invalid device ID parameter" ); +_LIT8( KErrorAddCaseFile, "ERROR: Add Case File failed" ); +_LIT8( KErrorRemoveCaseFile, "ERROR: Remove Case File failed" ); +_LIT8( KErrorFileServer, "ERROR: Failed to connect to file server" ); +_LIT8( KErrorCaseFileNotFound, "ERROR: Given test case file was not found" ); +_LIT8( KErrorIniFileNotFound, "ERROR: Given ini-file was not found" ); +_LIT8( KErrorCaseMessage, "ERROR: Test case message sending failed" ); +_LIT8( KErrorCharConv, "ERROR: Character conversion failed" ); +_LIT8( KErrorInvalidAttributeId, "ERROR: Invalid attribute id parameter" ); +_LIT8( KErrorSetAttribute, "ERROR: Failed to set attribute" ); +_LIT8( KErrorUnknown, "ERROR: Unspecified error occured" ); + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::CHtiStifTfIf +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CHtiStifTfIf::CHtiStifTfIf():iIsBusy( EFalse ), + iMessage( NULL ), + iErrorCode( 0 ), + iStifTfOpen( EFalse ), + iDevId( KDefaultDevId ), + iConsole( NULL ) + { + } + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::ConstructL( CHtiStifTfServicePlugin* aPlugin ) + { + iCommandId = 0; + iParameters = new (ELeave) CDesC8ArrayFlat( 5 ); + iPlugin = aPlugin; + } + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CHtiStifTfIf* CHtiStifTfIf::NewL( CHtiStifTfServicePlugin* aPlugin ) + { + CHtiStifTfIf* self = new( ELeave ) CHtiStifTfIf; + CleanupStack::PushL( self ); + self->ConstructL( aPlugin ); + CleanupStack::Pop(); + return self; + } + + +// Destructor +CHtiStifTfIf::~CHtiStifTfIf() + { + if ( iParameters ) + { + iParameters->Reset(); + } + delete iParameters; + iLoadedInfos.ResetAndDestroy(); + iLoadedInfos.Close(); + delete iMessage; + if ( iStifTfOpen ) Close(); + iPlugin = NULL; // Not owned, so not deleted. + iConsole = NULL; // Not owned, so not deleted. + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::ProcessMessageL +// Interpretes the message and calls appropriate command handling method. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::ProcessMessageL( const TDesC8& aMessage, + THtiMessagePriority /*aPriority*/) + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::ProcessMessageL" ); + HTI_LOG_FORMAT( "Message length = %d", aMessage.Length() ); + + if ( iIsBusy ) + { + HTI_LOG_TEXT( "Plugin is busy - leaving" ); + User::Leave( KErrInUse ); + } + + iIsBusy = ETrue; + + if ( aMessage.Length() < 1 ) + { + User::LeaveIfError( + SendErrorResponseMsg( KErrArgument, KErrorNoCmd ) ); + return; + } + + iCommandId = aMessage[0]; + HTI_LOG_FORMAT( "Command = %d", iCommandId ); + + TRAPD( err, ParseParametersL( aMessage ) ); + + if ( err == KErrNoMemory ) + { + User::LeaveIfError( SendErrorResponseMsg( err, KErrorNoMemory ) ); + return; + } + + else if ( err ) + { + User::LeaveIfError( + SendErrorResponseMsg( KErrGeneral, KErrorUnknown ) ); + return; + } + + // If STIF TF is not open, any other command than OPEN returns KErrNotReady + if ( !iStifTfOpen ) + { + if ( iCommandId == ECmdOpen ) + { + HandleOpenCmdL(); + return; + } + else + { + User::LeaveIfError( + SendErrorResponseMsg( KErrNotReady, KErrorStifTfNotOpen ) ); + return; + } + } + + + // Go through the rest of the commands + if ( iCommandId == ECmdLoadModule ) + { + HandleLoadModuleCmdL(); + } + + else if ( iCommandId == ECmdUnloadModule ) + { + HandleUnloadModuleCmdL(); + } + + else if ( iCommandId == ECmdListCases ) + { + HandleListCasesCmdL(); + } + + else if ( iCommandId == ECmdStartCase ) + { + HandleStartCaseCmdL(); + } + + else if ( iCommandId == ECmdCancelCase ) + { + HandleCancelCaseCmdL(); + } + + else if ( iCommandId == ECmdPauseCase ) + { + HandlePauseCaseCmdL(); + } + + else if ( iCommandId == ECmdResumeCase ) + { + HandleResumeCaseCmdL(); + } + + else if ( iCommandId == ECmdAddCaseFile ) + { + HandleAddCaseFileCmdL(); + } + + else if ( iCommandId == ECmdRemoveCaseFile ) + { + HandleRemoveCaseFileCmdL(); + } + + else if ( iCommandId == ECmdCaseMsg ) + { + HandleCaseMsgCmdL(); + } + + else if ( iCommandId == ECmdSetDevId ) + { + HandleSetDevIdCmdL(); + } + + else if ( iCommandId == ECmdSetAttribute ) + { + HandleSetAttributeCmdL(); + } + + else if ( iCommandId == ECmdClose ) + { + HandleCloseCmdL(); + } + + else if ( iCommandId == ECmdOpen ) + { + User::LeaveIfError( + SendErrorResponseMsg( KErrArgument, KErrorAlreadyOpen ) ); + } + + else + { + User::LeaveIfError( + SendErrorResponseMsg( KErrArgument, KErrorUnknownCmd ) ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::ProcessMessageL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleOpenCmdL +// Handles opening of the STIF Test Framework. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleOpenCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleOpenCmdL" ); + + TInt err = KErrNone; + + // OPEN command has 1 optional parameter (test framework ini-file) + if ( iParameters->Count() == 0 ) + { + err = Open(); + if ( err ) + { + SendErrorResponseMsg( err, KErrorOpen ); + return; + } + + iStifTfOpen = ETrue; + SendResponseMsg( _L8( "OK" ) ); + } + + else if ( iParameters->Count() == 1 ) + { + TBuf iniFilePath; + if ( (*iParameters)[0].Length() > iniFilePath.MaxLength() ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterTooLong ); + return; + } + + iniFilePath.Copy( (*iParameters)[0] ); + + RFs fsSession; + err = fsSession.Connect(); + if ( err ) + { + SendErrorResponseMsg( err, KErrorFileServer ); + return; + } + + if ( !( BaflUtils::FileExists( fsSession, iniFilePath ) ) ) + { + SendErrorResponseMsg( KErrNotFound, KErrorIniFileNotFound ); + fsSession.Close(); + return; + } + + fsSession.Close(); + + err = Open( iniFilePath ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorOpen ); + return; + } + + // Load the test case infos of all currently loaded test + // modules (modules listed in the given ini-file). + TRAP( err, LoadTestCaseInfosL() ); + if ( err ) + { + SendErrorResponseMsg( err, KErrorGetTestCaseInfos ); + return; + } + + iStifTfOpen = ETrue; + SendResponseMsg( _L8( "OK" ) ); + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleOpenCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleCloseCmdL +// Closes the STIF Test Framework. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleCloseCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleCloseCmdL" ); + + TInt err = KErrNone; + + // CLOSE command has no parameters + if ( iParameters->Count() == 0 ) + { + err = Close(); + if ( err ) + { + SendErrorResponseMsg( err, KErrorClose ); + return; + } + + iStifTfOpen = EFalse; + iLoadedInfos.ResetAndDestroy(); // empty the cache of test case infos + SendResponseMsg( _L8( "OK" ) ); + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleCloseCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleLoadModuleCmdL +// Loads a STIF TF test module (optionally with ini-file). +// Also calls the LoadTestCaseInfosL helper method to load the test case info +// objects from the test module. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleLoadModuleCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleLoadModuleCmdL" ); + + TInt err = KErrNone; + + TBuf moduleName; + TBuf iniFilePath; + + // LOAD_MODULE command has 1 mandatory parameter (module name) + // and 1 optional parameter (ini-file path). + if ( iParameters->Count() == 0 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + else if ( iParameters->Count() == 1 ) + { + if ( (*iParameters)[0].Length() > moduleName.MaxLength() ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterTooLong ); + return; + } + moduleName.Copy( (*iParameters)[0] ); + err = AddTestModule( moduleName ); + } + + else if ( iParameters->Count() == 2 ) + { + if ( (*iParameters)[0].Length() > moduleName.MaxLength() || + (*iParameters)[1].Length() > iniFilePath.MaxLength() ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterTooLong ); + return; + } + + moduleName.Copy( (*iParameters)[0] ); + iniFilePath.Copy( (*iParameters)[1] ); + + RFs fsSession; + err = fsSession.Connect(); + if ( err ) + { + SendErrorResponseMsg( err, KErrorFileServer ); + return; + } + + if ( !( BaflUtils::FileExists( fsSession, iniFilePath ) ) ) + { + SendErrorResponseMsg( KErrNotFound, KErrorIniFileNotFound ); + fsSession.Close(); + return; + } + + fsSession.Close(); + + err = AddTestModule( moduleName, iniFilePath ); + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + return; + } + + if ( err ) + { + HTI_LOG_FORMAT( "LoadModule: Error %d", err ); + SendErrorResponseMsg( err, KErrorLoadModule ); + } + + else + { + TRAP( err, LoadTestCaseInfosL( moduleName ) ); + + if ( err ) + { + HTI_LOG_FORMAT( + "LoadModule - Error from LoadTestCaseInfosL %d", err ); + RemoveTestModule( moduleName ); + SendErrorResponseMsg( err, KErrorGetTestCases ); + return; + } + + // Sends the name of the loaded module as a response. + SendResponseMsg( (*iParameters)[0] ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleLoadModuleCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleUnloadModuleCmdL +// Unloads a STIF TF test module. +// Also removes and deletes the corresponding CHtiTestModuleCaseInfos object +// from iLoadedInfos pointer array. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleUnloadModuleCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleUnloadModuleCmdL" ); + + TInt err = KErrNone; + + TBuf moduleName; + + // UNLOAD_MODULE command has always 1 parameter (module name). + if ( iParameters->Count() == 0 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + if ( iParameters->Count() == 1 ) + { + if ( (*iParameters)[0].Length() > moduleName.MaxLength() ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterTooLong ); + return; + } + moduleName.Copy( (*iParameters)[0] ); + err = RemoveTestModule( moduleName ); + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + return; + } + + if ( err ) + { + HTI_LOG_FORMAT( "UnloadModule: Error %d", err ); + SendErrorResponseMsg( err, KErrorUnloadModule ); + } + + else + { + // Remove the test case infos of the unloaded module. + TInt moduleIndex = IndexByModuleName( moduleName ); + if ( moduleIndex != KErrNotFound ) + { + CHtiTestModuleCaseInfos* module = iLoadedInfos[moduleIndex]; + iLoadedInfos.Remove( moduleIndex ); + delete module; + } + + // Sends the name of the unloaded module as a response. + SendResponseMsg( (*iParameters)[0] ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleUnloadModuleCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleListCasesCmdL +// Creates a list of titles of the test cases inside the given test module. +// Output is a string of test case titles separated with the | character. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleListCasesCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleListCasesCmdL" ); + + TInt err = KErrNone; + + TBuf moduleName; + TBuf8<128> buf8; // temporary buffer for case titles + + CHtiTestModuleCaseInfos* module = NULL; + CTestInfo* caseInfo = NULL; + + // LIST_CASES command has 1 optional parameter (module name). + + // If no parameter given all cases of all currently loaded + // modules are listed. + if ( iParameters->Count() == 0 ) + { + /* + // (Re)load case infos from all loaded modules + TRAP( err, LoadTestCaseInfosL() ); + + if ( err ) + { + HTI_LOG_FORMAT( + "ListCases - Error from LoadTestCaseInfosL %d", err ); + SendErrorResponseMsg( err, KErrorGetTestCaseInfos ); + } + */ + CBufFlat* caseListBuf = NULL; + TRAP( err, caseListBuf = CBufFlat::NewL( 128 ) ); + if ( err ) + { + SendErrorResponseMsg( KErrNoMemory, KErrorNoMemory ); + return; + } + + // Loop all loaded test modules + TInt pos = 0; + for ( TInt i = 0; i < iLoadedInfos.Count(); i++ ) + { + module = NULL; + module = iLoadedInfos[i]; + HTI_LOG_FORMAT( "Listing cases from module %S", + module->iModuleName ); + + // Loop all case infos in this module + for ( TInt j = 0; j < module->iTestInfos.Count(); j++ ) + { + caseInfo = NULL; + caseInfo = module->iTestInfos[j]; + + if ( !( i == 0 && j == 0 ) ) + { + buf8.Append( KParameterDelimiter ); + } + + buf8.Append( caseInfo->TestCaseTitle() ); + + TRAP( err, caseListBuf->ExpandL( pos, buf8.Length() ) ); + if ( err ) + { + SendErrorResponseMsg( KErrNoMemory, KErrorNoMemory ); + delete caseListBuf; + return; + } + caseListBuf->Write( pos, buf8, buf8.Length() ); + pos += buf8.Length(); + buf8.Zero(); + } + } + + if ( caseListBuf->Size() > 0 ) + { + TPtr8 ptr = caseListBuf->Ptr( 0 ); + SendResponseMsg( ptr ); + } + + else + { + SendResponseMsg( buf8 ); + } + + delete caseListBuf; + } + + else if ( iParameters->Count() == 1 ) + { + if ( (*iParameters)[0].Length() > moduleName.MaxLength() ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterTooLong ); + return; + } + + moduleName.Copy( (*iParameters)[0] ); + TInt moduleIndex = IndexByModuleName( moduleName ); + + if ( moduleIndex == KErrNotFound ) + { + HTI_LOG_TEXT( "Module is not loaded" ); + SendErrorResponseMsg( KErrNotFound, KErrorModuleNotLoaded ); + return; + } + /* + // (Re)load the case infos of given module + TRAP( err, LoadTestCaseInfosL( moduleName ) ); + if ( err ) + { + HTI_LOG_FORMAT( + "ListCases - Error from LoadTestCaseInfosL %d", err ); + SendErrorResponseMsg( err, KErrorGetTestCaseInfos ); + return; + } + */ + module = iLoadedInfos[moduleIndex]; + CBufFlat* caseListBuf = NULL; + + TRAP( err, caseListBuf = CBufFlat::NewL( 128 ) ); + + if ( err ) + { + SendErrorResponseMsg( KErrNoMemory, KErrorNoMemory ); + return; + } + + TInt pos = 0; + for ( TInt i = 0; i < module->iTestInfos.Count(); i++ ) + { + caseInfo = NULL; + caseInfo = module->iTestInfos[i]; + buf8.Copy( caseInfo->TestCaseTitle() ); + if ( !( i == module->iTestInfos.Count() - 1 ) ) + { + buf8.Append( KParameterDelimiter ); + } + TRAP( err, caseListBuf->ExpandL( pos, buf8.Length() ) ); + if ( err ) + { + SendErrorResponseMsg( KErrNoMemory, KErrorNoMemory ); + delete caseListBuf; + return; + } + caseListBuf->Write( pos, buf8, buf8.Length() ); + pos += buf8.Length(); + buf8.Zero(); + } + + if ( module->iTestInfos.Count() > 0 ) + { + TPtr8 ptr = caseListBuf->Ptr( 0 ); + SendResponseMsg( ptr ); + } + + else + { + SendResponseMsg( buf8 ); + } + + delete caseListBuf; + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleListCasesCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleStartCaseCmdL +// Starts one test case based on test module name and test case index number. +// STIF TF gives an ID to the started case and that ID is sent as a response +// message. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleStartCaseCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleStartCaseCmdL" ); + + TInt err = KErrNone; + TInt caseNumber = -1; + + // START_CASE command has 1 or 2 parameters. + // If only one parameter given, it's the index of test case to start. The + // index refers to the list of test cases of all currently loaded modules. + // If two parameters given, then the first one is the module name and + // second is the test case index number inside the given module, + + if ( iParameters->Count() == 0 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + else if ( iParameters->Count() == 1 ) + { + TLex8 lex( (*iParameters)[0] ); + err = lex.Val( caseNumber ); + if ( err ) + { + SendErrorResponseMsg( err, KErrorInvalidCaseNumber ); + return; + } + + CTestInfo* caseInfo = NULL; + TRAP( err, caseInfo = GetCaseInfoL( caseNumber ) ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorInvalidCaseNumber ); + return; + } + + TInt caseId = -1; + + err = StartTestCase( caseId, *caseInfo ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorStartTestCase ); + return; + } + + TBuf8<32> msg; + msg.AppendNum( caseId ); + SendResponseMsg( msg ); + } + + else if ( iParameters->Count() == 2 ) + { + TBuf moduleName; + if ( (*iParameters)[0].Length() > moduleName.MaxLength() ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterTooLong ); + return; + } + + moduleName.Copy( (*iParameters)[0] ); + TLex8 lex( (*iParameters)[1] ); + err = lex.Val( caseNumber ); + if ( err ) + { + SendErrorResponseMsg( err, KErrorInvalidCaseNumber ); + return; + } + + TInt moduleIndex = IndexByModuleName( moduleName ); + + if ( moduleIndex == KErrNotFound ) + { + // We don't have case infos of given module loaded - try to + // load them. + TRAP( err, LoadTestCaseInfosL( moduleName ) ); + if ( err ) + { + HTI_LOG_FORMAT( + "StartCase - Error from LoadTestCaseInfosL %d", err ); + SendErrorResponseMsg( err, KErrorModuleNotLoaded ); + return; + } + // Now there should be the module added - get its index + moduleIndex = IndexByModuleName( moduleName ); + } + + CHtiTestModuleCaseInfos* module = iLoadedInfos[moduleIndex]; + + if ( caseNumber < 0 || + caseNumber >= module->iTestInfos.Count() || + module->iTestInfos.Count() == 0 ) + { + SendErrorResponseMsg( KErrArgument, KErrorInvalidCaseNumber ); + return; + } + + CTestInfo* caseInfo = module->iTestInfos[caseNumber]; + TInt caseId = -1; + + err = StartTestCase( caseId, *caseInfo ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorStartTestCase ); + return; + } + + TBuf8<32> msg; + msg.AppendNum( caseId ); + SendResponseMsg( msg ); + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleStartCaseCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleCancelCaseCmdL +// Cancels test case execution based on test case ID. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleCancelCaseCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleCancelCaseCmdL" ); + + TInt err = KErrNone; + + // CANCEL_CASE command always has 1 parameter (test case id). + if ( iParameters->Count() == 0 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + else if ( iParameters->Count() == 1 ) + { + TInt caseId = -1; + TLex8 lex( (*iParameters)[0] ); + err = lex.Val( caseId ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorInvalidCaseNumber ); + return; + } + + err = CancelTestCase( caseId ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorCancelTestCase ); + } + + else + { + SendResponseMsg( _L8( "OK" ) ); + } + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleCancelCaseCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandlePauseCaseCmdL +// Pauses test case execution based on test case ID. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandlePauseCaseCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandlePauseCaseCmdL" ); + + TInt err = KErrNone; + + // PAUSE_CASE command always has 1 parameter (test case id). + if ( iParameters->Count() == 0 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + else if ( iParameters->Count() == 1 ) + { + TInt caseId = -1; + TLex8 lex( (*iParameters)[0] ); + err = lex.Val( caseId ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorInvalidCaseNumber ); + return; + } + + err = PauseTestCase( caseId ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorPauseTestCase ); + } + + else + { + SendResponseMsg( _L8( "OK" ) ); + } + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandlePauseCaseCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleResumeCaseCmdL +// Resumes execution of a paused test case based on test case ID. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleResumeCaseCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleResumeCaseCmdL" ); + + TInt err = KErrNone; + + // RESUME_CASE command always has 1 parameter (test case id). + if ( iParameters->Count() == 0 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + else if ( iParameters->Count() == 1 ) + { + TInt caseId = -1; + TLex8 lex( (*iParameters)[0] ); + err = lex.Val( caseId ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorInvalidCaseNumber ); + return; + } + + err = ResumeTestCase( caseId ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorResumeTestCase ); + } + + else + { + SendResponseMsg( _L8( "OK" ) ); + } + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleResumeCaseCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleAddCaseFileCmdL +// Adds a test case file to an earlier loaded test module. +// Checks that the module is loaded and that the given test case file exists. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleAddCaseFileCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleAddCaseFileCmdL" ); + + TInt err = KErrNone; + + TBuf moduleName; + TBuf caseFilePath; + + // ADD_CASE_FILE command always has 2 mandatory parameters (module name + // and test case file path). + if ( iParameters->Count() == 0 || iParameters->Count() == 1 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + else if ( iParameters->Count() == 2 ) + { + if ( (*iParameters)[0].Length() > moduleName.MaxLength() || + (*iParameters)[1].Length() > caseFilePath.MaxLength() ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterTooLong ); + return; + } + + moduleName.Copy( (*iParameters)[0] ); + caseFilePath.Copy( (*iParameters)[1] ); + + RFs fsSession; + err = fsSession.Connect(); + if ( err ) + { + SendErrorResponseMsg( err, KErrorFileServer ); + return; + } + + if ( !( BaflUtils::FileExists( fsSession, caseFilePath ) ) ) + { + SendErrorResponseMsg( KErrNotFound, KErrorCaseFileNotFound ); + fsSession.Close(); + return; + } + + fsSession.Close(); + + err = AddTestCaseFile( moduleName, caseFilePath ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorAddCaseFile ); + return; + } + + // Test case file has been added - update test case infos + TRAP( err, LoadTestCaseInfosL( moduleName ) ); + + if ( err ) + { + HTI_LOG_FORMAT( + "AddCaseFile - Error from LoadTestCaseInfosL %d", err ); + SendErrorResponseMsg( err, KErrorGetTestCases ); + return; + } + + SendResponseMsg( _L8( "OK" ) ); + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleAddCaseFileCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleRemoveCaseFileCmdL +// Removes a test case file from test module. +// Checks that the module is loaded and that the given test case file exists. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleRemoveCaseFileCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleRemoveCaseFileCmdL" ); + + TInt err = KErrNone; + + TBuf moduleName; + TBuf caseFilePath; + + // REMOVE_CASE_FILE command always has 2 mandatory parameters (module name + // and test case file path). + if ( iParameters->Count() == 0 || iParameters->Count() == 1 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + else if ( iParameters->Count() == 2 ) + { + if ( (*iParameters)[0].Length() > moduleName.MaxLength() || + (*iParameters)[1].Length() > caseFilePath.MaxLength() ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterTooLong ); + return; + } + + moduleName.Copy( (*iParameters)[0] ); + caseFilePath.Copy( (*iParameters)[1] ); + + RFs fsSession; + err = fsSession.Connect(); + if ( err ) + { + SendErrorResponseMsg( err, KErrorFileServer ); + return; + } + + if ( !( BaflUtils::FileExists( fsSession, caseFilePath ) ) ) + { + SendErrorResponseMsg( KErrNotFound, KErrorCaseFileNotFound ); + fsSession.Close(); + return; + } + + fsSession.Close(); + + err = RemoveTestCaseFile( moduleName, caseFilePath ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorRemoveCaseFile ); + return; + } + + // Test case file has been removed - update test case infos + TRAP( err, LoadTestCaseInfosL( moduleName ) ); + + if ( err ) + { + HTI_LOG_FORMAT( + "RemoveCaseFile - Error from LoadTestCaseInfosL %d", err ); + SendErrorResponseMsg( err, KErrorGetTestCases ); + return; + } + + SendResponseMsg( _L8( "OK" ) ); + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleRemoveCaseFileCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleCaseMsgCmdL +// Sends a message to STIF Test Framework. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleCaseMsgCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleCaseMsgCmdL" ); + + TInt err = KErrNone; + + // CASE_MESSAGE command always has 1 parameter (the message). + if ( iParameters->Count() == 0 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + else if ( iParameters->Count() == 1 ) + { + HBufC* msg = HBufC::New( (*iParameters)[0].Length() ); + if ( msg == NULL ) + { + SendErrorResponseMsg( KErrNoMemory, KErrorNoMemory ); + return; + } + msg->Des().Copy( (*iParameters)[0] ); + HTI_LOG_TEXT( "Sending case message:" ); + HTI_LOG_DES( *msg ); + err = AtsReceive( *msg ); + delete msg; + + if ( err ) + { + SendErrorResponseMsg( err, KErrorCaseMessage ); + } + + else + { + SendResponseMsg( _L8( "OK" ) ); + } + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleCaseMsgCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleSetDevIdCmdL +// Sets device ID. If successfull sends the set ID back as response message. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleSetDevIdCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleSetDevIdCmdL" ); + + TInt err = KErrNone; + + // SET_DEVICEID command always has 1 parameter (device id). + if ( iParameters->Count() == 0 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + return; + } + + else if ( iParameters->Count() == 1 ) + { + TUint16 deviceId = KDefaultDevId; + TLex8 lex( (*iParameters)[0] ); + err = lex.Val( deviceId, EDecimal ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorInvalidDeviceId ); + return; + } + + iDevId = deviceId; + + // On success sends the set device id as response. + TBuf8<32> msg; + msg.AppendNum( (TInt)iDevId ); + SendResponseMsg( msg ); + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleSetDevIdCmdL" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::HandleSetAttributeCmdL +// Sets attributes for test framework. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::HandleSetAttributeCmdL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::HandleSetAttributeCmdL" ); + + TInt err = KErrNone; + + // SET_ATTRIBUTE command always has 2 paramters (attribute id and value) + if ( iParameters->Count() < 2 ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterMissing ); + } + + else if ( iParameters->Count() == 2 ) + { + TInt attributeId = -1; + TLex8 lex( (*iParameters)[0] ); + err = lex.Val( attributeId ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorInvalidAttributeId ); + return; + } + + TBuf<256> value; + if ( (*iParameters)[1].Length() > value.MaxLength() ) + { + SendErrorResponseMsg( KErrArgument, KErrorParameterTooLong ); + return; + } + value.Copy( (*iParameters)[1] ); + + err = SetAttribute( (TAttribute)attributeId, value ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorSetAttribute ); + } + + else + { + SendResponseMsg( _L8( "OK" ) ); + } + } + + else + { + SendErrorResponseMsg( KErrArgument, KErrorTooManyParameters ); + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::HandleSetAttributeCmdL" ); + } + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::TestCompleted +// This method is called by the STIF TF when a test case execution completes. +// The test case result is send out as a formatted string. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::TestCompleted( TInt aTestId, + TInt aTestExecutionResult, + TTestResult& aTestResult ) + { + // Note that the STIF TF is not aware whether the service is busy processing, + // sending, or waiting to send a previous message. So if this method + // is called by the STIF TF while the service is busy, the currently + // pending message will be overridden by the message sent from this method. + + HTI_LOG_FUNC_IN( "CHtiStifTfIf::TestCompleted" ); + + iIsBusy = ETrue; // Will be set to EFalse when response have been sent + + // The maximum length of TResultDes is 128, so a buffer of 256 + // should be enough for the whole "Test Completed" message. + TBuf8<256> buf8; + + // Add first the test id + buf8.AppendFormat( _L8( "%d" ), aTestId ); + buf8.Append( KParameterDelimiter ); + + // Add the test result - if it's 0 case has passed + buf8.AppendFormat( _L8( "%d" ), aTestResult.iResult ); + buf8.Append( KParameterDelimiter ); + + // Add the test execution result + buf8.AppendFormat( _L8( "%d" ), aTestExecutionResult ); + buf8.Append( KParameterDelimiter ); + + // Finally add the description (if there's any) + if ( aTestResult.iResultDes.Length() > 0 ) + { + buf8.Append( aTestResult.iResultDes ); + } + + // and send it + SendResponseMsg( buf8, ECmdTestCompleted ); + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::TestCompleted" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::AtsSend +// This method is called by the STIF TF when it needs to send a message to ATS +// (or some other PC-side component listening for messages) +// The message is converted to 8-bit representation before sending. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::AtsSend( const TDesC& aMessage ) + { + // Note that the STIF TF is not aware whether the service is busy processing, + // sending, or waiting to send a previous message. So if this method + // is called by the STIF TF while the service is busy, the currently + // pending message will be overridden by the message sent from this method. + + HTI_LOG_FUNC_IN( "CHtiStifTfIf::AtsSend" ); + HTI_LOG_TEXT( "Message: " ); + HTI_LOG_DES( aMessage ); + + iIsBusy = ETrue; // Will be set to EFalse when response have been sent + + TInt err = KErrNone; + + CCnvCharacterSetConverter* converter = NULL; + TRAP( err, converter = CCnvCharacterSetConverter::NewL() ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorCharConv ); + return; + } + + RFs fsSession; + err = fsSession.Connect(); + if ( err ) + { + SendErrorResponseMsg( err, KErrorFileServer ); + delete converter; + return; + } + + CCnvCharacterSetConverter::TAvailability availability = + CCnvCharacterSetConverter::ENotAvailable; + + TRAP( err, availability = converter->PrepareToConvertToOrFromL( + KCharacterSetIdentifierAscii, fsSession ) ); + + if ( err || availability == CCnvCharacterSetConverter::ENotAvailable ) + { + SendErrorResponseMsg( err, KErrorCharConv ); + fsSession.Close(); + delete converter; + return; + } + + fsSession.Close(); + + HBufC8* asciiBuffer = NULL; + TRAP( err, asciiBuffer = HBufC8::NewL( aMessage.Length() ) ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorNoMemory ); + delete converter; + return; + } + + TPtr8 ptr8 = asciiBuffer->Des(); + ptr8.Zero(); + + err = converter->ConvertFromUnicode( ptr8, aMessage ); + + if ( err ) + { + SendErrorResponseMsg( err, KErrorCharConv ); + } + + else + { + TPtr8 converted = asciiBuffer->Des(); + HTI_LOG_TEXT( "Converted message: " ); + HTI_LOG_DES( converted ); + SendResponseMsg( converted, ECmdAtsMessage ); + } + + delete converter; + delete asciiBuffer; + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::AtsSend" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::Print +// This method is called by the STIF TF when a test case prints. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::Print( TInt /*aTestId*/, + TTestProgress& aProgress ) + { + if ( iConsole ) + { + iConsole->Printf( _L("%S: %S\n"), + &aProgress.iDescription, + &aProgress.iText ); + } + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::LoadTestCaseInfosL +// A helper method that loads the test case info objects from all currently +// loaded test modules. Creates and inserts new CHtiTestModuleCaseInfos objects +// to iLoadedInfos pointer array. Leaves on failure. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::LoadTestCaseInfosL() + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::LoadTestCaseInfosL()" ); + + RPointerArray allTestInfos; + CleanupClosePushL( allTestInfos ); + + HTI_LOG_TEXT( "Getting test cases" ); + // Ignoring possible errors + GetTestCases( allTestInfos ); + HTI_LOG_FORMAT( "Got %d cases", allTestInfos.Count() ); + + // Clear all old test case infos from iLoadedInfos + iLoadedInfos.ResetAndDestroy(); + + // Loop through all test case infos and add them to the correct modules + // to iLoadedInfos + for ( TInt i = 0; i < allTestInfos.Count(); i++ ) + { + CHtiTestModuleCaseInfos* currentModule = NULL; + CTestInfo* caseInfo = NULL; + + caseInfo = allTestInfos[i]; + + // Get or create the CHtiTestModuleCaseInfos where this case belongs. + TInt moduleIndex = IndexByModuleName( caseInfo->ModuleName() ); + + if ( moduleIndex == KErrNotFound ) + { + HTI_LOG_TEXT( "Module not found - adding it" ); + currentModule = CHtiTestModuleCaseInfos::NewLC( + caseInfo->ModuleName() ); + User::LeaveIfError( iLoadedInfos.Append( currentModule ) ); + CleanupStack::Pop(); // currentModule + } + + else + { + HTI_LOG_TEXT( "Module found - getting it" ); + currentModule = iLoadedInfos[moduleIndex]; + } + + // Add the case info to the CHtiTestModuleCaseInfos object + currentModule->iTestInfos.Append( caseInfo ); + } + + HTI_LOG_FORMAT( "Case infos of %d modules added", iLoadedInfos.Count() ); + allTestInfos.Reset(); + CleanupStack::PopAndDestroy(); // allTestInfos + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::LoadTestCaseInfosL()" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::LoadTestCaseInfosL +// A helper method that loads the test case info objects from the given test +// module. Creates and inserts a new CHtiTestModuleCaseInfos object to +// iLoadedInfos pointer array. Leaves on failure. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::LoadTestCaseInfosL( TDesC& aModuleName ) + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::LoadTestCaseInfosL( moduleName )" ); + + // Check if test case infos of this module already loaded + TInt index = IndexByModuleName( aModuleName ); + if ( index != KErrNotFound ) + { + // If infos already loaded, delete and load again + HTI_LOG_TEXT( "Already loaded - updating" ); + CHtiTestModuleCaseInfos* module = iLoadedInfos[index]; + iLoadedInfos.Remove( index ); + delete module; + } + + CHtiTestModuleCaseInfos* newModule = + CHtiTestModuleCaseInfos::NewLC( aModuleName ); + + HTI_LOG_TEXT( "Getting test cases" ); + + // If the module is not loaded STIF TF seems to behave so that + // GetTestCases method does not return error but it returns + // zero test cases. + // At least in some cases if the module is loaded but it does not have + // any test cases, GetTestCases returns KErrNotFound. + // So possible errors or zero test case situations from GetTestCases + // are ignored here - if there's an error then the module will just + // have 0 test case infos. + GetTestCases( newModule->iTestInfos, aModuleName ); + + HTI_LOG_FORMAT( "Got %d cases", newModule->iTestInfos.Count() ); + + User::LeaveIfError( iLoadedInfos.Append( newModule ) ); + CleanupStack::Pop(); // newModule + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::LoadTestCaseInfosL( moduleName )" ); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::ParseParametersL +// A helper method for parsing the parameters from the given command message. +// Parameters must be separated with a character defined by the +// KParameterDelimiter. Parsed parameters are stored to iParameters array. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::ParseParametersL( const TDesC8& aCommand ) + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::ParseParametersL" ); + + // Clear the parameter array + iParameters->Reset(); + + // Then loop all the parameters. + TInt sectionStart = 0; + TInt sectionEnd = 0; + while ( true ) + { + sectionStart = sectionEnd + 1; + if ( sectionStart >= aCommand.Length() ) + { + HTI_LOG_FORMAT( "Parameters %d", iParameters->Count() ); + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::ParseParametersL" ); + return; + } + + sectionEnd = aCommand.Mid( sectionStart ).Find( KParameterDelimiter ) + + sectionStart; + + if ( sectionEnd >= sectionStart ) + { + iParameters->AppendL( + aCommand.Mid( sectionStart, sectionEnd - sectionStart ) ); + HTI_LOG_DES( aCommand.Mid( sectionStart, sectionEnd - sectionStart ) ); + } + else + { + iParameters->AppendL( aCommand.Mid( sectionStart ) ); + HTI_LOG_DES( aCommand.Mid( sectionStart ) ); + HTI_LOG_FORMAT( "Parameters %d", iParameters->Count() ); + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::ParseParametersL" ); + return; // End of parameters. + } + } + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::SetDispatcher +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::SetDispatcher( MHtiDispatcher* aDispatcher ) + { + iDispatcher = aDispatcher; + iConsole = iDispatcher->GetConsole(); + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::NotifyMemoryChange +// Called when HTI Framework has dispatched a message forward and the amount +// of free memory in the message queue has changed. +// ----------------------------------------------------------------------------- +// +void CHtiStifTfIf::NotifyMemoryChange( TInt aAvailableMemory ) + { + if ( iIsBusy && iMessage ) + { + if ( aAvailableMemory >= iMessage->Size() ) + { + + if ( iErrorCode == 0 ) + { + TInt err = iDispatcher->DispatchOutgoingMessage( + iMessage, KStifTfServiceUid ); + + if ( err == KErrNone ) + { + // Ownership of iMessage has been transferred + iMessage = NULL; + iIsBusy = EFalse; + iDispatcher->RemoveMemoryObserver( + ( MHtiMemoryObserver* ) iPlugin ); + } + + else if ( err == KErrNoMemory ) + { + // Just keep retrying. + } + + else // Give up on sending + { + delete iMessage; + iMessage = NULL; + iIsBusy = EFalse; + iDispatcher->RemoveMemoryObserver( + ( MHtiMemoryObserver* ) iPlugin ); + } + + } + + else + { + TInt err = iDispatcher->DispatchOutgoingErrorMessage( + iErrorCode, *iMessage, KStifTfServiceUid ); + + // If it was success or some other error than KErrNoMemory + // we are done sending or trying to send this message. + if ( err != KErrNoMemory ) + { + delete iMessage; + iMessage = NULL; + iIsBusy = EFalse; + iDispatcher->RemoveMemoryObserver( + ( MHtiMemoryObserver* ) iPlugin ); + } + + else + { + // Just keep retrying. + } + } + } + } + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::SendResponseMsg +// Sends a message out to the message dispatcher. +// ----------------------------------------------------------------------------- +// +TInt CHtiStifTfIf::SendResponseMsg( const TDesC8& aMsg, + const TUint8 aCommandId ) + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::SendResponseMsg" ); + + iErrorCode = 0; + + if ( iDispatcher == NULL ) + { + iIsBusy = EFalse; + return KErrGeneral; + } + + iDispatcher->RemoveMemoryObserver( ( MHtiMemoryObserver* ) iPlugin ); + + delete iMessage; + iMessage = NULL; + iMessage = HBufC8::New( aMsg.Length() + 1 ); + + + if ( iMessage == NULL ) + { + iIsBusy = EFalse; + return KErrNoMemory; + } + + TPtr8 ptr8 = iMessage->Des(); + if ( aCommandId != 0 ) + { + ptr8.Append( aCommandId ); + } + else + { + ptr8.Append( iCommandId ); + } + + ptr8.Append( aMsg ); + + TInt err = KErrNone; + + err = iDispatcher->DispatchOutgoingMessage( iMessage, KStifTfServiceUid ); + + if ( err == KErrNoMemory ) + { + HTI_LOG_TEXT( "Message queue memory full - waiting" ); + iIsBusy = ETrue; // Should already be true, but just in case + iDispatcher->AddMemoryObserver( ( MHtiMemoryObserver* ) iPlugin ); + // For the caller of this method all is OK, sending is just delayed + err = KErrNone; + } + + else if ( err == KErrNone ) + { + HTI_LOG_TEXT( "Message sent to dispatcher" ); + iMessage = NULL; // Ownership of iMessage has been transferred + iIsBusy = EFalse; + } + + else // give up on sending + { + HTI_LOG_FORMAT( "Other dispatcher error %d", err ); + delete iMessage; + iMessage = NULL; + iIsBusy = EFalse; + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::SendResponseMsg" ); + return err; + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::SendErrorResponseMsg +// Sends an error message out to the message dispatcher. +// ----------------------------------------------------------------------------- +// +TInt CHtiStifTfIf::SendErrorResponseMsg( TInt aErrorCode, + const TDesC8& aErrorDescription, + const TUint8 aCommandId ) + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::SendErrorResponseMsg" ); + + iErrorCode = aErrorCode; + + if ( iDispatcher == NULL ) + { + iIsBusy = EFalse; + return KErrGeneral; + } + + iDispatcher->RemoveMemoryObserver( ( MHtiMemoryObserver* ) iPlugin ); + + delete iMessage; + iMessage = NULL; + iMessage = HBufC8::New( aErrorDescription.Length() + 1 ); + + if ( iMessage == NULL ) + { + iIsBusy = EFalse; + return KErrNoMemory; + } + + TPtr8 ptr8 = iMessage->Des(); + if ( aCommandId != 0 ) + { + ptr8.Append( aCommandId ); + } + else + { + ptr8.Append( iCommandId ); + } + + ptr8.Append( aErrorDescription ); + + TInt err = KErrNone; + + err = iDispatcher->DispatchOutgoingErrorMessage( + aErrorCode, *iMessage, KStifTfServiceUid ); + + if ( err == KErrNoMemory ) + { + HTI_LOG_TEXT( "Message queue memory full - waiting" ); + iIsBusy = ETrue; // Should already be true, but just in case + iDispatcher->AddMemoryObserver( ( MHtiMemoryObserver* ) iPlugin ); + // For the caller of this method all is OK, sending is just delayed + err = KErrNone; + } + + else if ( err == KErrNone ) + { + HTI_LOG_TEXT( "Error message sent to dispatcher" ); + delete iMessage; + iMessage = NULL; + iIsBusy = EFalse; + } + + else // give up on sending + { + HTI_LOG_FORMAT( "Other dispatcher error %d", err ); + delete iMessage; + iMessage = NULL; + iIsBusy = EFalse; + } + + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::SendErrorResponseMsg" ); + return err; + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::IndexByModuleName +// A helper method to search for a CHtiTestModuleCaseInfos object from the +// iLoadedInfos array based on the module name. +// ----------------------------------------------------------------------------- +// +TInt CHtiStifTfIf::IndexByModuleName( const TDesC& aModuleName ) + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::IndexByModuleName" ); + + CHtiTestModuleCaseInfos* module; + for ( TInt i = 0; i < iLoadedInfos.Count(); i++ ) + { + module = NULL; + module = iLoadedInfos[i]; + if ( module->iModuleName->Compare( aModuleName ) == 0 ) + { + HTI_LOG_FORMAT( "Module found from index %d", i ); + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::IndexByModuleName" ); + return i; + } + } + HTI_LOG_TEXT( "Module not found" ); + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::IndexByModuleName" ); + return KErrNotFound; + } + + +// ----------------------------------------------------------------------------- +// CHtiStifTfIf::GetCaseInfoL +// A helper method to get the correct CTestInfo object based on the index +// number, referring to list of case infos of all loaded test modules. +// ----------------------------------------------------------------------------- +// +CTestInfo* CHtiStifTfIf::GetCaseInfoL( TInt aCaseIndex ) + { + HTI_LOG_FUNC_IN( "CHtiStifTfIf::GetCaseInfoL" ); + + if ( aCaseIndex < 0 ) + { + User::Leave( KErrArgument ); + } + + TInt index = -1; + TInt caseCount = 0; + CHtiTestModuleCaseInfos* module = NULL; + for ( TInt i = 0; i < iLoadedInfos.Count(); i++ ) + { + module = NULL; + module = iLoadedInfos[i]; + caseCount += module->iTestInfos.Count(); + HTI_LOG_FORMAT( "Case count = %d", caseCount ); + if ( aCaseIndex < caseCount ) + { + // This is the right module + // Get the case index inside this module + index = module->iTestInfos.Count() - ( caseCount - aCaseIndex ); + } + if ( index >= 0 ) break; // Case found - break out of loop + } + + if ( index < 0 ) + { + HTI_LOG_TEXT( "Given index was too big - case not found" ); + User::Leave( KErrNotFound ); + } + + // Following should never be true - this is for testing. + if ( index > module->iTestInfos.Count() ) + { + HTI_LOG_TEXT( "**Calculated index > test info count of module**" ); + User::Leave( KErrGeneral ); + } + + HTI_LOG_FORMAT( "Case found from index %d", index ); + HTI_LOG_FUNC_OUT( "CHtiStifTfIf::GetCaseInfoL" ); + return module->iTestInfos[index]; + } + + +// ============================ MEMBER FUNCTIONS =============================== + + +// ----------------------------------------------------------------------------- +// CHtiTestModuleCaseInfos::NewL +// ----------------------------------------------------------------------------- +// +CHtiTestModuleCaseInfos* CHtiTestModuleCaseInfos::NewL( + const TDesC& aModuleName ) + { + CHtiTestModuleCaseInfos* self = NewLC( aModuleName ); + CleanupStack::Pop( self ); + return self; + } + + +// ----------------------------------------------------------------------------- +// CHtiTestModuleCaseInfos::NewLC +// ----------------------------------------------------------------------------- +// +CHtiTestModuleCaseInfos* CHtiTestModuleCaseInfos::NewLC( + const TDesC& aModuleName ) + { + CHtiTestModuleCaseInfos* self = new (ELeave) CHtiTestModuleCaseInfos; + CleanupStack::PushL( self ); + self->ConstructL( aModuleName ); + return self; + } + + +// ----------------------------------------------------------------------------- +// CHtiTestModuleCaseInfos::ConstructL +// 2nd phase constructor. +// ----------------------------------------------------------------------------- +// +void CHtiTestModuleCaseInfos::ConstructL( const TDesC& aModuleName ) + { + iModuleName = aModuleName.AllocL(); + } + + +// ----------------------------------------------------------------------------- +// CHtiTestModuleCaseInfos::CHtiTestModuleCaseInfos +// C++ default constructor +// ----------------------------------------------------------------------------- +// +CHtiTestModuleCaseInfos::CHtiTestModuleCaseInfos() + { + } + + +// ----------------------------------------------------------------------------- +// CHtiTestModuleCaseInfos::~CHtiTestModuleCaseInfos +// Destructor. +// ----------------------------------------------------------------------------- +// +CHtiTestModuleCaseInfos::~CHtiTestModuleCaseInfos() + { + delete iModuleName; + iTestInfos.ResetAndDestroy(); + iTestInfos.Close(); + } + + +// ----------------------------------------------------------------------------- +// CHtiTestModuleCaseInfos::Compare +// Compares the order of two CHtiTestModuleCaseInfos objects using module name +// as the ordering key. +// ----------------------------------------------------------------------------- +// +TInt CHtiTestModuleCaseInfos::Compare( const CHtiTestModuleCaseInfos& aFirst, + const CHtiTestModuleCaseInfos& aSecond ) + { + return ( aFirst.iModuleName )->Compare( *aSecond.iModuleName ); + } + + +// ----------------------------------------------------------------------------- +// CHtiTestModuleCaseInfos::Match +// Checks the equality of two CHtiTestModuleCaseInfos objects. +// Objects are considered to be equal if their module name is equal. +// ----------------------------------------------------------------------------- +// +TBool CHtiTestModuleCaseInfos::Match( const CHtiTestModuleCaseInfos& aFirst, + const CHtiTestModuleCaseInfos& aSecond ) + { + if ( ( aFirst.iModuleName )->Compare( *aSecond.iModuleName ) == 0 ) + { + return true; + } + + return false; + } + + +// End of File