imagingtestenv/imagingtestfw/Source/TestFrameworkClient/TestStep.cpp
changeset 0 5752a19fdefe
equal deleted inserted replaced
-1:000000000000 0:5752a19fdefe
       
     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 //
       
    15 
       
    16 // EPOC includes
       
    17 #include <e32base.h>
       
    18 
       
    19 // Test system includes
       
    20 #include <testframework.h>
       
    21 #include "TestIniData.h"
       
    22 #include "asyncscheduler.h"
       
    23 
       
    24 // do not export if Unit Testing
       
    25 #if defined (__TSU_TESTFRAMEWORK__)
       
    26 #undef EXPORT_C
       
    27 #define EXPORT_C
       
    28 #endif
       
    29 
       
    30 static const TUint16*const KVerdictString[] = // must match up with TVerdict
       
    31 	{
       
    32 	_S("EPass"),
       
    33 	_S("EFail"),
       
    34 	_S("EInconclusive"),
       
    35 	_S("ETestSuiteError"),
       
    36 	_S("EAbort"),
       
    37 	_S("EKnownFailure")
       
    38 	};
       
    39 
       
    40 /**
       
    41  *
       
    42  * Test step constructor.
       
    43  *
       
    44  * @xxxx
       
    45  *
       
    46  */
       
    47 EXPORT_C RTestStep::RTestStep()
       
    48 	{
       
    49 	iTestStepResult = EPass;
       
    50 	iTestStepName.Zero();
       
    51 	iSuite = NULL;
       
    52 	iConfigData = NULL;
       
    53 	iConfigDataAvailable = EFalse;
       
    54 	iStackSize = KTestStackSize;
       
    55 	iHeapSize = KMaxTestThreadHeapSize;
       
    56 
       
    57 	// NB : RTestStep has no destructor
       
    58 	}
       
    59 
       
    60 /**
       
    61  *
       
    62  * CBase compatibility functionality.
       
    63  *
       
    64  * @xxxx
       
    65  *
       
    66  */
       
    67 
       
    68 
       
    69 EXPORT_C TAny* RTestStep::operator new(TUint aSize, TAny* aBase) __NO_THROW
       
    70 	{
       
    71 	Mem::FillZ(aBase,aSize);
       
    72 	return(aBase);
       
    73 	}
       
    74 
       
    75 
       
    76 EXPORT_C TAny* RTestStep::operator new(TUint aSize, TLeave)
       
    77 	{
       
    78 	return newL(aSize);		// will leave on alloc failure
       
    79 	}
       
    80 
       
    81 EXPORT_C TAny* RTestStep::operator new(TUint aSize) __NO_THROW
       
    82 	{
       
    83 	TAny* pM=User::Alloc(aSize);
       
    84 	if (pM)
       
    85 		Mem::FillZ(pM,aSize);
       
    86 	return(pM);
       
    87 	}
       
    88 
       
    89 EXPORT_C TAny* RTestStep::newL(TUint aSize)
       
    90 	{
       
    91 	TAny* pM=User::AllocL(aSize);
       
    92 	Mem::FillZ(pM,aSize);
       
    93 	return pM;
       
    94 	}
       
    95 
       
    96 EXPORT_C TAny* RTestStep::operator new(TUint aSize,TUint anExtraSize) __NO_THROW
       
    97 	{
       
    98 	aSize+=anExtraSize;
       
    99 	TAny *pM=User::Alloc(aSize);
       
   100 	if (pM)
       
   101 		Mem::FillZ(pM,aSize);
       
   102 	return(pM);
       
   103 	}
       
   104 
       
   105 /**
       
   106  *
       
   107  * Pre-preamble for all test steps. This grows the cleanup stack to
       
   108  * allow for allocation errors.
       
   109  *
       
   110  * @xxxx
       
   111  *
       
   112  */
       
   113 EXPORT_C void RTestStep::PreOpenL()
       
   114 	{
       
   115 	TAny* dummyPtr = NULL;
       
   116 	for(TInt i = 0 ; i < 20 ; i++)
       
   117 		CleanupStack::PushL(dummyPtr); // Grow the cleanup stack.
       
   118 	CleanupStack::PopAndDestroy(20);
       
   119 	}
       
   120 
       
   121 /**
       
   122  *
       
   123  * Default empty implementation of OpenL (preamble).
       
   124  * Test steps can override this to implement required code.
       
   125  *
       
   126  * @return	"TVerdict"
       
   127  *			Result of preamble (should only be EPass or EInconclusive)
       
   128  *
       
   129  * @xxxx
       
   130  *
       
   131  */
       
   132 EXPORT_C TVerdict RTestStep::OpenL()
       
   133 	{
       
   134 	// for backward compatibility with CTestStep
       
   135 	return DoTestStepPreambleL();
       
   136 	}
       
   137 
       
   138 /**
       
   139  *
       
   140  * Default empty implementation of CleanupAfterOpenFail (preamble cleanup).
       
   141  * Test steps can override this to implement required code.
       
   142  *
       
   143  * @xxxx
       
   144  *
       
   145  */
       
   146 EXPORT_C void RTestStep::CleanupAfterOpenFail()
       
   147 	{
       
   148 	// default empty implementation
       
   149 	// a step should implement its own method if required
       
   150 	}
       
   151 
       
   152 /**
       
   153  *
       
   154  * Default empty implementation of Close (postamble)
       
   155  * Test steps can override this to implement required code.
       
   156  *
       
   157  * NB this does NOT leave - any leaves should be trapped and panicked.
       
   158  *
       
   159  * @xxxx
       
   160  *
       
   161  */
       
   162 EXPORT_C void RTestStep::Close()
       
   163 	{
       
   164 	// for backward compatibility with CTestStep
       
   165 	_LIT(KPanicStr, "RTestStep::Close");
       
   166 	TVerdict ver = EPass;
       
   167 	TRAPD(err, ver = DoTestStepPostambleL());
       
   168 	if(err != KErrNone)
       
   169 		User::Panic(KPanicStr, 0);
       
   170 	// any DoTestStepPostambleL() which returns EInconclusive should be panicked
       
   171  	if(ver != EPass)
       
   172 		User::Panic(KPanicStr, 1);
       
   173 
       
   174 	}
       
   175 
       
   176 /**
       
   177  *
       
   178  * Set the test suite
       
   179  *
       
   180  * @param	"CTestSuite*"
       
   181  *			The test suite
       
   182  *
       
   183  * @xxxx
       
   184  *
       
   185  */
       
   186 EXPORT_C void RTestStep::SetSuite(CTestSuite* aSuite)
       
   187 	{
       
   188 	iSuite = aSuite;
       
   189 	}
       
   190 
       
   191 /**
       
   192  *
       
   193  * Set the test result
       
   194  *
       
   195  * @param	"TVerdict"
       
   196  *			The test result
       
   197  *
       
   198  * @xxxx
       
   199  *
       
   200  */
       
   201 EXPORT_C void RTestStep::SetResult(TVerdict aResult)
       
   202 	{
       
   203 	iTestStepResult = aResult;
       
   204 	}
       
   205 
       
   206 /**
       
   207  *
       
   208  * Get the step name
       
   209  *
       
   210  * @return	"TPtrC"
       
   211  *			The step name
       
   212  *
       
   213  * @xxxx
       
   214  *
       
   215  */
       
   216 EXPORT_C TPtrC RTestStep::StepName() const
       
   217 	{
       
   218 	return iTestStepName;
       
   219 	}
       
   220 
       
   221 /**
       
   222  *
       
   223  * General logging function for test steps.
       
   224  *
       
   225  * @param	"TRefByValue<const TDesC16> aFmt"
       
   226  *			Printf-style aFmt.
       
   227  *
       
   228  * @param	"..."
       
   229  *			Variable print parameters
       
   230  *
       
   231  * @xxxx
       
   232  *
       
   233  */
       
   234 EXPORT_C void RTestStep::Log(TRefByValue<const TDesC16> aFmt, ...)
       
   235 	{
       
   236     
       
   237 	VA_LIST aList;
       
   238 	VA_START(aList, aFmt);
       
   239 
       
   240 	TIntegrationTestLog16Overflow iOverflow16;
       
   241 
       
   242 	// decode formatted data for display on console
       
   243 	TBuf<KMaxLogLineLength> lineBuf;
       
   244 	lineBuf.AppendFormatList(aFmt, aList, &iOverflow16);
       
   245 
       
   246 	// send the data to the log system via the suite
       
   247 	iSuite->Log(_L("%S"),&lineBuf);
       
   248 
       
   249 	VA_END(aList); 
       
   250 
       
   251 	}
       
   252 
       
   253 /**
       
   254  *
       
   255  * General logging function for test steps, with severity.
       
   256  *
       
   257  * @param	"TInt aSeverity"
       
   258  *			Severity level required to log
       
   259  *
       
   260  * @param	"TRefByValue<const TDesC16> aFmt"
       
   261  *			Printf-style aFmt.
       
   262  *
       
   263  * @param	"..."
       
   264  *			Variable print parameters
       
   265  *
       
   266  * @xxxx
       
   267  *
       
   268  */
       
   269 EXPORT_C void RTestStep::Log( TInt aSeverity, TRefByValue<const TDesC16> aFmt, ... )
       
   270 {
       
   271 	VA_LIST aList;
       
   272 	VA_START(aList, aFmt);
       
   273 
       
   274 	TIntegrationTestLog16Overflow iOverflow16;
       
   275 
       
   276 	// decode formatted data for display on console
       
   277 	TBuf<KMaxLogLineLength> lineBuf;
       
   278 	lineBuf.AppendFormatList(aFmt, aList, &iOverflow16);
       
   279 
       
   280 	// send the data to the log system via the suite
       
   281 	if(LogSeverity::IsActive(aSeverity, iSuite->Severity()))
       
   282 		iSuite->Log(aSeverity, _L("%S"),&lineBuf);
       
   283 
       
   284 	VA_END(aList); 
       
   285 }
       
   286 
       
   287 /**
       
   288  *
       
   289  * Traceable logging function for test steps.
       
   290  *
       
   291  * @param	"const TText8* aFile"
       
   292  *			Source code file name
       
   293  *
       
   294  * @param	"TInt aLine"
       
   295  *			Source code line
       
   296  *
       
   297  * @param	"TInt aSeverity"
       
   298  *			Severity level required to log
       
   299  *
       
   300  * @param	"TRefByValue<const TDesC16> aFmt"
       
   301  *			Printf-style format.
       
   302  *
       
   303  * @param	"..."
       
   304  *			Variable print parameters
       
   305  *
       
   306  * @xxxx
       
   307  *
       
   308  */
       
   309 EXPORT_C void RTestStep::LogExtra(const TText8* aFile, TInt aLine, TInt aSeverity,
       
   310 		TRefByValue<const TDesC16> aFmt,...)
       
   311 	{
       
   312 	VA_LIST aList;
       
   313 	VA_START(aList, aFmt);
       
   314 
       
   315 	TIntegrationTestLog16Overflow iOverflow16;
       
   316 
       
   317 	// decode formatted data for display on console
       
   318 	TBuf<KMaxLogLineLength> lineBuf;
       
   319 	lineBuf.AppendFormatList(aFmt, aList, &iOverflow16);
       
   320 
       
   321 	// send the data to the log system via the suite
       
   322 	if(LogSeverity::IsActive(aSeverity, iSuite->Severity()))
       
   323 		iSuite->LogExtra(aFile, aLine, aSeverity, lineBuf);
       
   324 
       
   325 	VA_END(aList); 
       
   326 	}
       
   327 	
       
   328 /**
       
   329 Set default paramSet
       
   330 Test steps can use this when looking up configs, to provide a level of script control
       
   331 */
       
   332 void RTestStep::SetDefaultParamSet(const TDesC& aParamSet)
       
   333 	{
       
   334 	iDefaultParamSet.Set(aParamSet);
       
   335 	}
       
   336 
       
   337 /**
       
   338  *
       
   339  * Load a configuration file.
       
   340  * If successful, data member iConfigDataAvailable is set.
       
   341  *
       
   342  * @param	"TPtrC aConfig"
       
   343  *			The configuration file name.
       
   344  *
       
   345  * @xxxx
       
   346  *
       
   347  */
       
   348 EXPORT_C void RTestStep::LoadConfig(const TDesC& aConfig)
       
   349 	{
       
   350 
       
   351 	// if a config file supplied then use
       
   352 	if (aConfig.Length() != 0)
       
   353 		{
       
   354 
       
   355 		// get the full pathname default drive name and extension
       
   356 		_LIT(KRelated,"C:\\config.ini"); 
       
   357 		TParse configFileName;
       
   358 		TInt returnCode = configFileName.Set(aConfig, &KRelated, NULL);
       
   359 
       
   360 		if (returnCode != KErrNone)
       
   361 			{
       
   362 			// error opening FileManager
       
   363 			ERR_PRINTF2(_L("Error opening config file %S"), &(configFileName.FullName())); 
       
   364 			}
       
   365 
       
   366 		// create and load the CTestIniData object
       
   367 		TRAPD(r, iConfigData = CTestIniData::NewL(configFileName.FullName()));
       
   368 		
       
   369 		// check if loaded ok
       
   370 		if (r == KErrNone)
       
   371 			{
       
   372 			// loaded ok
       
   373 			iConfigDataAvailable = ETrue;
       
   374 			}
       
   375 		else
       
   376 			{
       
   377 			// failed to load
       
   378 			iConfigDataAvailable = EFalse;
       
   379 			iConfigData = NULL;
       
   380 
       
   381 			// report error 
       
   382 			TPtrC errortxt = CLog::EpocErrorToText(r);
       
   383 			ERR_PRINTF2(_L("Failed to load config data file - error %S"), &errortxt);
       
   384 			}
       
   385 		}
       
   386 	}
       
   387 
       
   388 /**
       
   389  *
       
   390  * Unload any existing configuration data.
       
   391  *
       
   392  * @xxxx
       
   393  *
       
   394  */
       
   395 EXPORT_C void RTestStep::UnloadConfig()
       
   396 	{
       
   397 	iConfigDataAvailable = EFalse;
       
   398 
       
   399 	// clean up Config data object
       
   400 	delete iConfigData;
       
   401 	iConfigData = NULL;
       
   402 
       
   403 	}
       
   404 
       
   405 /**
       
   406  *
       
   407  * Check the config file for a boolean value
       
   408  *
       
   409  * @param	"const TDesC &aSectName"
       
   410  *			Section name to check in
       
   411  *
       
   412  * @param	"const TDesC &aKeyName"
       
   413  *			Key name to check for
       
   414  *
       
   415  * @param	"Bool &aResult"
       
   416  *			TBool returned from config file
       
   417  *
       
   418  * @return	"TBool"
       
   419  *			Result (ETrue if found)
       
   420  *
       
   421  * @xxxx
       
   422  *
       
   423  */
       
   424 EXPORT_C TBool RTestStep::GetBoolFromConfig(const TDesC &aSectName, const TDesC &aKeyName, TBool &aResult)
       
   425 	{
       
   426 	// check file available
       
   427 	if (!iConfigDataAvailable)
       
   428 		{
       
   429 		ERR_PRINTF1(_L("No config file available"));
       
   430 		return EFalse;
       
   431 		}
       
   432 
       
   433 	TBool ret = EFalse;
       
   434 	TPtrC result;
       
   435 
       
   436 	// get the value 
       
   437 	ret = iConfigData->FindVar(aSectName, aKeyName, result);
       
   438 
       
   439 	// if failed to decode display error
       
   440 	if (!ret) 
       
   441 		{
       
   442 		// display error message
       
   443 		ERR_PRINTF3(_L("Failed to read section:%S key:%S "),
       
   444 				&aSectName, &aKeyName );
       
   445 
       
   446 		// return fail
       
   447 		return EFalse;
       
   448 		}
       
   449 
       
   450 	// set result as a TBool
       
   451 	if (result.FindF(_L("true")) == KErrNotFound)
       
   452 		aResult = EFalse;
       
   453 	else
       
   454 		aResult = ETrue;
       
   455 	// return success
       
   456 	return ETrue;
       
   457 	}
       
   458 
       
   459 /**
       
   460  *
       
   461  * Check the config file for a TInt value
       
   462  *
       
   463  * @param	"const TDesC &aSectName"
       
   464  *			Section name to check in
       
   465  *
       
   466  * @param	"const TDesC &aKeyName"
       
   467  *			Key name to check for
       
   468  *
       
   469  * @param	"TInt &aResult"
       
   470  *			TInt returned from config file
       
   471  *
       
   472  * @return	"TBool"
       
   473  *			Result (ETrue if found)
       
   474  *
       
   475  * @xxxx
       
   476  *
       
   477  */
       
   478 EXPORT_C TBool RTestStep::GetIntFromConfig(const TDesC &aSectName, const TDesC &aKeyName, TInt &aResult)
       
   479 	{
       
   480 	// check file available
       
   481 	if ( !iConfigDataAvailable )
       
   482 		{
       
   483 		ERR_PRINTF1(_L("No config file available"));
       
   484 		return EFalse;
       
   485 		}	
       
   486 
       
   487 	TBool ret = EFalse;
       
   488 	TPtrC result;
       
   489 
       
   490 	// get the value 
       
   491 	ret = iConfigData->FindVar(aSectName, aKeyName, result);
       
   492 
       
   493 	// if failed to decode display error
       
   494 	if (!ret) 
       
   495 		{
       
   496 		// display error message
       
   497 		ERR_PRINTF3(_L("Failed to read section:%S key:%S "),
       
   498 				&aSectName, &aKeyName );
       
   499 
       
   500 		// return fail
       
   501 		return EFalse;
       
   502 		}
       
   503 
       
   504 	// use TLex to convert to a TInt
       
   505 	TLex lex(result);
       
   506 	if (lex.Val(aResult) == KErrNone)
       
   507 		return ETrue;
       
   508 	else
       
   509 		return EFalse;
       
   510 }
       
   511 
       
   512 /**
       
   513  *
       
   514  * Check the config file for a string TPtr value
       
   515  *
       
   516  * @param	"const TDesC &aSectName"
       
   517  *			Section name to check in
       
   518  *
       
   519  * @param	"const TDesC &aKeyName"
       
   520  *			Key name to check for
       
   521  *
       
   522  * @param	"TPtrC &aResult"
       
   523  *			String returned from config file
       
   524  *
       
   525  * @return	"TBool"
       
   526  *			Result (ETrue if found)
       
   527  *
       
   528  * @xxxx
       
   529  *
       
   530  */
       
   531 EXPORT_C TBool RTestStep::GetStringFromConfig(const TDesC &aSectName, const TDesC &aKeyName, TPtrC &aResult)
       
   532 	{
       
   533 	// check file available
       
   534 	if (!iConfigDataAvailable)
       
   535 		{
       
   536 		ERR_PRINTF1(_L("No config file available"));
       
   537 		return EFalse;
       
   538 		}	
       
   539 
       
   540 	// get the value 
       
   541 	TBool ret = iConfigData->FindVar(aSectName, aKeyName, aResult);
       
   542 
       
   543 	// if failed to decode display error
       
   544 	if (ret == EFalse) 
       
   545 		{
       
   546 		ERR_PRINTF3(_L("Failed to read section:%S key:%S "),
       
   547 				&aSectName, &aKeyName );
       
   548 		}
       
   549 
       
   550 	return ret;
       
   551 }
       
   552 
       
   553 /**
       
   554  * Reads the value present from the test steps ini file within the mentioned section name and key name
       
   555  * Copies the value to the TInt reference passed in
       
   556  * @param aSectName - Section within the test steps ini file
       
   557  * @param aKeyName - Name of a key within a section
       
   558  * @return aResult - The integer value of the Hex input
       
   559  * @return TBool - ETrue for found, EFalse for not found 
       
   560  */	
       
   561 EXPORT_C TBool RTestStep::GetHexFromConfig(const TDesC &aSectName,const TDesC &aKeyName,TInt &aResult)
       
   562 	{
       
   563 	TPtrC result;
       
   564 	if(!iConfigData)
       
   565 		return EFalse;
       
   566 	if(!iConfigData->FindVar(aSectName, aKeyName, result))
       
   567 		return EFalse;
       
   568 	TLex lex(result);
       
   569 	TInt err = lex.Val((TUint &)aResult, EHex);
       
   570 	if(err)
       
   571 		return EFalse;
       
   572 	
       
   573 	return(ETrue);
       
   574 	}
       
   575 	
       
   576 /**
       
   577  *
       
   578  * Default empty implementation of DoTestStepPreambleL.
       
   579  * Test steps can override this to implement required code.
       
   580  *
       
   581  * @return	"TVerdict"
       
   582  *			Result of preamble (should only be EPass or EInconclusive)
       
   583  *
       
   584  * @xxxx
       
   585  *
       
   586  */
       
   587 // for backward compatibility with CTestStep
       
   588 EXPORT_C TVerdict RTestStep::DoTestStepPreambleL()
       
   589 	{
       
   590 	return EPass;
       
   591 	}
       
   592 
       
   593 /**
       
   594  *
       
   595  * Default empty implementation of DoTestStepPostambleL.
       
   596  * Test steps can override this to implement required code.
       
   597  *
       
   598  * @return	"TVerdict"
       
   599  *			Result of postamble (should only be EPass or EInconclusive)
       
   600  *
       
   601  * @xxxx
       
   602  *
       
   603  */
       
   604 // for backward compatibility with CTestStep
       
   605 EXPORT_C TVerdict RTestStep::DoTestStepPostambleL()
       
   606 	{
       
   607 	return EPass;
       
   608 	}
       
   609 
       
   610 /**
       
   611  *
       
   612  * Traceable Boolean condition tester.
       
   613  * If the condition is not true, record an error.
       
   614  *
       
   615  * @param	"TBool aCondition"
       
   616  *			Condition to be checked
       
   617  *
       
   618  * @param	"const TText8* aFile"
       
   619  *			Source code file name
       
   620  *
       
   621  * @param	"TInt aLine"
       
   622  *			Source code line
       
   623  *
       
   624  * @xxxx
       
   625  *
       
   626  */
       
   627 EXPORT_C void RTestStep::TestBooleanTrue(TBool aCondition, const TText8* aFile, TInt aLine)
       
   628 	{
       
   629 
       
   630 	// check condition
       
   631 	if (aCondition)
       
   632 		return;
       
   633 
       
   634 	// this is only relevant if the current result is pass
       
   635 	if (iTestStepResult == EPass)
       
   636 		iTestStepResult = EFail;
       
   637 
       
   638 	// convert filename for log
       
   639 	TBuf<KMaxLogFilenameLength> fileName;
       
   640 	TPtrC8 fileName8(aFile);
       
   641 	fileName.Copy(fileName8);  // TText8->TBuf16
       
   642 
       
   643 	// display a log message
       
   644  	ERR_PRINTF3(_L("Test Failed in file:%S line:%d"), &fileName, aLine);
       
   645 
       
   646 	}
       
   647 
       
   648 /**
       
   649  *
       
   650  * Traceable Boolean condition tester.
       
   651  * If the condition is not true, record an error and leave.
       
   652  *
       
   653  * @param	"TBool aCondition"
       
   654  *			Condition to be checked
       
   655  *
       
   656  * @param	"const TText8* aFile"
       
   657  *			Source code file name
       
   658  *
       
   659  * @param	"TInt aLine"
       
   660  *			Source code line
       
   661  *
       
   662  * @xxxx
       
   663  *
       
   664  */
       
   665 EXPORT_C void RTestStep::TestBooleanTrueL(TBool aCondition, const TText8* aFile, TInt aLine)
       
   666 	{
       
   667 
       
   668 	// check condition
       
   669 	if (aCondition)
       
   670 		return;
       
   671 
       
   672 	// this is only relevant if the current result is pass
       
   673 	if (iTestStepResult == EPass)
       
   674 		iTestStepResult = EFail;
       
   675 
       
   676 	// convert filename for log
       
   677 	TBuf<KMaxLogFilenameLength> fileName;
       
   678 	TPtrC8 fileName8(aFile);
       
   679 	fileName.Copy(fileName8);  // TText8->TBuf16
       
   680 
       
   681 	// display a log message
       
   682  	ERR_PRINTF3(_L("Test Failed in file:%S line:%d"), &fileName, aLine);
       
   683 
       
   684 	// leave with error code
       
   685 	User::Leave(KTestErrorCode);
       
   686 
       
   687 	}
       
   688 
       
   689 /**
       
   690  *
       
   691  * Traceable Boolean condition tester.
       
   692  * If the condition is not true, record an error with the supplied 
       
   693  * error code, and leave.
       
   694  *
       
   695  * @param	"TBool aCondition"
       
   696  *			Condition to be checked
       
   697  *
       
   698  * @param	"TInt aErrorCode"
       
   699  *			Supplied error code
       
   700  *
       
   701  * @param	"const TText8* aFile"
       
   702  *			Source code file name
       
   703  *
       
   704  * @param	"TInt aLine"
       
   705  *			Source code line
       
   706  *
       
   707  * @xxxx
       
   708  *
       
   709  */
       
   710 EXPORT_C void RTestStep::TestBooleanTrueWithErrorCodeL(TBool aCondition, TInt aErrorCode, const TText8* aFile, TInt aLine)
       
   711 	{
       
   712 	// check condition
       
   713 	if (aCondition)
       
   714 		return;
       
   715 
       
   716 	// this is only relevant if the current result is pass
       
   717 	if (iTestStepResult == EPass)
       
   718 		iTestStepResult = EFail;
       
   719 
       
   720 	// convert filename for log
       
   721 	TBuf<KMaxLogFilenameLength> fileName;
       
   722 	TPtrC8 fileName8(aFile);
       
   723 	fileName.Copy(fileName8);  // TText8->TBuf16
       
   724 
       
   725 	// get the error text
       
   726 	TPtrC errortxt = CLog::EpocErrorToText(aErrorCode);
       
   727 
       
   728 	// display a log message
       
   729 	ERR_PRINTF4(_L("Test Failed with error:%S in file:%S line:%d"),
       
   730 			&errortxt, &fileName, aLine);
       
   731 
       
   732 	// leave with error code
       
   733 	User::Leave(aErrorCode);
       
   734 	
       
   735 	}
       
   736 
       
   737 /**
       
   738  *
       
   739  * Traceable Boolean condition tester.
       
   740  * If the condition is not true, record an error with the supplied 
       
   741  * error code.
       
   742  *
       
   743  * @param	"TBool aCondition"
       
   744  *			Condition to be checked
       
   745  *
       
   746  * @param	"TInt aErrorCode"
       
   747  *			Supplied error code
       
   748  *
       
   749  * @param	"const TText8* aFile"
       
   750  *			Source code file name
       
   751  *
       
   752  * @param	"TInt aLine"
       
   753  *			Source code line
       
   754  *
       
   755  * @xxxx
       
   756  *
       
   757  */
       
   758 EXPORT_C void RTestStep::TestBooleanTrueWithErrorCode(TBool aCondition, TInt aErrorCode, const TText8* aFile, TInt aLine)
       
   759 	{
       
   760 	// check condition
       
   761 	if (aCondition)
       
   762 		return;
       
   763 
       
   764 	// this is only relevant if the current result is pass
       
   765 	if (iTestStepResult == EPass)
       
   766 		iTestStepResult = EFail;
       
   767 
       
   768 	// convert filename for log
       
   769 	TBuf<KMaxLogFilenameLength> fileName;
       
   770 	TPtrC8 fileName8(aFile);
       
   771 	fileName.Copy(fileName8);  // TText8->TBuf16
       
   772 
       
   773 	// get the error text
       
   774 	TPtrC errortxt = CLog::EpocErrorToText(aErrorCode);
       
   775 
       
   776 	// display a log message
       
   777 	ERR_PRINTF4(_L("Test Failed with error:%S in file:%S line:%d"),
       
   778 			&errortxt, &fileName, aLine);
       
   779 	}
       
   780 
       
   781 /**
       
   782  *
       
   783  * Traceable checkpoint tester.
       
   784  * If the value does not match expected, record an error with supplied
       
   785  * text string, and leave.
       
   786  *
       
   787  * @param	"TInt aVal"
       
   788  *			Value to be checked
       
   789  *
       
   790  * @param	"TInt aExpectedVal"
       
   791  *			Value expected
       
   792  *
       
   793  * @param	"const TDesC& aText"
       
   794  *			Supplied text string
       
   795  *
       
   796  * @param	"const TText8* aFile"
       
   797  *			Source code file name
       
   798  *
       
   799  * @param	"TInt aLine"
       
   800  *			Source code line
       
   801  *
       
   802  * @xxxx
       
   803  *
       
   804  */
       
   805 EXPORT_C void RTestStep::TestCheckPointCompareL(TInt aVal, TInt aExpectedVal, 
       
   806 												  const TDesC& aText, const TText8* aFile, TInt aLine)
       
   807 	{
       
   808 	if(aVal != aExpectedVal)
       
   809 		{
       
   810 		// this is only relevant if the current result is pass
       
   811 		if (iTestStepResult == EPass)
       
   812 			iTestStepResult = EFail;
       
   813 
       
   814 		// convert filename for log
       
   815 		TBuf<KMaxLogFilenameLength> fileName;
       
   816 		TPtrC8 fileName8(aFile);
       
   817 		fileName.Copy(fileName8);  // TText8->TBuf16
       
   818 
       
   819 		ERR_PRINTF6(_L("FAILED test:  Val = %d Exp Val = %d %S in file:%S line:%d"), 
       
   820 			aVal, aExpectedVal, &aText, &fileName, aLine);
       
   821 
       
   822 		User::Leave(aVal);
       
   823 		}
       
   824 	}
       
   825 
       
   826 /** 
       
   827  *
       
   828  * Accessors for stack / heap size
       
   829  *
       
   830  * NB - These can only be set from within the RTestStep derived constructor itself - there
       
   831  * are no setter accessors.
       
   832  *
       
   833  * @xxxx
       
   834  *
       
   835  */
       
   836 EXPORT_C TInt RTestStep::StackSize() const
       
   837 {
       
   838 	return iStackSize;
       
   839 }
       
   840 
       
   841 EXPORT_C TInt RTestStep::HeapSize() const
       
   842 {
       
   843 	return iHeapSize;
       
   844 }
       
   845 
       
   846 
       
   847 /** 
       
   848  *
       
   849  * Virtual destructor for CTestStep
       
   850  * Provided for backward compatibility ONLY
       
   851  *
       
   852  * @xxxx
       
   853  *
       
   854  */
       
   855 EXPORT_C CTestStep::~CTestStep()
       
   856 {
       
   857 }
       
   858 
       
   859 //
       
   860 // RAsyncTestStep
       
   861 //
       
   862 
       
   863 EXPORT_C RAsyncTestStep::RAsyncTestStep():
       
   864 	iReason (KErrNone),
       
   865 	iResult (EPass),
       
   866 	iStartAO (NULL),
       
   867 	iActiveSchedulerWait (NULL),
       
   868 	iStarted (EFalse)
       
   869 	{
       
   870 	}
       
   871 
       
   872 EXPORT_C TVerdict RAsyncTestStep::DoTestStepL()
       
   873 	{
       
   874 	// allow recalls to same test step (?), so re-initialise the basic variables. Can't delete
       
   875 	// as if in that case, old heap would be dead
       
   876 	iReason = KErrNone;
       
   877 	iResult = EPass;
       
   878 	iScheduler = NULL;
       
   879 	iActiveSchedulerWait = NULL;
       
   880 	
       
   881 	iScheduler = new (ELeave) CAsyncTestActiveScheduler(*this);	
       
   882 	CActiveScheduler::Install(iScheduler);
       
   883 	iActiveSchedulerWait = new (ELeave) CActiveSchedulerWait();
       
   884 	
       
   885 	// arrange for DoCallBack() to be called as the first thing. Use low priority to reduce
       
   886 	// the overhead of an extra AO on everything else
       
   887 	TCallBack callback (CallBack, this);
       
   888 	iStartAO = NULL;
       
   889 	iStartAO = new (ELeave) CAsyncCallBack (callback, CActive::EPriorityIdle); 
       
   890 	iStartAO->Call();
       
   891 	
       
   892 	iStarted = ETrue; // obviously do this before we start, as can't once it is
       
   893 	iActiveSchedulerWait->Start();
       
   894 	return CheckTestResult();
       
   895 	}
       
   896 
       
   897 EXPORT_C TVerdict RAsyncTestStep::DoTestStepPostambleL()
       
   898 	{
       
   899 	CloseTest();
       
   900 	delete iStartAO; // no need to Cancel 
       
   901 	iStartAO = NULL;
       
   902 	delete iActiveSchedulerWait;
       
   903 	iActiveSchedulerWait = NULL;
       
   904 	delete iScheduler; 
       
   905 	iScheduler = NULL;
       
   906 	return EPass;
       
   907 	}
       
   908 	
       
   909 EXPORT_C void RAsyncTestStep::StopTest()
       
   910 	{
       
   911 	StopTest(KErrNone);
       
   912 	}
       
   913 	
       
   914 EXPORT_C void RAsyncTestStep::StopTest(TInt aReason)
       
   915 	{
       
   916 	TVerdict resultToUse = (aReason==KErrNone) ? EPass : EFail;
       
   917 	StopTest (aReason, resultToUse);
       
   918 	}
       
   919 
       
   920 EXPORT_C void RAsyncTestStep::StopTest(TInt aReason, TVerdict aResult)
       
   921 	{
       
   922 	// note if stop is called multiple times, we record last
       
   923 	// non-KErrNone reason and last non-Pass result, but only actually stop once
       
   924 	if (aReason!=KErrNone)
       
   925 		{
       
   926 		iReason = aReason;		
       
   927 		}
       
   928 	SetResult(aResult);
       
   929 	if (iStarted)
       
   930 		{
       
   931 		iStarted = EFalse;
       
   932 		iActiveSchedulerWait->AsyncStop();
       
   933 		}
       
   934 	}
       
   935 	
       
   936 EXPORT_C TInt RAsyncTestStep::Reason() const
       
   937 	{
       
   938 	return iReason;
       
   939 	}
       
   940 	
       
   941 EXPORT_C TVerdict RAsyncTestStep::Result() const
       
   942 	{
       
   943 	return iResult;
       
   944 	}
       
   945 	
       
   946 void RAsyncTestStep::SetResult(TVerdict aResult)
       
   947 	{
       
   948 	// remember the last non-Pass result
       
   949 	if (aResult!=EPass)
       
   950 		{
       
   951 		iResult = aResult;
       
   952 		}	
       
   953 	}
       
   954 	
       
   955 EXPORT_C TVerdict RAsyncTestStep::CheckTestResult()
       
   956 	{
       
   957 	TVerdict result = Result();
       
   958 	
       
   959 	if (result!=EPass) // if the result is a Pass, even if error is too we treat as test pass
       
   960 		{
       
   961 		INFO_PRINTF3(_L("Failed test with error %d, result %s"), Reason(), KVerdictString[result]);
       
   962 		}
       
   963 	return result;
       
   964 	}
       
   965 
       
   966 TInt RAsyncTestStep::CallBack(TAny* aPtr)
       
   967 	{
       
   968 	RAsyncTestStep* self = static_cast<RAsyncTestStep*> (aPtr);
       
   969 	self->DoCallBack(); // if this fails, it will stop itself
       
   970 	return KErrNone;
       
   971 	}
       
   972 	
       
   973 void RAsyncTestStep::DoCallBack()
       
   974 	{
       
   975 	TRAPD(error, KickoffTestL()); 
       
   976 	if (error!=KErrNone)
       
   977 		{
       
   978 		StopTest(error); // if kickoff fails, we stop here
       
   979 		}	
       
   980 	}
       
   981 
       
   982 void RAsyncTestStep::HandleError(TInt aError)
       
   983 	{
       
   984 	INFO_PRINTF2(_L("ActiveScheduler::Error(%d)"), aError);
       
   985 	StopTest(aError);
       
   986 	}
       
   987 	
       
   988 //
       
   989 // CBusyTestUnit
       
   990 //
       
   991 
       
   992 CBusyTestUnit::CBusyTestUnit():
       
   993 		iPercentBusy(0), iThreadPriority(EPriorityNormal)
       
   994 	{
       
   995 	// non exported default constructor to enforce non-derivation
       
   996 	}
       
   997 
       
   998 CBusyTestUnit::CBusyTestUnit(TInt aPercentBusy, TThreadPriority aThreadPriority):
       
   999 		iPercentBusy(aPercentBusy), iThreadPriority(aThreadPriority)
       
  1000 	{
       
  1001 	ASSERT(aPercentBusy>=0 && aPercentBusy<=100); // assume this
       
  1002 	}
       
  1003 	
       
  1004 void CBusyTestUnit::ConstructL()
       
  1005 	{
       
  1006 	}
       
  1007 	
       
  1008 EXPORT_C CBusyTestUnit* CBusyTestUnit::NewLC(TInt aPercentBusy, TThreadPriority aThreadPriority)
       
  1009 	{
       
  1010 	CBusyTestUnit* self = new (ELeave) CBusyTestUnit(aPercentBusy, aThreadPriority);
       
  1011 	CleanupStack::PushL(self);
       
  1012 	self->ConstructL();
       
  1013 	return self;
       
  1014 	}
       
  1015 	
       
  1016 EXPORT_C CBusyTestUnit* CBusyTestUnit::NewL(TInt aPercentBusy, TThreadPriority aThreadPriority)
       
  1017 	{
       
  1018 	CBusyTestUnit* self = NewLC(aPercentBusy, aThreadPriority);
       
  1019 	CleanupStack::Pop(self);
       
  1020 	return self;
       
  1021 	}
       
  1022 	
       
  1023 CBusyTestUnit::~CBusyTestUnit()
       
  1024 	{
       
  1025 	Stop();
       
  1026 	}
       
  1027 	
       
  1028 EXPORT_C void CBusyTestUnit::Stop()
       
  1029 	{
       
  1030 	if (iTimer)
       
  1031 		{
       
  1032 		iTimer->Cancel();
       
  1033 		delete iTimer;
       
  1034 		iTimer=NULL;
       
  1035 		}
       
  1036 	if (iChildThread.Handle())
       
  1037 		{
       
  1038 		// child thread created, so kill
       
  1039 		iChildThread.Kill(0);
       
  1040 		iChildThread.Close();
       
  1041 		}
       
  1042 	}
       
  1043 	
       
  1044 EXPORT_C TInt CBusyTestUnit::Start()
       
  1045 	{
       
  1046 	return Start(0);	
       
  1047 	}
       
  1048 	
       
  1049 EXPORT_C TInt CBusyTestUnit::Start(TTimeIntervalMicroSeconds aRunFor)
       
  1050 	{
       
  1051 	return Start(0, aRunFor);
       
  1052 	}
       
  1053 	
       
  1054 EXPORT_C TInt CBusyTestUnit::Start(TTimeIntervalMicroSeconds32 aDelayFor, TTimeIntervalMicroSeconds aRunFor)
       
  1055 	{
       
  1056 	iRunFor = aRunFor;
       
  1057 	if (!aDelayFor.Int())
       
  1058 		{
       
  1059 		// run immediately
       
  1060 		return RunThread();
       
  1061 		}
       
  1062 	else
       
  1063 		{
       
  1064 		iTimer = CPeriodic::NewL(CActive::EPriorityHigh);
       
  1065 		TCallBack callback(StaticTimerCallback, this);
       
  1066 		iTimer->Start(aDelayFor, 0, callback);
       
  1067 		return KErrNone;
       
  1068 		}
       
  1069 	}
       
  1070 	
       
  1071 TInt CBusyTestUnit::StaticTimerCallback(TAny* aPtr)
       
  1072 	{
       
  1073 	CBusyTestUnit* self = static_cast<CBusyTestUnit*>(aPtr);
       
  1074 	return self->TimerCallback();
       
  1075 	}
       
  1076 	
       
  1077 TInt CBusyTestUnit::TimerCallback()
       
  1078 	{
       
  1079 	// called on timer callback, so assume iTimer!
       
  1080 	ASSERT(iTimer);
       
  1081 	// first stop and delete timer - don't need again this run
       
  1082 	iTimer->Cancel();
       
  1083 	// then kick off the thread
       
  1084 	TInt error = RunThread(); 
       
  1085 	// now delete the timer - do now as we've been called back by it!
       
  1086 	delete iTimer;
       
  1087 	iTimer = NULL;
       
  1088 	return error; // any error will stop the test, in theory
       
  1089 	}
       
  1090 	
       
  1091 TInt CBusyTestUnit::RunThread()
       
  1092 	{
       
  1093 	TAny* paramPtr = this;
       
  1094 	TInt error = iChildThread.Create(KNullDesC, StartThread, 
       
  1095 					KDefaultStackSize, NULL, paramPtr, EOwnerThread);
       
  1096 	if (!error)
       
  1097 		{
       
  1098 		iChildThread.SetPriority(iThreadPriority);
       
  1099 		iChildThread.Resume();
       
  1100 		}
       
  1101 	return error;
       
  1102 	}
       
  1103 	
       
  1104 TInt CBusyTestUnit::StartThread(TAny* aPtr)
       
  1105 	{
       
  1106 	CBusyTestUnit* self = static_cast<CBusyTestUnit*>(aPtr);
       
  1107 	if (self)
       
  1108 		{
       
  1109 		self->ThreadFunction();
       
  1110 		}
       
  1111 	return KErrNone;
       
  1112 	}
       
  1113 	
       
  1114 void CBusyTestUnit::ThreadFunction()
       
  1115 	{
       
  1116 	// this runs in a separate thread and tries to use lots of CPU time up to percentage
       
  1117 	// nominally we run busy for loops for iPercentBusy/100ms, and then wait for rest of the
       
  1118 	// 100ms using User::After(). We keep doing this until we reach the target time, if there is
       
  1119 	// one
       
  1120 	
       
  1121 	const TInt KDefaultLoop = 10000;
       
  1122 	TTime timeAtStart; 
       
  1123 	timeAtStart.UniversalTime(); // time of start
       
  1124 	
       
  1125 	const TInt KLoopInterval =100000; // 100ms - loop time
       
  1126 	TTimeIntervalMicroSeconds32 busyInterval(KLoopInterval*iPercentBusy/100); // how much of loop time to be busy
       
  1127 	TTimeIntervalMicroSeconds32 quietInterval(KLoopInterval-busyInterval.Int()); // how much of loop time to be quiet
       
  1128 	
       
  1129 	while (ETrue)
       
  1130 		{
       
  1131 		// the interval, for loops for the busy bit and then a User::After()
       
  1132 		TTime startOfInterval;
       
  1133 		startOfInterval.UniversalTime();
       
  1134 		while (ETrue)
       
  1135 			{
       
  1136 			// the busy bit - iBusyVariable is volatile so should never be optimised out
       
  1137 			for (TInt i=0; i<KDefaultLoop; i++)
       
  1138 				{
       
  1139 				iBusyVariable = i;
       
  1140 				}
       
  1141 			TTime now;
       
  1142 			now.UniversalTime();
       
  1143 			if (startOfInterval + busyInterval < now)
       
  1144 				{
       
  1145 				// we're passed the time
       
  1146 				break;
       
  1147 				}
       
  1148 			}
       
  1149 		User::After(quietInterval);		
       
  1150 			
       
  1151 		if (iRunFor.Int64())
       
  1152 			{
       
  1153 			// check to see if we are passed the interval given at Start()
       
  1154 			TTime now;
       
  1155 			now.UniversalTime();
       
  1156 			if (timeAtStart + iRunFor < now)
       
  1157 				{
       
  1158 				// we're passed the time
       
  1159 				break;
       
  1160 				}
       
  1161 			}
       
  1162 		}
       
  1163 	}
       
  1164