mmtestenv/mmtestfw/Source/TestFramework/parseline.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // This module contains CParseLine and CSuiteDll classes
       
    15 // CParseLine contains the functions required to execute
       
    16 // a line of test script file.
       
    17 // CSuiteDll objects contains information about test suite
       
    18 // dlls that have been loaded.
       
    19 // 
       
    20 //
       
    21 
       
    22 // system includes
       
    23 #include <f32file.h>
       
    24 
       
    25 // test system includes
       
    26 #include "TestFramework.h"
       
    27 #include "script.h"
       
    28 #include "parseline.h"
       
    29 #include "Filename.h" 
       
    30 
       
    31 #include "parseline.inl"
       
    32 
       
    33 const TInt KTimeIncrement = 100*1000000; // max wait interval in micro-seconds (100s)
       
    34 const TUint KMaxThreadAttempts = 128;	// max number of times to attempt to create a thread
       
    35 
       
    36 /**
       
    37  *
       
    38  * File path literals
       
    39  *
       
    40  * @xxxx
       
    41  *
       
    42  */
       
    43 _LIT(KTxtDLLpath, "c:\\;c:\\system\\libs;d:\\;d:\\system\\libs;e:\\;e:\\system\\libs;z:\\;z:\\system\\libs");
       
    44 
       
    45 /**
       
    46  *
       
    47  * Script parameter defaults
       
    48  *
       
    49  * @xxxx
       
    50  *
       
    51  */
       
    52 //const TInt KTestGuardTimerDefault = 1000L;	// EABI warning removal
       
    53 const TInt KPanicGuardTimerDefault = 1000000L;
       
    54 const TInt KPanicExitReasonDefault = 0;
       
    55 
       
    56 /**
       
    57  *
       
    58  * CParseLine first-phase constructor
       
    59  *
       
    60  * @xxxx
       
    61  *
       
    62  */
       
    63 CParseLine::CParseLine(const TDesC& aMatchString)
       
    64 	:iTestVerdict(EPass), iMatchString(aMatchString)
       
    65 	{
       
    66 	}
       
    67 
       
    68 /**
       
    69  *
       
    70  * CParseLine second-phase constructor 
       
    71  *
       
    72  * @param	"CScript* aScript"
       
    73  *			The script to be parsed
       
    74  *
       
    75  * @param	"CTestUtils* aTestUtils"
       
    76  *			The TestUtils object to use
       
    77  *
       
    78  * @param	"CLog* aLog"
       
    79  *			The logger to use
       
    80  *
       
    81  * @xxxx
       
    82  *
       
    83  */
       
    84 void CParseLine::ConstructL(CScript* aScript, CTestUtils* aTestUtils, CLog* aLog, TInt64 aGuardTimer)
       
    85 	{
       
    86 	// create a new Array to store the test steps in
       
    87 	iArrayLoadedSuiteDll = new(ELeave) CArrayPtrFlat<CSuiteDll>(1);
       
    88 
       
    89 	iScript = aScript;
       
    90 	iTestUtils = aTestUtils;
       
    91 	iLog = aLog;
       
    92 	iGuardTimer = aGuardTimer;
       
    93 	iSeverity = ESevrAll;
       
    94 	iBreakOnError = EFalse;
       
    95 	}
       
    96 
       
    97 /**
       
    98  *
       
    99  * CParseLine static constructor 
       
   100  *
       
   101  * @param	"CScript* aScript"
       
   102  *			The script to be parsed
       
   103  *
       
   104  * @param	"CTestUtils* aTestUtils"
       
   105  *			The TestUtils object to use
       
   106  *
       
   107  * @param	"CLog* aLog"
       
   108  *			The logger to use
       
   109  *
       
   110  * @xxxx
       
   111  *
       
   112  */
       
   113 CParseLine* CParseLine::NewL(CScript* aScript, CTestUtils* aTestUtils, CLog* aLog, TInt64 aGuardTimer, const TDesC& aMatchString)
       
   114 	{
       
   115 	CParseLine* self = new(ELeave) CParseLine(aMatchString);
       
   116 	CleanupStack::PushL(self);
       
   117 	self->ConstructL(aScript, aTestUtils, aLog, aGuardTimer);
       
   118 	CleanupStack::Pop();
       
   119 	return self;
       
   120 	}
       
   121 
       
   122 /**
       
   123  *
       
   124  * CParseLine destructor 
       
   125  *
       
   126  * @xxxx
       
   127  *
       
   128  */
       
   129 CParseLine::~CParseLine()
       
   130 	{
       
   131 
       
   132 	// unload DLLs and their records
       
   133 	if (iArrayLoadedSuiteDll)
       
   134 		{
       
   135 		// delete all objects in iArrayLoadedSuiteDll
       
   136 		// the destructors will unload any loaded DLLS
       
   137 		iArrayLoadedSuiteDll->ResetAndDestroy();
       
   138 		delete iArrayLoadedSuiteDll;
       
   139 		}
       
   140 
       
   141 	}
       
   142 
       
   143 /**
       
   144  *
       
   145  * Process a single line from the script file.
       
   146  *
       
   147  * @param	"const TDesC8& aNarrowline"
       
   148  *			The script line
       
   149  *
       
   150  * @param	"TInt8 aLineNo"
       
   151  *			The script line number
       
   152  *
       
   153  * @xxxx
       
   154  *
       
   155  */
       
   156 void CParseLine::ProcessLineL(const TDesC8& aNarrowline, TInt aLineNo)
       
   157 	{
       
   158 	// make a local unicode buffer
       
   159 	TPtr16 lineBuf(REINTERPRET_CAST(TUint16*,User::AllocLC(KMaxLenScriptLine*2)), 0, KMaxLenScriptLine);
       
   160 	lineBuf.Fill('\0', KMaxLenScriptLine);
       
   161 
       
   162 	// convert the narrow script file to Unicode
       
   163 	// TBC find a better way to do this
       
   164 	CFileName* testnameU = CFileName::NewLC();
       
   165 	testnameU->Copy(aNarrowline);
       
   166 
       
   167 	// find the end of the line
       
   168 	TInt end = testnameU->Locate('\n');
       
   169 
       
   170 	// copy the line into lineBuf
       
   171 	if ((end != KErrNotFound) && (end < KMaxLenScriptLine))
       
   172 		lineBuf = testnameU->Left(end - 1);
       
   173 	else
       
   174 		lineBuf = testnameU->FileName();
       
   175 
       
   176 	// destroy filename
       
   177 	CleanupStack::PopAndDestroy(testnameU);
       
   178 
       
   179 	// the parser relies on spaces between tokens. Commas are
       
   180 	// allowed but are just replaced with spaces
       
   181 	TInt findComma = lineBuf.Locate(TChar(','));
       
   182 	while (findComma != KErrNotFound )
       
   183 		{
       
   184 		// found a comma so replace with space
       
   185 		lineBuf.Replace(findComma, 1, _L(" "));
       
   186 		findComma = lineBuf.Locate(TChar(','));
       
   187 		}
       
   188 
       
   189 	// for debugging display the line with a line no
       
   190 #ifdef SCRIPT_DEBUG
       
   191 	INFO_PRINTF3(_L("Line:%d %S "), aLineNo, &lineBuf);
       
   192 #endif
       
   193 
       
   194 	// if there has been a failure and the user has selected
       
   195 	// x then the next commands in the script are skipped until
       
   196 	// a test complete statement is found
       
   197 	if (iBreakOnError)
       
   198 		{
       
   199 		if (lineBuf.FindF(_L("TEST_COMPLETE")) == 0)
       
   200 			{
       
   201 			TestComplete(lineBuf);
       
   202 			// reset flag now test complete found
       
   203 			iBreakOnError = EFalse;
       
   204 			}
       
   205 
       
   206 		CleanupStack::PopAndDestroy(); // linebuf
       
   207 		// do not process the rest of the line
       
   208 		return;
       
   209 		}
       
   210 
       
   211 	// check the line for command keywords
       
   212 	if ((lineBuf.Find(_L("//")) == 0) || (lineBuf.Find(_L("#")) == 0))
       
   213 		{
       
   214 		// ignore comments
       
   215 		}
       
   216 	else if (lineBuf.FindF(_L("LOAD_SUITE")) == 0)
       
   217 		{
       
   218 		LoadSuiteL(lineBuf);
       
   219 		}
       
   220 	else if (lineBuf.FindF(_L("RUN_SCRIPT")) == 0)
       
   221 		{
       
   222 		RunScriptL(lineBuf);
       
   223 		}
       
   224 	else if (lineBuf.FindF(_L("RUN_TEST_STEP")) == 0)
       
   225 		{
       
   226 		RunTestStep(lineBuf);
       
   227 		}
       
   228 	else if (lineBuf.FindF(_L("RUN_PANIC_STEP")) == 0)
       
   229 		{
       
   230 		RunPanicTestStep(lineBuf);
       
   231 		}
       
   232 	else if (lineBuf.FindF(_L("RUN_TERMINATION_STEP")) == 0)
       
   233 		{
       
   234 		RunTerminationTestStep(lineBuf);
       
   235 		}
       
   236 	else if (lineBuf.FindF(_L("RUN_UTILS")) == 0)
       
   237 		{
       
   238 		RunUtil(lineBuf);
       
   239 		}
       
   240 	else if (lineBuf.FindF(_L("RUN_PROGRAM")) == 0)
       
   241 		{
       
   242 		RunProgram(lineBuf);
       
   243 		}
       
   244 	else if (lineBuf.FindF(_L("UNLOAD")) == 0)
       
   245 		{
       
   246 		Unload();
       
   247 		}
       
   248 	else if (lineBuf.FindF(_L("HEAP_MARK")) == 0)
       
   249 		{
       
   250 		HeapMark();
       
   251 		}
       
   252 	else if (lineBuf.FindF(_L("HEAP_CHECK")) == 0)
       
   253 		{
       
   254 		HeapCheck();
       
   255 		}
       
   256 	else if (lineBuf.FindF(_L("REQUEST_MARK")) == 0)
       
   257 		{
       
   258 		RequestMark();	
       
   259 		}
       
   260 	else if (lineBuf.FindF(_L("REQUEST_CHECK")) == 0)
       
   261 		{
       
   262 		RequestCheck();
       
   263 		}
       
   264 	else if (lineBuf.FindF(_L("HANDLES_MARK")) == 0)
       
   265 		{
       
   266 		HandlesMark();
       
   267 		}
       
   268 	else if (lineBuf.FindF(_L("HANDLES_CHECK")) == 0)
       
   269 		{
       
   270 		HandlesCheck();
       
   271 		}
       
   272 	else if (lineBuf.FindF(_L("PRINT")) == 0)
       
   273 		{
       
   274 		ScriptPrint(lineBuf);
       
   275 		}
       
   276 	else if (lineBuf.FindF(_L("DELAY")) == 0)
       
   277 		{
       
   278 		Delay(lineBuf);
       
   279 		}
       
   280 	else if (lineBuf.FindF(_L("SEVERITY")) == 0)
       
   281 		{
       
   282 		SetSeverity(lineBuf);
       
   283 		}
       
   284 	else if (lineBuf.FindF(_L("PAUSE_AT_END")) == 0)
       
   285 		{
       
   286 		// if implemented, add iScript->iPauseAtEnd = ETrue;
       
   287 		WARN_PRINTF1(_L("Warning : PAUSE_AT_END not implemented"));
       
   288 		}
       
   289 	else if (lineBuf.FindF(_L("MULTITHREAD")) == 0)
       
   290 		{
       
   291 		WARN_PRINTF1(_L("Warning : MULTITHREAD keyword no longer required"));
       
   292 		}
       
   293 	else if (lineBuf.FindF(_L("SINGLETHREAD")) == 0)
       
   294 		{
       
   295 		ERR_PRINTF1(_L("Error : Single thread operation no longer supported"));
       
   296 		}
       
   297 	else if (lineBuf.FindF(_L("PAUSE")) == 0)
       
   298 		{
       
   299 		iScript->Pause();
       
   300 		}
       
   301 	else if (lineBuf.FindF(_L("BREAK_ON_ERROR")) == 0)
       
   302 		{
       
   303 		// if the current test verdict is not PASS
       
   304 		// give the user the chance to quit
       
   305 		if ( iTestVerdict != EPass )
       
   306 			iBreakOnError = iScript->BreakOnError();
       
   307 		}
       
   308 	else if (lineBuf.FindF(_L("TEST_COMPLETE")) == 0)
       
   309 		{
       
   310 		// use Tlex to decode the cmd line
       
   311 		TestComplete(lineBuf);
       
   312 		}
       
   313 	else if (lineBuf.FindF(_L("LOG_SETTINGS")) == 0)
       
   314 		{
       
   315 		// use Tlex to decode the cmd line
       
   316 		LogSettings(lineBuf);
       
   317 		}
       
   318 	else if (lineBuf.Length() == 0)
       
   319 		{
       
   320 		// ignore blank lines
       
   321 		}
       
   322 	else
       
   323 		{
       
   324 		// failed to decode line
       
   325 		ERR_PRINTF3(_L("Error in script line:%d - \'%S\'"), aLineNo, &lineBuf);
       
   326 		}
       
   327 
       
   328 	CleanupStack::PopAndDestroy(); // linebuf
       
   329 	}
       
   330 
       
   331 /**
       
   332  *
       
   333  * Implements the TEST_COMPLETE script command.
       
   334  *
       
   335  * @param	"const TDesC& aText"
       
   336  *			The script line
       
   337  *
       
   338  * @xxxx
       
   339  *
       
   340  */
       
   341 void CParseLine::TestComplete(const TDesC& aText)
       
   342 	{
       
   343 	// use Tlex to decode the cmd line
       
   344 	TLex lex(aText);
       
   345 
       
   346 	// start at the begining
       
   347 	TPtrC token = lex.NextToken();
       
   348 
       
   349 	// get suite name, if any
       
   350 	token.Set(lex.NextToken());
       
   351 
       
   352 	if (token.Length() != 0)
       
   353 		{
       
   354 		TBuf<KMaxLenTestSuiteName> currentSuiteName;
       
   355 		currentSuiteName = token;
       
   356 
       
   357 		// get step name, if any
       
   358 		token.Set(lex.NextToken());
       
   359 	
       
   360 		if (token.Length() != 0)
       
   361 			{	
       
   362 			iCurrentStepName = token;
       
   363 			iCurrentSuiteName = currentSuiteName;
       
   364 			}
       
   365 		else
       
   366 			{
       
   367 			// failed to decode line - require 0 or 2 parameters exactly
       
   368 			// use last suite/step name, return fail
       
   369 			ERR_PRINTF2(_L("Error in script line: \'%S\'"), &aText);
       
   370 			iTestVerdict = EFail;
       
   371 			}
       
   372 		}
       
   373 
       
   374 	if (!iSkip)
       
   375 		{
       
   376 		// add the current result to the script
       
   377 		iScript->AddResult(iTestVerdict);		
       
   378 		}
       
   379 		
       
   380 	// reset for next test
       
   381 	iTestVerdict = EPass;
       
   382 	}
       
   383 
       
   384 /**
       
   385  *
       
   386  * Implements the PRINT script command.
       
   387  *
       
   388  * @param	"const TDesC& aText"
       
   389  *			The script line
       
   390  *
       
   391  * @xxxx
       
   392  *
       
   393  */
       
   394 void CParseLine::ScriptPrint(const TDesC& aText)
       
   395 	{
       
   396 	// display the text after the PRINT and 1 space = 6
       
   397 	INFO_PRINTF2(_L("%s "), (aText.Ptr() + 6));
       
   398 	}
       
   399 
       
   400 /**
       
   401  *
       
   402  * Implements the DELAY script command.
       
   403  *
       
   404  * @param	"const TDesC& aText"
       
   405  *			The script line
       
   406  *
       
   407  * @xxxx
       
   408  *
       
   409  */
       
   410 void CParseLine::Delay(const TDesC& aText)
       
   411 	{
       
   412 	// if the test has already failed skip the delay
       
   413 	if (iTestVerdict != EPass)
       
   414 		{
       
   415 		WARN_PRINTF1(_L("Skipped delay as test has already failed"));
       
   416 		return;
       
   417 		}
       
   418 
       
   419 	// get the required time for the delay
       
   420 	// first get the value as a string
       
   421 	TLex timeOut(aText);
       
   422 	timeOut.NextToken();
       
   423 	TPtrC token = timeOut.NextToken();
       
   424 
       
   425 	// convert the value into a TInt
       
   426 	TLex lexTime(token);
       
   427 	TInt64 guardTimerValue;
       
   428 	if (lexTime.Val(guardTimerValue) != KErrNone  )
       
   429 		{
       
   430 		ERR_PRINTF2(_L("Error in guard timer value : could not decode \'%S\' as value"), 
       
   431 					&token);
       
   432 		return;
       
   433 		}
       
   434 
       
   435 	INFO_PRINTF2(_L("Delay for %ld mS"), guardTimerValue);
       
   436 
       
   437 	// wait for the required delay
       
   438 	User::After(I64INT(guardTimerValue) * 1000);
       
   439 	}
       
   440 	
       
   441 /**
       
   442  *
       
   443  * Implements the SEVERITY script command.
       
   444  *
       
   445  * @param	"const TDesC& aText"
       
   446  *			The script line
       
   447  *
       
   448  * @xxxx
       
   449  *
       
   450  */
       
   451 void CParseLine::SetSeverity(const TDesC& aText)
       
   452 	{
       
   453 	// get the required time for the delay
       
   454 	// first get the value as a string
       
   455 	TLex severityOut(aText);
       
   456 	severityOut.NextToken();
       
   457 	TPtrC token = severityOut.NextToken();
       
   458 
       
   459 	// convert the value into a TInt
       
   460 	TLex lexSeverity(token);
       
   461 	TInt severityValue = ESevrAll;
       
   462 	if (lexSeverity.Val(severityValue) != KErrNone)
       
   463 		{
       
   464 		ERR_PRINTF2(_L("Error in severity level value : could not decode \'%S\' as value"),
       
   465 					&token);
       
   466 		return;
       
   467 		}
       
   468 
       
   469 	// check severity value to ensure that only bitmasks in use are set...
       
   470 	if(!LogSeverity::IsValid(severityValue))
       
   471 		{
       
   472 		ERR_PRINTF1(_L("Error in severity value : out of range"));
       
   473 		return;
       
   474 		}
       
   475 	else
       
   476 		{
       
   477 		iSeverity = severityValue;
       
   478 
       
   479 		TInt noOfDlls = iArrayLoadedSuiteDll->Count();
       
   480 		for ( TInt i = 0; i < noOfDlls; i++)
       
   481 			{
       
   482 			CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
       
   483 			CTestSuite* testSuite = ptrSuite->Suite();
       
   484 			testSuite->SetSeverity(iSeverity);
       
   485 			}
       
   486 		}
       
   487 
       
   488 	INFO_PRINTF2(_L("Severity is set to %d"), severityValue);
       
   489 	}
       
   490 
       
   491 /**
       
   492  *
       
   493  * Implements the RUN_SCRIPT script command.
       
   494  *
       
   495  * @param	"const TDesC& aText"
       
   496  *			The script line
       
   497  *
       
   498  * @xxxx
       
   499  *
       
   500  */
       
   501 void CParseLine::RunScriptL(const TDesC& aText)
       
   502 	{
       
   503 	// use Tlex to decode the cmd line
       
   504 	TLex lex(aText);
       
   505 
       
   506 	// start at the begining
       
   507 	TPtrC token=lex.NextToken();
       
   508 
       
   509 	// step over the keyword
       
   510 	token.Set(lex.NextToken());
       
   511 
       
   512 	// format for printing
       
   513 	INFO_PRINTF2(_L("RUN_SCRIPT %S"), &token);
       
   514 
       
   515 	// create a new Script object (but use the current parser
       
   516 	// as it has the dll loaded record)
       
   517 	CScript* newScript=CScript::NewLC(this, iTestUtils, iLog, iGuardTimer, iMatchString);
       
   518 
       
   519 	// read in the script file
       
   520 	CFileName* scriptFileName = CFileName::NewLC();
       
   521 	*scriptFileName = token;
       
   522 
       
   523 	if (newScript->OpenScriptFile(scriptFileName))
       
   524 		{
       
   525 		// process it
       
   526 		iTestVerdict = newScript->ExecuteScriptL();
       
   527 
       
   528 		// don't bother logging verdicts for scripts - not really useful
       
   529 		// add results from the new script to the owner script
       
   530 		iScript->AddResult(newScript);
       
   531 		}
       
   532 	else
       
   533 		{
       
   534 		// failed to find script so verdict incloncusive
       
   535 		iTestVerdict = EInconclusive;
       
   536 		}
       
   537 
       
   538 	CleanupStack::PopAndDestroy(scriptFileName);
       
   539 	CleanupStack::PopAndDestroy(newScript);
       
   540 	}
       
   541 
       
   542 /**
       
   543  *
       
   544  * Implements the RUN_TEST_STEP script command.
       
   545  *
       
   546  * @param	"const TDesC& aText"
       
   547  *			The script line
       
   548  *
       
   549  * @xxxx
       
   550  *
       
   551  */
       
   552 void CParseLine::RunTestStep(const TDesC& aText)
       
   553 	{
       
   554 	// use TLex to decode the cmd line
       
   555 	TLex lex(aText);
       
   556 
       
   557 	// step over keyword
       
   558 	lex.NextToken();
       
   559 
       
   560 	// get guard timer
       
   561 	TPtrC timeout;
       
   562 	timeout.Set(lex.NextToken());
       
   563 
       
   564 	// get the other parameters
       
   565 	TPtrC suite, step, config, name, paramSet;
       
   566 	suite.Set(lex.NextToken());
       
   567 	step.Set(lex.NextToken());
       
   568 	config.Set(lex.NextToken());
       
   569 	name.Set(lex.NextToken());
       
   570 	if (name.Length()==0)
       
   571 		{
       
   572 		// name is optional, if not given use step 
       
   573 		name.Set(step);
       
   574 		}
       
   575 	paramSet.Set(lex.NextToken()); 
       
   576 	if (paramSet.Length()==0)
       
   577 		{
       
   578 		// paramSet is optional, if not given use name 
       
   579 		paramSet.Set(name);
       
   580 		}
       
   581 
       
   582 	// save the name of the current test suite / step
       
   583 	iCurrentSuiteName = suite;
       
   584 	iCurrentStepName = name;
       
   585 
       
   586 	TVerdict currentTestVerdict;
       
   587 
       
   588 	INFO_PRINTF2(_L("<a name=\"%S\"</a>"),&name);
       
   589 	
       
   590 	if (iMatchString.Length()>0 && name.Match(iMatchString)<0)
       
   591 		{
       
   592 		// we have a match string but no match - so skip
       
   593 		INFO_PRINTF2(_L("TEST_STEP:%S skipped"), &name);
       
   594 		iSkip = ETrue;
       
   595 		return;
       
   596 		}
       
   597 		
       
   598 	iSkip = EFalse;
       
   599 
       
   600 	// convert the guard timer value to a TInt64
       
   601 	TLex lexTimeOut(timeout);
       
   602 	TInt64 guardTimerValue;
       
   603 	if (lexTimeOut.Val(guardTimerValue) != KErrNone)
       
   604 		{
       
   605 		ERR_PRINTF2(_L("Error in guard timer value: %S"),
       
   606 					&timeout);
       
   607 		currentTestVerdict = EInconclusive;
       
   608 		}
       
   609 
       
   610 	else
       
   611 		{
       
   612 		// override guard timer if necessary
       
   613 		if((guardTimerValue == KNoGuardTimer) && (iGuardTimer != KNoGuardTimer))
       
   614 			{
       
   615 			INFO_PRINTF3(_L("Warning : Guard timer value overridden from %ld to %ld"),
       
   616 							guardTimerValue, iGuardTimer);
       
   617 			guardTimerValue = iGuardTimer;
       
   618 			}
       
   619 
       
   620 		// log the start of a test step
       
   621 		INFO_PRINTF7(_L("RUN_TEST_STEP:%S (step:%S suite:%S timeout:%ldmS config:%S(%S))"),
       
   622 					&name, &step, &suite, guardTimerValue, &config, &paramSet);
       
   623 
       
   624 		// NOTE. Now running multithreaded all the time.
       
   625 		currentTestVerdict = DoTestNewThread(suite, step, guardTimerValue, config, paramSet);
       
   626 		}
       
   627 
       
   628 	TPtrC verdictText = CLog::TestResultText(currentTestVerdict);
       
   629 	
       
   630 	INFO_PRINTF3(_L("TEST_STEP:%S returned:%S "), 
       
   631 				&name, &verdictText);
       
   632 
       
   633 	// this result is only significant if everything else has passed
       
   634 	if (iTestVerdict == EPass)
       
   635 		iTestVerdict = currentTestVerdict;
       
   636 
       
   637 	}
       
   638 
       
   639 /**
       
   640  *
       
   641  * Implements the RUN_PANIC_STEP script command.
       
   642  *
       
   643  * @param	"const TDesC& aText"
       
   644  *			The script line
       
   645  *
       
   646  * @xxxx
       
   647  *
       
   648  */
       
   649 void CParseLine::RunPanicTestStep(const TDesC& aText)
       
   650 	{
       
   651 	// NOTE. RUN_PANIC_STEP now incorporates the panic reason and category
       
   652 
       
   653 	// use Tlex to decode the cmd line
       
   654 	TLex lex(aText);
       
   655 
       
   656 	// start at the begining
       
   657 	TPtrC timeout=lex.NextToken();
       
   658 
       
   659 	// step over the keyword
       
   660 	timeout.Set(lex.NextToken());
       
   661 
       
   662 	// get the other parameters
       
   663 	TPtrC suite, step;
       
   664 	TPtrC category, reason;
       
   665 	TPtrC config, name, paramSet;
       
   666 
       
   667 	suite.Set(lex.NextToken());
       
   668 	step.Set(lex.NextToken());
       
   669 	category.Set(lex.NextToken());
       
   670 	reason.Set(lex.NextToken());
       
   671 	config.Set(lex.NextToken());
       
   672 	name.Set(lex.NextToken());
       
   673 	if (name.Length()==0)
       
   674 		{
       
   675 		// name is optional, if not given use step 
       
   676 		name.Set(step);
       
   677 		}
       
   678 	paramSet.Set(lex.NextToken()); 
       
   679 	if (paramSet.Length()==0)
       
   680 		{
       
   681 		// paramSet is optional, if not given use name 
       
   682 		paramSet.Set(name);
       
   683 		}
       
   684 
       
   685 	if (iMatchString.Length()>0 && name.Match(iMatchString)<0)
       
   686 		{
       
   687 		// we have a match string but no match - so skip
       
   688 		INFO_PRINTF2(_L("TEST_STEP:%S skipped"), &name);
       
   689 		iSkip = ETrue;
       
   690 		return;
       
   691 		}
       
   692 		
       
   693 	iSkip = EFalse;
       
   694 
       
   695 	// save the name of the current test suite / step
       
   696 	iCurrentSuiteName = suite;
       
   697 	iCurrentStepName = name;
       
   698 
       
   699 	// convert the guard timer value to a TInt
       
   700 	TLex lexTimeOut(timeout);
       
   701 	TInt64 guardTimerValue;
       
   702 	if (lexTimeOut.Val(guardTimerValue) != KErrNone)
       
   703 		{
       
   704 		ERR_PRINTF3(_L("Error in guard timer value:%S using default %dmS"), 
       
   705 					&timeout, KPanicGuardTimerDefault);
       
   706 		guardTimerValue = KPanicGuardTimerDefault;
       
   707 		}
       
   708 
       
   709 	// convert the exitReason value to a TInt
       
   710 	TLex lexReason(reason);
       
   711 	TInt exitReason;
       
   712 	if (lexReason.Val(exitReason) != KErrNone)
       
   713 		{
       
   714 		ERR_PRINTF3(_L("Error in exitReason value:%S using default %d"), 
       
   715 					&reason, KPanicExitReasonDefault);
       
   716 		exitReason = KPanicExitReasonDefault;
       
   717 		}
       
   718 
       
   719 	// override guard timer if necessary
       
   720 	if((guardTimerValue == KNoGuardTimer) && (iGuardTimer != KNoGuardTimer))
       
   721 		{
       
   722 		INFO_PRINTF3(_L("Warning : Guard timer value overridden from %ld to %ld"),
       
   723 						guardTimerValue, iGuardTimer);
       
   724 		guardTimerValue = iGuardTimer;
       
   725 		}
       
   726 
       
   727 	// log the start of a test step
       
   728 	INFO_PRINTF9(_L("RUN_PANIC_STEP:%S (step:%S suite:%S timeout:%ldmS category:%S reason:%d config:%S(%S))"),
       
   729 				&name, &step, &suite, guardTimerValue, &category, exitReason, &config, &paramSet);
       
   730 
       
   731 	// run the test step
       
   732 	TVerdict currentTestVerdict;
       
   733 
       
   734 	// now running multithreaded all the time
       
   735 	currentTestVerdict = DoPanicTest(suite, step, guardTimerValue,
       
   736 									 category, exitReason, config, paramSet);
       
   737 
       
   738 	TPtrC verdictText = CLog::TestResultText(currentTestVerdict);
       
   739 	INFO_PRINTF3(_L("TEST_STEP:%S returned:%S "), 
       
   740 				&name, &verdictText);
       
   741 
       
   742 	// this result is only significant if every thing else has passed
       
   743 	if (iTestVerdict == EPass)
       
   744 		iTestVerdict = currentTestVerdict;
       
   745 
       
   746 	}
       
   747 	
       
   748 /**
       
   749  *
       
   750  * Implements the RUN_TERMINATION_STEP script command.
       
   751  *
       
   752  * @param	"const TDesC& aText"
       
   753  *			The script line
       
   754  *
       
   755  * @xxxx
       
   756  *
       
   757  */
       
   758 void CParseLine::RunTerminationTestStep(const TDesC& aText)
       
   759 	{
       
   760 	// use Tlex to decode the cmd line
       
   761 	TLex lex(aText);
       
   762 
       
   763 	// start at the begining
       
   764 	TPtrC timeout=lex.NextToken();
       
   765 
       
   766 	// step over the keyword
       
   767 	timeout.Set(lex.NextToken());
       
   768 
       
   769 	// get the other parameters
       
   770 	TPtrC suite, step;
       
   771 	TPtrC reason;
       
   772 	TPtrC config;
       
   773 
       
   774 	suite.Set(lex.NextToken());
       
   775 	step.Set(lex.NextToken());
       
   776 	reason.Set(lex.NextToken());
       
   777 	config.Set(lex.NextToken());
       
   778 
       
   779 	// save the name of the current test suite / step
       
   780 	iCurrentSuiteName = suite;
       
   781 	iCurrentStepName = step;
       
   782 
       
   783 	// convert the guard timer value to a TInt
       
   784 	TLex lexTimeOut(timeout);
       
   785 	TInt64 guardTimerValue;
       
   786 	if (lexTimeOut.Val(guardTimerValue) != KErrNone)
       
   787 		{
       
   788 		ERR_PRINTF3(_L("Error in guard timer value:%S using default %dmS"), 
       
   789 					&timeout, KPanicGuardTimerDefault);
       
   790 		guardTimerValue = KPanicGuardTimerDefault;
       
   791 		}
       
   792 
       
   793 	// convert the exitReason value to a TInt
       
   794 	TLex lexReason(reason);
       
   795 	TInt exitReason;
       
   796 	if (lexReason.Val(exitReason) != KErrNone)
       
   797 		{
       
   798 		ERR_PRINTF3(_L("Error in exitReason value:%S using default %d"), 
       
   799 					&reason, KPanicExitReasonDefault);
       
   800 		exitReason = KPanicExitReasonDefault;
       
   801 		}
       
   802 
       
   803 	// override guard timer if necessary
       
   804 	if((guardTimerValue == KNoGuardTimer) && (iGuardTimer != KNoGuardTimer))
       
   805 	{
       
   806 		INFO_PRINTF3(_L("Warning : Guard timer value overridden from %ld to %ld"),
       
   807 						guardTimerValue, iGuardTimer);
       
   808 		guardTimerValue = iGuardTimer;
       
   809 	}
       
   810 
       
   811 	// log the start of a test step
       
   812 	INFO_PRINTF6(_L("RUN_TERMINATION_STEP:%S suite:%S timeout:%ldmS reason:%d config:%S"),
       
   813 				&step, &suite, guardTimerValue, exitReason, &config);
       
   814 
       
   815 	// run the test step
       
   816 	TVerdict currentTestVerdict;
       
   817 
       
   818 	// now running multithreaded all the time
       
   819 	currentTestVerdict = DoTerminationTest(suite, step, guardTimerValue,
       
   820 									 exitReason, config);
       
   821 
       
   822 	TPtrC verdictText = CLog::TestResultText(currentTestVerdict);
       
   823 	INFO_PRINTF3(_L("TEST_STEP:%S returned:%S "), 
       
   824 				&step, &verdictText);
       
   825 
       
   826 	// this result is only significant if every thing else has passed
       
   827 	if (iTestVerdict == EPass)
       
   828 		iTestVerdict = currentTestVerdict;
       
   829 
       
   830 	}
       
   831 
       
   832 /**
       
   833  *
       
   834  * Implements the RUN_UTILS script command.
       
   835  *
       
   836  * @param	"const TDesC& aText"
       
   837  *			The script line
       
   838  *
       
   839  * @xxxx
       
   840  *
       
   841  */
       
   842 void CParseLine::RunUtil(const TDesC& aText)
       
   843 	{
       
   844 	// Call the utils
       
   845 	iTestUtils->RunUtils(aText);
       
   846 	}
       
   847 
       
   848 /**
       
   849  *
       
   850  * Implements the REBOOT script command.
       
   851  *
       
   852  * @param	"const TDesC& aText"
       
   853  *			The script line
       
   854  *
       
   855  * @xxxx
       
   856  *
       
   857  */
       
   858 void CParseLine::Reboot()
       
   859 	{
       
   860 	WARN_PRINTF1(_L("Warning : REBOOT command not implemented"));
       
   861 	}
       
   862 
       
   863 /**
       
   864  *
       
   865  * Static function to call DoTestStep which is run
       
   866  * in a separate thread
       
   867  *
       
   868  * @param	"TAny* aPtr"
       
   869  *			The test step data
       
   870  *
       
   871  * @return "TInt"
       
   872  *			EPOC error code
       
   873  *
       
   874  * @xxxx
       
   875  *
       
   876  */
       
   877 TInt CParseLine::ThreadFunctionL(TAny* aPtr)
       
   878 	{
       
   879 	TInt result = KErrNone;
       
   880 
       
   881 	// get clean-up stack
       
   882   	CTrapCleanup* trapCleanup = CTrapCleanup::New();
       
   883 
       
   884 	TRAPD(err, result = ThreadTrapFunctionL(aPtr));
       
   885 
       
   886 	delete trapCleanup;
       
   887 	return((err != KErrNone) ? err : result);
       
   888 	}
       
   889 
       
   890 /**
       
   891  *
       
   892  * Main function to call DoTestStep, called from within
       
   893  * a trap
       
   894  *
       
   895  * @param	"TAny* aPtr"
       
   896  *			The test step data
       
   897  *
       
   898  * @return "TInt"
       
   899  *			EPOC error code
       
   900  *
       
   901  * @xxxx
       
   902  *
       
   903  */
       
   904 TInt CParseLine::ThreadTrapFunctionL(TAny* aPtr)
       
   905 	{
       
   906 	// get the data for the test
       
   907 	CStepData* data = REINTERPRET_CAST(CStepData*, aPtr);
       
   908 	CSuiteDll* suiteDll = data->SuiteDll();
       
   909 	CTestSuite* testSuite = suiteDll->Suite();
       
   910 
       
   911 	// setup local logger
       
   912 	CLog* logClient	= CLog::NewLC();
       
   913 	logClient->OpenLogFileL();
       
   914 	testSuite->SetLogSystem(logClient);
       
   915 
       
   916 	// do the test step 
       
   917 	TVerdict result =  testSuite->DoTestStep(data->Step(), data->Config(), data->ParamSet());
       
   918 
       
   919 	// NB it is the CALLING program's responsibility to save/restore the logger.
       
   920 	// If the thread terminates prematurely, the logger is in an undefined state.
       
   921 
       
   922 	CleanupStack::PopAndDestroy(logClient);
       
   923 	testSuite->SetLogSystem(NULL);
       
   924 
       
   925 	// return the test result
       
   926 	return result;
       
   927 	}
       
   928 
       
   929 /**
       
   930  *
       
   931  * Do a test step in a new thread.
       
   932  *
       
   933  * @param	"const TDesC& aSuite"
       
   934  *			The test suite
       
   935  *
       
   936  * @param	"const TDesC& aStep"
       
   937  *			The test step
       
   938  *
       
   939  * @param	"TInt aGuardTimerValue"
       
   940  *			The guard timer value
       
   941  *
       
   942  * @param	"const TDesC& aConfig"
       
   943  *			The config data
       
   944  *
       
   945  * @return  "TVerdict"
       
   946  *			The test result
       
   947  *
       
   948  * @xxxx
       
   949  *
       
   950  */
       
   951 TVerdict CParseLine::DoTestNewThread(const TDesC& aSuite, const TDesC& aStep, 
       
   952 							TInt64 aGuardTimerValue, const TDesC& aConfig, const TDesC& aParamSet)
       
   953 	{
       
   954 	//	get the number of suites loaded
       
   955 	TInt noOfDlls = iArrayLoadedSuiteDll->Count();
       
   956 
       
   957 	// search the list of loaded test suite DLLs for the required one
       
   958 	for (TInt i = 0; i < noOfDlls; i++)
       
   959 		{
       
   960 		CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
       
   961 		TPtrC name = ptrSuite->Name();
       
   962 
       
   963 		if (name.FindF(aSuite)!= KErrNotFound)
       
   964 			{
       
   965 			// reset step status
       
   966 			CTestSuite* testSuite = ptrSuite->Suite();
       
   967 			testSuite->SetStepStatus(EStepStatusNone);
       
   968 
       
   969 			// store old log status, for restore at thread exit
       
   970 			// NB we must do this here, as if thread times out, the log
       
   971 			// is in an undefined state
       
   972 			CLog* oldLogger = testSuite->LogSystem();
       
   973 
       
   974 			CStepData* data = NULL;
       
   975 			TRAPD(err, data = CStepData::NewL(aStep, aConfig, aParamSet, ptrSuite));
       
   976 			if (err != KErrNone)
       
   977 				{
       
   978 				ERR_PRINTF2(_L("CStepData::NewL() left with error %d : unable to create test data!"), err);
       
   979 				return EFail;
       
   980 				}
       
   981 			
       
   982 			// get step's own stack and heap sizes
       
   983 			TInt theHeapSize = KMaxTestThreadHeapSize;
       
   984 			TInt theStackSize = KTestStackSize;
       
   985 			GetHeapAndStackSize(data, &theHeapSize, &theStackSize);
       
   986 
       
   987 			TInt res = KErrAlreadyExists;
       
   988 			RThread newThread;
       
   989 
       
   990 			TPtrC threadBaseName(_L("DoTestThread"));
       
   991 			TBuf<32> threadName;
       
   992 			
       
   993 			// create a unique named test thread
       
   994 			// this will leave if creation is not successful
       
   995 			TRAP (res, CreateUniqueTestThreadL( threadBaseName, 
       
   996 												threadName, 
       
   997 												newThread, 
       
   998 												ThreadFunctionL,
       
   999 												theStackSize,
       
  1000 												KMinHeapSize,
       
  1001 												theHeapSize,
       
  1002 												data ) );
       
  1003 
       
  1004 			
       
  1005 			if (res != KErrNone)
       
  1006 				{
       
  1007 				ERR_PRINTF2(_L("CreateUniqueTestThreadL() left with error %d : unable to create test thread "), res);
       
  1008 				delete data;
       
  1009 				data = NULL;
       
  1010 				return EFail;
       
  1011 				}
       
  1012 
       
  1013 			// start clock
       
  1014 			TTime testStart, testStop;
       
  1015 			testStart.HomeTime();
       
  1016 			
       
  1017 			// start the thread and request the status
       
  1018 			TRequestStatus threadStatus;
       
  1019 			newThread.Logon(threadStatus);
       
  1020 
       
  1021 			// if there is no guard timer value, don't time at all
       
  1022 			if (aGuardTimerValue == KNoGuardTimer)
       
  1023 				{
       
  1024 				// no guard timer
       
  1025 				newThread.Resume();
       
  1026 				User::WaitForRequest(threadStatus);
       
  1027 				}
       
  1028 			else
       
  1029 				{
       
  1030 				// wait for either test thread or timer to end
       
  1031 				RTimer guardTimer;
       
  1032 				guardTimer.CreateLocal();			// create for this thread
       
  1033 				TRequestStatus timerStatus;
       
  1034 				newThread.Resume();
       
  1035 
       
  1036 				// NB now using At() to allow 64-bit timer values
       
  1037 				TInt64 guardTimerUsec = aGuardTimerValue * 1000;
       
  1038 				TInt64 totalTime = 0;
       
  1039 
       
  1040 				for (;;)
       
  1041 					{
       
  1042 					if (totalTime>=guardTimerUsec) // timeout has occured
       
  1043 						break;
       
  1044 					TInt timeout;
       
  1045 
       
  1046 					if (totalTime+KTimeIncrement >= guardTimerUsec)
       
  1047 						{
       
  1048 						TInt64 temp = guardTimerUsec-totalTime;
       
  1049 						timeout = I64INT(temp);
       
  1050 						}
       
  1051 					else
       
  1052 						timeout = KTimeIncrement;
       
  1053 					totalTime += timeout;
       
  1054 					guardTimer.After(timerStatus, timeout);
       
  1055 					User::WaitForRequest(threadStatus, timerStatus);
       
  1056 					if (threadStatus!=KRequestPending) // normal exit
       
  1057 						break;
       
  1058 					}
       
  1059 
       
  1060 				guardTimer.Cancel();
       
  1061 				guardTimer.Close();
       
  1062 				}
       
  1063 
       
  1064 			// reset any file server error simulations
       
  1065 			RFs fs;
       
  1066 			TInt fsError = fs.Connect();
       
  1067 			if (fsError == KErrNone)
       
  1068 				{
       
  1069 				fs.SetErrorCondition(KErrNone);
       
  1070 				}
       
  1071 			fs.Close();
       
  1072 
       
  1073 			// restore logger
       
  1074 			testSuite->SetLogSystem(oldLogger);
       
  1075 
       
  1076 			// get the test result
       
  1077 			TVerdict result = STATIC_CAST(TVerdict, threadStatus.Int());
       
  1078 
       
  1079 			// check terminated ok
       
  1080 			switch(newThread.ExitType())
       
  1081 				{
       
  1082 				case EExitTerminate:
       
  1083 				case EExitKill:
       
  1084 					break;
       
  1085 				case EExitPanic:
       
  1086 					{
       
  1087 					TExitCategoryName exitCategory = newThread.ExitCategory();
       
  1088 					TInt exitReason = newThread.ExitReason();
       
  1089  					ERR_PRINTF3(_L("Thread had a panic %S:%d"), &exitCategory, exitReason);
       
  1090 
       
  1091 					result = EFail;
       
  1092 					}
       
  1093 					break;
       
  1094 				case EExitPending:
       
  1095 					// if the thread is still pending then the guard timer must have expired
       
  1096 					ERR_PRINTF1(_L("Thread timed out"));
       
  1097 					// kill the test step thread
       
  1098 					newThread.Kill(1);
       
  1099 					// give the OS time to cleanup devices, etc.
       
  1100 					// NB if the thread dies, the postamble will NOT run
       
  1101 					User::After(2000000);
       
  1102 					result = EFail;
       
  1103 					break;
       
  1104 				default:
       
  1105 					break;
       
  1106 				}
       
  1107 
       
  1108 			// done with the test thread
       
  1109 			newThread.Close();
       
  1110 
       
  1111 			// stop clock
       
  1112 			testStop.HomeTime();
       
  1113 
       
  1114 			TUint testDuration = I64INT(testStop.MicroSecondsFrom(testStart).Int64());
       
  1115 			testDuration /= 1000; // to microseconds
       
  1116 			TUint testDurationMsec = testDuration % 1000;
       
  1117 			TUint testDurationSec = testDuration / 1000;
       
  1118 			INFO_PRINTF3(_L("Test took %d.%03d sec"), testDurationSec, testDurationMsec);
       
  1119 
       
  1120 			// return the test verdict
       
  1121 			delete data;
       
  1122 			data = NULL;
       
  1123 			return result;
       
  1124 			}
       
  1125 		}
       
  1126 
       
  1127 	// the required suite has not been found
       
  1128 	ERR_PRINTF3(_L("Error in test step:%S - cannot find suite:%S" ),
       
  1129 					&aStep, &aSuite);
       
  1130 
       
  1131 	return ETestSuiteError;
       
  1132 	}
       
  1133 
       
  1134 /**
       
  1135  *
       
  1136  * Do a test step which is expected to panic.
       
  1137  *
       
  1138  * @param	"const TDesC& aSuite"
       
  1139  *			The test suite
       
  1140  *
       
  1141  * @param	"const TDesC& aStep"
       
  1142  *			The test step
       
  1143  *
       
  1144  * @param	"TInt aGuardTimerValue"
       
  1145  *			The guard timer value
       
  1146  *
       
  1147  * @param	"const TExitCategoryName aExitCategory"
       
  1148  *			The expected exit category
       
  1149  *
       
  1150  * @param	"TInt aExitReason"
       
  1151  *			The expected exit reason
       
  1152  *
       
  1153  * @param	"const TDesC& aConfig"
       
  1154  *			The config data
       
  1155  *
       
  1156  * @return "TVerdict"
       
  1157  *			The test result
       
  1158  *
       
  1159  * @xxxx
       
  1160  *
       
  1161  */
       
  1162 TVerdict CParseLine::DoPanicTest(const TDesC& aSuite, const TDesC& aStep, TInt64 aGuardTimerValue,
       
  1163 									  const TExitCategoryName aExitCategory, TInt aExitReason, 
       
  1164 									  const TDesC& aConfig, const TDesC& aParamSet)
       
  1165 	{
       
  1166 
       
  1167 	//	get the number of suites loaded
       
  1168 	TInt noOfDlls = iArrayLoadedSuiteDll->Count();
       
  1169 
       
  1170 	// search the list of loaded test suite DLLs for the required one
       
  1171 	for (TInt i = 0; i < noOfDlls; i++)
       
  1172 		{
       
  1173 		CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
       
  1174 		TPtrC name = ptrSuite->Name();
       
  1175 
       
  1176 		if (name.FindF(aSuite)!= KErrNotFound)
       
  1177 			{
       
  1178 			// reset step status
       
  1179 			CTestSuite* testSuite = ptrSuite->Suite();
       
  1180 			testSuite->SetStepStatus(EStepStatusNone);
       
  1181 
       
  1182 			// store old log status, for restore at thread exit
       
  1183 			// NB we must do this here, as if thread times out, the log
       
  1184 			// is in an undefined state
       
  1185 			CLog* oldLogger = testSuite->LogSystem();
       
  1186 
       
  1187 			CStepData* data = NULL;
       
  1188 			TRAPD(err, data = CStepData::NewL(aStep, aConfig, aParamSet, ptrSuite));
       
  1189 			if (err != KErrNone)
       
  1190 				{
       
  1191 				ERR_PRINTF2(_L("CStepData::NewL() left with error %d : unable to create test data!"), err);
       
  1192 				return EFail;
       
  1193 				}
       
  1194 
       
  1195 			// get step's own stack and heap sizes
       
  1196 			TInt theHeapSize = KMaxTestThreadHeapSize;
       
  1197 			TInt theStackSize = KTestStackSize;
       
  1198 			GetHeapAndStackSize(data, &theHeapSize, &theStackSize);
       
  1199 
       
  1200 			TInt res = KErrAlreadyExists;
       
  1201 			RThread newThread;
       
  1202 
       
  1203 			// create a unique test name by appending a counter
       
  1204 			TPtrC threadBaseName(_L("DoTestThread"));
       
  1205 			TBuf<32> threadName;
       
  1206 			
       
  1207 			// create a unique named test thread
       
  1208 			// this will leave if creation is not successful
       
  1209 			TRAP (res, CreateUniqueTestThreadL( threadBaseName, 
       
  1210 												threadName, 
       
  1211 												newThread, 
       
  1212 												ThreadFunctionL,
       
  1213 												theStackSize,
       
  1214 												KMinHeapSize,
       
  1215 												theHeapSize,
       
  1216 												data ) );
       
  1217 			
       
  1218 			if (res != KErrNone)
       
  1219 				{
       
  1220 				ERR_PRINTF2(_L("CreateUniqueTestThreadL() left with error %d : unable to create test thread "), res);
       
  1221 				delete data;
       
  1222 				data = NULL;
       
  1223 				return EFail;
       
  1224 				}
       
  1225 
       
  1226 			// start clock
       
  1227 			TTime testStart, testStop;
       
  1228 			testStart.HomeTime();
       
  1229 			
       
  1230 			// start the thread and request the status
       
  1231 			TRequestStatus threadStatus;
       
  1232 			newThread.Logon(threadStatus);
       
  1233 
       
  1234 			// if there is no guard timer value, don't time at all
       
  1235 			if (aGuardTimerValue == KNoGuardTimer)
       
  1236 				{
       
  1237 				// no guard timer
       
  1238 				newThread.Resume();
       
  1239 				User::WaitForRequest(threadStatus);
       
  1240 				}
       
  1241 			else
       
  1242 				{
       
  1243 				// wait for either test thread or timer to end
       
  1244 				RTimer guardTimer;
       
  1245 				guardTimer.CreateLocal();			// create for this thread
       
  1246 				TRequestStatus timerStatus;
       
  1247 				newThread.Resume();
       
  1248 
       
  1249 				// NB now using At() to allow 64-bit timer values
       
  1250 				TInt64 guardTimerUsec = aGuardTimerValue * 1000;
       
  1251 				TInt64 totalTime = 0;
       
  1252 
       
  1253 				for (;;)
       
  1254 					{
       
  1255 					if (totalTime>=guardTimerUsec) // timeout has occured
       
  1256 						break;
       
  1257 					TInt timeout;
       
  1258 
       
  1259 					if (totalTime+KTimeIncrement >= guardTimerUsec)
       
  1260 						{
       
  1261 						TInt64 temp = guardTimerUsec-totalTime;
       
  1262 						timeout = I64INT(temp);
       
  1263 						}
       
  1264 					else
       
  1265 						timeout = KTimeIncrement;
       
  1266 						totalTime += timeout;
       
  1267 					guardTimer.After(timerStatus, timeout);
       
  1268 					User::WaitForRequest(threadStatus, timerStatus);
       
  1269 					if (threadStatus!=KRequestPending) // normal exit
       
  1270 						break;
       
  1271 					}
       
  1272 
       
  1273 				guardTimer.Cancel();
       
  1274 				guardTimer.Close();
       
  1275 				}
       
  1276 
       
  1277 			// restore logger
       
  1278 			testSuite->SetLogSystem(oldLogger);
       
  1279 
       
  1280 			// get the test result
       
  1281 			TVerdict result = STATIC_CAST(TVerdict, threadStatus.Int());
       
  1282 
       
  1283 			// check terminated ok
       
  1284 			switch(newThread.ExitType())
       
  1285 				{
       
  1286 				case EExitPanic:
       
  1287 					{
       
  1288 					TExitCategoryName exitCategory = newThread.ExitCategory();
       
  1289 					TInt exitReason = newThread.ExitReason();
       
  1290 					if((exitCategory != aExitCategory) || (exitReason != aExitReason && aExitReason != KNoPanicReason) )
       
  1291 						{
       
  1292 						ERR_PRINTF3(_L("Test step had an unexpected panic %S:%d and failed"),
       
  1293 									&exitCategory, exitReason);
       
  1294 						result = EFail;
       
  1295 						}
       
  1296 					else
       
  1297 						{
       
  1298 						// check here that the panic occurred within the test itself
       
  1299 						CTestSuite* testSuite = ptrSuite->Suite();
       
  1300 						TTestStepStatus status = testSuite->StepStatus();
       
  1301 						switch(status)
       
  1302 							{
       
  1303 							case EStepStatusPreamble:
       
  1304 								{
       
  1305 								// thread panicked in the test itself - success
       
  1306 								INFO_PRINTF3(_L("Test step had a panic %S:%d and passed"),
       
  1307 											&exitCategory, exitReason);
       
  1308 								result = EPass;
       
  1309 								}
       
  1310 								break;
       
  1311 							case EStepStatusStart:
       
  1312 								{
       
  1313 								// thread panicked in preamble
       
  1314 								ERR_PRINTF3(_L("Test step had a panic %S:%d in preamble"),
       
  1315 											&exitCategory, exitReason);
       
  1316 								result = EFail;
       
  1317 								}
       
  1318 								break;
       
  1319 							case EStepStatusTest:
       
  1320 								{
       
  1321 								// thread panicked in postamble
       
  1322 								ERR_PRINTF3(_L("Test step had a panic %S:%d in postamble"),
       
  1323 											&exitCategory, exitReason);
       
  1324 								result = EFail;
       
  1325 								}
       
  1326 								break;
       
  1327 							default:
       
  1328 								{
       
  1329 								// thread panicked outside the test
       
  1330 								ERR_PRINTF3(_L("Test step had a panic %S:%d outside the test"),
       
  1331 											&exitCategory, exitReason);
       
  1332 								result = EFail;
       
  1333 								}
       
  1334 								break;
       
  1335 							}	// end switch
       
  1336 						}
       
  1337 					}
       
  1338 					break;
       
  1339 				case EExitPending:
       
  1340 					// if the thread is still pending then the guard timer must have expired
       
  1341 					ERR_PRINTF1(_L("Thread timed out"));
       
  1342 					// kill the test step thread
       
  1343 					newThread.Kill(1);
       
  1344 					// give the OS time to cleanup devices, etc.
       
  1345 					// NB if the thread dies, the postamble will NOT run
       
  1346 					User::After(2000000);
       
  1347 					result = EFail;
       
  1348 					break;
       
  1349 				case EExitTerminate:
       
  1350 				case EExitKill:
       
  1351 				default:
       
  1352 					ERR_PRINTF1(_L("Test did not panic, so failed"));
       
  1353 					result = EFail;
       
  1354 					break;
       
  1355 				}
       
  1356 
       
  1357 			// done with the test thread
       
  1358 			newThread.Close();
       
  1359 
       
  1360 			// stop clock
       
  1361 			testStop.HomeTime();
       
  1362 
       
  1363 			TUint testDuration = I64INT(testStop.MicroSecondsFrom(testStart).Int64());
       
  1364 			testDuration /= 1000; // to microseconds
       
  1365 			TUint testDurationMsec = testDuration % 1000;
       
  1366 			TUint testDurationSec = testDuration / 1000;
       
  1367 			INFO_PRINTF3(_L("Test took %d.%03d sec"), testDurationSec, testDurationMsec);
       
  1368 
       
  1369 			// return the test verdict
       
  1370 			delete data;
       
  1371 			data = NULL;
       
  1372 			return result;
       
  1373 			}
       
  1374 		}
       
  1375 
       
  1376 	// the required suite has not been found
       
  1377 	ERR_PRINTF3(_L("Error in test step:%S - cannot find suite:%S"),
       
  1378 				&aStep, &aSuite );
       
  1379 
       
  1380 	return ETestSuiteError;
       
  1381 	}
       
  1382 	
       
  1383 /**
       
  1384  *
       
  1385  * Do a test step which is expected to terminate.
       
  1386  *
       
  1387  * @param	"const TDesC& aSuite"
       
  1388  *			The test suite
       
  1389  *
       
  1390  * @param	"const TDesC& aStep"
       
  1391  *			The test step
       
  1392  *
       
  1393  * @param	"TInt aGuardTimerValue"
       
  1394  *			The guard timer value
       
  1395  *
       
  1396  * @param	"TInt aExitReason"
       
  1397  *			The expected exit reason
       
  1398  *
       
  1399  * @param	"const TDesC& aConfig"
       
  1400  *			The config data
       
  1401  *
       
  1402  * @return "TVerdict"
       
  1403  *			The test result
       
  1404  *
       
  1405  * @xxxx
       
  1406  *
       
  1407  */
       
  1408 TVerdict CParseLine::DoTerminationTest(const TDesC& aSuite, const TDesC& aStep, TInt64 aGuardTimerValue,
       
  1409 									  TInt aExitReason, const TDesC& aConfig)
       
  1410 	{
       
  1411 
       
  1412 	//	get the number of suites loaded
       
  1413 	TInt noOfDlls = iArrayLoadedSuiteDll->Count();
       
  1414 
       
  1415 	// search the list of loaded test suite DLLs for the required one
       
  1416 	for (TInt i = 0; i < noOfDlls; i++)
       
  1417 		{
       
  1418 		CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
       
  1419 		TPtrC name = ptrSuite->Name();
       
  1420 
       
  1421 		if (name.FindF(aSuite)!= KErrNotFound)
       
  1422 			{
       
  1423 			// reset step status
       
  1424 			CTestSuite* testSuite = ptrSuite->Suite();
       
  1425 			testSuite->SetStepStatus(EStepStatusNone);
       
  1426 
       
  1427 			// store old log status, for restore at thread exit
       
  1428 			// NB we must do this here, as if thread times out, the log
       
  1429 			// is in an undefined state
       
  1430 			CLog* oldLogger = testSuite->LogSystem();
       
  1431 
       
  1432 			CStepData* data = NULL;
       
  1433 			TRAPD(err, data = CStepData::NewL(aStep, aConfig, ptrSuite));
       
  1434 			if (err != KErrNone)
       
  1435 				{
       
  1436 				ERR_PRINTF2(_L("CStepData::NewL() left with error %d : unable to create test data!"), err);
       
  1437 				return EFail;
       
  1438 				}
       
  1439 
       
  1440 			// get step's own stack and heap sizes
       
  1441 			TInt theHeapSize = KMaxTestThreadHeapSize;
       
  1442 			TInt theStackSize = KTestStackSize;
       
  1443 			GetHeapAndStackSize(data, &theHeapSize, &theStackSize);
       
  1444 
       
  1445 			TInt res = KErrAlreadyExists;
       
  1446 			RThread newThread;
       
  1447 
       
  1448 			// create a unique test name by appending a counter
       
  1449 			TPtrC threadBaseName(_L("DoTestThread"));
       
  1450 			TBuf<32> threadName;
       
  1451 			
       
  1452 			// create a unique named test thread
       
  1453 			// this will leave if creation is not successful
       
  1454 			TRAP (res, CreateUniqueTestThreadL( threadBaseName, 
       
  1455 												threadName, 
       
  1456 												newThread, 
       
  1457 												ThreadFunctionL,
       
  1458 												theStackSize,
       
  1459 												KMinHeapSize,
       
  1460 												theHeapSize,
       
  1461 												data ) );
       
  1462 			
       
  1463 			if (res != KErrNone)
       
  1464 				{
       
  1465 				ERR_PRINTF2(_L("CreateUniqueTestThreadL() left with error %d : unable to create test thread "), res);
       
  1466 				delete data;
       
  1467 				data = NULL;
       
  1468 				return EFail;
       
  1469 				}
       
  1470 
       
  1471 			// start clock
       
  1472 			TTime testStart, testStop;
       
  1473 			testStart.HomeTime();
       
  1474 			
       
  1475 			// start the thread and request the status
       
  1476 			TRequestStatus threadStatus;
       
  1477 			newThread.Logon(threadStatus);
       
  1478 
       
  1479 			// if there is no guard timer value, don't time at all
       
  1480 			if (aGuardTimerValue == KNoGuardTimer)
       
  1481 				{
       
  1482 				// no guard timer
       
  1483 				newThread.Resume();
       
  1484 				User::WaitForRequest(threadStatus);
       
  1485 				}
       
  1486 			else
       
  1487 				{
       
  1488 				// wait for either test thread or timer to end
       
  1489 				RTimer guardTimer;
       
  1490 				guardTimer.CreateLocal();			// create for this thread
       
  1491 				TRequestStatus timerStatus;
       
  1492 				newThread.Resume();
       
  1493 
       
  1494 				// NB now using At() to allow 64-bit timer values
       
  1495 				TInt64 guardTimerUsec = aGuardTimerValue * 1000;
       
  1496 				TInt64 totalTime = 0;
       
  1497 
       
  1498 				for (;;)
       
  1499 					{
       
  1500 					if (totalTime>=guardTimerUsec) // timeout has occured
       
  1501 						break;
       
  1502 					TInt timeout;
       
  1503 
       
  1504 					if (totalTime+KTimeIncrement >= guardTimerUsec)
       
  1505 						{
       
  1506 						TInt64 temp = guardTimerUsec-totalTime;
       
  1507 						timeout = I64INT(temp);
       
  1508 						}
       
  1509 					else
       
  1510 						timeout = KTimeIncrement;
       
  1511 						totalTime += timeout;
       
  1512 					guardTimer.After(timerStatus, timeout);
       
  1513 					User::WaitForRequest(threadStatus, timerStatus);
       
  1514 					if (threadStatus!=KRequestPending) // normal exit
       
  1515 						break;
       
  1516 					}
       
  1517 
       
  1518 				guardTimer.Cancel();
       
  1519 				guardTimer.Close();
       
  1520 				}
       
  1521 
       
  1522 			// restore logger
       
  1523 			testSuite->SetLogSystem(oldLogger);
       
  1524 
       
  1525 			// get the test result
       
  1526 			TVerdict result = STATIC_CAST(TVerdict, threadStatus.Int());
       
  1527 
       
  1528 			// check terminated ok
       
  1529 			switch(newThread.ExitType())
       
  1530 				{
       
  1531 				case EExitTerminate:
       
  1532 				case EExitKill:
       
  1533 					{
       
  1534 					TInt exitReason = newThread.ExitReason();
       
  1535 					if(exitReason != aExitReason)
       
  1536 						{
       
  1537 						ERR_PRINTF2(_L("Test step had an unexpected exit reason:%d and failed"),
       
  1538 									exitReason);
       
  1539 						result = EFail;
       
  1540 						}
       
  1541 					else
       
  1542 						{
       
  1543 						// check here that the panic occurred within the test itself
       
  1544 						CTestSuite* testSuite = ptrSuite->Suite();
       
  1545 						TTestStepStatus status = testSuite->StepStatus();
       
  1546 						switch(status)
       
  1547 							{
       
  1548 							case EStepStatusPreamble:
       
  1549 								{
       
  1550 								// thread terminated in the test itself - success
       
  1551 								INFO_PRINTF2(_L("Test step had terminated:%d and passed"),
       
  1552 											exitReason);
       
  1553 								result = EPass;
       
  1554 								}
       
  1555 								break;
       
  1556 							case EStepStatusStart:
       
  1557 								{
       
  1558 								// thread panicked in preamble
       
  1559 								ERR_PRINTF2(_L("Test step had terminated:%d in preamble"),
       
  1560 											exitReason);
       
  1561 								result = EFail;
       
  1562 								}
       
  1563 								break;
       
  1564 							case EStepStatusTest:
       
  1565 								{
       
  1566 								// thread panicked in postamble
       
  1567 								ERR_PRINTF2(_L("Test step had terminated:%d in postamble"),
       
  1568 											exitReason);
       
  1569 								result = EFail;
       
  1570 								}
       
  1571 								break;
       
  1572 							default:
       
  1573 								{
       
  1574 								// thread panicked outside the test
       
  1575 								ERR_PRINTF2(_L("Test step had terminated:%d outside the test"),
       
  1576 											exitReason);
       
  1577 								result = EFail;
       
  1578 								}
       
  1579 								break;
       
  1580 							}	// end switch
       
  1581 						}
       
  1582 					}
       
  1583 					break;
       
  1584 				case EExitPending:
       
  1585 					// if the thread is still pending then the guard timer must have expired
       
  1586 					ERR_PRINTF1(_L("Thread timed out"));
       
  1587 					// kill the test step thread
       
  1588 					newThread.Kill(1);
       
  1589 					// give the OS time to cleanup devices, etc.
       
  1590 					// NB if the thread dies, the postamble will NOT run
       
  1591 					User::After(2000000);
       
  1592 					result = EFail;
       
  1593 					break;
       
  1594 				case EExitPanic:
       
  1595 				default:
       
  1596 					ERR_PRINTF1(_L("Test did not terminate, so failed"));
       
  1597 					result = EFail;
       
  1598 					break;
       
  1599 				}
       
  1600 
       
  1601 			// done with the test thread
       
  1602 			newThread.Close();
       
  1603 
       
  1604 			// stop clock
       
  1605 			testStop.HomeTime();
       
  1606 
       
  1607 			TUint testDuration = I64INT(testStop.MicroSecondsFrom(testStart).Int64());
       
  1608 			testDuration /= 1000; // to microseconds
       
  1609 			TUint testDurationMsec = testDuration % 1000;
       
  1610 			TUint testDurationSec = testDuration / 1000;
       
  1611 			INFO_PRINTF3(_L("Test took %d.%03d sec"), testDurationSec, testDurationMsec);
       
  1612 
       
  1613 			// return the test verdict
       
  1614 			delete data;
       
  1615 			data = NULL;
       
  1616 			return result;
       
  1617 			}
       
  1618 		}
       
  1619 
       
  1620 	// the required suite has not been found
       
  1621 	ERR_PRINTF3(_L("Error in test step:%S - cannot find suite:%S"),
       
  1622 				&aStep, &aSuite );
       
  1623 
       
  1624 	return ETestSuiteError;
       
  1625 	}
       
  1626 
       
  1627 /**
       
  1628  *
       
  1629  * Gets a step's heap and stack size.
       
  1630  *
       
  1631  * @param	"const CStepData& aStepData"
       
  1632  *			The step data
       
  1633  * @param	"TInt* aHeapSize"
       
  1634  *			Returns the step's heap size
       
  1635  * @param	"TInt* aStackSize"
       
  1636  *			Returns the step's stack size
       
  1637  *
       
  1638  * @xxxx
       
  1639  *
       
  1640  */
       
  1641 void CParseLine::GetHeapAndStackSize(const CStepData* aStepData, TInt* aHeapSize, TInt* aStackSize)
       
  1642 	{
       
  1643 	CSuiteDll* suiteDll = aStepData->SuiteDll();
       
  1644 	CTestSuite* testSuite = suiteDll->Suite();
       
  1645 	testSuite->GetHeapAndStackSize(aStepData->Step(), aHeapSize, aStackSize);
       
  1646 	}
       
  1647 
       
  1648 /**
       
  1649  *
       
  1650  * Implements the RUN_PROGRAM script command.
       
  1651  *
       
  1652  * @param	"const TDesC& aText"
       
  1653  *			The script line
       
  1654  *
       
  1655  * @xxxx
       
  1656  *
       
  1657  */
       
  1658 void CParseLine::RunProgram(const TDesC& aText)
       
  1659 	{
       
  1660 	TPtrC param;
       
  1661 
       
  1662 	// use Tlex to decode the cmd line
       
  1663 	TLex lex(aText);
       
  1664 
       
  1665 	// step over the keyword
       
  1666 	lex.NextToken();
       
  1667 
       
  1668 	// get program name	
       
  1669 	TPtrC token;
       
  1670 	token.Set(lex.NextToken());
       
  1671 
       
  1672 	// get the parameters
       
  1673 	param.Set(lex.NextToken());
       
  1674 
       
  1675 	INFO_PRINTF1(_L("Run Program "));
       
  1676 
       
  1677 
       
  1678 	// In the ARM build run program as a new process
       
  1679 	// use the rest of the text as parameters
       
  1680 	RProcess program;
       
  1681 	TInt ret = program.Create(token, lex.Remainder());
       
  1682 
       
  1683 	if (ret != KErrNone)
       
  1684 		{
       
  1685 		TPtrC errortxt = CLog::EpocErrorToText(ret);
       
  1686 		ERR_PRINTF2(_L("Failed to start process - error %S"), &errortxt);
       
  1687 		return;
       
  1688 		}
       
  1689 	else
       
  1690 		{
       
  1691 		INFO_PRINTF1(_L("Program started"));
       
  1692 
       
  1693 		// start program
       
  1694 		TRequestStatus threadStatus;
       
  1695 		program.Logon(threadStatus);
       
  1696 		program.Resume();
       
  1697 
       
  1698 		// wait for guard timer
       
  1699 		User::WaitForRequest(threadStatus);
       
  1700 
       
  1701 		// check return type
       
  1702 		if (program.ExitType() == EExitPanic)
       
  1703 			INFO_PRINTF1(_L("Program returned EExitPanic"));
       
  1704 		else if (program.ExitType() == EExitPending)
       
  1705 			INFO_PRINTF1(_L("Program returned EExitPending"));
       
  1706 		else
       
  1707 			INFO_PRINTF1(_L("Program returned EExitTerminate"));
       
  1708 		}
       
  1709 	}
       
  1710 
       
  1711 /**
       
  1712  *
       
  1713  * Implements the LOG_SETTINGS script command.
       
  1714  * Command format is LOG_SETTINGS "put src." (1/0),
       
  1715  * "HTML format" (1/0)
       
  1716  *
       
  1717  * @param	"const TDesC& aText"
       
  1718  *			The script line
       
  1719  *
       
  1720  * @xxxx
       
  1721  *
       
  1722  */
       
  1723 void CParseLine::LogSettings(const TDesC& aText)
       
  1724 	{
       
  1725 	// use Tlex to decode the cmd line
       
  1726 	TLex lex(aText);
       
  1727 
       
  1728 	// start at the begining
       
  1729 	TPtrC token=lex.NextToken();
       
  1730 
       
  1731 	// step over the keyword
       
  1732 	//Get information about source
       
  1733 	token.Set(lex.NextToken());
       
  1734 
       
  1735 	TLex srcLex(token);
       
  1736 	TInt isSrc = ETrue; //Shall we put src information?
       
  1737 	if (srcLex.Val(isSrc) != KErrNone)
       
  1738 		{
       
  1739 		ERR_PRINTF2(_L("Error in LOG_SETTINGS: could not decode >%S< as value(0/1)"),
       
  1740 					&token);
       
  1741 		}
       
  1742 	else
       
  1743 		{
       
  1744 		iLog->SetPutSrcInfo(isSrc) ;
       
  1745 		}
       
  1746 	//Get information about format
       
  1747 	token.Set(lex.NextToken());
       
  1748 	TLex htmlLex(token);
       
  1749 
       
  1750 	if (htmlLex.Val(isSrc) != KErrNone)
       
  1751 		{
       
  1752 		ERR_PRINTF2(_L("Error in LOG_SETTINGS: could not decode >%S< as value(0/1)"),
       
  1753 					&token);
       
  1754 		}
       
  1755 	else
       
  1756 		{
       
  1757 		iLog->SetHtmlLogMode(isSrc);
       
  1758 		}
       
  1759 	}
       
  1760 
       
  1761 
       
  1762 /**
       
  1763  *
       
  1764  * Implements the LOAD_SUITE script command.
       
  1765  * This function loads a required test suite DLL
       
  1766  * It also creates a CTestSuite object as a record
       
  1767  * of the loaded DLL.
       
  1768  *
       
  1769  * @param	"const TDesC& aText"
       
  1770  *			The script line
       
  1771  *
       
  1772  * @xxxx
       
  1773  *
       
  1774  */
       
  1775 void CParseLine::LoadSuiteL(const TDesC& aText)
       
  1776 	{
       
  1777 	// use Tlex to decode the cmd line
       
  1778 	TLex lex(aText);
       
  1779 
       
  1780 	// step over the keyword
       
  1781 	lex.NextToken();
       
  1782 
       
  1783 	// get suite name
       
  1784 	TPtrC token;
       
  1785 	token.Set(lex.NextToken());
       
  1786 
       
  1787 	// check not already loaded
       
  1788 	// by searching the list of loaded test suite DLLs for the required one
       
  1789 	// start with the number of suites loaded
       
  1790 	TInt noOfDlls = iArrayLoadedSuiteDll->Count();
       
  1791 	for (TInt i = 0; i < noOfDlls; i++)
       
  1792 		{
       
  1793 		CSuiteDll* ptrSuite = iArrayLoadedSuiteDll->At(i);
       
  1794 		TPtrC name = ptrSuite->Name();
       
  1795 
       
  1796 		// check the names
       
  1797 		if (name.FindF(token) != KErrNotFound)
       
  1798 			{
       
  1799 			// this suite DLL is already loaded
       
  1800 	 		WARN_PRINTF2(_L("Warning: Test suite %S already loaded - not re-loaded"), &token);
       
  1801 			return;
       
  1802 			}
       
  1803 		}
       
  1804 
       
  1805 
       
  1806 	// create a new CSuiteDll object to store info on loaded DLL
       
  1807 	CSuiteDll* newRef = NULL;
       
  1808 
       
  1809 	newRef = CSuiteDll::NewL(token, iLog);
       
  1810 
       
  1811 	CTestSuite* testSuite = newRef->Suite();
       
  1812 
       
  1813 	// set default severity and logging system
       
  1814 	testSuite->SetSeverity(iSeverity);
       
  1815 	testSuite->SetLogSystem(iLog);
       
  1816 	
       
  1817 	// add to data
       
  1818 	iArrayLoadedSuiteDll->AppendL(newRef);
       
  1819 	}
       
  1820 
       
  1821 
       
  1822 /**
       
  1823  *
       
  1824  * Unload all the loaded DLLs
       
  1825  *
       
  1826  * @xxxx
       
  1827  *
       
  1828  */
       
  1829 void CParseLine::Unload()
       
  1830 	{
       
  1831 	if (iArrayLoadedSuiteDll)
       
  1832 		{
       
  1833 		// unload all the loaded DLLS and their records
       
  1834 		iArrayLoadedSuiteDll->ResetAndDestroy();
       
  1835 		}
       
  1836 	}
       
  1837 
       
  1838 /**
       
  1839  *
       
  1840  * Mark the heap
       
  1841  *
       
  1842  * @xxxx
       
  1843  *
       
  1844  */
       
  1845 void CParseLine::HeapMark()
       
  1846 	{
       
  1847 	ERR_PRINTF1(_L("Warning: Command HEAP_MARK no longer supported. Heap marking/checking should be done within test code"));
       
  1848 
       
  1849 	// __UHEAP_MARK;
       
  1850 	}
       
  1851 
       
  1852 
       
  1853 /**
       
  1854  *
       
  1855  * Check the heap
       
  1856  *
       
  1857  * @xxxx
       
  1858  *
       
  1859  */
       
  1860 void CParseLine::HeapCheck()
       
  1861 	{
       
  1862 	ERR_PRINTF1(_L("Warning: Command HEAP_CHECK no longer supported. Heap marking/checking should be done within test code"));
       
  1863 
       
  1864 	// __UHEAP_MARKEND;
       
  1865 	}
       
  1866 
       
  1867 /**
       
  1868  *
       
  1869  * Mark request
       
  1870  *
       
  1871  * @xxxx
       
  1872  *
       
  1873  */
       
  1874 void CParseLine::RequestMark()
       
  1875 	{
       
  1876 	// get number of outstanding requetsts on thread before we run the test
       
  1877 	iReqsAtStart = RThread().RequestCount();
       
  1878 	INFO_PRINTF2(_L("Requests at the start %d "),iReqsAtStart);
       
  1879 	}
       
  1880 
       
  1881 
       
  1882 /**
       
  1883  *
       
  1884  * Check request
       
  1885  *
       
  1886  * @xxxx
       
  1887  *
       
  1888  */
       
  1889 void CParseLine::RequestCheck()
       
  1890 	{
       
  1891 	// check the number of outstanding requests against recorded value
       
  1892 	INFO_PRINTF3(_L("Requests at the start %d now %d"),
       
  1893 				iReqsAtStart, RThread().RequestCount());
       
  1894 
       
  1895 	if (iReqsAtStart != RThread().RequestCount())
       
  1896 		{
       
  1897 		ERR_PRINTF1(_L("Test failed on requests count"));
       
  1898 
       
  1899 		// this result is only significant if every thing else has passed
       
  1900 		if (iTestVerdict == EPass)
       
  1901 			iTestVerdict = EFail;
       
  1902 
       
  1903 		}
       
  1904 	}
       
  1905 
       
  1906 
       
  1907 /**
       
  1908  *
       
  1909  * Mark number of handles
       
  1910  *
       
  1911  * @xxxx
       
  1912  *
       
  1913  */
       
  1914 void CParseLine::HandlesMark()
       
  1915 	{
       
  1916 	// get number of Handles *before* we start the program
       
  1917 	RThread().HandleCount(iProcessHandleCountBefore, iThreadHandleCountBefore);
       
  1918 
       
  1919 	INFO_PRINTF3(_L("HandlesMark : process handle count %d thread handle count %d"),
       
  1920 				iProcessHandleCountBefore,
       
  1921 				iThreadHandleCountBefore);
       
  1922 	}
       
  1923 
       
  1924 /**
       
  1925  *
       
  1926  * Check number of handles
       
  1927  *
       
  1928  * @xxxx
       
  1929  *
       
  1930  */
       
  1931 void CParseLine::HandlesCheck()
       
  1932 	{
       
  1933 	TInt processHandleCountAfter;
       
  1934 	TInt threadHandleCountAfter;
       
  1935 	RThread().HandleCount(processHandleCountAfter, threadHandleCountAfter);
       
  1936 
       
  1937 	INFO_PRINTF3(_L("HandlesCheck : process handle count %d thread handle count %d"),
       
  1938 				processHandleCountAfter,
       
  1939 				threadHandleCountAfter);
       
  1940 
       
  1941 	// check that we are closing all the threads
       
  1942 	if(iThreadHandleCountBefore != threadHandleCountAfter)
       
  1943 		{
       
  1944 		ERR_PRINTF1(_L("Test failed on thread handle count"));
       
  1945 
       
  1946 		// this result is only significant if everything else has passed
       
  1947 		if (iTestVerdict == EPass)
       
  1948 			iTestVerdict = EFail;
       
  1949 		}
       
  1950 
       
  1951 	// check that we are closing all the handles
       
  1952 	if(iProcessHandleCountBefore != processHandleCountAfter)
       
  1953 		{
       
  1954 		ERR_PRINTF1(_L("Test failed on process handle count"));
       
  1955 
       
  1956 		// this result is only significant if everything else has passed
       
  1957 		if (iTestVerdict == EPass)
       
  1958 			iTestVerdict = EFail;
       
  1959 		}
       
  1960 	}
       
  1961 
       
  1962 /**
       
  1963  *
       
  1964  * Traceable logging function for parseline.
       
  1965  * To be called only with macros
       
  1966  *
       
  1967  * @param	"const TText8* aFile"
       
  1968  *			Source code file name
       
  1969  *
       
  1970  * @param	"TInt aLine"
       
  1971  *			Source code line
       
  1972  *
       
  1973  * @param	"TInt aSeverity"
       
  1974  *			Severity level required to log
       
  1975  *
       
  1976  * @param	"TRefByValue<const TDesC16> aFmt"
       
  1977  *			Printf-style format.
       
  1978  *
       
  1979  * @param	"..."
       
  1980  *			Variable print parameters
       
  1981  *
       
  1982  * @xxxx
       
  1983  *
       
  1984  */
       
  1985 void CParseLine::LogExtra(const TText8* aFile, TInt aLine, TInt aSeverity,
       
  1986 		TRefByValue<const TDesC16> aFmt,...)
       
  1987 	{
       
  1988 	VA_LIST aList;
       
  1989 	VA_START(aList, aFmt);
       
  1990 
       
  1991 	if(LogSeverity::IsActive(aSeverity, iSeverity))
       
  1992 		{
       
  1993 		if(iLog)
       
  1994 			{
       
  1995 			iLog->LogExtra(aFile, aLine, aSeverity, aFmt, aList);
       
  1996 			}
       
  1997 		}
       
  1998 
       
  1999 	VA_END(aList);
       
  2000 	}
       
  2001 
       
  2002 /**
       
  2003  *
       
  2004  * Get current suite name.
       
  2005  *
       
  2006  * @return "TPtrC"
       
  2007  *			The suite name
       
  2008  *
       
  2009  * @xxxx
       
  2010  *
       
  2011  */
       
  2012 TPtrC CParseLine::CurrentSuiteName() const
       
  2013 	{
       
  2014 	return iCurrentSuiteName;
       
  2015 	}
       
  2016 
       
  2017 /**
       
  2018  *
       
  2019  * Get current step name.
       
  2020  *
       
  2021  * @return "TPtrC"
       
  2022  *			The step name
       
  2023  *
       
  2024  * @xxxx
       
  2025  *
       
  2026  */
       
  2027 TPtrC CParseLine::CurrentStepName() const
       
  2028 	{
       
  2029 	return iCurrentStepName;
       
  2030 	}
       
  2031 
       
  2032 /**
       
  2033  *
       
  2034  * Create a thread with a unique name from a base thread name
       
  2035  * e.g. "TestThread" may become "TestThread00000002"
       
  2036  * This test will leave instantly if an error other than 
       
  2037  * KErrAlreadyExists occurs. 
       
  2038  *
       
  2039  *
       
  2040  * @param	"TDesC& aBaseName"
       
  2041  *			The base name to use.  This will be modified to contain
       
  2042  *			the new unique thread name if creation is successful.
       
  2043  *
       
  2044  * @param	"TDes& aThreadName"
       
  2045  *			The thread name to use.  This will be modified to contain
       
  2046  *			the new unique thread name if creation is successful.  This must
       
  2047  *			be non NULL.
       
  2048  *
       
  2049  * @param	"RThread&"
       
  2050  *			An RThread which will be created.  This must not be a valid handle.
       
  2051  *
       
  2052  * @param	"TThreadFunction aFunction"
       
  2053  *			Thread function to use in RThread.
       
  2054  *
       
  2055  * @param	"TInt aStackSize"
       
  2056  *			The size of the new thread's stack.
       
  2057  *
       
  2058  * @param	"TInt aHeapMinSize"
       
  2059  *			The minimum size for the new thread's heap.
       
  2060  *
       
  2061  * @param	"TInt aHeapMaxSize"
       
  2062  *			The maximum size for the new thread's heap.
       
  2063  *
       
  2064  * @param	"TAny *aPtr"
       
  2065  *			Data to pass to the new thread.
       
  2066  *
       
  2067  * @leave	"function will leave with an error code if a thread cannot
       
  2068  *			be created after KMaxThreadAttempts tries."
       
  2069  *
       
  2070  * @xxxx
       
  2071  *
       
  2072  */
       
  2073 void CParseLine::CreateUniqueTestThreadL(const TDesC& aBaseName, TDes& aThreadName, RThread& aTestThread, TThreadFunction aFunction, TInt aStackSize, TInt aHeapMinSize, TInt aHeapMaxSize, TAny *aPtr)
       
  2074 	{	
       
  2075 	TInt res = KErrAlreadyExists;
       
  2076 	
       
  2077 	// attempt to create a thread with the name aBaseName + counter.
       
  2078 	for (TUint i = 0; i < KMaxThreadAttempts; i++)
       
  2079 		{
       
  2080 		// copy the base thread name
       
  2081 		aThreadName.Copy(aBaseName);
       
  2082 		
       
  2083 		// append the current counter to the threadname
       
  2084 		aThreadName.AppendNumFixedWidth(i, EDecimal, 8);
       
  2085 			
       
  2086 		// run in a new thread, with a new heap		
       
  2087 		res = aTestThread.Create(aThreadName,
       
  2088 				aFunction,
       
  2089 				aStackSize,
       
  2090 				aHeapMinSize,
       
  2091 				aHeapMaxSize,
       
  2092 				aPtr);
       
  2093 					
       
  2094 		// if thread created successfully then we have
       
  2095 		// a unique threadname else if an error code other
       
  2096 		// than KErrAlreadyExists occurs then exit immediately.
       
  2097 		if ((res == KErrNone) || (res != KErrAlreadyExists)) 
       
  2098 			break;
       
  2099 		}
       
  2100 		
       
  2101 	User::LeaveIfError(res);
       
  2102 	}
       
  2103 
       
  2104 /**
       
  2105  *
       
  2106  * Static constructor for CSuiteDll.
       
  2107  *
       
  2108  *
       
  2109  * @return	"CSuiteDll*"
       
  2110  *			The constructed CSuiteDll
       
  2111  *
       
  2112  * @xxxx
       
  2113  *
       
  2114  */
       
  2115 CSuiteDll* CSuiteDll::NewL(const TDesC& aName, CLog* aLog)
       
  2116 	{
       
  2117 	CSuiteDll* self = new(ELeave) CSuiteDll;
       
  2118 	CleanupStack::PushL(self);
       
  2119 	self->ConstructL(aName, aLog);
       
  2120 	CleanupStack::Pop();
       
  2121 	return self;
       
  2122 	}
       
  2123 
       
  2124 /**
       
  2125  *
       
  2126  * CSuiteDLL second-phase constructor
       
  2127  * Loads a test suite dll and saves the name and test
       
  2128  * suite pointers.
       
  2129  *
       
  2130  * @param "TDesC& aName"
       
  2131  *			The test suite name
       
  2132  *
       
  2133  * @param "CLog* aLog"
       
  2134  *			The logger to use
       
  2135  *
       
  2136  * @xxxx
       
  2137  *
       
  2138  */
       
  2139 void CSuiteDll::ConstructL(const TDesC& aName, CLog* aLog)
       
  2140 	{
       
  2141 	iLog = aLog;
       
  2142 
       
  2143 	User::Check();
       
  2144 	// load DLL by name
       
  2145 	TInt ret = iLibrary.Load(aName, KTxtDLLpath);
       
  2146 
       
  2147 	User::Check();
       
  2148 
       
  2149 	if (ret == KErrNotFound)
       
  2150 		{
       
  2151 		iLog->LogExtra(__FILE8__, __LINE__, ESevrErr, _L("Test suite %S was not found. Check any other DLLs required by %S"), &aName, &aName);
       
  2152 		User::Leave(ret);
       
  2153 		}
       
  2154 	else if (ret != KErrNone)
       
  2155 		{
       
  2156 		iLog->LogExtra(__FILE8__, __LINE__, ESevrErr, _L("Test suite %S found but would not load. Check any other DLLs required by %S"), &aName, &aName);
       
  2157 		User::Leave(ret);
       
  2158 		}
       
  2159 
       
  2160 	// save the name
       
  2161 	iName.Copy(aName);
       
  2162 
       
  2163 	// get the interface pointer at ordinal 1
       
  2164 	const TInt KLibraryOrdinal = 1;
       
  2165 	TLibraryFunction  entryL = iLibrary.Lookup(KLibraryOrdinal);
       
  2166 
       
  2167     // Call this interface pointer to create new CTestSuite
       
  2168 	// If this call goes to the wrong function then the test
       
  2169 	// suite does not have the correct function at ordinal 1.
       
  2170 	// This is usually caused by an error in the def file.
       
  2171     iTestSuite = REINTERPRET_CAST(CTestSuite*, entryL());
       
  2172 
       
  2173     // NB :- Second-phase constructor for CTestSuite has already been called in entryL() above.
       
  2174 	// There is no need to call it again!
       
  2175 
       
  2176 	// set suite severity level
       
  2177 	iTestSuite->SetSeverity(iLog->Severity());
       
  2178 
       
  2179 	// get the version information
       
  2180 	TPtrC versiontxt = iTestSuite->GetVersion();
       
  2181 
       
  2182 	// add to log
       
  2183 	iLog->LogExtra(__FILE8__, __LINE__, ESevrInfo, _L("LOAD_SUITE %S version %S loaded ok"),&aName, &versiontxt );
       
  2184 	}
       
  2185 
       
  2186 /**
       
  2187  *
       
  2188  * CSuiteDLL destructor
       
  2189  *
       
  2190  * @xxxx
       
  2191  *
       
  2192  */
       
  2193 CSuiteDll::~CSuiteDll()
       
  2194 	{
       
  2195 	// delete the TestSuiteObject in the loaded DLL
       
  2196 	delete iTestSuite;
       
  2197 
       
  2198 	// close and unload the library
       
  2199 	iLibrary.Close();
       
  2200 	}
       
  2201 
       
  2202 /**
       
  2203  *
       
  2204  * CSuiteDLL accessor : suite
       
  2205  *
       
  2206  * @return "CTestSuite*"
       
  2207  *			The test suite.
       
  2208  *
       
  2209  * @xxxx
       
  2210  *
       
  2211  */
       
  2212 CTestSuite* CSuiteDll::Suite() const
       
  2213 	{
       
  2214 	return iTestSuite;
       
  2215 	}
       
  2216 
       
  2217 /**
       
  2218  *
       
  2219  * CSuiteDLL accessor : suite name
       
  2220  *
       
  2221  * @return "TPtrC"
       
  2222  *			The suite name.
       
  2223  *
       
  2224  * @xxxx
       
  2225  *
       
  2226  */
       
  2227 TPtrC CSuiteDll::Name() const
       
  2228 	{
       
  2229 	return iName;
       
  2230 	}
       
  2231 
       
  2232 /**
       
  2233  *
       
  2234  * CStepData
       
  2235  *
       
  2236  * @xxxx
       
  2237  *
       
  2238  */
       
  2239 CStepData* CStepData::NewL(const TDesC& aStep, const TDesC& aConfig, CSuiteDll* aSuite)
       
  2240 	{
       
  2241 	return NewL(aStep, aConfig, KNullDesC, aSuite);
       
  2242 	}
       
  2243 
       
  2244 CStepData* CStepData::NewL(const TDesC& aStep, const TDesC& aConfig, const TDesC& aParamSet, CSuiteDll* aSuite)
       
  2245 	{
       
  2246 	CStepData* self = new(ELeave) CStepData;
       
  2247 	CleanupStack::PushL(self);
       
  2248 	self->ConstructL(aStep, aConfig, aParamSet, aSuite);
       
  2249 	CleanupStack::Pop();
       
  2250 	return self;
       
  2251 	}
       
  2252 
       
  2253 CStepData::CStepData()
       
  2254 	{
       
  2255 	}
       
  2256 
       
  2257 CStepData::~CStepData()
       
  2258 	{
       
  2259 	}
       
  2260 
       
  2261 void CStepData::ConstructL(const TDesC& aStep, const TDesC& aConfig, const TDesC& aParamSet, CSuiteDll* aSuite)
       
  2262 	{
       
  2263 	iStep = aStep;
       
  2264 	iConfig = aConfig;
       
  2265 	iParamSet = aParamSet;
       
  2266 	iSuite = aSuite;
       
  2267 	}
       
  2268 
       
  2269 const TDesC& CStepData::ParamSet() const
       
  2270 	{
       
  2271 	return iParamSet;
       
  2272 	}
       
  2273 
       
  2274