testfws/testexecmdw/tef/scriptengine/src/scriptengine.cpp
changeset 2 73b88125830c
equal deleted inserted replaced
1:6edeef394eb7 2:73b88125830c
       
     1 /*
       
     2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 * Design Overview:
       
    16 * The diagram below shows the Script Engine classes and their parent child
       
    17 * hierarchy. All classes have a CActive base, and apart from CTaskTimer, all classes
       
    18 * have their own state machine. Apart from CScriptMaster, all classes have a reference
       
    19 * to a Mixin/Interface completion call of its parent, which it calls when the object
       
    20 * needs to notify the parent of an event.
       
    21 * CScriptMaster (derived CActive)
       
    22 * CScriptControl (derived CActiveBase - Can go recursive)
       
    23 * CProgramControl (derived CTaskControlBase) CClientControl ( derived CTaskControlBase maps to n x test steps)
       
    24 * CTaskTimer                                 CTaskTimer (derived CTimer)
       
    25 *  state transition tables for CScriptMaster, CScriptControl & CClientControl
       
    26 * CActiveBase:
       
    27 * Derives CActive.
       
    28 * Contains code for priming, triggering and completing AO's
       
    29 * Implements the pure abstract MChildCompletion::ChildCompletion() method
       
    30 * CTaskControlBase:
       
    31 * Derives CActiveBase.
       
    32 * Abstract class. Base for CClientControl and CProgramControl.
       
    33 * CScriptMaster:
       
    34 * Derives CActiveBase.
       
    35 * Master control active object with simple state machine.
       
    36 * Instantiates the top level CScriptControl object and triggers its state machine.
       
    37 * CScriptContol:
       
    38 * Derives CActiveBase.
       
    39 * Main script interpreter state machine. Creates one or more CClientControl and/or
       
    40 * CProgramControl objects.
       
    41 * In CONCURRENT mode, it can create as many instances as there are RUN_TEST_STEP and/or 
       
    42 * RUN_PROGRAM calls.
       
    43 * Creates root sessions with the xxxtest servers using the RTestServ::Connect() client call.
       
    44 * In the case of non-nested scripts, the parent object is CScriptMaster.
       
    45 * When scripts are nested and it goes recursive, the parent object could be another 
       
    46 * CScriptControl.
       
    47 * Implements the MTaskCompletion pure abstract class for callbacks from
       
    48 * CClientControl or CProgramControl objects
       
    49 * Calls back into its parent object when the script is complete and all async commands have
       
    50 * completed.
       
    51 * CClientControl:
       
    52 * Derives CTaskControlBase.
       
    53 * Test Step Controler. Instantiated by CScriptControl when a RUN_TEST_STEP line is interpreted
       
    54 * Creates and kicks off a CTaskTimer object set to the timeout value for the test step.
       
    55 * Opens a test step using the RTestSession::Open() client call.
       
    56 * Executes a test step using the RTestSession::RunTestStep() client call.
       
    57 * This method issues the client RTestSession::AbortTestStep() call and
       
    58 * the RunL() state machine handles the completion from the test server.
       
    59 * Implements the MTaskTimerCompletion pure abstract class for callbacks from the
       
    60 * CTaskTimer class.
       
    61 * Calls back into its parent CScriptControl object when a test step completes.
       
    62 * CProgramControl
       
    63 * Derives CTaskControlBase
       
    64 * Kicks off an executable in its own process and handles process completion asynchronously
       
    65 * CTaskTimer:
       
    66 * Derives CTimer.
       
    67 * Calls back into its parent object if the timer expires.
       
    68 * EPOC include
       
    69 *
       
    70 */
       
    71 
       
    72 
       
    73 
       
    74 /**
       
    75  @file scriptengine.cpp
       
    76 */
       
    77 
       
    78 // User include
       
    79 #include <test/testexecuteclient.h>
       
    80 #include "scriptengine.h"
       
    81 
       
    82 // Fix defect 119337, initialize the integer to zero
       
    83 GLDEF_D TInt CScriptControl::iNestedNumRunScriptInLoop=0;
       
    84 // End defect 119337
       
    85 
       
    86 /**
       
    87  * @param aPtrC1 - Instance of TPtrC to compare
       
    88  * @param aPtrC2 - Instance of TPtrC to compare
       
    89  * Function to implement the comparison algo for RArray::Find to work with
       
    90  */
       
    91 TBool TSelectiveTestingOptions::CompareTPtrC(const TPtrC& aPtrC1, const TPtrC& aPtrC2)
       
    92 	{
       
    93 	TInt ret =aPtrC1.CompareF(aPtrC2);
       
    94 	return (ret==0) ? ETrue : EFalse;
       
    95 	} 
       
    96 
       
    97 /**
       
    98  * @param aRng1 - Instance of TRange to compare
       
    99  * @param aRng2 - Instance of TRange to compare
       
   100  * Function to implement the comparison algo for RArray::Find to work with.
       
   101  * TRange::iStartTestCase determines the match
       
   102  */
       
   103 TBool TRange::CompareTRangeStartCase(const TRange& aRng1, const TRange& aRng2) 
       
   104 	{
       
   105 	TInt ret =aRng2.iStartTestCase.CompareF(aRng1.iStartTestCase);
       
   106 	return (ret==0) ? ETrue : EFalse;
       
   107 	}
       
   108 
       
   109 /**
       
   110  * @param aRng1 - Instance of TRange to compare
       
   111  * @param aRng2 - Instance of TRange to compare
       
   112  * Function to implement the comparison algo for RArray::Find to work with.
       
   113  * TRange::iEndTestCase determines the match
       
   114  */
       
   115 TBool TRange::CompareTRangeEnd(const TRange& aRng1, const TRange& aRng2) 
       
   116 	{
       
   117 	TInt ret =aRng2.iEndTestCase.CompareF(aRng1.iEndTestCase);
       
   118 	return (ret==0) ? ETrue : EFalse;  
       
   119 	}
       
   120 
       
   121 /**
       
   122  * @param aRng1 - Instance of TRange to compare
       
   123  * @param aRng2 - Instance of TRange to compare
       
   124  * Function to implement the comparison algo for RArray::Sort to work with.
       
   125  * TRange::iStartTestCase is used as the sort key
       
   126  */
       
   127 TInt TRange::CompareTRangeStartOrder(const TRange& aRng1, const TRange& aRng2) 
       
   128 	{
       
   129 	return aRng1.iStartTestCase.CompareF( aRng2.iStartTestCase);
       
   130 	}
       
   131 
       
   132 /**
       
   133  * @param aPtrC1 - Instance of TPtrC to compare
       
   134  * @param aPtrC2 - Instance of TPtrC to compare
       
   135  * Function to implement the comparison algo for RArray::Sort to work with.
       
   136  */
       
   137 TInt TSelectiveTestingOptions::CompareTPtrCOrder(const TPtrC& aPtrC1, const TPtrC& aPtrC2) 
       
   138 	{
       
   139 	return aPtrC1.CompareF(aPtrC2);
       
   140 	}
       
   141 
       
   142 /**
       
   143  * @param aServ - Instance of the test server handle
       
   144  * @param aStepName - Test step name
       
   145  * Wrapper around the RTestServ class. Performs counting on test step sessions
       
   146  */
       
   147 TInt RScriptTestSession::Open(RScriptTestServ& aServ, const TBool aIsTestStep, const TDesC& aStepName )
       
   148 	{
       
   149 	if(aServ.SharedData() && aServ.SessionCount())
       
   150 			return KErrInUse;
       
   151 	TInt ret = KErrNone;
       
   152 	
       
   153 	if( aIsTestStep )
       
   154 		{
       
   155 		ret = RTestSession::Open(aServ, aStepName, aServ.SharedData());
       
   156 		}
       
   157 	else
       
   158 		{
       
   159 		ret = RTestSession::Open(aServ, aServ.SharedData());
       
   160 		}
       
   161 	if(ret)
       
   162 		return ret;
       
   163 	aServ.AddSession();
       
   164 	iServ = &aServ;
       
   165 	return KErrNone;
       
   166 	}
       
   167 	
       
   168 /**
       
   169  * @param aScriptFilePath - The full path and filename of a script command file.
       
   170  * @param aLogger - Reference to a logger interface object that contains HTML & XML log client sessions.
       
   171  * @param aConsole - Reference to console object for printing script line during test execution
       
   172  * @param aSysDrive - Default System drive letter
       
   173  * @param aTestSysDrive - Default System drive letter overwritten through testexecute.ini
       
   174  * Constructor
       
   175  */
       
   176 CScriptMaster::CScriptMaster(const TDesC& aScriptFilePath, CTestExecuteLogger& aLogger, RConsoleLogger& aConsole, const TDriveName& aSysDrive, const TDriveName& aTestSysDrive, TSelectiveTestingOptions* aSelTestingOptions ) :
       
   177 	iState(EInit), iScriptFilePath(aScriptFilePath), iLogger(aLogger), iConsoleLogger(aConsole), iDefaultSysDrive(aSysDrive), iTestSysDrive(aTestSysDrive), iSelTestingOptions(aSelTestingOptions)
       
   178 	{
       
   179 	}
       
   180 
       
   181 /**
       
   182  * Destructor
       
   183  */
       
   184 CScriptMaster::~CScriptMaster()
       
   185 	{
       
   186 	}
       
   187 
       
   188 /**
       
   189  * Pure virtual implementation.
       
   190  * The Top level state machine Kick'd() into by MainL()
       
   191  * Picks up the completion from a CScriptControl instance then exits the scheduler
       
   192  */
       
   193 void CScriptMaster::RunL()
       
   194 	{
       
   195 	switch (iState)
       
   196 		{
       
   197 	case EInit	:
       
   198 		{
       
   199 		// Create the master CScriptControl instance. 
       
   200 		CScriptControl* scriptControl = new (ELeave) CScriptControl(*this,iScriptFilePath,Logger(),ConsoleLogger(),iStartLooping,iLoop,iDefaultSysDrive,iTestSysDrive,iSelTestingOptions);
       
   201 		iState = ERunning;
       
   202 		// Set our AO up ready for completion
       
   203 		Prime();
       
   204 		// Kick the CScriptControl state machine
       
   205 		scriptControl->Kick();
       
   206 		}
       
   207 		break;
       
   208 	case ERunning	:
       
   209 		{
       
   210 		// All child AO's have completed and been deleted so it's safe to exit.
       
   211 		CActiveScheduler::Stop();
       
   212 		}
       
   213 		break;
       
   214 	default:
       
   215 		break;
       
   216 		}
       
   217 	}
       
   218 
       
   219 /**
       
   220  * @param aCompletion - Callback into the parent object.
       
   221  * @param aScriptFilePath - The full path and filename of a script file
       
   222  * @param aLogger - Reference to a logger instance
       
   223  * @param aConsole - Reference to console object for printing script line during test execution
       
   224  * @param aStartLooping - Initiate the looping
       
   225  * @param aLoop - Check for nesting of loops
       
   226  * @param aSysDrive - Default System drive letter
       
   227  * @param aTestSysDrive - System drive letter overwritten from testexecute.ini
       
   228  * Constructor
       
   229  */
       
   230 CScriptControl::CScriptControl(MChildCompletion& aCompletion, const TDesC& aScriptFilePath, CTestExecuteLogger& aLogger, RConsoleLogger& aConsole, TBool aStartLooping, TBool aLoop, const TDriveName& aSysDrive, const TDriveName& aTestSysDrive, TSelectiveTestingOptions* aSelTestingOptions):
       
   231 	iScriptFile(aScriptFilePath),
       
   232 	iState(EInit),
       
   233 	iParent(aCompletion),
       
   234 	iConcurrent(EFalse),
       
   235 	iCanComplete(ETrue),
       
   236 	iBreakOnError(EFalse),
       
   237 	iAsyncTasksOutstanding(0),
       
   238 	iCurrentScriptLineNumber(0),
       
   239 	iLogger(aLogger),
       
   240 	iConsoleLogger(aConsole),
       
   241 	iScriptLinePrefixSet(EFalse),
       
   242 	iStartLooping(aStartLooping),
       
   243 	iLoop(aLoop),
       
   244 	iSharedDataNum(KTEFZeroValue),
       
   245 	iIsSharedData(EFalse),
       
   246 	iSyncControl(NULL),
       
   247 	iTestCaseID(KTEFTestCaseDefault),
       
   248 	iDefaultSysDrive(aSysDrive),
       
   249 	iTestSysDrive(aTestSysDrive),
       
   250 	iSelTestingOptions(aSelTestingOptions),
       
   251 	iSelectOne(EFalse),
       
   252 	iRangeRefCounter(0),
       
   253 	iTestCaseCounter(0)
       
   254 	{
       
   255 	}
       
   256 
       
   257 /**
       
   258  * Destructor
       
   259  */
       
   260 CScriptControl::~CScriptControl()
       
   261 	{
       
   262 	iTimer.Cancel();
       
   263 	iTimer.Close();
       
   264 	// We read the complete script into the heap for parsing so:
       
   265 	delete iScriptData;
       
   266 	for (TInt index = 0; index < iSharedDataNum; index++)
       
   267 		{
       
   268 		delete iSharedDataArray[index];
       
   269 		}
       
   270 	// Instance has an array of pointers to RTestServer objects.
       
   271 	// Loop through deleting and closing
       
   272 	TInt i = 0;
       
   273 	TInt count = iServers.Count();
       
   274 	for(i=0;i<count;i++)
       
   275 		{
       
   276 		iServers[0]->Close();
       
   277 		delete iServers[0];
       
   278 		iServers.Remove(0);
       
   279 		}
       
   280 	iServers.Close();
       
   281 	if( iSyncControl )
       
   282 		{
       
   283 		delete iSyncControl;
       
   284 		}
       
   285 	}
       
   286 
       
   287 /**
       
   288  * @param aError - Integer error value returned by the active object while leaving
       
   289  * @return TInt - System-wide error codes
       
   290  * Error Handler for active object
       
   291  */
       
   292 TInt CScriptControl::RunError(TInt aError)
       
   293 	{
       
   294 	if (aError == KErrNoMemory)
       
   295 		{
       
   296 		ERR_PRINTF1(_L("Insufficient memory available to perform further operation.\n\tPlease increase the maximum heap size from the testexecute.mmp and try running the test again. Exiting test script..."));
       
   297 		}
       
   298 	else
       
   299 		{
       
   300 		ERR_PRINTF2(_L("Test execution failed with error %d. Terminating tests.."), aError);
       
   301 		}
       
   302 	iParent.ChildCompletion(KErrNone);
       
   303 	delete this;
       
   304 	return KErrNone;
       
   305 	}
       
   306 
       
   307 /**
       
   308  * Implementation of pure virtual
       
   309  * The main script interpreter state machine.
       
   310  * Kick'd() into by CScriptMaster or, in the case of nested scripts, another CScriptControl
       
   311  * instance.
       
   312  * Picks up the completions from CClientControls and/or, in the case of nested scripts,
       
   313  * another CScriptControl instance.
       
   314  */
       
   315 void CScriptControl::RunL()
       
   316 	{
       
   317 	switch (iState)
       
   318 		{
       
   319 	case EInit		:
       
   320 		// First state after Kick() from parent
       
   321 		{
       
   322 		// Standard log output goes to flogger
       
   323 		// Result log goes to a propietary file in c:\logs\testexecute
       
   324 		User::LeaveIfError(iTimer.CreateLocal());
       
   325 		TRAPD(err,CreateScriptDataFromScriptFileL());
       
   326 		if(err)
       
   327 			{
       
   328 			// If we can't open the script file then log the fact and gracefully exit
       
   329 			// the state machine.
       
   330 			TBuf<KMaxTestExecuteCommandLength> buf(iScriptFile);
       
   331 			_LIT(KScriptFileError,"Failed Script File Open %S");
       
   332 			ERR_PRINTF2(KScriptFileError,&buf);
       
   333 			iState = EClosing;
       
   334 			//condition used for checking failure in testexecute.cpp
       
   335 			commentedCommandsCount=-1;
       
   336 			iRunScriptFailCount++;
       
   337 			Kick();
       
   338 			break;
       
   339 			}
       
   340 
       
   341 		// Script file reading state next
       
   342 		iState = ERunning;
       
   343 		// Kick ourselves into the next state
       
   344 		Kick();
       
   345 		}
       
   346 		break;
       
   347 
       
   348 	case ERunning	:
       
   349 		// Always in this state whilst we're reading lines from script file data member
       
   350 		{
       
   351 		TPtrC scriptLine;
       
   352 		if(!iStartLooping)
       
   353 			{
       
   354 			if(!GetNextScriptLine(scriptLine))
       
   355 				{
       
   356 				// End of the script file
       
   357 				// Check see if there are any async requests outstanding
       
   358 				// In concurrent mode there are very likely to be
       
   359 				if(iAsyncTasksOutstanding == 0)
       
   360 					{
       
   361 					// No requests outstanding so call into the parent
       
   362 					iParent.ChildCompletion(KErrNone);
       
   363 					delete this;
       
   364 					}
       
   365 				else
       
   366 					{
       
   367 					// Requests outstanding
       
   368 					// Next time we're completed we'll be in the closing state
       
   369 					iState = EClosing;
       
   370 					iCanComplete =ETrue;
       
   371 					// Prime ourselves for completion
       
   372 					Prime();
       
   373 					}
       
   374 				break;
       
   375 				}
       
   376 			}
       
   377 		//Get the script lines which are to be looped
       
   378 		else if(!GetLoopScriptLine(scriptLine))
       
   379 			{
       
   380 			// End of the script file
       
   381 			// Check see if there are any async requests outstanding
       
   382 			// In concurrent mode there are very likely to be
       
   383 			if(iAsyncTasksOutstanding == 0)
       
   384 				{
       
   385 				// No requests outstanding so call into the parent
       
   386 				iParent.ChildCompletion(KErrNone);
       
   387 				delete this;
       
   388 				}
       
   389 			else
       
   390 				{
       
   391 				// Requests outstanding
       
   392 				// Next time we're completed we'll be in the closing state
       
   393 				iState = EClosing;
       
   394 				iCanComplete =ETrue;
       
   395 				// Prime ourselves for completion
       
   396 				Prime();
       
   397 				}
       
   398 			break;
       
   399 			}
       
   400 
       
   401 		iCurrentScriptLine.Set(scriptLine);
       
   402 		
       
   403 		TBool commentedCommand = CheckCommentedCommands();
       
   404 		if(commentedCommand)
       
   405 			{
       
   406 			iCanComplete = EFalse;
       
   407 			Kick();
       
   408 			break;
       
   409 			}
       
   410 
       
   411 		if (iScriptLinePrefixSet )
       
   412 			{
       
   413 			TLex lookahead(iCurrentScriptLine);
       
   414 
       
   415 			TPtrC firstCommand(lookahead.NextToken());
       
   416 
       
   417 			if (firstCommand.CompareF(KTEFRemovePrefixCommand) != 0)
       
   418 				{
       
   419 				// If we aren't the Remove_Prefix command, prefix the current line...
       
   420 				iPrefixedCurrentScriptLine = iScriptLinePrefix;
       
   421 				iPrefixedCurrentScriptLine.Append(scriptLine);
       
   422 				iCurrentScriptLine.Set(iPrefixedCurrentScriptLine);
       
   423 				}
       
   424 			}
       
   425 
       
   426 		TRAPD(err, MakeAbsoluteFilePathsL(iCurrentScriptLine));
       
   427 		PrintCurrentScriptLine();
       
   428 		
       
   429 		TLex lex(iCurrentScriptLine);
       
   430 
       
   431 		TPtrC token(lex.NextToken());
       
   432 
       
   433 		if (err == KTEFErrInvalidRelPath)
       
   434 			{
       
   435 			_LIT(KTEFErrInvalidRelPathText,"Invalid relative path provided in the script file. Skipping the script line from execution..");
       
   436 			ERR_PRINTF1(KTEFErrInvalidRelPathText);
       
   437 
       
   438 			if (token.CompareF(KTEFRunTestStepCommand) == 0 ||
       
   439 				token.CompareF(KTEFRunPanicStepCommand) == 0 ||
       
   440 				token.CompareF(KTEFRunTestStepResultCommand) == 0 ||
       
   441 				token.CompareF(KTEFRunPanicStepResultCommand) == 0)
       
   442 				{
       
   443 				TExitCategoryName  blankPanicString; //Not a Panic
       
   444 				LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine);
       
   445 				}
       
   446 			iCanComplete = EFalse;
       
   447 			Kick();
       
   448 			break;
       
   449 			}
       
   450 
       
   451 		if(err == KErrTooBig)
       
   452 			{
       
   453 			_LIT(KTEFErrTooBigArguments, "One or more arguments for the command exceeded allowed limit for length. Skipping test..");
       
   454 			ERR_PRINTF1(KTEFErrTooBigArguments);
       
   455 
       
   456 			if (token.CompareF(KTEFRunTestStepCommand) == 0 ||
       
   457 				token.CompareF(KTEFRunPanicStepCommand) == 0 ||
       
   458 				token.CompareF(KTEFRunTestStepResultCommand) == 0 ||
       
   459 				token.CompareF(KTEFRunPanicStepResultCommand) == 0)
       
   460 				{
       
   461 				TExitCategoryName  blankPanicString; //Not a Panic
       
   462 				LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine);
       
   463 				}
       
   464 			iCanComplete = EFalse;
       
   465 			Kick();
       
   466 			break;
       
   467 			}
       
   468 
       
   469 		// Main parser
       
   470 		if(token.CompareF(KTEFLoadSuiteCommand) == 0 || token.CompareF(KTEFLoadServerCommand) == 0)
       
   471 			{
       
   472 			TRAPD(err,CreateServerFromScriptLineL());
       
   473 			
       
   474 			// Create a TLogField structure array
       
   475 			// Size of array equals to number of fields to be displayed for the command
       
   476 			TExtraLogField logField[2];
       
   477 
       
   478 			// The first member of the structure stores the field name
       
   479 			// The second one holds the value for the particular field
       
   480 			_LIT(KSuiteName, "SUITE_NAME");
       
   481 			logField[0].iLogFieldName.Copy(KSuiteName);
       
   482 			logField[0].iLogFieldValue.Copy(lex.NextToken());
       
   483 			
       
   484 			logField[1].iLogFieldName.Copy(KTEFResultString);
       
   485 			if(err != KErrNone)
       
   486 				{
       
   487 				logField[1].iLogFieldValue.Copy(KTEFResultFail);
       
   488 				if( KErrNotFound == err )
       
   489 					{
       
   490 					_LIT(KServerNotFound,"Failed to create server, either the server or one of its dependancies could not be found.");
       
   491 					ERR_PRINTF1(KServerNotFound);
       
   492 					}
       
   493 				else
       
   494 					{
       
   495 					_LIT(KServerCreateError,"Failed to Create Server Err = %d");
       
   496 					ERR_PRINTF2(KServerCreateError,err);
       
   497 					}
       
   498 				}
       
   499 			else
       
   500 				{
       
   501 				logField[1].iLogFieldValue.Copy(KTEFResultPass);
       
   502 				}
       
   503 			
       
   504 			// Call the Logger().LogToXml routine which handles XML logging for individual commands
       
   505 			// Takes in the command name, number of fields and the struture array
       
   506 			Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, token, 2, logField);
       
   507 			iCanComplete = EFalse;
       
   508 			Kick();
       
   509 			}
       
   510 		else if(token.CompareF(KTEFStartTestBlock)==0)
       
   511 			{
       
   512 			// Parse the START_TEST_BLOCK command line
       
   513 			TInt index = 0;
       
   514 			TBool taskCanComplete = ETrue;
       
   515 			TBool concurrent = iConcurrent;
       
   516 			// Make sure the server is loaded
       
   517 			if(!GetServerIndexFromScriptLine(index))
       
   518 				{
       
   519 				// Not loaded. Skip the line, but ensure its logged as a failure.
       
   520 				TExitCategoryName  blankPanicString; //Not a Panic
       
   521 				LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine);
       
   522 
       
   523 				iCanComplete = EFalse;
       
   524 				Kick();
       
   525 				break;
       
   526 				}
       
   527 			
       
   528 			TBuf<KMaxTestExecuteCommandLength>	startBlockLine = iCurrentScriptLine;
       
   529 			
       
   530 			// Parse the test block of commands
       
   531 			TTEFItemArray* itemArray = new (ELeave) TTEFItemArray(1);
       
   532 			CleanupStack::PushL( itemArray );
       
   533 			TRAPD( err, ParseTestBlockL(*itemArray) );
       
   534 			
       
   535 			if( KErrNone == err )
       
   536 				{
       
   537 				if(!iConcurrent)
       
   538 					{
       
   539 					// If we're not in concurrent mode then child objects can complete us
       
   540 					taskCanComplete = ETrue;
       
   541 					// Prime ready for completion
       
   542 					Prime();
       
   543 					}
       
   544 				else
       
   545 					{
       
   546 					// In concurrent mode children can't complete us as we kick() ourselves.
       
   547 					taskCanComplete = EFalse;
       
   548 					Kick();
       
   549 					}
       
   550 				// Create the test block controler object
       
   551 				TInt loopIndex = -1;
       
   552 				if (iLoop)
       
   553 					{
       
   554 					loopIndex = iLoopCounter + 1;
       
   555 					}
       
   556 				
       
   557 				CClientControl* blockController = CClientControl::NewL(	*iServers[index],
       
   558 																		startBlockLine,
       
   559 																		*this,
       
   560 																		iCurrentScriptLineNumber,
       
   561 																		Logger(),
       
   562 																		loopIndex,
       
   563 																		iTestCaseID,
       
   564 																		iCurrentScriptLine,
       
   565 																		iScriptFile,
       
   566 																		*itemArray,
       
   567 																		iDefaultSysDrive,
       
   568 																		iTestSysDrive);
       
   569 
       
   570 				blockController->SetTaskComplete(taskCanComplete);
       
   571 				iAsyncTasksOutstanding++;
       
   572 				// Kick() the test step  object into its state machine
       
   573 				blockController->Kick();
       
   574 				}
       
   575 			else
       
   576 				{
       
   577 				iCanComplete = EFalse;
       
   578 				Kick();				
       
   579 				}
       
   580 
       
   581 			iConcurrent = concurrent;
       
   582 			CleanupStack::PopAndDestroy( itemArray );
       
   583 			}
       
   584 		else if(token.CompareF(KTEFEndTestBlock)==0)
       
   585 			{
       
   586 			// If this is called then there is a missing START_TEST_BLOCK command
       
   587 			TExitCategoryName  blankPanicString;
       
   588 			LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine);
       
   589 			iCanComplete = EFalse;
       
   590 			Kick();
       
   591 			}
       
   592 		else if(token.CompareF(KTEFStartRepeat)==0)
       
   593 			{
       
   594 			TPtrC iniFile(lex.NextToken());
       
   595 			TPtrC iniSection(lex.NextToken());
       
   596 			TPtrC tempRepeatParam=lex.NextToken();
       
   597 			CIniData* configData = NULL;
       
   598 			TInt err = 0;
       
   599 			if(iniFile.Length())
       
   600 				{
       
   601 				TRAP(err,configData = CIniData::NewL(iniFile));
       
   602 				}
       
   603 			if(err != KErrNone)
       
   604 				{
       
   605 				_LIT(KTEFIniFileNotFound,"Ini file not found.. Looping Ignored");
       
   606 				ERR_PRINTF1(KTEFIniFileNotFound);
       
   607 				Kick();
       
   608 				break;
       
   609 				}
       
   610 			iRepeatParam=0;
       
   611 			CleanupStack::PushL(configData);
       
   612 			if(configData)
       
   613 				{
       
   614 				//For Syntax Error  continue ignoring looping
       
   615 				if (!configData->FindVar(iniSection, tempRepeatParam, iRepeatParam))
       
   616 					{
       
   617 					_LIT(KIniFailMessage,"The input data is not found in the ini specified");
       
   618 					INFO_PRINTF1(KIniFailMessage);
       
   619 					CleanupStack::PopAndDestroy(configData);
       
   620 					Kick();
       
   621 					break;
       
   622 					}
       
   623 				}
       
   624 				
       
   625 			CleanupStack::PopAndDestroy(configData);
       
   626 			TExtraLogField logField[1];
       
   627 			_LIT(KIterations,"ITERATIONS");
       
   628 			logField[0].iLogFieldName.Copy(KIterations);
       
   629 			logField[0].iLogFieldValue.Copy(KNull);
       
   630 			logField[0].iLogFieldValue.AppendNum(iRepeatParam);
       
   631 			Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, token, 1, logField);
       
   632 
       
   633 			if(tempRepeatParam.Compare(KNull)==0)
       
   634 				{
       
   635 				_LIT(KRepeatKeyNotFound,"Repeat Parameter Key Not Found");
       
   636 				INFO_PRINTF1(KRepeatKeyNotFound);
       
   637 				Kick();
       
   638 				break;
       
   639 				}
       
   640 			//Nesting of Control Logic is Not supported
       
   641 			if(iLoop)
       
   642 				{
       
   643 				_LIT(KNestingNotAllowed,"Nesting of START_REPEAT is not supported.. Looping Ignored");
       
   644 				WARN_PRINTF1(KNestingNotAllowed);
       
   645 				iLoop=EFalse;
       
   646 				Kick();
       
   647 				break;
       
   648 				}
       
   649 			//Looping is not to be started with Concurrent mode
       
   650 			if(iConcurrent)
       
   651 				{
       
   652 				_LIT(KConcurrentNotAllowed,"No concurrent Execution is Allowed in Looping");
       
   653 				INFO_PRINTF1(KConcurrentNotAllowed);
       
   654 				Kick();
       
   655 				break;
       
   656 				}
       
   657 				
       
   658 			iLoopCounter=0;
       
   659 			//For Invalid Parameter continue ignoring looping
       
   660 			if(iRepeatParam<1)
       
   661 				{
       
   662 				_LIT(KInvalidRepeatParam,"The repeat Parameter is invalid");
       
   663 				INFO_PRINTF1(KInvalidRepeatParam);
       
   664 				Kick();
       
   665 				break;
       
   666 				}
       
   667 			iLoop=ETrue;
       
   668 			iCheckVar=EFalse;
       
   669 			Kick();
       
   670 			}
       
   671 		else if(token.CompareF(KTEFEndRepeat)==0)
       
   672 			{
       
   673 			if(!iLoop)
       
   674 				{
       
   675 				_LIT(KLoopNotInitiated,"The Looping is Not Initiated");
       
   676 				INFO_PRINTF1(KLoopNotInitiated);
       
   677 				Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, token);
       
   678 				Kick();
       
   679 				break;
       
   680 				}
       
   681 				
       
   682 			iLoopCounter++;
       
   683 			if(iLoopCounter==iRepeatParam)
       
   684 				{
       
   685 				Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, token);
       
   686 				iStartLooping=EFalse;
       
   687 				iLoop=EFalse;
       
   688 				}
       
   689 			else
       
   690 				{
       
   691 				iStartLooping=ETrue;
       
   692 				//Looping needs to be started in CONSECUTIVE mode
       
   693 				if(iConcurrent)
       
   694 					{
       
   695 					iConcurrent=EFalse;
       
   696 					}
       
   697 				}
       
   698 			Kick();
       
   699 			}
       
   700 		else if(token.CompareF(KTEFRunTestStepCommand) == 0 ||
       
   701 				token.CompareF(KTEFRunPanicStepCommand) == 0 ||
       
   702 				token.CompareF(KTEFRunTestStepResultCommand) == 0 ||
       
   703 				token.CompareF(KTEFRunPanicStepResultCommand) == 0
       
   704 				)
       
   705 			{
       
   706 			if(!CheckValidScriptLine())
       
   707 				{
       
   708 				// Not a Valid Script Line
       
   709 
       
   710 				TExitCategoryName  blankPanicString; //Not a Panic
       
   711 				LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine);
       
   712 				// End of defect 037066
       
   713 
       
   714 				iCanComplete = EFalse;
       
   715 				Kick();
       
   716 				break;
       
   717 				}
       
   718 			
       
   719 			TInt index;
       
   720 			TBool taskCanComplete = ETrue;
       
   721 			TBool concurrent = iConcurrent;
       
   722 			// Make sure the server is loaded
       
   723 			if(!GetServerIndexFromScriptLine(index))
       
   724 				{
       
   725 				// Not loaded. Skip the line, but ensure its logged as a failure.
       
   726 
       
   727 				// Start of defect 037066
       
   728 				TExitCategoryName  blankPanicString; //Not a Panic
       
   729 				LogResult(EIgnore, blankPanicString, iCurrentScriptLineNumber, iCurrentScriptLine);
       
   730 				// End of defect 037066
       
   731 
       
   732 				iCanComplete = EFalse;
       
   733 				Kick();
       
   734 				break;
       
   735 				}
       
   736 
       
   737 			if(!iConcurrent)
       
   738 				{
       
   739 				// If we're not in concurrent mode then child objects can complete us
       
   740 				taskCanComplete = ETrue;
       
   741 				// Prime ready for completion
       
   742 				Prime();
       
   743 				}
       
   744 			else
       
   745 				{
       
   746 				// In concurrent mode children can't complete us as we kick() ourselves.
       
   747 				taskCanComplete = EFalse;
       
   748 				Kick();
       
   749 				}
       
   750 			iConcurrent = concurrent;
       
   751 			// Create the test step controler object
       
   752 			TInt loopIndex = -1;
       
   753 			if (iLoop)
       
   754 				{
       
   755 				loopIndex = iLoopCounter + 1;
       
   756 				}
       
   757 			CClientControl* stepController = new (ELeave) CClientControl(*iServers[index],iCurrentScriptLine,*this,iCurrentScriptLineNumber,Logger(), loopIndex, iTestCaseID, iScriptFile, iDefaultSysDrive, iTestSysDrive);
       
   758 			stepController->SetTaskComplete(taskCanComplete);
       
   759 			iAsyncTasksOutstanding++;
       
   760 			// Kick() the test step  object into its state machine
       
   761 			stepController->Kick();
       
   762 			}
       
   763 		else if(token.CompareF(KTEFRunProgramCommand) == 0)
       
   764 			{
       
   765 			TBool taskCanComplete = ETrue;
       
   766 			if(!iConcurrent)
       
   767 				{
       
   768 				// If we're not in concurrent mode then child objects can complete us
       
   769 				taskCanComplete = ETrue;
       
   770 				// Prime ready for completion
       
   771 				Prime();
       
   772 				}
       
   773 			else
       
   774 				{
       
   775 				// In concurrent mode children can't complete us as we kick() ourselves.
       
   776 				taskCanComplete = EFalse;
       
   777 				Kick();
       
   778 				}
       
   779 			// Create the test step controller object
       
   780 			CProgramControl* programController = new (ELeave) CProgramControl(iCurrentScriptLine,*this,iCurrentScriptLineNumber,Logger());
       
   781 			programController->SetTaskComplete(taskCanComplete);
       
   782 			iAsyncTasksOutstanding++;
       
   783 			// Kick() the test step  object into its state machine
       
   784 			programController->Kick();
       
   785 			}
       
   786 		else if(token.CompareF(KTEFRunWSProgramCommand) == 0)
       
   787 			{
       
   788 			TBool taskCanComplete = ETrue;
       
   789 			if(!iConcurrent)
       
   790 				{
       
   791 				// If we're not in concurrent mode then child objects can complete us
       
   792 				taskCanComplete = ETrue;
       
   793 				// Prime ready for completion
       
   794 				Prime();
       
   795 				}
       
   796 			else
       
   797 				{
       
   798 				// In concurrent mode children can't complete us as we kick() ourselves.
       
   799 				taskCanComplete = EFalse;
       
   800 				Kick();
       
   801 				}
       
   802 			// Create the test step controller object
       
   803 			CProgramControl* programController = new (ELeave) CProgramControl(iCurrentScriptLine,*this,iCurrentScriptLineNumber,Logger(),ETrue);
       
   804 			iAsyncTasksOutstanding++;
       
   805 			programController->SetTaskComplete(taskCanComplete);
       
   806 			// Kick() the test step  object into its state machine
       
   807 			programController->Kick();
       
   808 			}
       
   809 		else if(token.CompareF(KTEFConcurrentCommand) == 0)
       
   810 			{
       
   811 			// Go into concurrent mode
       
   812 			// Whilst we're in concurrent mode we always kick() ourselves
       
   813 			// around the state engine
       
   814 				iConcurrent = ETrue;
       
   815 			// Call the Logger()'s LogToXml routine to handle XML logging
       
   816 			// Takes in just the command name without any field
       
   817 			Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFConcurrentCommand);
       
   818 			iCanComplete = EFalse;
       
   819 			Kick();
       
   820 			}
       
   821 		else if(token.CompareF(KTEFConsecutiveCommand) == 0)
       
   822 			{
       
   823 			// If we go into consecutive mode we have to make sure there are no
       
   824 			// requests outstanding.Set the state accordingly
       
   825 			iConcurrent = EFalse;
       
   826 
       
   827 			// Call the Logger()'s LogToXml routine to handle XML logging
       
   828 			// Takes in just the command name without any field
       
   829 			Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFConsecutiveCommand);
       
   830 			if(iAsyncTasksOutstanding)
       
   831 				{
       
   832 				iCanComplete = ETrue;
       
   833 				iState = EWaitCompletions;
       
   834 				Prime();
       
   835 				}
       
   836 			else
       
   837 				{
       
   838 				iCanComplete = EFalse;
       
   839 				iState = ERunning;
       
   840 				Kick();
       
   841 				}
       
   842 			}
       
   843 		else if(token.CompareF(KTEFRunUtilsCommand) == 0)
       
   844 			{
       
   845 			// All utils complete synchronously
       
   846 			TRAPD(err,RunUtilsFromScriptLineL());
       
   847 			
       
   848 			// Create a TLogField structure array
       
   849 			// Size of array equals to number of fields to be displayed for the command
       
   850 			TExtraLogField logField[2];
       
   851 
       
   852 			// The first member of the structure stores the field name
       
   853 			// The second one holds the value for the particular field
       
   854 			_LIT(KCommand,"COMMAND");
       
   855 			logField[0].iLogFieldName.Copy(KCommand);
       
   856 			logField[0].iLogFieldValue.Copy(lex.NextToken());
       
   857 			
       
   858 			logField[1].iLogFieldName.Copy(KTEFResultString);
       
   859 			if (err == KErrNone)
       
   860 				{
       
   861 				logField[1].iLogFieldValue.Copy(KTEFResultPass);
       
   862 				}
       
   863 			else
       
   864 				{
       
   865 				logField[1].iLogFieldValue.Copy(KTEFResultFail);
       
   866 				}
       
   867 
       
   868 			// Call the Logger().LogToXml routine which handles XML logging for individual commands
       
   869 			// Takes in the command name, number of fields and the struture array
       
   870 			Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFRunUtilsCommand, 2, logField);
       
   871 			
       
   872 			if(err != KErrNone)
       
   873 				{
       
   874 				_LIT(KRunUtilsError,"RUN_UTILS ret = %d");
       
   875 				INFO_PRINTF2(KRunUtilsError,err);
       
   876 				}
       
   877 			iCanComplete = EFalse;
       
   878 			Kick();
       
   879 			}
       
   880 		else if(token.CompareF(KTEFPrintCommand) == 0)
       
   881 			{
       
   882 			PrintFromScriptLine();
       
   883 			iCanComplete = EFalse;
       
   884 			Kick();
       
   885 			}
       
   886 		else if (token.CompareF(KTEFPrefixCommand) == 0)
       
   887 			{
       
   888 
       
   889 			if(iAsyncTasksOutstanding)
       
   890 				// Don't run Prefix until all outstanding requests have completed
       
   891 				{
       
   892 				iState = EPrefixPending;
       
   893 				iCanComplete = ETrue;
       
   894 				Prime();
       
   895 				}
       
   896 			else
       
   897 				{
       
   898 				// Ok to run PREFIX - Kick the stated machine so it's run next time in the RunL()
       
   899 				iState = ERunPrefix;
       
   900 				iCanComplete = EFalse;
       
   901 				Kick();
       
   902 				}
       
   903 
       
   904 			}
       
   905 		else if (token.CompareF(KTEFRemovePrefixCommand) == 0)
       
   906 			{
       
   907 			iScriptLinePrefixSet = EFalse;
       
   908 			iCanComplete = EFalse;
       
   909 			Kick();
       
   910 			}
       
   911 		else if (token.CompareF(KTEFStartTestCaseCommand) == 0) 
       
   912 			{
       
   913 			if(ProceedTestCase())
       
   914 				{	
       
   915 				LogTestCaseMarkerL();
       
   916 				iCanComplete = EFalse;
       
   917 				Kick();	
       
   918 				}
       
   919 			else
       
   920 				{
       
   921 				iState = ETestCaseIgnore;
       
   922 				iCanComplete = EFalse;
       
   923 				Kick();	
       
   924 				}
       
   925 			}
       
   926 		else if (token.CompareF(KTEFEndTestCaseCommand) == 0)
       
   927 			{
       
   928 			ProcessEndCase();
       
   929 			if(iAsyncTasksOutstanding)
       
   930 				// Don't run END_TESTCASE until all outstanding requests have completed
       
   931 				{
       
   932 				iState = EEndTestCasePending;
       
   933 				iCanComplete = ETrue;
       
   934 				Prime();
       
   935 				}
       
   936 			else
       
   937 				{
       
   938 				// Ok to run END_TESTCASE - Kick the stated machine so it's run next time in the RunL()
       
   939 				iState = ERunEndTestCase;
       
   940 				iCanComplete = EFalse;
       
   941 				Kick();
       
   942 				}
       
   943 			}
       
   944 		else if (token.CompareF(KTEFStartSyncTestCaseCommand) == 0) 
       
   945 			{
       
   946 			if(ProceedTestCase())
       
   947 				{
       
   948 				// Start Synchronised Test Case
       
   949 				// Check to see if the Sync Data has been created
       
   950 				// If not then create it
       
   951 				if( iSyncControl == NULL )
       
   952 					{
       
   953 					iSyncControl = CSyncControl::NewL();
       
   954 					}
       
   955 				LogTestCaseMarkerL();
       
   956 				iState = ERunStartSyncTestCase;
       
   957 				iCanComplete = EFalse;
       
   958 				Kick();	
       
   959 				}
       
   960 			else
       
   961 				{
       
   962 				//go into some sleep state until you 
       
   963 				//encounter an end test case for this...
       
   964 				iState = ETestCaseIgnore;
       
   965 				iCanComplete = EFalse;
       
   966 				Kick();	
       
   967 				}
       
   968 			}
       
   969 		else if (token.CompareF(KTEFEndSyncTestCaseCommand) == 0)
       
   970 			{
       
   971 			ProcessEndCase();
       
   972 			// End Synchronised Test Case
       
   973 			if(iAsyncTasksOutstanding)
       
   974 				// Don't run END_SYNCHRONISED_TESTCASE until all outstanding requests have completed
       
   975 				{
       
   976 				iState = EEndTestCasePending;
       
   977 				iCanComplete = ETrue;
       
   978 				Prime();
       
   979 				}
       
   980 			else
       
   981 				{
       
   982 				// Ok to run END_SYNCHRONISED_TESTCASE - Kick the stated machine so it's run next time in the RunL()
       
   983 				iState = ERunEndTestCase;
       
   984 				iCanComplete = EFalse;
       
   985 				Kick();
       
   986 				}
       
   987 			}
       
   988 		else if(token.CompareF(KTEFRunScriptCommand) == 0)
       
   989 			{
       
   990 			// Create a TLogField structure array
       
   991 			// Size of array equals to number of fields to be displayed for the command
       
   992 			TExtraLogField logField[1];
       
   993 
       
   994 			// The first member of the structure stores the field name
       
   995 			// The second one holds the value for the particular field
       
   996 			_LIT(KScriptName,"SCRIPT_NAME");
       
   997 			logField[0].iLogFieldName.Copy(KScriptName);
       
   998 			logField[0].iLogFieldValue.Copy(lex.NextToken());
       
   999 			
       
  1000 			// Call the Logger().LogToXml routine which handles XML logging for individual commands
       
  1001 			// Takes in the command name, number of fields and the struture array
       
  1002 			Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrHigh, KTEFRunScriptCommand, 1, logField);
       
  1003 			if(iAsyncTasksOutstanding)
       
  1004 				{
       
  1005 				// Don't recursively process a new script until this one's async
       
  1006 				// requests are completed
       
  1007 				iState = ERunScriptPending;
       
  1008 				iCanComplete = ETrue;
       
  1009 				Prime();
       
  1010 				}
       
  1011 			else
       
  1012 				{
       
  1013 				// Ok to process the script recursively
       
  1014 				iState = ERunScript;
       
  1015 				iCanComplete = EFalse;
       
  1016 				Kick();
       
  1017 				}
       
  1018 			}
       
  1019 		else if(token.CompareF(KTEFCedCommand) == 0)
       
  1020 			// Run the CED comms database editor
       
  1021 			{
       
  1022 			if(iAsyncTasksOutstanding)
       
  1023 				// Don't run CED until all outstanding requests have completed
       
  1024 				{
       
  1025 				iState = ERunCedPending;
       
  1026 				iCanComplete = ETrue;
       
  1027 				Prime();
       
  1028 				}
       
  1029 			else
       
  1030 				{
       
  1031 				// Ok to run CED - Kick the stated machine so it's run next time in the RunL()
       
  1032 				iState = ERunCed;
       
  1033 				iCanComplete = EFalse;
       
  1034 				Kick();
       
  1035 				}
       
  1036 			}
       
  1037 		else if(token.CompareF(KTEFDelayCommand) == 0)
       
  1038 			// Delay n milliseconds
       
  1039 			{
       
  1040 			if(iAsyncTasksOutstanding)
       
  1041 				// Don't delay until all outstanding requests have completed
       
  1042 				{
       
  1043 				iState = EDelayPending;
       
  1044 				iCanComplete = ETrue;
       
  1045 				Prime();
       
  1046 				}
       
  1047 			else
       
  1048 				{
       
  1049 				// Ok to delay
       
  1050 				iState = EDelay;
       
  1051 				iCanComplete = EFalse;
       
  1052 				Kick();
       
  1053 				}
       
  1054 			}
       
  1055 		// Script can exit on error
       
  1056 		// Flag is checked on async task completion
       
  1057 		else if(token.CompareF(KTEFBreakErrorOnCommand) == 0)
       
  1058 			{
       
  1059 			// Set the flag and process next line
       
  1060 			iCanComplete = EFalse;
       
  1061 			iBreakOnError = ETrue;
       
  1062 
       
  1063 			// Call the Logger()'s LogToXml routine to handle XML logging
       
  1064 			// Takes in just the command name without any field
       
  1065 			Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFBreakErrorOnCommand);
       
  1066 			Kick();
       
  1067 			}
       
  1068 		else if(token.CompareF(KTEFBreakErrorOffCommand) == 0)
       
  1069 			{
       
  1070 			// Reset the flag and process next line
       
  1071 			iCanComplete = EFalse;
       
  1072 			iBreakOnError = EFalse;
       
  1073 
       
  1074 			// Call the Logger()'s LogToXml routine to handle XML logging
       
  1075 			// Takes in just the command name without any field
       
  1076 			Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrMedium, KTEFBreakErrorOffCommand);
       
  1077 			Kick();
       
  1078 			}
       
  1079 		// We only implement the pause command if JustInTime debugging is switched on
       
  1080 		else if(token.CompareF(KTEFPauseCommand) == 0 && User::JustInTime())
       
  1081 			{
       
  1082 			// Create a TLogField structure array
       
  1083 			// Size of array equals to number of fields to be displayed for the command
       
  1084 			TExtraLogField logField[1];
       
  1085 
       
  1086 			// The first member of the structure stores the field name
       
  1087 			// The second one holds the value for the particular field
       
  1088 			_LIT(KDelay,"DELAY");
       
  1089 			logField[0].iLogFieldName.Copy(KDelay);
       
  1090 			logField[0].iLogFieldValue.Copy(lex.NextToken());
       
  1091 
       
  1092 			// Call the Logger().LogToXml routine which handles XML logging for individual commands
       
  1093 			// Takes in the command name, number of fields and the struture array
       
  1094 			Logger().LogToXml(((TText8*)__FILE__), __LINE__, RFileFlogger::ESevrLow, KTEFPauseCommand, 1, logField);
       
  1095 
       
  1096 			if(iAsyncTasksOutstanding)
       
  1097 				// Don't pause until all outstanding requests have completed
       
  1098 				{
       
  1099 				iState = EPausePending;
       
  1100 				iCanComplete = ETrue;
       
  1101 				Prime();
       
  1102 				}
       
  1103 			else
       
  1104 				{
       
  1105 				// Ok to Pause
       
  1106 				iState = EPause;
       
  1107 				iCanComplete = EFalse;
       
  1108 				Kick();
       
  1109 				}
       
  1110 			}
       
  1111 		// Handles the shared comand and also creates the shared object
       
  1112 		// on reading user inputs from ini file
       
  1113 		else if(token.CompareF(KTEFSharedDataCommand) == 0)
       
  1114 			{
       
  1115 			if (iIsSharedData)
       
  1116 				{
       
  1117 				WARN_PRINTF1(KTEFSharedDataCommandRepeated);
       
  1118 				}
       
  1119 			else
       
  1120 				{
       
  1121 				TRAPD(err,CreateSharedObjectsFromScriptLineL());
       
  1122 				if (err != KErrNone)
       
  1123 					{
       
  1124 					ERR_PRINTF1(KTEFErrInCreatingSharedObjects);
       
  1125 					}
       
  1126 				}
       
  1127 			iCanComplete = EFalse;
       
  1128 			Kick();
       
  1129 			}
       
  1130 		else
       
  1131 			{
       
  1132 			// Command not implemented or a comment line
       
  1133 			// Code implemented for defect 047340
       
  1134 			TBuf<KMaxTestExecuteCommandLength> bufWarning;
       
  1135 			if(token.Length())
       
  1136 				{
       
  1137 				TInt firstChar = iCurrentScriptLine[0];
       
  1138 				if(firstChar != '\r' && firstChar != '\n' && firstChar != '#' && firstChar != '/' && token.CompareF(KTEFPauseCommand) != 0)
       
  1139 					{
       
  1140 					_LIT(KUnrecognised,"Unrecognised Command - %S");
       
  1141 					if(token.Length() < bufWarning.MaxLength())
       
  1142 						{
       
  1143 						bufWarning.Copy(token);
       
  1144 						WARN_PRINTF2(KUnrecognised,&bufWarning);
       
  1145 						}
       
  1146 					else
       
  1147 						{
       
  1148 						_LIT(KLineTooLong,"Command line too long");
       
  1149 						bufWarning.Copy(KLineTooLong);
       
  1150 						WARN_PRINTF2(KUnrecognised,&bufWarning);
       
  1151 						}
       
  1152 					}
       
  1153 				}
       
  1154 			iCanComplete = EFalse;
       
  1155 			Kick();
       
  1156 			}
       
  1157 		}
       
  1158 		break;
       
  1159 
       
  1160 	case EClosing :
       
  1161 		// Script has been processed
       
  1162 		// Pick up the completions
       
  1163 		{
       
  1164 		if(iAsyncTasksOutstanding == 0)
       
  1165 			{
       
  1166 			// Script finished
       
  1167 			// Call into the parent
       
  1168 			iParent.ChildCompletion(KErrNone);
       
  1169 			delete this;
       
  1170 			}
       
  1171 		else
       
  1172 			{
       
  1173 			// More requests to complete
       
  1174 			iCanComplete = ETrue;
       
  1175 			Prime();
       
  1176 			}
       
  1177 		}
       
  1178 		break;
       
  1179 
       
  1180 	case ERunScriptPending :
       
  1181 	case EWaitCompletions :
       
  1182 	case ERunCedPending :
       
  1183 	case EDelayPending :
       
  1184 	case EPausePending :
       
  1185 	case EEndTestCasePending :
       
  1186 	case EPrefixPending:
       
  1187 		// We go into this state if we're waiting for RUN_TEST_STEP's
       
  1188 		// to complete before we execute another command
       
  1189 		{
       
  1190 		if(iAsyncTasksOutstanding == 0)
       
  1191 			{
       
  1192 			// All steps complete
       
  1193 			// Set up the next state and kick() the state machine
       
  1194 			if(iState == ERunScriptPending)
       
  1195 				iState = ERunScript;
       
  1196 			else if(iState == EWaitCompletions)
       
  1197 				iState = ERunning;
       
  1198 			else if(iState == ERunCedPending)
       
  1199 				iState = ERunCed;
       
  1200 			else if(iState == EDelayPending)
       
  1201 				iState = EDelay;
       
  1202 			else if(iState == EPausePending)
       
  1203 				iState = EPause;
       
  1204 			else if(iState == EEndTestCasePending)
       
  1205 				iState = ERunEndTestCase;
       
  1206 			else if(iState == EPrefixPending)
       
  1207 				iState = ERunPrefix;
       
  1208 			// Safe to Kick() the state machine again
       
  1209 			iCanComplete = EFalse;
       
  1210 			Kick();
       
  1211 			}
       
  1212 		else
       
  1213 			{
       
  1214 			// More requests outstanding
       
  1215 			iCanComplete = ETrue;
       
  1216 			Prime();
       
  1217 			}
       
  1218 		}
       
  1219 		break;
       
  1220 
       
  1221 	case ERunScript :
       
  1222 		// Recursively instantiate the CScriptControl class
       
  1223 		{
       
  1224 		GetScriptFileFromScriptLine();
       
  1225 		CScriptControl* scriptControl = new (ELeave) CScriptControl(*this,iChildScriptFile,Logger(),ConsoleLogger(),iStartLooping,iLoop,iDefaultSysDrive,iTestSysDrive,iSelTestingOptions);
       
  1226 		// Kick the nested CScriptControl state machine
       
  1227 		scriptControl->Kick();
       
  1228 		// Put our instance in the idling state, Prime()'d ready for clild-parent
       
  1229 		// completion by the nested one.
       
  1230 		iState = EIdling;
       
  1231 		iCanComplete = ETrue;
       
  1232 		Prime();
       
  1233 		}
       
  1234 		break;
       
  1235 
       
  1236 	case ERunCed :
       
  1237 		// Slightly tricky one
       
  1238 		// WIN32 & Non-secure means we execute CED synchronously
       
  1239 		{
       
  1240 		SetActive();
       
  1241 		TRAPD(err,RunCedFromScriptLineL());
       
  1242 		if(!err)
       
  1243 			// Expect completion asynchronously
       
  1244 			// We're set for completion so just set the state
       
  1245 			iState = EIdling;
       
  1246 		else
       
  1247 			{
       
  1248 			_LIT(KCedError,"CED Error = %d");
       
  1249 			ERR_PRINTF2(KCedError,err);
       
  1250 			// A CED error so kick the state machine
       
  1251 			iState = ERunning;
       
  1252 			Kick();
       
  1253 			}
       
  1254 		}
       
  1255 		break;
       
  1256 	
       
  1257 	case EDelay :
       
  1258 		{
       
  1259 		// Kick the timer and wait for completion
       
  1260 		SetActive();
       
  1261 		StartTimerFromScriptLine();
       
  1262 		iState = EIdling;
       
  1263 		}
       
  1264 		break;
       
  1265 
       
  1266 	case ERunEndTestCase :
       
  1267 		{
       
  1268 			LogTestCaseMarkerL();
       
  1269 			iState = ERunning;
       
  1270 			iCanComplete = EFalse;
       
  1271 			Kick();
       
  1272 		}
       
  1273 		break;
       
  1274 
       
  1275 	case ERunStartSyncTestCase :
       
  1276 		{
       
  1277 			// Check to see if the test case is ready to continue
       
  1278 			SetActive();
       
  1279 			iTimer.After( iStatus, KTEFStatusDelay*1000 );
       
  1280 			TBool syncContinue = iSyncControl->TestCaseContinueL();
       
  1281 			if( syncContinue )
       
  1282 				{
       
  1283 				iState = EIdling;
       
  1284 				}
       
  1285 		}
       
  1286 		break;
       
  1287 	case ERunPrefix :
       
  1288 		{
       
  1289 			SetPrefix();
       
  1290 			iState = ERunning;
       
  1291 			iCanComplete = EFalse;
       
  1292 			Kick();
       
  1293 		}
       
  1294 		break;
       
  1295 		
       
  1296 	case EIdling :
       
  1297 		{
       
  1298 		// Woken up due to either:
       
  1299 		// A child CScriptControl instance completing OR
       
  1300 		// the delay timer has completed.
       
  1301 		iState = ERunning;
       
  1302 		iCanComplete = EFalse;
       
  1303 		Kick();
       
  1304 		}
       
  1305 		break;
       
  1306 
       
  1307 	case EPause :
       
  1308 		{
       
  1309 		_LIT(KPaused,"PAUSED - Hit Any Key to Continue\n");
       
  1310 		ConsoleLogger().Console().Printf(KPaused);
       
  1311 		ConsoleLogger().Console().Getch();
       
  1312 		iState = ERunning;
       
  1313 		iCanComplete = EFalse;
       
  1314 		Kick();
       
  1315 		}
       
  1316 		//Start of defect 115942 
       
  1317 		break;
       
  1318 		//End of defect 115942
       
  1319 
       
  1320 	case ETestCaseIgnore:
       
  1321 		{
       
  1322 		TPtrC scriptLine;
       
  1323 		//do we want to while till we come to end of test case?
       
  1324 		while(GetNextScriptLine(scriptLine))
       
  1325 			{
       
  1326 			TLex lex(scriptLine);
       
  1327 			TPtrC token(lex.NextToken());
       
  1328 			if((token.CompareF(KTEFEndTestCaseCommand) == 0)
       
  1329 					|| (token.CompareF(KTEFEndSyncTestCaseCommand) == 0)) //we found an end test case one
       
  1330 				{
       
  1331 				TPtrC testCID(lex.NextToken());
       
  1332 				//to support nested test cases
       
  1333 				if(iTestCaseIDToIgnore.CompareF(testCID) == 0)
       
  1334 				{
       
  1335 					//in any case...go back to running and re-evaluate our position at
       
  1336 					iState = ERunning;
       
  1337 					iTestCaseIDToIgnore.Set(KTEFNull);
       
  1338 					iCanComplete = EFalse;
       
  1339 					iCurrentScriptLine.Set(scriptLine);
       
  1340 					//before going back to running re-evaluate the 
       
  1341 					//state of selective testing
       
  1342 					ProcessEndCase() ; 
       
  1343 					Kick();
       
  1344 					break;
       
  1345 				}
       
  1346 				}
       
  1347 			}
       
  1348 		break;
       
  1349 		}
       
  1350 
       
  1351 	default:
       
  1352 		break;
       
  1353 		}
       
  1354 	}
       
  1355 
       
  1356 /**
       
  1357  * Implement the PRINT command
       
  1358  * Print the string(s) following the PRINT command to the log file
       
  1359  */
       
  1360 void CScriptControl::PrintFromScriptLine() const
       
  1361 	{
       
  1362 	TLex lex(iCurrentScriptLine);
       
  1363 	lex.NextToken();
       
  1364 	TBuf<KMaxTestExecuteCommandLength> buf;
       
  1365 	buf.Copy(lex.Remainder());
       
  1366 
       
  1367 	_LIT(KCommentString, " //");
       
  1368 
       
  1369 	TInt offset = buf.Find(KCommentString);
       
  1370 	if (offset != KErrNotFound)
       
  1371 		{
       
  1372 		buf.SetLength(offset);
       
  1373 		}
       
  1374 
       
  1375 	_LIT(KS,"%S");
       
  1376 	INFO_PRINTF2(KS,&buf);
       
  1377 	}
       
  1378 
       
  1379 /**
       
  1380  * Implement the PREFIX command
       
  1381  * Stores the prefix for command line prefixing
       
  1382  */
       
  1383 void CScriptControl::SetPrefix() 
       
  1384 	{
       
  1385 	TLex lex(iCurrentScriptLine);
       
  1386 	// Bypass the PREFIX command
       
  1387 	lex.NextToken();
       
  1388 
       
  1389 	// Get rid of any leading spaces
       
  1390 	while(!lex.Eos())
       
  1391 		{
       
  1392 		TChar peek = lex.Peek();
       
  1393 		if(peek == ' ')
       
  1394 			{
       
  1395 			lex.Inc();
       
  1396 			}
       
  1397 		else
       
  1398 			break;
       
  1399 		}
       
  1400 
       
  1401 	// Chop off the carriage return and insert a space
       
  1402 	// If there  is a preceding comment line, get rid of that.
       
  1403 
       
  1404 	iScriptLinePrefix.Copy(lex.Remainder());
       
  1405 
       
  1406 	_LIT(KCarriageReturn, "\r\n");
       
  1407 	_LIT(KCommentString, " //");
       
  1408 
       
  1409 	TInt offset = iScriptLinePrefix.Find(KCommentString);
       
  1410 	if (offset != KErrNotFound)
       
  1411 		{
       
  1412 		iScriptLinePrefix.SetLength(offset);
       
  1413 		}
       
  1414 	else
       
  1415 		{
       
  1416 		offset = iScriptLinePrefix.Find(KCarriageReturn);
       
  1417 
       
  1418 		if (offset != KErrNotFound)
       
  1419 			{
       
  1420 			iScriptLinePrefix.SetLength(offset);
       
  1421 			}
       
  1422 		}
       
  1423 
       
  1424 	_LIT(KTEFSpace, " ");
       
  1425 	iScriptLinePrefix.Append(KTEFSpace);
       
  1426 
       
  1427 	iScriptLinePrefixSet = ETrue;
       
  1428 		
       
  1429 	}
       
  1430 
       
  1431 /**
       
  1432  * Function to evaluate the situation of selective testing 
       
  1433  * Returns whether the testcase on the current script line 
       
  1434  * should be run.
       
  1435  */
       
  1436 TBool CScriptControl::ProceedTestCase() 
       
  1437 	{ 
       
  1438 	
       
  1439 	//if selective testing is not on, dont bother
       
  1440 	if(iSelTestingOptions == NULL)
       
  1441 		return ETrue;
       
  1442 	iTestCaseCounter++;
       
  1443 	if(iTestCaseCounter > 1) //if this is nested, let it run unconditionally
       
  1444 		return ETrue;
       
  1445 	// the remaining continues only if selective testing is on
       
  1446 	// AND we have a non-null, and hopefully valid instance of
       
  1447 	// iSelTestingOptions
       
  1448 	TLex lex(iCurrentScriptLine);
       
  1449 	TPtrC token(lex.NextToken());
       
  1450 	TPtrC testCaseID(lex.NextToken());
       
  1451 	//evaluating class state variables...
       
  1452 	//check range
       
  1453 	TIdentityRelation<TPtrC> crackID(TSelectiveTestingOptions::CompareTPtrC);
       
  1454 	TIdentityRelation<TRange> rangeComprtr(TRange::CompareTRangeStartCase);
       
  1455 	TRange dummy(testCaseID,testCaseID);
       
  1456 	for ( TInt index=0; index<iSelTestingOptions->iSelectiveCaseRange.Count(); ++index )
       
  1457 		{
       
  1458 		if ( testCaseID.CompareF(iSelTestingOptions->iSelectiveCaseRange[index].iStartTestCase) == 0 )
       
  1459 			{
       
  1460 			iSelTestingOptions->iSelectiveCaseRange[index].iState=TRange::EStateInUse;
       
  1461 			++iRangeRefCounter;//number of ranges now in operation	
       
  1462 			}
       
  1463 		}
       
  1464 	
       
  1465 	
       
  1466 	TBool runCase = ETrue ; //run everything by def
       
  1467 	if( iSelTestingOptions->iSelectiveTestingType == iInclusive )
       
  1468 		{
       
  1469 		//so selective testing is on and also its inclusive...
       
  1470 		runCase = (iRangeRefCounter>0) || iSelectOne ; 
       
  1471 		}
       
  1472 	else if(iSelTestingOptions->iSelectiveTestingType == iExclusive)
       
  1473 		{
       
  1474 		//so selective testing is on and also its exclusive...
       
  1475 		runCase = (iRangeRefCounter<=0) && !iSelectOne ; 
       
  1476 		}
       
  1477 	if(!runCase)//if the test case is to be selectively skipped, log it...
       
  1478 		{
       
  1479 		//use this one to log unexecuted cases...
       
  1480 		Logger().LogTestCaseResult(iScriptFile, iCurrentScriptLineNumber, RFileFlogger::ESevrInfo, token, testCaseID,ESkippedSelectively);
       
  1481 		}
       
  1482 	if(runCase == EFalse)
       
  1483 		{
       
  1484 			iTestCaseIDToIgnore.Set(testCaseID) ; 
       
  1485 		}
       
  1486 		
       
  1487 	return runCase ; 	
       
  1488 	}
       
  1489 
       
  1490 /**
       
  1491  * Function to evaluate the state variables 
       
  1492  * at the end of test case 
       
  1493  */
       
  1494 void CScriptControl::ProcessEndCase()
       
  1495 	{
       
  1496 	if(iSelTestingOptions==NULL) //selective testing is not on
       
  1497 		return;					// dont bother
       
  1498 	iTestCaseCounter--;
       
  1499 	if(iTestCaseCounter<0) //in case we encountered unmatched end cases
       
  1500 		iTestCaseCounter=0;
       
  1501 	TLex lex(iCurrentScriptLine);
       
  1502 	TPtrC token(lex.NextToken());
       
  1503 	TPtrC testCaseID(lex.NextToken());	
       
  1504 	//check if this is ending a range
       
  1505 	TRange dummy(testCaseID,testCaseID);
       
  1506 	TIdentityRelation<TRange> crackIDRangeend(TRange::CompareTRangeEnd);
       
  1507 	for ( TInt index=0; index<iSelTestingOptions->iSelectiveCaseRange.Count(); ++index )
       
  1508 		{
       
  1509 		if ( testCaseID.CompareF(iSelTestingOptions->iSelectiveCaseRange[index].iEndTestCase) == 0 )
       
  1510 			{
       
  1511 			if ( iSelTestingOptions->iSelectiveCaseRange[index].iState == TRange::EStateInUse )
       
  1512 				{
       
  1513 				iSelTestingOptions->iSelectiveCaseRange[index].iState=TRange::EStateUsed;
       
  1514 				--iRangeRefCounter;
       
  1515 				}
       
  1516 			else
       
  1517 				{
       
  1518 				//	Error condition. An end test case has been matched to a range that has not processed the start test case
       
  1519 				//	Either the start test case does not exist or the start test case comes after the end test case in the script
       
  1520 				//or maybe do nothing
       
  1521 				
       
  1522 				}
       
  1523 			}
       
  1524 		}
       
  1525 	
       
  1526 		
       
  1527 	//always reset the onetime test case thing
       
  1528 	iSelectOne = EFalse;
       
  1529 	}
       
  1530 
       
  1531 /**
       
  1532  * Implement START_TESTCASE/ END_TESTCASE commands
       
  1533  * Write a testcase marker to the logfile
       
  1534  */
       
  1535 void CScriptControl::LogTestCaseMarkerL() 
       
  1536 	{
       
  1537 	TLex lex(iCurrentScriptLine);
       
  1538 	TPtrC token(lex.NextToken());
       
  1539 	TVerdict TestCaseResult(EFail);
       
  1540 
       
  1541 	TPtrC TestCaseMarker(lex.NextToken());
       
  1542 
       
  1543 		if (token.CompareF(KTEFStartTestCaseCommand) == 0 || token.CompareF(KTEFStartSyncTestCaseCommand) == 0)
       
  1544 		{
       
  1545 		// Call the interface routine for logging in HTML & XML format
       
  1546 		Logger().LogTestCaseResult(iScriptFile, iCurrentScriptLineNumber, RFileFlogger::ESevrHigh, token, TestCaseMarker);
       
  1547 		iTestCaseID.Copy(TestCaseMarker);
       
  1548 		}
       
  1549 	else
       
  1550 		{
       
  1551 		// Its an END_TESTCASE.
       
  1552 		// Need to identify whether all preceding test steps in the file
       
  1553 		// passed (back to a *matching* START_TESTCASE).
       
  1554 		TestCaseResult = HasTestCasePassedL(TestCaseMarker);
       
  1555 
       
  1556 			// Special case for KTEFEndSyncTestCaseCommand where the result in 
       
  1557 			// the shared data area needs to be updated so STAT can retrieve it later.
       
  1558 			if( token.CompareF(KTEFEndSyncTestCaseCommand) == 0 )
       
  1559 				{
       
  1560 				// Check to see if the Sync Data has been created
       
  1561 				if( iSyncControl != NULL )
       
  1562 					{
       
  1563 					// Update the TEFResult shared data value
       
  1564 					iSyncControl->SetResultL( TestCaseResult );
       
  1565 					}
       
  1566 				else
       
  1567 					{
       
  1568 					User::Leave( KErrNotReady );
       
  1569 					}
       
  1570 				}
       
  1571 		// Call the interface routine for logging in HTML & XML format
       
  1572 		Logger().LogTestCaseResult(iScriptFile, iCurrentScriptLineNumber, RFileFlogger::ESevrHigh, token, TestCaseMarker, TestCaseResult);
       
  1573 		iTestCaseID.Copy(KTEFTestCaseDefault);
       
  1574 		}
       
  1575 	}
       
  1576 
       
  1577 /**
       
  1578  *
       
  1579  * Implement TestCase pass checking
       
  1580  */
       
  1581 TVerdict CScriptControl::HasTestCasePassedL(TPtrC aTestCaseMarker)
       
  1582 	{
       
  1583 	// Looks from the top of the file for the equivalent Start_TestCase
       
  1584 	// when it finds it it checks that all the steps to the bottom of 
       
  1585 	// the file (the current position) 
       
  1586 
       
  1587 	// Create a Cinidata object to parse through the testexecute.ini
       
  1588 	// To retrieve the path where the log is to be placed
       
  1589 
       
  1590 	CTestExecuteIniData* parseTestExecuteIni = NULL;
       
  1591 	TBuf<KMaxTestExecuteNameLength> resultFilePath;
       
  1592 
       
  1593 	TRAPD(err,parseTestExecuteIni = CTestExecuteIniData::NewL(iDefaultSysDrive));
       
  1594 	if (err == KErrNone)
       
  1595 		{
       
  1596 		CleanupStack::PushL(parseTestExecuteIni);
       
  1597 		parseTestExecuteIni->ExtractValuesFromIni();
       
  1598 		parseTestExecuteIni->GetKeyValueFromIni(KTEFHtmlKey, resultFilePath);
       
  1599 		}
       
  1600 	else
       
  1601 		{
       
  1602 		resultFilePath.Copy(KTestExecuteLogPath);
       
  1603 		resultFilePath.Replace(0, 2, iDefaultSysDrive);
       
  1604 		}
       
  1605 
       
  1606 	TBuf<KMaxTestExecuteNameLength> resultFileName(resultFilePath);
       
  1607 	// loading the simplified test result in case of out-of-memory 
       
  1608 	resultFileName.Append(KTEFTestExecuteResultSimplifiedSummaryFile);
       
  1609 	if (parseTestExecuteIni != NULL)
       
  1610 		{
       
  1611 		CleanupStack::PopAndDestroy(parseTestExecuteIni);
       
  1612 		}
       
  1613 
       
  1614 	// Open the result summary file
       
  1615 	RFs fS;
       
  1616 	User::LeaveIfError(fS.Connect());
       
  1617 	CleanupClosePushL(fS);
       
  1618 
       
  1619 	RFile logFile;
       
  1620 	User::LeaveIfError(logFile.Open(fS,resultFileName, EFileWrite | EFileRead | EFileShareAny));
       
  1621 	CleanupClosePushL(logFile);
       
  1622 	TInt fileSize;
       
  1623 	// Read the complete result summary file onto the heap
       
  1624 	// It wont be that large
       
  1625 	User::LeaveIfError(logFile.Size(fileSize));
       
  1626 	HBufC* resultData = HBufC::NewLC(fileSize);
       
  1627 	HBufC8* resultData8 = HBufC8::NewLC(fileSize);	
       
  1628 	TPtr8 ptrData8(resultData8->Des());
       
  1629 	User::LeaveIfError(logFile.Read(ptrData8));
       
  1630 	TPtr ptrData(resultData->Des());
       
  1631 	ptrData.Copy(ptrData8);
       
  1632 	CleanupStack::PopAndDestroy(resultData8);
       
  1633 
       
  1634 	TBool foundMarker(EFalse);
       
  1635 	TBool foundNonPassResult(EFalse);
       
  1636 	TInt duplicatesCounter(0);
       
  1637 
       
  1638 	TLex lex(ptrData);
       
  1639 	while (!lex.Eos())
       
  1640 		{
       
  1641 		// Find the ***Result keywords
       
  1642 		TPtrC commandName( lex.NextToken() );
       
  1643 		if(	commandName.CompareF(KTEFStartTestCaseCommand) == 0 ||
       
  1644 			commandName.CompareF(KTEFStartSyncTestCaseCommand) == 0 )
       
  1645 			{
       
  1646 			if (lex.NextToken() == aTestCaseMarker)
       
  1647 				{
       
  1648 				// Increment the counter to identify that the test case id is duplicated
       
  1649 				duplicatesCounter++;
       
  1650 				if (duplicatesCounter == 2)
       
  1651 					{
       
  1652 					// If the test case id is duplicated for more than once,
       
  1653 					// issue a warning in the log file, mentioning duplicate of test case id
       
  1654 					_LIT(KWarnDuplicateTCID, "Test Case ID : %S re-used");
       
  1655 					WARN_PRINTF2(KWarnDuplicateTCID, &aTestCaseMarker);
       
  1656 					}
       
  1657 
       
  1658 				// When a matching test case id is found, the found marker is set to ETrue
       
  1659 				foundMarker = ETrue;
       
  1660 				// Initialise the foundNonPassResult to EFalse, on entry into each test case result in the log
       
  1661 				foundNonPassResult = EFalse;
       
  1662 				continue;
       
  1663 				}
       
  1664 			continue;
       
  1665 			}
       
  1666 		else if (foundMarker && commandName == KTEFResultTag)
       
  1667 			{
       
  1668 			// If the START_TESTCASE is found and a RESULT tag is found in the test result file,
       
  1669 			// Extract the result value set for every test step called within
       
  1670 			// and check to see if there are any non-pas results
       
  1671 			_LIT(KTEFEquals,"=");
       
  1672 			if (lex.NextToken() != KTEFEquals)
       
  1673 			continue;
       
  1674 			TPtrC result(lex.NextToken());
       
  1675 			if(result != KTEFResultPass)
       
  1676 				{
       
  1677 				// Set the foundNonPassResult to ETrue indicating the test case to fail
       
  1678 				foundNonPassResult = ETrue;
       
  1679 				}
       
  1680 			}			
       
  1681 		}
       
  1682 
       
  1683 	CleanupStack::PopAndDestroy(resultData);
       
  1684 	CleanupStack::Pop(&logFile);
       
  1685 	logFile.Close();
       
  1686 	CleanupStack::Pop(&fS);
       
  1687 	fS.Close();
       
  1688 
       
  1689 	if (foundMarker)
       
  1690 		{
       
  1691 		if (foundNonPassResult)
       
  1692 			{
       
  1693 			return EFail;
       
  1694 			}
       
  1695 		else
       
  1696 			{
       
  1697 			return EPass;
       
  1698 			}
       
  1699 		}
       
  1700 	else
       
  1701 		{
       
  1702 		return EInconclusive;
       
  1703 		}
       
  1704 	}
       
  1705 
       
  1706 /**
       
  1707  * Implement the DELAY command
       
  1708  */
       
  1709 void CScriptControl::StartTimerFromScriptLine()
       
  1710 	{
       
  1711 	TLex lex(iCurrentScriptLine);
       
  1712 	lex.NextToken();
       
  1713 	TLex delayLex(lex.NextToken());
       
  1714 	TInt delay;
       
  1715 	// Read the delay in milliseconds
       
  1716 	TInt err = delayLex.Val(delay);
       
  1717 	if(err)
       
  1718 		// Set the default
       
  1719 		delay = KDefaultDelayMilliseconds;
       
  1720 	iTimer.After(iStatus,delay*1000);
       
  1721 	}
       
  1722 
       
  1723 /**
       
  1724  * Secure - same for Target and Wins
       
  1725  */
       
  1726 void CScriptControl::RunCedFromScriptLineL()
       
  1727 	{
       
  1728 	TLex lex(iCurrentScriptLine);
       
  1729 	// Skip CED
       
  1730 	lex.NextToken();
       
  1731 	TPtrC cedCommandLine(lex.Remainder());
       
  1732 	iCurrentScriptLine.Set(cedCommandLine);
       
  1733 	RProcess process;
       
  1734 	User::LeaveIfError(process.Create(_L("ced.exe"),iCurrentScriptLine));
       
  1735 	process.Rendezvous(iStatus);
       
  1736 	// Run CED asynchronously
       
  1737 	process.Resume();
       
  1738 	process.Close();
       
  1739 	}
       
  1740 
       
  1741 /**
       
  1742  * Set up the path of a script file for a child CScriptControl object
       
  1743  */
       
  1744 void CScriptControl::GetScriptFileFromScriptLine()
       
  1745 	{
       
  1746 	TLex lex(iCurrentScriptLine);
       
  1747 	lex.NextToken();
       
  1748 	iChildScriptFile.Set(lex.NextToken());
       
  1749 	}
       
  1750 
       
  1751 /**
       
  1752  * @param aUtilsCommand - Command string for the utilities command
       
  1753  * Implement basic commands:
       
  1754  * NB: Always requires the full path
       
  1755  * Logic borrowed from Scheduletest
       
  1756  * Always complete synchronously
       
  1757  * 
       
  1758  * CopyFile
       
  1759  * MKDir
       
  1760  * MakeReadWrite
       
  1761  * Delete
       
  1762  * DeleteDirectory
       
  1763  */
       
  1764 void CScriptControl::RunUtilsFromScriptLineL() const
       
  1765 	{
       
  1766 	_LIT(KDefault,				"?:\\default");
       
  1767 	_LIT(KCDrive,				"?:\\"); 
       
  1768 	_LIT(KTEFBackslash,			"\\" );
       
  1769 
       
  1770 	TBuf<10> defaultPath(KDefault);
       
  1771 	defaultPath.Replace(0, 2, iTestSysDrive);
       
  1772 
       
  1773 	TBuf<3> cDrive(KCDrive);
       
  1774 	cDrive.Replace(0, 2, iTestSysDrive);
       
  1775 
       
  1776 	RFs fS;
       
  1777 	User::LeaveIfError(fS.Connect() );
       
  1778 	CleanupClosePushL(fS);
       
  1779 
       
  1780 	TLex lex(iCurrentScriptLine);
       
  1781 	lex.NextToken();
       
  1782 	TPtrC token(lex.NextToken());
       
  1783 	if(token.CompareF(KTEFRunUtilsCopyFile) == 0)
       
  1784 		{
       
  1785 		TPtrC file1=lex.NextToken();
       
  1786 		TPtrC file2=lex.NextToken();
       
  1787 		TParse source, dest;
       
  1788 		CFileMan* fMan = CFileMan::NewL(fS);
       
  1789 		CleanupStack::PushL(fMan);
       
  1790 		User::LeaveIfError(source.Set(file1, &defaultPath, NULL) );
       
  1791 		User::LeaveIfError(dest.Set(file2, &defaultPath, NULL) );
       
  1792 		User::LeaveIfError(fMan->Copy(source.FullName(), dest.FullName(), CFileMan::EOverWrite) );
       
  1793 		CleanupStack::PopAndDestroy(fMan);
       
  1794 		}
       
  1795 	else if(token.CompareF(KTEFRunUtilsMkDir) == 0)
       
  1796 		{
       
  1797 		token.Set(lex.NextToken());
       
  1798 		TParse fileName;
       
  1799 
       
  1800 		if (!token.Length())
       
  1801 			User::Leave(KErrPathNotFound);
       
  1802 		
       
  1803 		TPtrC lastChar(token.Mid(token.Length() - 1));
       
  1804 		if ( lastChar.CompareF(KTEFBackslash) != 0 )
       
  1805 			{
       
  1806 			TBuf<64> tempToken(token);
       
  1807 			tempToken.Append(KTEFBackslash);
       
  1808 			token.Set(tempToken);
       
  1809 			}
       
  1810 
       
  1811 		User::LeaveIfError( fileName.Set(token, &cDrive, NULL) );
       
  1812 		User::LeaveIfError( fS.MkDir( fileName.DriveAndPath() ) );
       
  1813 		}
       
  1814 	else if(token.CompareF(KTEFRunUtilsDeleteFile) == 0 ||
       
  1815 	         token.CompareF(KTEFRunUtilsDelete) == 0)
       
  1816 		{
       
  1817 		token.Set(lex.NextToken());
       
  1818 		// defect047128 - Code change for handling wildcard deletes
       
  1819 		CFileMan* fMan = CFileMan::NewL(fS);
       
  1820 		CleanupStack::PushL(fMan);
       
  1821 		User::LeaveIfError(fMan->Delete(token) );
       
  1822 		CleanupStack::PopAndDestroy(fMan);
       
  1823 		}
       
  1824 	else if(token.CompareF(KTEFRunUtilsMakeReadWrite) == 0)
       
  1825 		{
       
  1826 		token.Set(lex.NextToken());
       
  1827 		TParse fileName;
       
  1828 		User::LeaveIfError(fileName.Set(token, &defaultPath, NULL) );
       
  1829 		TInt err = fS.SetAtt(fileName.FullName(),0, KEntryAttReadOnly);
       
  1830 		if (err != KErrNone && err != KErrNotFound)
       
  1831 			User::Leave(err);
       
  1832 		}
       
  1833 	//It deletes the specified directory
       
  1834 	else if(token.CompareF(KTEFDeleteDirectory) == 0)
       
  1835 		{
       
  1836 		token.Set(lex.NextToken());
       
  1837 		TParse fileName;
       
  1838 
       
  1839 		if (!token.Length())
       
  1840 			User::Leave(KErrPathNotFound);
       
  1841 		
       
  1842 		TPtrC lastChar(token.Mid(token.Length() - 1));
       
  1843 		if ( lastChar.CompareF(KTEFBackslash) != 0 )
       
  1844 			{
       
  1845 			TBuf<64> tempToken(token);
       
  1846 			tempToken.Append(KTEFBackslash);
       
  1847 			token.Set(tempToken);
       
  1848 			}
       
  1849 
       
  1850 		CFileMan* fMan = CFileMan::NewL(fS);
       
  1851 		CleanupStack::PushL(fMan);
       
  1852 
       
  1853 		User::LeaveIfError(fileName.Set(token, &cDrive, NULL) );
       
  1854 		User::LeaveIfError( fMan->RmDir( fileName.DriveAndPath() ) );
       
  1855 
       
  1856 		CleanupStack::PopAndDestroy(fMan);
       
  1857 		}
       
  1858 	
       
  1859 	fS.Close();
       
  1860 	CleanupStack::Pop(&fS);	
       
  1861 	}
       
  1862 
       
  1863 /**
       
  1864  * Read the Script File data into a heap buffer
       
  1865  * We could read the file line by line but that would be cumbersome, and unless there
       
  1866  * is a heap size problem, this is tidier.
       
  1867  */
       
  1868 void CScriptControl::CreateScriptDataFromScriptFileL()
       
  1869 	{
       
  1870 	RFs fS;
       
  1871 	User::LeaveIfError(fS.Connect());
       
  1872 	CleanupClosePushL(fS);
       
  1873 	RFile scriptFile;
       
  1874 	User::LeaveIfError(scriptFile.Open(fS,iScriptFile,EFileRead | EFileShareAny));
       
  1875 	CleanupClosePushL(scriptFile);
       
  1876 	TInt fileSize;
       
  1877 	User::LeaveIfError(scriptFile.Size(fileSize));
       
  1878 	// Create a 16bit heap buffer
       
  1879 	iScriptData = HBufC::NewL(fileSize);
       
  1880 	HBufC8* narrowData = HBufC8::NewL(fileSize);
       
  1881 	CleanupStack::PushL(narrowData);
       
  1882 	TPtr8 narrowPtr=narrowData->Des();
       
  1883 	// Read the file into an 8bit heap buffer
       
  1884 	User::LeaveIfError(scriptFile.Read(narrowPtr));
       
  1885 	TPtr widePtr(iScriptData->Des());
       
  1886 	// Copy it to the 16bit buffer
       
  1887 	widePtr.Copy(narrowData->Des());
       
  1888 	CleanupStack::PopAndDestroy(narrowData);
       
  1889 	CleanupStack::Pop(2);
       
  1890 	scriptFile.Close();
       
  1891 	fS.Close();
       
  1892 	// Set up the instance token parser
       
  1893 	iScriptLex = iScriptData->Des();
       
  1894 	}
       
  1895 
       
  1896 /**
       
  1897  * Extracts the human readable server name from the current script line then
       
  1898  * calls Client RTestServ Interface to make a connection to the server.
       
  1899  */
       
  1900 void CScriptControl::CreateServerFromScriptLineL()
       
  1901 	{
       
  1902 	TLex lex(iCurrentScriptLine);
       
  1903 	lex.NextToken();
       
  1904 	TInt i=0;
       
  1905 	TInt count = iServers.Count();
       
  1906 	TPtrC serverName(lex.NextToken());
       
  1907 	
       
  1908 	// We loop through to see if the server has already been created
       
  1909 	for(i=0;i<count;i++)
       
  1910 		{
       
  1911 		if(iServers[i]->ServerName() == serverName)
       
  1912 			// Server already exists in our array
       
  1913 			break;
       
  1914 		}
       
  1915 	if(i == count)
       
  1916 		{
       
  1917 		// Create a new RTestServ pointer and add it to the list
       
  1918 		RScriptTestServ* serv = new (ELeave) RScriptTestServ;
       
  1919 		// Connect using the client API
       
  1920 		TInt err;
       
  1921 		if(lex.NextToken().CompareF(KTEFLoadSuiteSharedData) == 0)
       
  1922 			{
       
  1923 			err = serv->Connect(serverName,ETrue);
       
  1924 			}
       
  1925 		else
       
  1926 			err = serv->Connect(serverName,EFalse);
       
  1927 		if(err)
       
  1928 			{
       
  1929 			// Don't add the server to the array if we fail to connect.
       
  1930 			delete serv;
       
  1931 			// Caller TRAP's
       
  1932 			User::Leave(err);
       
  1933 			}
       
  1934 		iServers.Append(serv);
       
  1935 		}
       
  1936 	}
       
  1937 
       
  1938 /**
       
  1939  * @param aIndex - Return the index of the RTestServ instance - If found
       
  1940  * @return - EFalse if server not found. ETrue if server found.
       
  1941  * 
       
  1942  */
       
  1943 TBool CScriptControl::GetServerIndexFromScriptLine(TInt& aIndex)
       
  1944 	{
       
  1945 	TLex lex(iCurrentScriptLine);
       
  1946 	TLex lexTimeout;
       
  1947 	_LIT(KErrInvalidArgumentSet,"The arguments are not provided in proper format.\
       
  1948 			Unable to retrieve the details of the server from the command line");
       
  1949 
       
  1950 	TPtrC command(lex.NextToken());
       
  1951 	if(command.CompareF(KTEFRunTestStepResultCommand) == 0)
       
  1952 		{
       
  1953 		lex.NextToken();
       
  1954 		lex.SkipSpace();
       
  1955 		lex.Mark();
       
  1956 		}
       
  1957 		
       
  1958 	else if(command.CompareF(KTEFRunPanicStepResultCommand) == 0)
       
  1959 		{
       
  1960 		lex.NextToken();
       
  1961 		TPtrC panicString(lex.NextToken());
       
  1962 		// Check to see if the panic string contains open quotes and close quotes
       
  1963 		// If the panic string token contains open quote, it is understood that the panic string contains spaces
       
  1964 		// So, look for close quote in the subsequent tokens. If not found, return boolean false as return value
       
  1965 		if(panicString.Left(1).Compare(KTEFOpenQuotes) == 0 && panicString.Right(1).Compare(KTEFOpenQuotes) != 0)
       
  1966 			{
       
  1967 			TBool validCommandLine(EFalse);
       
  1968 			while(!lex.Eos() && !validCommandLine)
       
  1969 				{				
       
  1970 				panicString.Set(lex.NextToken());
       
  1971 				if(panicString.Right(1).Compare(KTEFOpenQuotes) == 0)
       
  1972 					validCommandLine = ETrue;
       
  1973 				}
       
  1974 			if (!validCommandLine)
       
  1975 				{
       
  1976 				ERR_PRINTF1(KErrInvalidArgumentSet);
       
  1977 				return EFalse;
       
  1978 				}
       
  1979 			}
       
  1980 		lex.SkipSpace();
       
  1981 		lex.Mark();
       
  1982 		}
       
  1983 	else if(command.CompareF(KTEFRunTestStepCommand) == 0 ||
       
  1984 			command.CompareF(KTEFStartTestBlock) == 0)
       
  1985 		{
       
  1986 		TInt firstChar;
       
  1987 		TPtrC commandStr;
       
  1988 		TBool panicStringComplete(ETrue);
       
  1989 		while(!lex.Eos())
       
  1990 			{
       
  1991 			lex.SkipSpace();
       
  1992 			lex.Mark();
       
  1993 			
       
  1994 			TPtrC	token = lex.NextToken();
       
  1995 			if( token.Length()>0 )
       
  1996 				{
       
  1997 				commandStr.Set( token );
       
  1998 				firstChar = commandStr[0];
       
  1999 				// 33 is the ascii value for "!". Used here for confirming switches
       
  2000 				if (firstChar != KTEFAsciiExclamation && panicStringComplete)
       
  2001 					{
       
  2002 					break;
       
  2003 					}
       
  2004 				// Check to see if !PanicString TEF parameter contains panic string with spaces
       
  2005 				// If so, see if they are enclosed within a open & close braces
       
  2006 				if(commandStr.Length() > 14 && 
       
  2007 					commandStr.Mid(0,14).Compare(_L("!PanicString=\"")) == 0)
       
  2008 						panicStringComplete = EFalse;
       
  2009 				if(!panicStringComplete && commandStr.Right(1).Compare(KTEFOpenQuotes) == 0)
       
  2010 					panicStringComplete = ETrue;
       
  2011 				}
       
  2012 			}
       
  2013 			if (!panicStringComplete)
       
  2014 				{
       
  2015 				ERR_PRINTF1(KErrInvalidArgumentSet);
       
  2016 				return EFalse;
       
  2017 				}
       
  2018 		}
       
  2019 	
       
  2020 	// We need to skip the timeout if it's there.
       
  2021 	if(	command.CompareF(KTEFRunTestStepCommand) == 0 ||
       
  2022 		command.CompareF(KTEFStartTestBlock) == 0)
       
  2023 		lexTimeout=lex.MarkedToken();
       
  2024 	else
       
  2025 		lexTimeout=lex.NextToken();
       
  2026 	TInt timeout;
       
  2027 	TPtrC serverName;
       
  2028 	if(lexTimeout.Val(timeout) != KErrNone)
       
  2029 		// No timeout so use the second token
       
  2030 		serverName.Set(lex.MarkedToken());
       
  2031 	else
       
  2032 		// Timeout value there
       
  2033 		serverName.Set(lex.NextToken());
       
  2034 	TInt i=0;
       
  2035 	// Loop through the installed servers
       
  2036 	TInt count = iServers.Count();
       
  2037 	for(i=0;i<count;i++)
       
  2038 		{
       
  2039 		if(iServers[i]->ServerName() == serverName)
       
  2040 			// Found server installed
       
  2041 			break;
       
  2042 		}
       
  2043 	// Return found or not found
       
  2044 	if(i == count)
       
  2045 		return EFalse;
       
  2046 	else
       
  2047 		{
       
  2048 		aIndex = i;
       
  2049 		if (iServers[i]->SharedData())
       
  2050 			{
       
  2051 			iConcurrent = EFalse;
       
  2052 			}
       
  2053 		return ETrue;
       
  2054 		}
       
  2055 	}
       
  2056 
       
  2057 /**
       
  2058  *  * @return - ETrue if the scriptline is valid, else retuens EFalse
       
  2059  */
       
  2060 TBool CScriptControl::CheckValidScriptLine() const
       
  2061 	{
       
  2062 	TLex lex(iCurrentScriptLine);
       
  2063 	TPtrC command(lex.NextToken());
       
  2064 	TBool panicCodeSet(EFalse);
       
  2065 	TBool panicStringSet(EFalse);
       
  2066 	TBool heapValueSet(EFalse);
       
  2067 	TBool validScript(ETrue);
       
  2068 	TBool oomRequestSet(EFalse);
       
  2069 	TBool setupOptionSet(EFalse);
       
  2070 	
       
  2071 	if(command.CompareF(KTEFRunTestStepCommand) == 0)
       
  2072 		{
       
  2073 		TInt firstChar;
       
  2074 		TPtrC commandStr;
       
  2075 		while(!lex.Eos())
       
  2076 			{
       
  2077 			lex.SkipSpace();
       
  2078 			commandStr.Set(lex.NextToken());
       
  2079 			firstChar = commandStr[0];
       
  2080 			// 33 is the ascii value for "!". Used here for confirming switches
       
  2081 			if (firstChar == KTEFAsciiExclamation)
       
  2082 				{
       
  2083 				if (commandStr.Length() >= KTEFMinErrorParamLength && commandStr.Mid(0,KTEFMinErrorParamLength).CompareF(KTEFError) == 0)
       
  2084 					{
       
  2085 					if(command.CompareF(KTEFRunTestStepCommand) == 0)
       
  2086 						command.Set(KTEFRunErrorStepResultCommand);
       
  2087 					else
       
  2088 						validScript = EFalse;
       
  2089 					}
       
  2090 				else if (commandStr.Length() >= KTEFMinSetupParamLength && commandStr.Mid(0,KTEFMinSetupParamLength).CompareF(KTEFSetUpParam) == 0)
       
  2091 					{
       
  2092 					if(command.CompareF(KTEFRunTestStepCommand) == 0 && !setupOptionSet)
       
  2093 						setupOptionSet = ETrue;
       
  2094 					else
       
  2095 						validScript = EFalse;
       
  2096 					}
       
  2097 				else if (commandStr.Length() > KTEFMinResultParamLength && commandStr.Mid(0,KTEFMinResultParamLength).CompareF(KTEFResult) == 0 && commandStr.Mid(KTEFMinResultParamLength).Length() <= KTEFMaxVerdictLength)
       
  2098 					{
       
  2099 					if (command.CompareF(KTEFRunTestStepCommand)  == 0)
       
  2100 						command.Set(KTEFRunTestStepResultCommand);
       
  2101 					else
       
  2102 						validScript = EFalse;
       
  2103 					}
       
  2104 				else if (commandStr.Length() >= KTEFMinPanicCodeParamLength && commandStr.Mid(0,KTEFMinPanicCodeParamLength).CompareF(KTEFPanicCode) == 0)
       
  2105 					{
       
  2106 					if ((command.CompareF(KTEFRunTestStepCommand) == 0 || command.CompareF(KTEFRunPanicStepResultCommand) == 0) && !panicCodeSet)
       
  2107 						{
       
  2108 						command.Set(KTEFRunPanicStepResultCommand);
       
  2109 						panicCodeSet=ETrue;
       
  2110 						}
       
  2111 					else
       
  2112 						validScript = EFalse;
       
  2113 					}
       
  2114 				else if (commandStr.Length() >= KTEFMinPanicStringParamLength && commandStr.Mid(0,KTEFMinPanicStringParamLength).CompareF(KTEFPanicString) == 0)
       
  2115 					{
       
  2116 					if ((command.CompareF(KTEFRunTestStepCommand) == 0 || command.CompareF(KTEFRunPanicStepResultCommand) == 0) && !panicStringSet)
       
  2117 						{
       
  2118 						command.Set(KTEFRunPanicStepResultCommand);
       
  2119 						panicStringSet = ETrue;
       
  2120 						}
       
  2121 					else
       
  2122 						validScript = EFalse;
       
  2123 					}
       
  2124 				else
       
  2125 					{
       
  2126 					if (commandStr.Length() >= KTEFMinHeapParamLength && commandStr.Mid(0,KTEFMinHeapParamLength).CompareF(KTEFHeap) == 0 && !heapValueSet)
       
  2127 						heapValueSet = ETrue;
       
  2128 					else if (commandStr.Length() >= KTEFMinOomParamLength && commandStr.Mid(0,KTEFMinOomParamLength).CompareF(KTEFOom) == 0 && !oomRequestSet)
       
  2129 						oomRequestSet = ETrue;
       
  2130 					else
       
  2131 						validScript = EFalse;
       
  2132 					}
       
  2133 				}
       
  2134 			else
       
  2135 				break;
       
  2136 			}
       
  2137 		}
       
  2138 		return validScript;
       
  2139 	}
       
  2140 
       
  2141 /**
       
  2142  * Return the next line in the script file
       
  2143  * @param aScriptLine - return line in the script file minus CRLF
       
  2144  * @return - True if line found, false for end of file.
       
  2145  */	
       
  2146 TBool CScriptControl::GetNextScriptLine(TPtrC& aScriptLine)
       
  2147 	{
       
  2148 	if(iScriptLex.Eos())
       
  2149 		{
       
  2150 		// Fix defect 1193337, check the value is zero or not. If zero, this should be no nested run script
       
  2151 		if((0 == iNestedNumRunScriptInLoop) && iLoop)
       
  2152 		// End defect 119337
       
  2153 			{
       
  2154 			_LIT(KEndRepeatNotFound,"The END_REPEAT command is not found");
       
  2155 			INFO_PRINTF1(KEndRepeatNotFound);
       
  2156 			}
       
  2157 		
       
  2158 		// Fix defect 119337, check if this is still in loop and this run script command is nested
       
  2159 		// decrease one shows that the nested number is decreased
       
  2160 		else if (iNestedNumRunScriptInLoop > 0 && iLoop)
       
  2161 			{
       
  2162 			--iNestedNumRunScriptInLoop;
       
  2163 			}
       
  2164 		// End defect 119337
       
  2165 		
       
  2166 		return EFalse;
       
  2167 		}
       
  2168 	// Mark the current script line to return
       
  2169 	iScriptLex.Mark();
       
  2170 	if(iLoop && !iCheckVar)
       
  2171 		{
       
  2172 		iStoreLoop.Assign(iScriptLex.RemainderFromMark());
       
  2173 		iTempStoreLoop.Assign(iScriptLex.RemainderFromMark());
       
  2174 		iCheckVar=ETrue;
       
  2175 		}
       
  2176 	// Place the lex marker for the next read
       
  2177 	while(!iScriptLex.Eos())
       
  2178 		{
       
  2179 		TChar peek = iScriptLex.Peek();
       
  2180 		if(peek == '\n')
       
  2181 			{
       
  2182 			iScriptLex.Inc();
       
  2183 			iCurrentScriptLineNumber++;
       
  2184 			break;
       
  2185 			}
       
  2186 		else
       
  2187 			iScriptLex.Inc();
       
  2188 		}
       
  2189 	aScriptLine.Set(iScriptLex.MarkedToken());
       
  2190 	if(aScriptLine.FindF(KTEFRunScriptCommand)!=KErrNotFound && iLoop)
       
  2191 		{
       
  2192 		// Fix defect 119337, add this integer shows a nested run script added.
       
  2193 		++iNestedNumRunScriptInLoop;
       
  2194 		// End Fix defect 119337
       
  2195 		}
       
  2196 	if(aScriptLine.Length() || !iScriptLex.Eos())
       
  2197 		return ETrue;
       
  2198 	else
       
  2199 		return EFalse;
       
  2200 	}
       
  2201 
       
  2202 /**
       
  2203  * Return the next line from script file which is to be looped
       
  2204  * @param aScriptLine - return line in the script file which is under loop minus CRLF
       
  2205  * @return -True if line is found else return false
       
  2206  * 
       
  2207  * If RUN_SCRIPT command has been encountered return the line from GetNextScriptLine Function
       
  2208  */
       
  2209 TBool CScriptControl::GetLoopScriptLine(TPtrC& aScriptLine)
       
  2210 	{
       
  2211 	// Fix defect 119337, check if the run script is nested
       
  2212 	if (0 != iNestedNumRunScriptInLoop)
       
  2213 	// End defect 119337
       
  2214 		return(GetNextScriptLine(aScriptLine));
       
  2215 	if(iStoreLoop.Eos())
       
  2216 		return EFalse;
       
  2217 	iStoreLoop.Mark();
       
  2218 	while(!iStoreLoop.Eos())
       
  2219 		{
       
  2220 		TChar peek = iStoreLoop.Peek();
       
  2221 		if(peek == '\n')
       
  2222 			{
       
  2223 			iStoreLoop.Inc();
       
  2224 			break;
       
  2225 			}
       
  2226 		else
       
  2227 			iStoreLoop.Inc();
       
  2228 		}
       
  2229 	aScriptLine.Set(iStoreLoop.MarkedToken());
       
  2230 	if(aScriptLine.Find(KTEFEndRepeat)!=KErrNotFound)
       
  2231 		{
       
  2232 		iStoreLoop.Assign(iTempStoreLoop);	
       
  2233 		}
       
  2234 	if(aScriptLine.FindF(KTEFRunScriptCommand)!=KErrNotFound)
       
  2235 		{
       
  2236 		// Fix defect 119337, add this integer shows a nested run script added.
       
  2237 		++iNestedNumRunScriptInLoop;
       
  2238 		// End defect 119337
       
  2239 		}
       
  2240 	if(aScriptLine.Length() || !iStoreLoop.Eos())
       
  2241 		return ETrue;
       
  2242 	else
       
  2243 		return EFalse;
       
  2244 	}
       
  2245 
       
  2246 /**
       
  2247  * @param aErr - The completion code
       
  2248  * @param aPanicString - Descriptor reference containing the panic string if a test were to panic
       
  2249  * @param aScriptLineNumber - Script line number used for printing result into log file
       
  2250  * @param aCommand - Command name also used for printing result into log file
       
  2251  * Called by a CClientControl or CProgramControl child object
       
  2252  */
       
  2253 void CScriptControl::TaskCompletion(TInt aErr, const TDesC& aPanicString, TInt aScriptLineNumber,const TDesC& aCommand,TBool aTaskCanComplete,TTEFItemArray* aItemArray)
       
  2254 	{
       
  2255 	if(aItemArray)
       
  2256 		{
       
  2257 		TVerdict err = Logger().LogBlock( aItemArray, aScriptLineNumber );
       
  2258 		
       
  2259 		// If no error was set on the server side (ie. a panic) then set
       
  2260 		//  it here with the post processing result
       
  2261 		if( EPass == aErr && aPanicString.Length() == 0 )
       
  2262 			{
       
  2263 			aErr = err;
       
  2264 			}
       
  2265 		}
       
  2266 	// Log the test step result to the output file
       
  2267 	LogResult((TVerdict)aErr, aPanicString, aScriptLineNumber, aCommand);
       
  2268 		
       
  2269 	if(aErr != KErrNone && aErr != KErrNotSupported && iBreakOnError)
       
  2270 		// Put this instance of the script engine into the closing state as we've
       
  2271 		// encountered the BREAK_ERROR_ON command.
       
  2272 		// KErrNotSupported is considered a benign error 
       
  2273 		{
       
  2274 		iState = EClosing;
       
  2275 		}
       
  2276 	iAsyncTasksOutstanding--;
       
  2277 	// Check the flag first then trigger our own RunL()
       
  2278 	if(aTaskCanComplete || iCanComplete)
       
  2279 		Complete(aErr);
       
  2280 	}
       
  2281 
       
  2282 /**
       
  2283  * Print the current script line to the console
       
  2284  */
       
  2285 void CScriptControl::PrintCurrentScriptLine() const
       
  2286 	{
       
  2287 	// Check we don't overflow
       
  2288 	TBuf<KMaxTestExecuteLogLineLength> output;
       
  2289 	if((iCurrentScriptLine.Length() + iScriptFile.Length() + 4 ) > output.MaxLength())
       
  2290 		{
       
  2291 		output.Copy(iAlteredScriptLine);
       
  2292 		Logger().PrintCurrentScriptLine(output);
       
  2293 		return;
       
  2294 		}
       
  2295 	// Copy the script filename. Handy for recursion
       
  2296 	output.Copy(iScriptFile);
       
  2297 	output.Append(KTEFSpace);
       
  2298 	// Append the script file line
       
  2299 	output.Append(iCurrentScriptLine);
       
  2300 	// Write to console
       
  2301 	ConsoleLogger().Console().Printf(KTEFStringFormat,&output);
       
  2302 
       
  2303 	Logger().PrintCurrentScriptLine(output);
       
  2304 	}
       
  2305 
       
  2306 /**
       
  2307  * Checks for commented commands and increments a counter for logging
       
  2308  */
       
  2309 TBool CScriptControl::CheckCommentedCommands() const
       
  2310 	{
       
  2311 	if(!iCurrentScriptLine.Length())
       
  2312 		return ETrue;
       
  2313 	
       
  2314 	TLex lex(iCurrentScriptLine);
       
  2315 	TPtrC token(lex.NextToken());
       
  2316 	if (!token.Length())
       
  2317 		return ETrue;
       
  2318 	
       
  2319 	TInt firstChar = iCurrentScriptLine[0];
       
  2320 	if(firstChar == '/')
       
  2321 		{
       
  2322 		TInt findRunTestStep;
       
  2323 		TInt findRunPanicStep;
       
  2324 		TInt findRunScript;
       
  2325 		TInt findRunProgram;
       
  2326 		TInt findRunWSProgram;
       
  2327 		TInt findStartTestBlock;
       
  2328 		findRunTestStep=iCurrentScriptLine.Find(KTEFRunTestStepCommand);
       
  2329 		findRunScript=iCurrentScriptLine.Find(KTEFRunScriptCommand);
       
  2330 		findRunPanicStep=iCurrentScriptLine.Find(KTEFRunPanicStepCommand);
       
  2331 		findRunProgram=iCurrentScriptLine.Find(KTEFRunProgramCommand);
       
  2332 		findRunWSProgram=iCurrentScriptLine.Find(KTEFRunWSProgramCommand);
       
  2333 		findStartTestBlock=iCurrentScriptLine.Find(KTEFStartTestBlock);
       
  2334 		if(findRunTestStep>0 || findRunScript>0 || findRunPanicStep>0 || findRunProgram>0 || findRunWSProgram>0 || findStartTestBlock>0 && !iStartLooping)
       
  2335 			{
       
  2336 			commentedCommandsCount++;
       
  2337 			}
       
  2338 		}
       
  2339 	if(firstChar == '\r' || firstChar == '\n' || firstChar == '#' || firstChar == '/')
       
  2340 		return ETrue;
       
  2341 	return EFalse;
       
  2342 	}
       
  2343 
       
  2344 /**
       
  2345  * @param aResult - Test Step result
       
  2346  * @param aPanicString - Descriptor containing the panic string if test were to panic
       
  2347  * @param aScriptLineNumber - The line in the script file
       
  2348  * @param aCommand - Command name whose result is set for logging
       
  2349  * Log a RUN_TEST_STEP, RUN_PANIC_STEP or RUN_PROGRAM result to file
       
  2350  */
       
  2351 void CScriptControl::LogResult(TVerdict aResult, const TDesC& aPanicString, TInt aScriptLineNumber,const TDesC& aCommand)
       
  2352 	{
       
  2353 	// Call the Logger()'s LogResult() routine to manipulate results of RUN_TEST_STEP command/variants
       
  2354 	// Also controls the fields for logging both HTML & XML logging
       
  2355 	Logger().LogResult(aResult, aPanicString, aScriptLineNumber, aCommand, iScriptFile, RFileFlogger::ESevrHigh);
       
  2356 	}
       
  2357 
       
  2358 /**
       
  2359  * Constructor
       
  2360  * @param RTestServ - Reference to a root RTestServer instance
       
  2361  * @param aCommand - Reference to a RUN_TEST_STEP script line
       
  2362  * @param MTaskCompletion - Reference to the parent completion interface
       
  2363  * @param aScriptLineNumber - The line in script file
       
  2364  * @param aLogger - Reference to the Logger class
       
  2365  * @param aLoopIndex - TInt reference that provides the loop index for the test. The value is 0 if not in loop.
       
  2366  * @param aTestCaseID - Descriptor containing the test case id, if test run is within a test case
       
  2367  * @param aScriptFilePath - The path of the script file being executed
       
  2368  * @param aSysDrive - Default system drive letter
       
  2369  * @param aTestSysDrive - System drive letter overwritten from testexecute.ini
       
  2370  */
       
  2371 CClientControl::CClientControl(RScriptTestServ& aServ,const TDesC& aCommand, MTaskCompletion& aCompletion, TInt aScriptLineNumber, CTestExecuteLogger& aLogger, TInt aLoopIndex, const TDesC& aTestCaseID, TPtrC& aScriptFilePath, const TDriveName& aSysDrive, const TDriveName& aTestSysDrive)
       
  2372 :	CTaskControlBase(aCommand,aCompletion,aScriptLineNumber,aLogger)
       
  2373 ,	iServ(aServ)
       
  2374 ,	iRetryCount(0)
       
  2375 ,	iLoopIndex(aLoopIndex)
       
  2376 ,	iTestCaseID(aTestCaseID)
       
  2377 ,	iBlockArrayPkg(NULL)
       
  2378 ,	iBlockArrayPtr(STATIC_CAST(TUint8*,NULL), 0)
       
  2379 ,	iScriptFilePath(aScriptFilePath)
       
  2380 ,	iDefaultSysDrive(aSysDrive)
       
  2381 ,	iTestSysDrive(aTestSysDrive)
       
  2382 	{
       
  2383 	// Extract the parameters to the test step and store them in the class
       
  2384 	GetStepParamsFromStepCommand();
       
  2385 	}
       
  2386 
       
  2387 CClientControl* CClientControl::NewL(	RScriptTestServ& aTestServ,
       
  2388 										const TDesC& aCommand,
       
  2389 										MTaskCompletion& aCompletion,
       
  2390 										TInt aScriptLineNumber,
       
  2391 										CTestExecuteLogger& aLogger,
       
  2392 										TInt aLoopIndex,
       
  2393 										const TDesC& aTestCaseID,
       
  2394 										const TDesC& aEndBlockCommand,
       
  2395 										TPtrC& aScriptFilePath,
       
  2396 										const TTEFItemArray& aBlockArray,
       
  2397 										const TDriveName& aSysDrive,
       
  2398 										const TDriveName& aTestSysDrive)
       
  2399 	{
       
  2400 	CClientControl* self = new (ELeave) CClientControl(	aTestServ,
       
  2401 														aCommand,
       
  2402 														aCompletion,
       
  2403 														aScriptLineNumber,
       
  2404 														aLogger,
       
  2405 														aLoopIndex,
       
  2406 														aTestCaseID,
       
  2407 														aScriptFilePath,
       
  2408 														aSysDrive,
       
  2409 														aTestSysDrive);
       
  2410 	CleanupStack::PushL(self);
       
  2411 	self->ConstructL(aEndBlockCommand, aBlockArray);
       
  2412 	CleanupStack::Pop();
       
  2413 	return self;
       
  2414 	}
       
  2415 
       
  2416 void CClientControl::ConstructL( const TDesC& aEndBlockCommand, const TTEFItemArray& aBlockArray )
       
  2417 	{
       
  2418 	iEndBlockCommand.Set( aEndBlockCommand );
       
  2419 	TTEFItemPkgBuf	itemPckgBuf;
       
  2420 	TInt			count = aBlockArray.Count();
       
  2421 	iBlockArrayPkg	= HBufC8::NewL( count * itemPckgBuf.Size() );
       
  2422 	iBlockArrayPtr.Set( iBlockArrayPkg->Des() );
       
  2423 	for( TInt i=0; i<count; i++ )
       
  2424 		{
       
  2425 		itemPckgBuf = aBlockArray.At(i);
       
  2426 		iBlockArrayPtr.Append( itemPckgBuf );
       
  2427 		}
       
  2428 	}
       
  2429 
       
  2430 TTEFItemArray* CClientControl::CreateBlockArrayLC()
       
  2431 	{
       
  2432 	TTEFItemPkgBuf	itemPckgBuf;
       
  2433 	TPtr8			blockArrayPtr(iBlockArrayPkg->Des());
       
  2434 	TInt			count = blockArrayPtr.Size()/itemPckgBuf.Size();
       
  2435 	TTEFItemArray*	itemArray = new (ELeave) TTEFItemArray( count );
       
  2436 	CleanupStack::PushL( itemArray );
       
  2437 
       
  2438 	TInt	pos = 0;
       
  2439 	for( TInt i=0; i<count; i++ )
       
  2440 		{
       
  2441 		itemPckgBuf.Copy(blockArrayPtr.Mid(pos, itemPckgBuf.Size()));
       
  2442 		pos += itemPckgBuf.Size();
       
  2443 		itemArray->AppendL( itemPckgBuf() );
       
  2444 		}
       
  2445 
       
  2446 	return itemArray;
       
  2447 	}
       
  2448 	
       
  2449 /**
       
  2450  * Destructor
       
  2451  */
       
  2452 CClientControl::~CClientControl()
       
  2453 	{
       
  2454 	iTimer.Cancel();
       
  2455 	iTimer.Close();
       
  2456 	
       
  2457 	if( iBlockArrayPkg )
       
  2458 		{
       
  2459 		delete iBlockArrayPkg;
       
  2460 		iBlockArrayPkg = NULL;
       
  2461 		}
       
  2462 	}
       
  2463 const TInt KDisableTimer = -1;
       
  2464 
       
  2465 /** 
       
  2466  * Test step has done. log the test result. 
       
  2467  */
       
  2468 void CClientControl::TestStepComplete()
       
  2469 	{
       
  2470 	iSession.Close();
       
  2471 	if(iBlockArrayPkg)
       
  2472 		{
       
  2473 		TTEFItemArray *itemArray = CreateBlockArrayLC();
       
  2474 		iParent.TaskCompletion(iStatus.Int(), iTaskExitCategory, iScriptLineNumber, iEndBlockCommand, iTaskCanComplete, itemArray);
       
  2475 		CleanupStack::PopAndDestroy(itemArray);
       
  2476 		}
       
  2477 	else
       
  2478 		{
       
  2479 		iParent.TaskCompletion(iStatus.Int(), iTaskExitCategory, iScriptLineNumber, iCommandLine, iTaskCanComplete);
       
  2480 		}
       
  2481 	}
       
  2482 
       
  2483 /**
       
  2484  * Pure virtual
       
  2485  * Test step handling state machine
       
  2486  * Kick'd() into by the parent CScriptControl object. Constructed in the EInit state
       
  2487  */
       
  2488 void CClientControl::RunL()
       
  2489 	{
       
  2490 	switch(iState)
       
  2491 		{
       
  2492 	case EInit	:
       
  2493 		User::LeaveIfError(iTimer.CreateLocal());
       
  2494 		if(iBlockArrayPkg)
       
  2495 			{
       
  2496 			User::LeaveIfError(iSession.Open(iServ, EFalse));		
       
  2497 			}
       
  2498 		else
       
  2499 			{
       
  2500 			User::LeaveIfError(iSession.Open(iServ, ETrue, iStepName));
       
  2501 			}
       
  2502 		// Whilst testing concurrent mode, the OS occasionally completes with
       
  2503 		// KErrServerBusy or KErrInUse.
       
  2504 		
       
  2505 		// clean up retry counter. case ERetry will using.
       
  2506 		iRetryCount = 0;
       
  2507 	case EServerRetry :
       
  2508 		{
       
  2509 		SetActive();
       
  2510 		
       
  2511 		// Set the heap size for creating the thread heap size
       
  2512 		iTaskExitCategory.Copy(iTaskHeapSize);
       
  2513 
       
  2514 		TBuf<5> checkOOMArgsBuf;
       
  2515 
       
  2516 		// Check if the step args has the OOM arguments already
       
  2517 		// A minimum 5 chars expected to check this : "OOM=0" or "OOM=1"
       
  2518 		if (iStepArgs.Length() >=5)
       
  2519 			{
       
  2520 			// Extract the first 5 chars from the start of step args string
       
  2521 			checkOOMArgsBuf.Copy(iStepArgs.Mid(0,5));
       
  2522 			}
       
  2523 
       
  2524 		_LIT(KOOMOne,"OOM=1");
       
  2525 		_LIT(KOOMZero,"OOM=0");
       
  2526 
       
  2527 		// Set the OOM argument after checking for existence of OOM param already
       
  2528 		if ((checkOOMArgsBuf.CompareF(KOOMOne) != KErrNone) && (checkOOMArgsBuf.CompareF(KOOMZero) != KErrNone))
       
  2529 			{
       
  2530 			// Insert the OOM arguments to the start of iStepArgs string
       
  2531 			if (iOOMRequestSet) // Set OOM=1 if !OOM is used in the RUN_TEST_STEP command
       
  2532 				iStepArgs.Insert(0,_L("OOM=1 "));
       
  2533 			else
       
  2534 				iStepArgs.Insert(0,_L("OOM=0 "));
       
  2535 			}
       
  2536 
       
  2537 		TBuf<KMaxTestExecuteCommandLength> checkSetUpArgsBuf;
       
  2538 
       
  2539 		// Check if the step args has the Setup arguments already
       
  2540 		// A min of 13 chars expected to check this : "OOM=0 !Setup=" or "OOM=1 !Setup="
       
  2541 		if (iStepArgs.Length() >=13)
       
  2542 			{
       
  2543 			// Extract 7 chars after skipping the OOM arguments "OOM=0 " or "OOM=1 "
       
  2544 			checkSetUpArgsBuf.Copy(iStepArgs.Mid(6,7));
       
  2545 			}
       
  2546 
       
  2547 		// Set the !Setup argument after checking for existence !Setup param already
       
  2548 		if (checkSetUpArgsBuf.CompareF(KTEFSetUpParam) != KErrNone)
       
  2549 			{
       
  2550 			// Retain the !Setup value from RUN_TEST_STEP command, if available
       
  2551 			if (iSetUpParamValue.Length() == KTEFZeroValue)
       
  2552 				{
       
  2553 				// If !Setup is not used in RUN_TEST_STEP, set the !Setup to TTestSetupState::ESetupNone (0)
       
  2554 				iSetUpParamValue.Copy(KTEFSetUpParam);
       
  2555 				iSetUpParamValue.AppendNum(TTestSetupState(ESetupNone));
       
  2556 				}
       
  2557 
       
  2558 			// Append a space and also include the loop index
       
  2559 			iSetUpParamValue.Append(KTEFSpace);
       
  2560 			// The loop index is 0 if the test is not in loop; loop index, otherwise
       
  2561 			iSetUpParamValue.AppendNum(iLoopIndex);
       
  2562 			iSetUpParamValue.Append(KTEFSpace);
       
  2563 			
       
  2564 			// Append the TestCaseID along with the Setup params
       
  2565 			iSetUpParamValue.Append(iTestCaseID);
       
  2566 			iSetUpParamValue.Append(KTEFSpace);
       
  2567 
       
  2568 			// Insert the !Setup arguments after the OOM arguments within the iStepArgs
       
  2569 			iStepArgs.Insert(6, iSetUpParamValue);
       
  2570 			}
       
  2571 		
       
  2572 		// Call the async client API to run the test step
       
  2573 		if(iBlockArrayPkg)
       
  2574 			{
       
  2575 			iSession.RunTestBlock(iStepArgs,iTaskExitCategory,iBlockArrayPtr,iStatus);
       
  2576 			}
       
  2577 		else
       
  2578 			{
       
  2579 			iSession.RunTestStep(iStepArgs,iTaskExitCategory,iStatus);
       
  2580 			}
       
  2581 		// Start a timer and provide it with our callback MTaskCompletion
       
  2582 		iState = ERunning;
       
  2583 		// Only start the timer if the disable value is not set
       
  2584 		if(iTaskTimeout != KDisableTimer)
       
  2585 			{
       
  2586 			iTaskTimer = CTaskTimer::NewL(*this);
       
  2587 			iTaskTimer->Timeout(iTaskTimeout);
       
  2588 			}
       
  2589 		}
       
  2590 		break;
       
  2591 
       
  2592 	case ERunning :
       
  2593 		{
       
  2594 		// We have been completed but we need to find out the source
       
  2595 		// If the timer expires it Aborts the server test step which results in
       
  2596 		// the RunTestStep call completing with KErrAbort.
       
  2597 		// When the timer expires it calls us back and we delete it then NULL it.
       
  2598 		if(iTaskTimer)
       
  2599 			{
       
  2600 			// The timer did not expire
       
  2601 			iTaskTimer->Cancel();
       
  2602 			delete iTaskTimer;
       
  2603 			iTaskTimer = NULL;
       
  2604 			}
       
  2605 		const TInt KRetry10Microseconds = 100000;
       
  2606 		const TInt KMaxRetryCount = 20;
       
  2607 		if(iStatus.Int() == KErrInUse && iRetryCount < KMaxRetryCount)
       
  2608 			{
       
  2609 			// OS (not the server) has rejected the call.
       
  2610 			// Timed retry
       
  2611 			// Noticed this one after panic's in shared data mode
       
  2612 			iState = EServerRetry;
       
  2613 			// Keep increasing the timeout
       
  2614 			iRetryCount++;
       
  2615 			SetActive();
       
  2616 			iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrInfo,
       
  2617 					_L("Error Message :: The Task Is Retrying "));
       
  2618 			iTimer.After(iStatus,KRetry10Microseconds * iRetryCount);							
       
  2619 			}		
       
  2620 		else if(iStatus.Int() == KErrServerBusy)
       
  2621 			{
       
  2622 			// tempt to do test again when test server return busy.
       
  2623 			iState = EServerRetry;
       
  2624 			iRetryCount++;
       
  2625 			if(iRetryCount < KMaxRetryCount)
       
  2626 				{
       
  2627 				iState = EServerRetry;
       
  2628 				SetActive();
       
  2629 				iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrInfo,
       
  2630 						_L("Error Message : Server return -16 = KErrServerBusy : Retrying %d"),iRetryCount);
       
  2631 				iTimer.After(iStatus,KRetry10Microseconds );
       
  2632 				}
       
  2633 			else//server alwayse busy. stop test. 
       
  2634 				{
       
  2635 				iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrErr,
       
  2636 										_L("Error Message : Server Busy Retrying %d times. Test Teminated!"),iRetryCount);
       
  2637 				iParent.TaskCompletion(iStatus.Int(),iTaskExitCategory,iScriptLineNumber,iCommandLine,iTaskCanComplete);
       
  2638 
       
  2639 				iSession.Close();
       
  2640 				delete this;				
       
  2641 				}
       
  2642 			}			
       
  2643 		else
       
  2644 			{
       
  2645 			// see testserverbase.cpp::void SytemWideErrToTefErr(TInt &aErr). converting thi value.
       
  2646 			//Check the status, if the status is KErrTestExecuteInUse
       
  2647 			//then log the information  and change it back to 
       
  2648 			if(iStatus.Int() == KErrTestExecuteInUse)
       
  2649 				{
       
  2650 				//Convert the status back to KErrInUse
       
  2651 				iStatus=KErrInUse;
       
  2652 				}
       
  2653 			else if(iStatus.Int() == KErrTestExecuteServerBusy)
       
  2654 				{
       
  2655 				//this is not server really busy! we should change the server side iStatus back to -16
       
  2656 				//Convert the status back to KErrServerBusy
       
  2657 				iStatus = KErrServerBusy;
       
  2658 				}
       
  2659 			// Step completion
       
  2660 			TestStepComplete();
       
  2661 			delete this;
       
  2662 			}
       
  2663 		}
       
  2664 		break;
       
  2665 
       
  2666 	default:
       
  2667 		break;
       
  2668 		}
       
  2669 	}
       
  2670 
       
  2671 /**
       
  2672  * @param aError - TInt value representing error returned due to processing request from RunL()
       
  2673  * Handles the leave from RunL() and cleans up the allocated objects
       
  2674  * Also returns KErrNone upon sucessful handling of leave
       
  2675  */
       
  2676 TInt CClientControl::RunError(TInt aError)
       
  2677 	{
       
  2678 	if(iBlockArrayPkg)
       
  2679 		{
       
  2680 		TTEFItemArray*	itemArray = CreateBlockArrayLC();
       
  2681 		iParent.TaskCompletion(aError,iTaskExitCategory,iScriptLineNumber,iEndBlockCommand,iTaskCanComplete,itemArray);
       
  2682 		CleanupStack::PopAndDestroy( itemArray );
       
  2683 		}
       
  2684 	else
       
  2685 		{
       
  2686 		iParent.TaskCompletion(aError,iTaskExitCategory,iScriptLineNumber,iCommandLine,iTaskCanComplete);
       
  2687 		}
       
  2688 	delete this;
       
  2689 	return KErrNone;
       
  2690 	}
       
  2691 
       
  2692 /**
       
  2693  * Extract and save the timeout, step name and test step arguments
       
  2694  */
       
  2695 void CClientControl::GetStepParamsFromStepCommand()
       
  2696 	{
       
  2697 	TLex scriptLineLex(iCommandLine);
       
  2698 	TPtrC command(scriptLineLex.NextToken());
       
  2699 	if(command.CompareF(KTEFRunTestStepResultCommand) == 0)
       
  2700 		scriptLineLex.NextToken();
       
  2701 	else if(command.CompareF(KTEFRunPanicStepResultCommand) == 0)
       
  2702 		{
       
  2703 		scriptLineLex.NextToken();
       
  2704 		TPtrC panicString(scriptLineLex.NextToken());
       
  2705 		if(panicString.Left(1).Compare(KTEFOpenQuotes) == 0 && panicString.Right(1).Compare(KTEFOpenQuotes) != 0)
       
  2706 			{
       
  2707 			TBool validCommandLine(EFalse);
       
  2708 			while(!scriptLineLex.Eos() && !validCommandLine)
       
  2709 				{				
       
  2710 				panicString.Set(scriptLineLex.NextToken());
       
  2711 				if(panicString.Right(1).Compare(KTEFOpenQuotes) == 0)
       
  2712 					validCommandLine = ETrue;
       
  2713 				}
       
  2714 			}
       
  2715 		}
       
  2716 	else if(command.CompareF(KTEFRunTestStepCommand) == 0 ||
       
  2717 			command.CompareF(KTEFStartTestBlock) == 0 )
       
  2718 		{
       
  2719 		TInt firstChar;
       
  2720 		TPtrC commandStr;
       
  2721 		TBool panicStringComplete(ETrue);
       
  2722 		while(!scriptLineLex.Eos())
       
  2723 			{
       
  2724 			scriptLineLex.SkipSpace();
       
  2725 			scriptLineLex.Mark();
       
  2726 			
       
  2727 			TPtrC	token = scriptLineLex.NextToken();
       
  2728 			if( token.Length()>0 )
       
  2729 				{
       
  2730 				commandStr.Set( token );
       
  2731 				firstChar = commandStr[0];
       
  2732 				// 33 is the ascii value for "!". Used here for confirming switches
       
  2733 				if (firstChar != KTEFAsciiExclamation && panicStringComplete)
       
  2734 					{
       
  2735 					break;
       
  2736 					}
       
  2737 				if(commandStr.Length() > 14 && 
       
  2738 					commandStr.Mid(0,14).Compare(_L("!PanicString=\"")) == 0)
       
  2739 						panicStringComplete = EFalse;
       
  2740 				if(!panicStringComplete && commandStr.Right(1).Compare(KTEFOpenQuotes) == 0)
       
  2741 					panicStringComplete = ETrue;
       
  2742 				if (commandStr.Length() >= KTEFMinHeapParamLength && commandStr.Mid(0,KTEFMinHeapParamLength).CompareF(KTEFHeap) == 0)
       
  2743 					iTaskHeapSize.Set(commandStr.Mid(KTEFMinHeapParamLength));
       
  2744 				else if (commandStr.Length() >= KTEFMinSetupParamLength && commandStr.Mid(0,KTEFMinSetupParamLength).CompareF(KTEFSetUpParam) == 0)
       
  2745 					iSetUpParamValue.Copy(commandStr);
       
  2746 				else if (commandStr.Length() >= KTEFMinOomParamLength && commandStr.Mid(0,KTEFMinOomParamLength).CompareF(KTEFOom) == 0)
       
  2747 					{
       
  2748 					// Out of memory cannot be supported for UREL builds due to UHEAP macros
       
  2749 					// not being supported in UREL builds
       
  2750 					#if defined(_DEBUG)
       
  2751 						iOOMRequestSet = ETrue;
       
  2752 					#else
       
  2753 						iOOMRequestSet = EFalse;
       
  2754 						iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrWarn,
       
  2755 								_L("Out of Memory Testing is not supported for UREL builds"));
       
  2756 					#endif
       
  2757 					}
       
  2758 				}
       
  2759 			}
       
  2760 		}
       
  2761 
       
  2762 	TLex timeoutLex;
       
  2763 	if(	command.CompareF(KTEFRunTestStepCommand) == 0 ||
       
  2764 		command.CompareF(KTEFStartTestBlock) == 0)
       
  2765 		timeoutLex = scriptLineLex.MarkedToken();
       
  2766 	else
       
  2767 		timeoutLex = scriptLineLex.NextToken();
       
  2768 	TInt err = timeoutLex.Val(iTaskTimeout);
       
  2769 	if(err)
       
  2770 		{
       
  2771 		// No timeout specified
       
  2772 		iTaskTimeout = KDefaultTimeoutSeconds;
       
  2773 		iStepName.Set(scriptLineLex.NextToken());
       
  2774 		}
       
  2775 	else
       
  2776 		{
       
  2777 		scriptLineLex.NextToken();
       
  2778 		if( command.CompareF(KTEFRunTestStepCommand) == 0 ||
       
  2779 			command.CompareF(KTEFRunTestStepResultCommand) == 0 ||
       
  2780 			command.CompareF(KTEFRunPanicStepResultCommand) == 0 ||
       
  2781 			command.CompareF(KTEFRunPanicStepCommand) == 0||
       
  2782 			command.CompareF(KTEFRunErrorStepResultCommand) == 0)
       
  2783 			{
       
  2784 			// Save the step name
       
  2785 			iStepName.Set(scriptLineLex.NextToken());
       
  2786 			}
       
  2787 		}
       
  2788 	// The rest is sent to the server
       
  2789 	scriptLineLex.SkipSpace();
       
  2790   	iStepArgs.Copy(iScriptFilePath.Mid(0,2));
       
  2791   	iStepArgs.Append(KTEFSpace);
       
  2792 	iStepArgs.Append(iDefaultSysDrive);
       
  2793 	iStepArgs.Append(KTEFSpace);
       
  2794 	iStepArgs.Append(iTestSysDrive);
       
  2795 	iStepArgs.Append(KTEFSpace);
       
  2796   	iStepArgs.Append(scriptLineLex.Remainder());
       
  2797 	}
       
  2798 
       
  2799 /**
       
  2800  * Callback from a CTaskTimer object
       
  2801  * Abort the test step, NULL the timer so we know that a timeout has caused test step completion
       
  2802  */
       
  2803 void CClientControl::TaskTimerCompletion()
       
  2804 	{
       
  2805 	delete iTaskTimer;
       
  2806 	iTaskTimer = NULL;
       
  2807 	iSession.AbortTestStep();
       
  2808 	}
       
  2809 
       
  2810 /**
       
  2811  * Constructor
       
  2812  * @param aCompletion - Reference to a callback method in the CClientControl parent object
       
  2813  */
       
  2814 CTaskTimer::CTaskTimer(MTaskTimerCompletion& aCompletion) : CTimer(EPriorityUserInput), iParent(aCompletion)
       
  2815 	{
       
  2816 	CActiveScheduler::Add(this);
       
  2817 	}
       
  2818 
       
  2819 /**
       
  2820  * Iterate till the timer has expired and callback into the parent
       
  2821  */
       
  2822 void CTaskTimer::RunL()
       
  2823 	{
       
  2824 	if (iTimesAfter > 0 || iSecondsRemaining > 0)
       
  2825 		{
       
  2826 		RunTimeout(); // Function call implementing the After() routines
       
  2827 		}
       
  2828 	else
       
  2829 		{
       
  2830 		iParent.TaskTimerCompletion(); // Call the completion routine for the timeout
       
  2831 		}
       
  2832 	}
       
  2833 
       
  2834 /**
       
  2835  * Implements a timeout based using CTimer::After()
       
  2836  * Modified for handling huge timeout values
       
  2837  * @param aSeconds - Timeout value in seconds
       
  2838  */
       
  2839  void CTaskTimer::Timeout(TInt aSeconds)
       
  2840 	{
       
  2841 	iTimesAfter = aSeconds/60; // Convert the aSeconds to equivalent minutes
       
  2842 	iSecondsRemaining = (aSeconds - (iTimesAfter*60)); // Remainder of seconds after converting to equivalent minutes
       
  2843 	RunTimeout();
       
  2844 	}
       
  2845 
       
  2846 /**
       
  2847  * Implements the After() routines for the timeout value specified
       
  2848  * The call is initiated from Timeout() & is iterated from the RunL()
       
  2849  */
       
  2850 void CTaskTimer::RunTimeout()
       
  2851 	{
       
  2852 	if (iTimesAfter > 0)
       
  2853 		{
       
  2854 		After(60*1000000); // Call After() for every minute until iTimesAfter is >0
       
  2855 		iTimesAfter--;
       
  2856 		}
       
  2857 	else if (iSecondsRemaining > 0)
       
  2858 		{
       
  2859 		After(iSecondsRemaining*1000000); // Call After() for remainder of microsec
       
  2860 		iSecondsRemaining = 0;
       
  2861 		}
       
  2862 	}
       
  2863 
       
  2864 /**
       
  2865  * Destructor
       
  2866  */
       
  2867 CTaskTimer::~CTaskTimer()
       
  2868 	{
       
  2869 	}
       
  2870 
       
  2871 /*
       
  2872  * @param aCompletion - Reference to a callback method in a CTaskControlBase parent object
       
  2873  * Two phase contruction
       
  2874  */
       
  2875 CTaskTimer* CTaskTimer::NewL(MTaskTimerCompletion& aCompletion)
       
  2876 	{
       
  2877 	CTaskTimer* taskTimer = new(ELeave) CTaskTimer(aCompletion);
       
  2878 	CleanupStack::PushL(taskTimer);
       
  2879 	// We have to call the base class second phase constructor
       
  2880 	taskTimer->ConstructL();
       
  2881 	CleanupStack::Pop(taskTimer);
       
  2882 	return taskTimer;
       
  2883 	}
       
  2884 
       
  2885 /**
       
  2886  * @param aCommand - Command for the derived class
       
  2887  * @param aCompletion - Reference to the parent class callback method
       
  2888  * @param aScriptLineNumber - The script file line number of this command
       
  2889  * @param aLogger - Reference to a Flogger derived session
       
  2890  * Constructor - Just initialise the abstract class data
       
  2891  */
       
  2892 CTaskControlBase::CTaskControlBase(const TDesC& aCommand, MTaskCompletion& aCompletion,TInt aScriptLineNumber, CTestExecuteLogger& aLogger) :
       
  2893 	iCommandLine(aCommand),
       
  2894 	iParent(aCompletion),
       
  2895 	iScriptLineNumber(aScriptLineNumber),
       
  2896 	iLogger(aLogger),
       
  2897 	iTaskTimer(NULL)
       
  2898 	{
       
  2899 	}
       
  2900 
       
  2901 /**
       
  2902  * Destructor
       
  2903  */
       
  2904 CTaskControlBase::~CTaskControlBase()
       
  2905 	{
       
  2906 	}
       
  2907 
       
  2908 /**
       
  2909  * @param aCommand - Command line for the program (Store in base class)
       
  2910  * @param aCompletion - Reference to the parent class callback method (Store in base class)
       
  2911  * @param aScriptLineNumber - The script file line number of this command (Store in base class)
       
  2912  * @param aLogger - Reference to a Flogger derived session (Store in base class)
       
  2913  * @param aWSProgRun - Boolean value used for identifying window server programs
       
  2914  */
       
  2915 CProgramControl::CProgramControl(const TDesC& aCommand,MTaskCompletion& aCompletion,TInt aScriptLineNumber, CTestExecuteLogger& aLogger, TBool aWSProgRun) : CTaskControlBase(aCommand,aCompletion,aScriptLineNumber,aLogger),
       
  2916 	iState(EInit)
       
  2917 	{
       
  2918  	// Extract the program arguments from the command line
       
  2919 	GetProgramArgsFromCommand();
       
  2920 
       
  2921 	// Try to connect to the window server (if available)
       
  2922 	iWSProgRun = aWSProgRun;
       
  2923   	#if !defined TEF_LITE
       
  2924 	if( iWSProgRun )
       
  2925 		{
       
  2926 		iWs.Connect();
       
  2927 		}
       
  2928   	#else
       
  2929   	// Always set to false if TEF_LITE is set
       
  2930   	//iWSProgRun = EFalse;
       
  2931   	#endif
       
  2932 	}
       
  2933 
       
  2934 /**
       
  2935  * Destructor
       
  2936  */
       
  2937 CProgramControl::~CProgramControl()
       
  2938 	{
       
  2939 	#if !defined TEF_LITE
       
  2940 	if( iWSProgRun )
       
  2941 		{
       
  2942 		iWs.Close();
       
  2943 		}
       
  2944 	#endif
       
  2945 	}
       
  2946 
       
  2947 /**
       
  2948  * Simple State machine.
       
  2949  * Kick()'d into by parent object.
       
  2950  * Runs an executable in its own process.
       
  2951  */
       
  2952 void CProgramControl::RunL()
       
  2953 	{
       
  2954 	switch(iState)
       
  2955 		{
       
  2956 	case EInit	:
       
  2957 		{
       
  2958 		TRAPD(err,RunProgramL());
       
  2959 		if(err != KErrNone)
       
  2960 			{
       
  2961 			// Special case where the executable has already completed
       
  2962 			if( err == KErrCompletion )
       
  2963 				{
       
  2964 				// Reset the error code
       
  2965 				err = KErrNone;
       
  2966 				}
       
  2967 			// Failed so complete immediately
       
  2968 			iParent.TaskCompletion(err,iTaskExitCategory,iScriptLineNumber,iCommandLine,iTaskCanComplete);
       
  2969 			delete this;
       
  2970 			}
       
  2971 		else
       
  2972 			{
       
  2973 			SetActive();
       
  2974 			iState = ERunning;
       
  2975 			// Only start the timer if the disable value is not set
       
  2976 			if(iTaskTimeout != KDisableTimer)
       
  2977 				{
       
  2978 				iTaskTimer = CTaskTimer::NewL(*this);
       
  2979 				iTaskTimer->Timeout(iTaskTimeout);
       
  2980 				}
       
  2981 			if (iProgRenamed == 1)
       
  2982  				{
       
  2983   				iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrInfo,
       
  2984   					_L(".EXE not found - .APP run instead"));
       
  2985   				}
       
  2986 
       
  2987 			}
       
  2988 		}
       
  2989 		break;
       
  2990 
       
  2991 	case ERunning :
       
  2992 		{
       
  2993 		if(iTaskTimer)
       
  2994 			{
       
  2995 			// The timer did not expire
       
  2996 			iTaskTimer->Cancel();
       
  2997 			delete iTaskTimer;
       
  2998 			iTaskTimer = NULL;
       
  2999 			}
       
  3000 		// Set up the panic string if the program panicked
       
  3001 		if( !iWSProgRun )
       
  3002 			{
       
  3003 			if(iProgram.ExitType() == EExitPanic)
       
  3004 				{
       
  3005 				iTaskExitCategory.Copy(KPanicEquals);
       
  3006 				iTaskExitCategory.Append(iProgram.ExitCategory());
       
  3007 				}
       
  3008 			else if (iProgram.ExitType() == EExitPending)
       
  3009 				{
       
  3010 				iProgram.Kill(KErrAbort);
       
  3011 				iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrWarn,
       
  3012 				  	_L("Program has been killed as the timeout is achieved."));
       
  3013 				}
       
  3014 			iProgram.Close();
       
  3015 			}
       
  3016   		#if !defined TEF_LITE
       
  3017 		else
       
  3018 			{
       
  3019 			if(iProgramWS.ExitType() == EExitPanic)
       
  3020 				{
       
  3021 				iTaskExitCategory.Copy(KPanicEquals);
       
  3022 				iTaskExitCategory.Append(iProgramWS.ExitCategory());
       
  3023 				}
       
  3024                 
       
  3025 		    // Delete dependence of MW apparc.lib. 
       
  3026 		    // apparc.lib is moved from OS layer to MW layer. 
       
  3027 		    // TEF will delete this dependece because TEF is built on OS layer.
       
  3028 			iProgramWS.Close();
       
  3029 			}
       
  3030 		#endif
       
  3031 		
       
  3032 		// Complete to the parent object.
       
  3033 		iParent.TaskCompletion(iStatus.Int(),iTaskExitCategory,iScriptLineNumber,iCommandLine,iTaskCanComplete);
       
  3034 		delete this;
       
  3035 		}
       
  3036 		break;
       
  3037 
       
  3038 	default:
       
  3039 		break;
       
  3040 		}
       
  3041 	}
       
  3042 
       
  3043 /**
       
  3044  * Retrieve the program arguments from the script line.
       
  3045  */
       
  3046 void CProgramControl::GetProgramArgsFromCommand()
       
  3047 	{
       
  3048 	TLex scriptLineLex(iCommandLine);
       
  3049 	// Skip the RUN_PROGRAM command
       
  3050 	scriptLineLex.NextToken();
       
  3051 	TLex lex(scriptLineLex);
       
  3052 	// Get the timer if it's been included
       
  3053 	TLex timeoutLex(lex.NextToken());
       
  3054 	TInt err = timeoutLex.Val(iTaskTimeout);
       
  3055 	if(err)
       
  3056 		// No timeout specified
       
  3057 		iTaskTimeout = KDefaultTimeoutSeconds;
       
  3058 	else
       
  3059 		// Skip the timeout value
       
  3060 		scriptLineLex.NextToken();
       
  3061 	scriptLineLex.SkipSpace();
       
  3062 	// Use the rest
       
  3063 	iProgramArgs.Set(scriptLineLex.Remainder());
       
  3064 	}
       
  3065 
       
  3066 /**
       
  3067  * Task timer expired
       
  3068  */
       
  3069 void CProgramControl::TaskTimerCompletion()
       
  3070 	{
       
  3071 	delete iTaskTimer;
       
  3072 	iTaskTimer = NULL;
       
  3073 		if( !iWSProgRun )
       
  3074 			{
       
  3075 			iProgram.RendezvousCancel(iStatus);
       
  3076 			}
       
  3077 		#if !defined TEF_LITE
       
  3078 		else
       
  3079 			{
       
  3080 			iProgramWS.RendezvousCancel(iStatus);
       
  3081 			}
       
  3082 		#endif
       
  3083 		// We ORPHAN the process
       
  3084 		// Our RunL() gets called immediately
       
  3085 		// Kill requires KillAnyProcess capability
       
  3086 		// ups the stakes as regards CAPABILITY
       
  3087 	}
       
  3088 
       
  3089 /**
       
  3090  * Processes RUN_PROGRAM command arguments and starts the program
       
  3091  */
       
  3092 void CProgramControl::RunProgramL()
       
  3093 	{
       
  3094 	TLex lex(iProgramArgs);
       
  3095 	//	Get program name.	
       
  3096 	lex.Mark();
       
  3097 	lex.NextToken();
       
  3098 #if   !defined TEF_LITE
       
  3099 	// Set up the program arguments
       
  3100 	TBuf<KMaxTestExecuteCommandLength> programArgs(lex.Remainder());
       
  3101 	programArgs.Trim();
       
  3102 	iProgramArgs.Set(programArgs);
       
  3103 
       
  3104 	if( !iWSProgRun )
       
  3105 		{
       
  3106 		// Create the Process
       
  3107 		User::LeaveIfError(iProgram.Create(lex.MarkedToken(),iProgramArgs));
       
  3108 		}
       
  3109 	else
       
  3110 		{
       
  3111  		if( !IsWindowServerAvailable() )
       
  3112  			{
       
  3113  			User::Leave(KErrNotSupported);
       
  3114  			}
       
  3115  	    // Delete dependence of MW apparc.lib. 
       
  3116  	    // apparc.lib is moved from OS layer to MW layer. 
       
  3117  	    // TEF will delete this dependece because TEF is built on OS layer.
       
  3118  		User::LeaveIfError(iProgramWS.Create(lex.MarkedToken(),iProgramArgs));
       
  3119 		}
       
  3120 #else
       
  3121 /**
       
  3122  * Kick off an exe in its own pocess
       
  3123  * completes asynchronously
       
  3124  */
       
  3125 	
       
  3126 	if (iWSProgRun)  //TEF lite doesn't support RUN_WS_PROGRAM.
       
  3127 		{
       
  3128 		iLogger.LogExtra((TText8*)__FILE__,__LINE__,ESevrErr,
       
  3129 				_L("Error Message :: TEF lite doesn't support RUN_WS_PROGRAM."));
       
  3130 		User::Leave(EFail);
       
  3131 		}
       
  3132 	
       
  3133 	// Set up the program arguments
       
  3134 	TPtrC commandLine(lex.Remainder());
       
  3135 	iProgramArgs.Set(commandLine);
       
  3136 	// Create the Process
       
  3137 	User::LeaveIfError(iProgram.Create(lex.MarkedToken(),iProgramArgs));
       
  3138 
       
  3139 #endif 
       
  3140 	if( !iWSProgRun )
       
  3141 		{
       
  3142 		iProgram.Rendezvous(iStatus);
       
  3143 		iProgram.Resume();
       
  3144 		}
       
  3145 	#if !defined TEF_LITE
       
  3146 	else
       
  3147 		{
       
  3148 		iProgramWS.Logon(iStatus);
       
  3149         iProgramWS.Resume();
       
  3150 		}
       
  3151 	#endif
       
  3152 	}
       
  3153 
       
  3154 /**
       
  3155  * @param aServerName - Test server to connect to
       
  3156  * @param aSharedData - Flag for shared data mode session with test server
       
  3157  * Connect to the test server
       
  3158  * EKA2 version requires a just in time debug flag for the test server process
       
  3159  * This is read from the command line.
       
  3160  * Base class connect acts on this.
       
  3161  */
       
  3162 TInt RScriptTestServ::Connect(const TDesC& aServerName,TBool aSharedData)
       
  3163 	{
       
  3164 	iSharedData = aSharedData;
       
  3165 	// Parse the command line for -d
       
  3166 	TBuf<KMaxTestExecuteCommandLength> commandLine;
       
  3167 	if(User::CommandLineLength() > commandLine.MaxLength())
       
  3168 		User::Leave(KErrTooBig);
       
  3169 	User::CommandLine(commandLine);
       
  3170 	TLex flagLex(commandLine);
       
  3171 	// Default to false
       
  3172 	TBool aJustInTime(EFalse);
       
  3173 	while(!flagLex.Eos())
       
  3174 		{
       
  3175 		TPtrC token(flagLex.NextToken());
       
  3176 		if(token == KTestExecuteCommandLineFlagDebugMode)
       
  3177 			{
       
  3178 			aJustInTime = ETrue;
       
  3179 			break;
       
  3180 			}
       
  3181 		}
       
  3182 	return RTestServ::Connect(aServerName,aJustInTime);
       
  3183 	
       
  3184 	}
       
  3185 
       
  3186 /**
       
  3187  * Copies the integer value read from ini file to the reference integer passed to the function
       
  3188  * @param aConfigData - Pointer to CIniData object used for reading data from ini file
       
  3189  * @param aConfigSection - Descriptor value describing the section name within an ini file for reading
       
  3190  * @param aSharedData - KeyName within a section where the input data is available in ini file
       
  3191  * @param aSharedDataNum - Reference integer variable for collecting the value at the keyname specified
       
  3192  * @Leave system wide errors
       
  3193  */
       
  3194 void CScriptControl::FindValueL(CIniData* aConfigData, TPtrC aConfigSection, TPtrC aSharedData, TInt& aSharedDataNum)
       
  3195 	{
       
  3196 	aConfigData->FindVar(aConfigSection, aSharedData, aSharedDataNum);
       
  3197 	if (aSharedDataNum == 0)
       
  3198 		{
       
  3199 		User::Leave(KErrGeneral);
       
  3200 		}
       
  3201 	}
       
  3202 
       
  3203 /**
       
  3204  * Copies the descriptor value read from ini file to the reference descriptor passed to the function
       
  3205  * @param aConfigData - Pointer to CIniData object used for reading data from ini file
       
  3206  * @param aConfigSection - Descriptor value describing the section name within an ini file for reading
       
  3207  * @param aSharedData - KeyName within a section where the input data is available in ini file
       
  3208  * @param aSharedDataName - Reference descriptor variable for collecting the value at the keyname specified
       
  3209  * @Leave system wide errors
       
  3210  */
       
  3211 void CScriptControl::FindValueL(CIniData* aConfigData, TPtrC aConfigSection, TPtrC aSharedData, TPtrC& aSharedDataName)
       
  3212 	{
       
  3213 	User::LeaveIfError(aConfigData->FindVar(aConfigSection, aSharedData, aSharedDataName));
       
  3214 	TPtrC blankString(KNull);
       
  3215 	if (aSharedDataName.CompareF(blankString) == 0)
       
  3216 		{
       
  3217 		User::Leave(KErrGeneral);
       
  3218 		}
       
  3219 	}
       
  3220 
       
  3221 /**
       
  3222  * Creates one or more shared objects based on the inputs provided in ini file
       
  3223  * @Leave system wide errors
       
  3224  */
       
  3225 void CScriptControl::CreateSharedObjectsFromScriptLineL()
       
  3226 	{
       
  3227 	CIniData* configData = NULL;
       
  3228 	TInt err = 0;
       
  3229 	TInt sharedDataCount = 0;
       
  3230 	TPtrC sharedDataName;
       
  3231 
       
  3232 	// Sets the boolean to ETrue
       
  3233 	// Avoids SHARED_DATA command being called more than once
       
  3234 	iIsSharedData = ETrue;
       
  3235 	
       
  3236 	//It copies the current line from the script to TLex object
       
  3237 	TLex shareLex(iCurrentScriptLine);
       
  3238 
       
  3239 	//reads the next word
       
  3240 	shareLex.NextToken();
       
  3241 
       
  3242 	TPtrC configFile(shareLex.NextToken());
       
  3243 
       
  3244 	TPtrC configSection(shareLex.NextToken());
       
  3245 
       
  3246 	if(configFile.Length())
       
  3247 		{
       
  3248 		// Create instance of CIniData for reading ini input
       
  3249 		TRAP(err,configData = CIniData::NewL(configFile));
       
  3250 		}
       
  3251 	if(err != KErrNone)
       
  3252 		{
       
  3253 		ERR_PRINTF1(KTEFErrorReadingIni);
       
  3254 		User::Leave(err);
       
  3255 		}
       
  3256 	if(configData)
       
  3257 		{
       
  3258 		CleanupStack::PushL(configData);
       
  3259 		TPtrC sharedDataNumberKey(KTEFSharedDataNum);
       
  3260 		// Read the ini file for number of shared objects to be created
       
  3261 		// Store the value into variable sharedDataCount
       
  3262 		TRAP(err,FindValueL(configData,configSection,sharedDataNumberKey,sharedDataCount));
       
  3263 		if (err != KErrNone)
       
  3264 			{
       
  3265 			ERR_PRINTF1(KTEFErrNumberOfShareNotInIni);
       
  3266 			}
       
  3267 		else
       
  3268 			{
       
  3269 			// If ini input is available for number of shared data
       
  3270 			// Run a loop to read individual shared objects name
       
  3271 			for (TInt i=1; i<=sharedDataCount; i++)
       
  3272 				{
       
  3273 				TBuf<20> keyName(KTEFSharedName);
       
  3274 
       
  3275 				keyName.AppendNum(i);
       
  3276 
       
  3277 				keyName.ZeroTerminate();
       
  3278 
       
  3279 				TPtrC sharedDataNameKey(keyName);
       
  3280 
       
  3281 				sharedDataName.Set(KNull);
       
  3282 
       
  3283 				// Read ini file for i th object name
       
  3284 				TRAP(err,FindValueL(configData,configSection,sharedDataNameKey,sharedDataName));
       
  3285 				if (err != KErrNone)
       
  3286 					{
       
  3287 					ERR_PRINTF2(KTEFErrShareNameNotInIni,i);
       
  3288 					}
       
  3289 				else
       
  3290 					{
       
  3291 					// Number of shared data is limited to the value set in the constant KTEFMaxSharedArraySize
       
  3292 					// The constant is defined in ScriptEngine.h which can be extended from there
       
  3293 					if (iSharedDataNum < KTEFMaxSharedArraySize)
       
  3294 						{
       
  3295 						// If ini input is available for i th object name
       
  3296 						// Creating template class object for sharing the object
       
  3297 						CTestSharedData* sharedObject = NULL;
       
  3298 
       
  3299 						CTEFSharedData<CTestSharedData>* sharedData1 = NULL;
       
  3300 						TRAP(err,sharedData1 = CTEFSharedData<CTestSharedData>::NewL(sharedObject, KTEFSharedDataSize, sharedDataName));
       
  3301 						if (err != KErrNone)
       
  3302 							{
       
  3303 							User::Leave(err);
       
  3304 							}
       
  3305 						else
       
  3306 							{
       
  3307 							sharedData1->EnterCriticalSection();
       
  3308 							sharedObject->Construct();
       
  3309 							sharedData1->ExitCriticalSection();
       
  3310 							// Adding the template object to an array
       
  3311 							iSharedDataArray[iSharedDataNum] = sharedData1;
       
  3312 							// Counting the number of objects created
       
  3313 							// destructor can destroy the objects based on this count
       
  3314 							iSharedDataNum++;
       
  3315 							}
       
  3316 						}
       
  3317 					else
       
  3318 						{
       
  3319 						WARN_PRINTF1(KTEFMaxNumberOfSharedObjectsReached);
       
  3320 						}
       
  3321 					}
       
  3322 				}
       
  3323 			}
       
  3324 		// Cleanup CInidata object
       
  3325 		CleanupStack::PopAndDestroy(configData);
       
  3326 		}
       
  3327 	}
       
  3328 	
       
  3329 /**
       
  3330  * Parses the test block header
       
  3331  * @Return ETrue if pass ok else EFalse
       
  3332  */
       
  3333 // Fix defect 118337, check the configuration file exists or not, and set the flag.
       
  3334 TBool CScriptControl::ParseTestBlockHeader()
       
  3335 	{
       
  3336 	TLex lex(iCurrentScriptLine);
       
  3337 	TPtrC token = lex.NextToken();
       
  3338 	TInt paraCount = 1;
       
  3339 	const TInt KLeastBlockHeaderParaCount = 4;
       
  3340 	_LIT(KLegacySysDrive, "C:");
       
  3341 	_LIT(KDefaultIniFilePath, "\\System\\Data\\");
       
  3342 	
       
  3343 	while (!lex.Eos())
       
  3344 		{
       
  3345 		token.Set(lex.NextToken());
       
  3346 		lex.SkipSpace();
       
  3347 		++paraCount;
       
  3348 		}
       
  3349 	
       
  3350 	if (paraCount < KLeastBlockHeaderParaCount)
       
  3351 		{
       
  3352 		_LIT(KBadError, "Bad error syntax!");
       
  3353 		ERR_PRINTF1(KBadError);
       
  3354 		return EFalse;
       
  3355 		}
       
  3356 
       
  3357 	TFileName defaultIniFilePath(KLegacySysDrive);
       
  3358 	defaultIniFilePath.Append(KDefaultIniFilePath);
       
  3359 	
       
  3360 	iFS.Connect();
       
  3361 	TFindFile fileFind(iFS);
       
  3362 	TInt ret = fileFind.FindByDir(token, defaultIniFilePath);
       
  3363 	iFS.Close();
       
  3364 	if (KErrNotFound == ret)
       
  3365 		{
       
  3366 		_LIT(KFileNotFound, "Configuration File %S Not Found!");
       
  3367 		ERR_PRINTF2(KFileNotFound, &token);
       
  3368 		return EFalse;
       
  3369 		}
       
  3370 	return ETrue;
       
  3371 	}
       
  3372 // End defect 118337
       
  3373 
       
  3374 /**
       
  3375  * Parses the test block and populates the iBlockArray
       
  3376  * @Leave system wide errors
       
  3377  */
       
  3378 void CScriptControl::ParseTestBlockL( TTEFItemArray& aItemArray )
       
  3379 	{
       
  3380 	// Iterate through the commands contained within the test block
       
  3381 	//  and append them to the itemArray.
       
  3382 	TPtrC	startBlockScriptLine	= iCurrentScriptLine;
       
  3383 	TInt	startBlockLineNumber 	= iCurrentScriptLineNumber;
       
  3384 	
       
  3385 	TBool parseResult = ParseTestBlockHeader();
       
  3386 	
       
  3387 	FOREVER
       
  3388 		{
       
  3389 		TTEFBlockItem	blockItem;
       
  3390 		
       
  3391 		// Read in the next script line
       
  3392 		TBool	scriptLineRes = EFalse;
       
  3393 		if( !iStartLooping )
       
  3394 			{
       
  3395 			scriptLineRes = GetNextScriptLine(iCurrentScriptLine);
       
  3396 			}
       
  3397 		else
       
  3398 			{
       
  3399 			scriptLineRes = GetLoopScriptLine(iCurrentScriptLine);
       
  3400 			}
       
  3401 		
       
  3402 		if( !scriptLineRes )
       
  3403 			{
       
  3404 			_LIT( KTEFEoF, "Unexpectedly hit the end of the file" );
       
  3405 			ERR_PRINTF1( KTEFEoF );
       
  3406 			TExitCategoryName  blankPanicString;
       
  3407 			LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine);
       
  3408 			User::Leave( KErrEof );
       
  3409 			}
       
  3410 
       
  3411 		// Strip off any trailling comment
       
  3412 		TInt offset = iCurrentScriptLine.Find(KTEFComment);
       
  3413 		if( offset != KErrNotFound )
       
  3414 			{
       
  3415 			iCurrentScriptLine.Set( iCurrentScriptLine.Mid(0, offset) );
       
  3416 			}
       
  3417 
       
  3418 		TLex lex(iCurrentScriptLine);
       
  3419 		TPtrC token(lex.NextToken());
       
  3420 		
       
  3421 		// Populate the blockItem with the data required for each command
       
  3422 		
       
  3423 		// CREATE_OBJECT <object type> <object name section>
       
  3424 		if(	0 == token.CompareF(KTEFCreateObject) )
       
  3425 			{
       
  3426 			blockItem.iItemType		= ETEFCreateObject;
       
  3427 			blockItem.iObjectType	= lex.NextToken().Left(KTEFMaxNameLength);
       
  3428 			blockItem.iSection		= lex.NextToken().Left(KTEFMaxNameLength);
       
  3429 			}
       
  3430 		// RESTORE_OBJECT <object type> <object name section>
       
  3431 		else if( 0 == token.CompareF(KTEFRestoreObject) )
       
  3432 			{
       
  3433 			blockItem.iItemType		= ETEFRestoreObject;
       
  3434 			blockItem.iObjectType	= lex.NextToken().Left(KTEFMaxNameLength);
       
  3435 			blockItem.iSection		= lex.NextToken().Left(KTEFMaxNameLength);
       
  3436 			}
       
  3437 		// COMMAND [Error TEFParameter] <object name section> <function name> [section]
       
  3438 		else if( 0 == token.CompareF(KTEFCommand) )
       
  3439 			{
       
  3440 			blockItem.iItemType = ETEFCommand;
       
  3441 			TPtrC param = lex.NextToken().Left(KTEFMaxNameLength);
       
  3442 			
       
  3443 			if( param.Length() > 0 )
       
  3444 				{
       
  3445 				while( param[0] == KTEFAsciiExclamation )
       
  3446 					{
       
  3447 					// This is a TEF Error Parameter
       
  3448 					// Extract the type of TEF parameter being read in
       
  3449 					if( param.Length() >= KTEFError().Length() &&
       
  3450 						0 == param.Mid(0,KTEFError().Length()).CompareF(KTEFError) )
       
  3451 						{
       
  3452 						TInt	start = KTEFError().Length();
       
  3453 						TInt	length = param.Length()-start;
       
  3454 						TLex	errorCodeLex( param.Mid(start,
       
  3455 														length ));
       
  3456 						
       
  3457 						TInt errorCode = 0;
       
  3458 						if( errorCodeLex.Val(errorCode) == KErrNone )
       
  3459 							{
       
  3460 							blockItem.iExpectedError = errorCode;
       
  3461 							}
       
  3462 						else
       
  3463 							{
       
  3464 							_LIT(KBadError,"Bad error syntax.");
       
  3465 							ERR_PRINTF1(KBadError);	
       
  3466 							blockItem.iError = KErrNotSupported;
       
  3467 							}
       
  3468 						}
       
  3469 					else if( param.Length() >= KTEFAsyncError().Length() &&
       
  3470 							 0 == param.Mid(0,KTEFAsyncError().Length()).CompareF(KTEFAsyncError))
       
  3471 						{
       
  3472 						TInt	start = KTEFAsyncError().Length();
       
  3473 						TInt	length = param.Length()-start;
       
  3474 						TLex	errorCodeLex( param.Mid(start,
       
  3475 														length ));
       
  3476 						
       
  3477 						TInt errorCode = 0;
       
  3478 						if( errorCodeLex.Val(errorCode) == KErrNone )
       
  3479 							{
       
  3480 							blockItem.iExpectedAsyncError = errorCode;
       
  3481 							}
       
  3482 						else
       
  3483 							{
       
  3484 							_LIT(KBadError,"Bad error syntax.");
       
  3485 							ERR_PRINTF1(KBadError);
       
  3486 							blockItem.iAsyncError = KErrNotSupported;					
       
  3487 							}
       
  3488 						}
       
  3489 					else
       
  3490 						{
       
  3491 						// Unknown TEFParameter
       
  3492 						_LIT(KUnknownTEFParam,"Unknown Test Block TEFParameter.");
       
  3493 						ERR_PRINTF1(KUnknownTEFParam);
       
  3494 						TExitCategoryName  blankPanicString;
       
  3495 						LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine);
       
  3496 						User::Leave(KErrNotSupported);
       
  3497 						}
       
  3498 
       
  3499 					// Read the next token
       
  3500 					param.Set( lex.NextToken().Left(KTEFMaxNameLength) );
       
  3501 					}
       
  3502 				}
       
  3503 				
       
  3504 			// Read in the object section name, function name and optional data section
       
  3505 			blockItem.iCommand.iObject		= param;
       
  3506 			blockItem.iCommand.iFunction	= lex.NextToken().Left(KTEFMaxNameLength);
       
  3507 			blockItem.iSection				= lex.NextToken().Left(KTEFMaxNameLength);
       
  3508 			}
       
  3509 		// STORE <section>
       
  3510 		else if( 0 == token.CompareF(KTEFStore) )
       
  3511 			{
       
  3512 			blockItem.iItemType		= ETEFStore;
       
  3513 			blockItem.iSection		= lex.NextToken().Left(KTEFMaxNameLength);
       
  3514 			}
       
  3515 		// OUTSTANDING <poll interval in ms>
       
  3516 		else if( 0 == token.CompareF(KTEFOutstanding) )
       
  3517 			{
       
  3518 			blockItem.iItemType		= ETEFOutstanding;
       
  3519 			TLex	pollLex( lex.NextToken().Left(KTEFMaxNameLength) );
       
  3520 			TInt	poll = 0;
       
  3521 			blockItem.iTime			= (KErrNone==pollLex.Val(poll)?poll:0);
       
  3522 			blockItem.iSection		= lex.NextToken().Left(KTEFMaxNameLength);		
       
  3523 			}
       
  3524 		// DELAY <time in ms>
       
  3525 		else if( 0 == token.CompareF(KTEFDelay) )
       
  3526 			{
       
  3527 			blockItem.iItemType		= ETEFDelay;
       
  3528 			TLex	delayLex( lex.NextToken().Left(KTEFMaxNameLength) );
       
  3529 			TInt	delay = 0;
       
  3530 			blockItem.iTime = (KErrNone==delayLex.Val(delay)?delay:0);		
       
  3531 			}
       
  3532 		// ASYNC_DELAY <time in ms>
       
  3533 		else if( 0 == token.CompareF(KTEFAsyncDelay) )
       
  3534 			{
       
  3535 			blockItem.iItemType		= ETEFAsyncDelay;
       
  3536 			TLex	delayLex( lex.NextToken().Left(KTEFMaxNameLength) );
       
  3537 			TInt	delay = 0;
       
  3538 			blockItem.iTime = (KErrNone==delayLex.Val(delay)?delay:0);
       
  3539 			}
       
  3540 		// SHARED_ACTIVE_SCHEDULER
       
  3541 		else if( 0 == token.CompareF(KTEFSharedActiveScheduler) )
       
  3542 			{
       
  3543 			blockItem.iItemType		= ETEFSharedActiveScheduler;			
       
  3544 			}
       
  3545 		// STORE_ACTIVE_SCHEDULER
       
  3546 		else if( 0 == token.CompareF(KTEFStoreActiveScheduler) )
       
  3547 			{
       
  3548 			blockItem.iItemType		= ETEFStoreActiveScheduler;			
       
  3549 			}
       
  3550 		// END_TEST_BLOCK [Scheduler Cleanup]
       
  3551 		else if( 0 == token.CompareF(KTEFEndTestBlock) )
       
  3552 			{
       
  3553 			TExitCategoryName  blankPanicString;
       
  3554 			if( 0 == aItemArray.Count() )
       
  3555 				{
       
  3556 				_LIT( KTEFEmptyBlock, "The Test Block is empty." );
       
  3557 				ERR_PRINTF1( KTEFEmptyBlock );
       
  3558 				LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine);
       
  3559 				User::Leave(KErrNotFound);
       
  3560 				}
       
  3561 			else
       
  3562 				{
       
  3563 				// Hit the end of the test block and the package is ready
       
  3564 				// Fix defect 118337, check parse result, and print corresponding message.
       
  3565 				LogResult(parseResult?EPass:EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine);
       
  3566 				//End defect 118337
       
  3567 				break;
       
  3568 				}
       
  3569 			}
       
  3570 		else if( 0 == token.CompareF(KTEFStartTestBlock) )
       
  3571 			{
       
  3572 			// Error - there was no end test block command
       
  3573 			_LIT(KMissingEnd,"Missing END_TEST_BLOCK command.");
       
  3574 			ERR_PRINTF1(KMissingEnd);
       
  3575 			TExitCategoryName  blankPanicString;
       
  3576 			LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine);
       
  3577 			User::Leave(KErrNotFound);
       
  3578 			}
       
  3579 		else
       
  3580 			{
       
  3581 			if( token.Length() > 0 )
       
  3582 				{
       
  3583 				if( 0 != token.Left(2).Compare(KTEFComment) )
       
  3584 					{
       
  3585 					// The SART_TEST_BLOCK command failed
       
  3586 					_LIT(KUnknownCmd,"Unknown Test Block command.");
       
  3587 					ERR_PRINTF1(KUnknownCmd);
       
  3588 					TExitCategoryName  blankPanicString;
       
  3589 					LogResult(EFail, blankPanicString, startBlockLineNumber, startBlockScriptLine);
       
  3590 		
       
  3591 					// Special case for END_TESTCASE commands
       
  3592 					//  If one has been hit here because an END_TEST_BLOCK command was missing
       
  3593 					//  the we must log its completion.
       
  3594 					if( token.CompareF(KTEFEndTestCaseCommand) == 0 || token.CompareF(KTEFEndSyncTestCaseCommand) == 0 )
       
  3595 						{
       
  3596 						LogTestCaseMarkerL();
       
  3597 						}
       
  3598 					User::Leave(KErrNotSupported);
       
  3599 					}
       
  3600 				}
       
  3601 			}
       
  3602 			
       
  3603 		// Append the blockItem to the package
       
  3604 		if( ETEFNull != blockItem.iItemType )
       
  3605 			{
       
  3606 			aItemArray.AppendL( blockItem );
       
  3607 			}
       
  3608 		}
       
  3609 	}
       
  3610 
       
  3611 
       
  3612 _LIT( KTEFSyncStatus, "TEFStatus" );
       
  3613 _LIT( KTEFSyncResult, "TEFResult" );
       
  3614 const TInt KDelay		= 3000000;
       
  3615 const TInt KRetryCount	= 10;
       
  3616 
       
  3617 enum TSyncStatus
       
  3618 	{
       
  3619 	ETEFSyncUnknown		= 0,
       
  3620 	ETEFSyncRunning		= 1,
       
  3621 	ETEFSyncComplete	= 2,
       
  3622 	ETEFSyncWaiting		= 3,
       
  3623 	ETEFSyncContinue	= 4,
       
  3624 	ETEFRetrieveResult	= 5
       
  3625 	};
       
  3626 
       
  3627 /**
       
  3628  * Constructor
       
  3629  */
       
  3630 CSyncControl::CSyncControl()
       
  3631 	: iSharedTEFStatus(NULL), iSharedTEFResult(NULL)
       
  3632 	{
       
  3633 	}
       
  3634 /**
       
  3635  * Destructor
       
  3636  */
       
  3637 CSyncControl::~CSyncControl()
       
  3638 	{
       
  3639 	if( iSharedTEFResult && iSharedTEFStatus )
       
  3640 		{
       
  3641 		// Don't cleanup until the status is correct
       
  3642 		// This will allow time for any retrieve result calls to get through before TEF exits
       
  3643 		// Will retry for 30 seconds
       
  3644 		CTestSharedData* tefStatus = iSharedTEFStatus->Ptr();
       
  3645 		if( tefStatus != NULL )
       
  3646 			{
       
  3647 			TInt64 status = ETEFRetrieveResult;
       
  3648 			TInt count = 0;
       
  3649 			while( status == ETEFRetrieveResult && count < KRetryCount )
       
  3650 				{
       
  3651 				iSharedTEFStatus->EnterCriticalSection();
       
  3652 				HBufC* statusBuffer = NULL;
       
  3653 				TRAPD( err, statusBuffer = HBufC::NewL(tefStatus->TextLength()) );
       
  3654 				if( err == KErrNone )
       
  3655 					{
       
  3656 					TPtr statusPtr( statusBuffer->Des() );
       
  3657 					tefStatus->GetText( statusPtr );
       
  3658 					TLex lex(statusPtr);
       
  3659 					lex.Val(status);
       
  3660 					delete statusBuffer;
       
  3661 					}
       
  3662 				iSharedTEFStatus->ExitCriticalSection();
       
  3663 
       
  3664 				// Don't deley for the first i
       
  3665 				if( count > 0 )
       
  3666 					{
       
  3667 					User::After( KDelay );
       
  3668 					}
       
  3669 				count++;
       
  3670 				}
       
  3671 			}
       
  3672 		delete iSharedTEFResult;
       
  3673 		delete iSharedTEFStatus;		
       
  3674 		}
       
  3675 	}
       
  3676 
       
  3677 /**
       
  3678  * Two phase construction
       
  3679  */	
       
  3680 CSyncControl* CSyncControl::NewL()
       
  3681 	{
       
  3682 	CSyncControl* self = CSyncControl::NewLC();
       
  3683 	CleanupStack::Pop();
       
  3684 	return self;
       
  3685 	}
       
  3686 
       
  3687 /**
       
  3688  * Two phase construction
       
  3689  */	
       
  3690 CSyncControl* CSyncControl::NewLC()
       
  3691 	{
       
  3692 	CSyncControl* self = new (ELeave) CSyncControl();
       
  3693 	CleanupStack::PushL(self);
       
  3694 	self->ConstructL();
       
  3695 	return self;
       
  3696 	}
       
  3697 
       
  3698 /**
       
  3699  * ConstructL
       
  3700  */	
       
  3701 void CSyncControl::ConstructL()
       
  3702 	{
       
  3703 	// Initialise the sync status shared data
       
  3704 	CTestSharedData* tefStatus = NULL;
       
  3705 	iSharedTEFStatus = CTEFSharedData<CTestSharedData>::NewL(	tefStatus,
       
  3706 																KMaxSharedDataLength,
       
  3707 																KTEFSyncStatus );
       
  3708 	iSharedTEFStatus->EnterCriticalSection();
       
  3709 	tefStatus->Construct();
       
  3710 	HBufC* statusBuffer = NULL;
       
  3711 	TRAPD( err, statusBuffer = HBufC::NewL(sizeof(TInt64)) );
       
  3712 	if( err != KErrNone )
       
  3713 		{
       
  3714 		iSharedTEFStatus->ExitCriticalSection();
       
  3715 		User::Leave( err );
       
  3716 		}
       
  3717 	TPtr statusPtr( statusBuffer->Des() );
       
  3718 	statusPtr.Num( ETEFSyncWaiting );
       
  3719 	tefStatus->SetText( statusPtr );
       
  3720 	delete statusBuffer;
       
  3721 	iSharedTEFStatus->ExitCriticalSection();
       
  3722 
       
  3723 	// Initialise the sync result shared data
       
  3724 	CTestSharedData* tefResult = NULL;
       
  3725 	iSharedTEFResult = CTEFSharedData<CTestSharedData>::NewL(	tefResult,
       
  3726 																KMaxSharedDataLength,
       
  3727 																KTEFSyncResult );
       
  3728 	iSharedTEFResult->EnterCriticalSection();
       
  3729 	tefResult->Construct();
       
  3730 	HBufC* resBuffer = NULL;
       
  3731 	TRAP( err, resBuffer = HBufC::NewL(sizeof(TInt64)) );
       
  3732 	if( err != KErrNone )
       
  3733 		{
       
  3734 		iSharedTEFResult->ExitCriticalSection();
       
  3735 		User::Leave( err );
       
  3736 		}
       
  3737 	TPtr resPtr( resBuffer->Des() );
       
  3738 	resPtr.Num( EInconclusive );
       
  3739 	tefResult->SetText( resPtr );
       
  3740 	delete resBuffer;
       
  3741 	iSharedTEFResult->ExitCriticalSection();
       
  3742 	}
       
  3743 
       
  3744 /**
       
  3745  * @param aError - Error value resulting from synchronised testcase for logging
       
  3746  * Sets the result obtained from synchronised testcase for logging
       
  3747  */
       
  3748 void CSyncControl::SetResultL( TVerdict aError )
       
  3749 	{
       
  3750 	// Retrieve the status and result shared data pointers
       
  3751 	CTestSharedData* tefResult = iSharedTEFResult->Ptr();
       
  3752 	CTestSharedData* tefStatus = iSharedTEFStatus->Ptr();
       
  3753 
       
  3754 	if( tefResult != NULL && tefStatus != NULL )
       
  3755 		{
       
  3756 		// Update the shared sync test case result code
       
  3757 		iSharedTEFResult->EnterCriticalSection();
       
  3758 		HBufC* resBuffer = NULL;
       
  3759 		TRAPD( err, resBuffer = HBufC::NewL(sizeof(TInt64)) );
       
  3760 		if( err != KErrNone )
       
  3761 			{
       
  3762 			iSharedTEFResult->ExitCriticalSection();
       
  3763 			User::Leave( err );
       
  3764 			}
       
  3765 		TPtr resPtr( resBuffer->Des() );
       
  3766 		resPtr.Num( (TInt64)aError );
       
  3767 		tefResult->SetText( resPtr );
       
  3768 		delete resBuffer;
       
  3769 		
       
  3770 		iSharedTEFResult->ExitCriticalSection();
       
  3771 		
       
  3772 		// So now the test has complete and the result has been updated
       
  3773 		//  we need to update the status to reflect this
       
  3774 		iSharedTEFStatus->EnterCriticalSection();
       
  3775 		HBufC* statusBuffer = NULL;
       
  3776 		TRAP( err, statusBuffer = HBufC::NewL(sizeof(TInt64)) );
       
  3777 		if( err != KErrNone )
       
  3778 			{
       
  3779 			iSharedTEFStatus->ExitCriticalSection();
       
  3780 			User::Leave( err );
       
  3781 			}
       
  3782 		TPtr statusPtr( statusBuffer->Des() );
       
  3783 		statusPtr.Num( ETEFRetrieveResult );
       
  3784 		tefStatus->SetText( statusPtr );
       
  3785 		delete statusBuffer;
       
  3786 		
       
  3787 		iSharedTEFStatus->ExitCriticalSection();
       
  3788 		}
       
  3789 	else
       
  3790 		{
       
  3791 		User::Leave( KErrNotFound );
       
  3792 		}
       
  3793 	}
       
  3794 
       
  3795 /**
       
  3796  * Identifies state of synchronised testcases and continues with the test or completes the tests
       
  3797  */
       
  3798 TBool CSyncControl::TestCaseContinueL()
       
  3799 	{
       
  3800 	TBool tefContinue = EFalse;
       
  3801 	
       
  3802 	// Retrieve the status and result shared data pointers
       
  3803 	CTestSharedData* tefStatus = iSharedTEFStatus->Ptr();
       
  3804 	CTestSharedData* tefResult = iSharedTEFResult->Ptr();
       
  3805 
       
  3806 	if( tefStatus != NULL && tefResult != NULL )
       
  3807 		{
       
  3808 		iSharedTEFStatus->EnterCriticalSection();
       
  3809 
       
  3810 		// Retrieve the current status
       
  3811 		HBufC* statusBuffer = NULL;
       
  3812 		TRAPD( err, statusBuffer = HBufC::NewL(tefStatus->TextLength()) );
       
  3813 		if( err != KErrNone )
       
  3814 			{
       
  3815 			iSharedTEFStatus->ExitCriticalSection();
       
  3816 			User::Leave( err );
       
  3817 			}
       
  3818 
       
  3819 		TPtr statusPtr( statusBuffer->Des() );
       
  3820 		tefStatus->GetText( statusPtr );
       
  3821 		TLex lex(statusPtr);
       
  3822 		TInt64	status = ETEFSyncUnknown;
       
  3823 		User::LeaveIfError( lex.Val(status) );
       
  3824 
       
  3825 		if( status == ETEFSyncContinue )
       
  3826 			{
       
  3827 			tefContinue = ETrue;
       
  3828 			// Update the status to running
       
  3829 			HBufC* buffer = NULL;
       
  3830 			TRAP( err, buffer = HBufC::NewL(sizeof(TInt64)) );
       
  3831 			if( err != KErrNone )
       
  3832 				{
       
  3833 				delete statusBuffer;
       
  3834 				iSharedTEFStatus->ExitCriticalSection();
       
  3835 				User::Leave( err );
       
  3836 				}
       
  3837 
       
  3838 			TPtr ptr( buffer->Des() );
       
  3839 			ptr.Num( ETEFSyncRunning );
       
  3840 			tefStatus->SetText( ptr );
       
  3841 			delete buffer;
       
  3842 			}
       
  3843 		else if( status == ETEFSyncComplete )
       
  3844 			{
       
  3845 			// Previous test has completed and a new sync block has been hit
       
  3846 			// Update the status to waiting
       
  3847 			HBufC* buffer = NULL;
       
  3848 			TRAP( err, buffer = HBufC::NewL(sizeof(TInt64)) );
       
  3849 			if( err != KErrNone )
       
  3850 				{
       
  3851 				delete statusBuffer;
       
  3852 				iSharedTEFStatus->ExitCriticalSection();
       
  3853 				User::Leave( err );
       
  3854 				}
       
  3855 
       
  3856 			TPtr ptr( buffer->Des() );
       
  3857 			ptr.Num( ETEFSyncWaiting );
       
  3858 			tefStatus->SetText( ptr );
       
  3859 			delete buffer;
       
  3860 			}
       
  3861 		delete statusBuffer;
       
  3862 		iSharedTEFStatus->ExitCriticalSection();
       
  3863 		}
       
  3864 	else
       
  3865 		{
       
  3866 		User::Leave( KErrNotFound );
       
  3867 		}
       
  3868 	return tefContinue;
       
  3869 	}
       
  3870 
       
  3871 /**
       
  3872  * Takes in a script line updates any relative file paths into corresponding absolute path based on the current script file path
       
  3873  * @param aScriptLineString - Pointer descriptor containing a particular script line for updation
       
  3874  */
       
  3875 void CScriptControl::MakeAbsoluteFilePathsL(TPtrC16& aScriptLineString)
       
  3876 	{
       
  3877 	TLex lex(aScriptLineString);
       
  3878 	iAlteredScriptLine.Zero(); // Initialise the altered script line to zero b4 we start processing
       
  3879 	TBuf<KMaxTestExecuteCommandLength> commandName; // To store the command name, basically first token of each script line
       
  3880 	TBuf<KMaxTestExecuteCommandLength> commandString; // To store individual tokens of script line for processing
       
  3881 	TBuf<KMaxTestExecuteCommandLength> prevCommandString;
       
  3882 	const TInt KTEFMinFileExtnSizeIni = 4;
       
  3883 	const TInt KTEFMinFileExtnSizeScript = 7;
       
  3884 
       
  3885 	while(!lex.Eos()) // start a loop for each token until end of the script line
       
  3886 		{
       
  3887 		lex.NextToken();
       
  3888 		lex.SkipSpace();
       
  3889 		if (lex.MarkedToken().Length() > KMaxTestExecuteCommandLength)
       
  3890 			{
       
  3891 			User::Leave(KErrTooBig);
       
  3892 			}
       
  3893 
       
  3894 		commandString.Copy(lex.MarkedToken());
       
  3895 		lex.Mark();
       
  3896 
       
  3897 		if (commandName.CompareF(KTEFRunScriptCommand) == 0 &&
       
  3898 			commandString.CompareF(KTEFNull) != 0)
       
  3899 			{
       
  3900 			// if the command name is RUN_SCRIPT, then check the parameter is not not null and has valid .script extn
       
  3901 			// We append .script extn if the length of the token is less than 7 (.script -> Length)
       
  3902 			// Or when the token does not end with .script enxtn
       
  3903 			if(commandString.Length() < KTEFMinFileExtnSizeScript ||
       
  3904 				commandString.Right(KTEFMinFileExtnSizeScript).CompareF(KTEFScriptExtension) != 0)
       
  3905 				{
       
  3906 				commandString.Append(KTEFScriptExtension);
       
  3907 				}
       
  3908 			}
       
  3909 
       
  3910 		// Expand recognised variables into their values
       
  3911 		// At the moment just ${SYSDRIVE} -> GetSystemDrive()
       
  3912 		ExpandVariables(commandString);
       
  3913 
       
  3914 		// we consider eligible path if the token is an argument for RUN_SCRIPT
       
  3915 		// or any INI file or an argument for RUN_UTILS command
       
  3916 		// Check to see if the token contains a ":" as second character represeting a drive letter
       
  3917 		if (commandString.Length() >= KTEFMinFileExtnSizeIni &&
       
  3918 			commandString.Mid(1,1).CompareF(KTEFColon) != 0)
       
  3919 			{
       
  3920 			// if the ":" is not found, we process converting relative -> absolute path
       
  3921 			// Provided the token ends with .script or .ini extns
       
  3922 		    if ((commandString.Length() >= KTEFMinFileExtnSizeScript && 
       
  3923 				commandString.Right(KTEFMinFileExtnSizeScript).CompareF(KTEFScriptExtension) == 0) ||
       
  3924 				(commandString.Length() >= KTEFMinFileExtnSizeIni && 
       
  3925 				commandString.Right(KTEFMinFileExtnSizeIni).CompareF(KTEFIniExtension) == 0))
       
  3926 				{
       
  3927 				// token does not does not have a ':' but is a eligible path,
       
  3928 				// so, convert relative path to absolute path
       
  3929 				TRAPD(err, ConvertRelativeToAbsoluteL(commandString));
       
  3930 				if(err != KErrNone)
       
  3931 					{
       
  3932 					// Leave here since we have got an invalid path
       
  3933 					User::Leave(err);
       
  3934 					}				
       
  3935 				}
       
  3936 			else if(commandName.CompareF(KTEFRunUtilsCommand) == 0 &&
       
  3937 					(prevCommandString.CompareF(KTEFRunUtilsCopyFile) == 0 ||
       
  3938 					prevCommandString.CompareF(KTEFRunUtilsMkDir) == 0 ||
       
  3939 					prevCommandString.CompareF(KTEFRunUtilsDeleteFile) == 0 ||
       
  3940 					prevCommandString.CompareF(KTEFRunUtilsDelete) == 0 ||
       
  3941 					prevCommandString.CompareF(KTEFRunUtilsMakeReadWrite) == 0 ||
       
  3942 					prevCommandString.CompareF(KTEFDeleteDirectory) == 0))
       
  3943 				{
       
  3944 				// token does not does not have a ':' but is a eligible path,
       
  3945 				// so, convert relative path to absolute path
       
  3946 				TRAPD(err, ConvertRelativeToAbsoluteL(commandString));
       
  3947 				if(err != KErrNone)
       
  3948 					{
       
  3949 					// Leave here since we have got an invalid path
       
  3950 					User::Leave(err);
       
  3951 					}
       
  3952 				}
       
  3953 			}
       
  3954 		//start defect 120600 
       
  3955 		//remove the code which append an extra space.
       
  3956 		// if (iAlteredScriptLine.Length())
       
  3957 		//end defect 120600
       
  3958 		if (iAlteredScriptLine.Length() == 0)
       
  3959 			{
       
  3960 			// While completng the processing for the first token in the script line,
       
  3961 			// we record the token as command name, so that we can use it to identify
       
  3962 			// eligible paths in the following loop cycles for the script line
       
  3963 			commandName.Copy(commandString);
       
  3964 			}
       
  3965 		prevCommandString.Copy(commandString);
       
  3966 		// Construct the altered script line with individual verified tokens of script line
       
  3967 		if(iAlteredScriptLine.Length() + commandString.Length() <= iAlteredScriptLine.MaxLength() )
       
  3968 			{
       
  3969 			iAlteredScriptLine.Append(commandString);			
       
  3970 			}
       
  3971 		else// this scipte too long buffer not long enought
       
  3972 			{			
       
  3973 			User::Leave(KErrTooBig);
       
  3974 			}
       
  3975 		}
       
  3976 	// At the end of the while loop, we are ready with new processed script line
       
  3977 	// which we shall update it with the original reference taken in
       
  3978 	aScriptLineString.Set(iAlteredScriptLine);
       
  3979 	}
       
  3980 
       
  3981 /**
       
  3982  * Takes in lex token and updates any relative file paths into corresponding absolute path based on the current script file path
       
  3983  * @param aCommandString - Pointer descriptor containing a particular token within a script line for updation
       
  3984  */
       
  3985 void CScriptControl::ConvertRelativeToAbsoluteL(TDes& aCommandString)
       
  3986 	{
       
  3987 	TInt offset = 0;
       
  3988 	TInt posOfLastSlash=iScriptFile.LocateReverse('\\') ;
       
  3989 	TBuf<KMaxTestExecuteCommandLength> tempStore(iScriptFile.Mid(0,posOfLastSlash)); // Initial script file path
       
  3990 
       
  3991 	if(aCommandString.FindC(KTEFOneUp) >= 0)
       
  3992 		{
       
  3993 		while(aCommandString.FindC(KTEFOneUp) >= 0)
       
  3994 			{
       
  3995 			offset = aCommandString.FindC(KTEFOneUp);
       
  3996 			posOfLastSlash=tempStore.LocateReverse('\\') ;
       
  3997 			if (posOfLastSlash <= 0)
       
  3998 				{
       
  3999 				User::Leave(KTEFErrInvalidRelPath);
       
  4000 				}
       
  4001 			tempStore.Copy(iScriptFile.Mid(0,posOfLastSlash));// script file path
       
  4002 			aCommandString.Copy(aCommandString.Mid(offset + 3)); // 3 for ..'\\'
       
  4003 			}
       
  4004 
       
  4005 		tempStore.Append('\\');
       
  4006 		}
       
  4007 	else if (aCommandString.FindC(KTEFDotSlash) >= 0)
       
  4008 		{
       
  4009 		offset = aCommandString.FindC(KTEFDotSlash);
       
  4010 		aCommandString.Copy(aCommandString.Mid(offset + 1));
       
  4011 		}
       
  4012 	else if(aCommandString.Locate('\\') == 0)
       
  4013 		{
       
  4014 		tempStore.Copy(iScriptFile.Mid(0,2)); // Example: c:
       
  4015 		}
       
  4016 	else
       
  4017 		{
       
  4018 		tempStore.Append('\\');
       
  4019 		}
       
  4020 
       
  4021 	tempStore.Append(aCommandString);
       
  4022 	aCommandString.Copy(tempStore);
       
  4023 	}
       
  4024 
       
  4025 /**
       
  4026  * Expand recognised variables in script file into their corresponding value
       
  4027  * Currently supported variable is ${SYSDRIVE} -> GetSystemDrive() / Drive letter set from testexecute.ini
       
  4028  * @param aCommandString - Descriptor containing a particular token within a script line for updation
       
  4029  */
       
  4030 void CScriptControl::ExpandVariables(TDes& aCommandString)
       
  4031 	{
       
  4032 	TInt offset = 0;
       
  4033 	if (aCommandString.FindC(KTEFSysDrive) >= 0)
       
  4034 		{
       
  4035 		// If we find ${SYSDRIVE} in the token, replace it with the drive letter to be substitued
       
  4036 		offset = aCommandString.FindC(KTEFSysDrive);
       
  4037 		aCommandString.Replace(offset, 11, iTestSysDrive);
       
  4038 		}
       
  4039 	}