toolsandutils/autotest/src/autotest.cpp
changeset 0 83f4b4db085c
child 1 d4b442d23379
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     1 // Copyright (c) 2000-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 // Framework for Automated Test code.
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file autotest.cpp
       
    20 */
       
    21 
       
    22 #include "autotest.h"
       
    23 
       
    24 #include <flogger.h>		// for RFileLogger 
       
    25 
       
    26 
       
    27 _LIT(KTestKeywordSuccess, "SUCCESS");
       
    28 _LIT(KTestKeywordFailed,  "FAILED");
       
    29 _LIT(KTestKeywordNotSupported,  "NOT SUPPORTED");
       
    30 
       
    31 //
       
    32 // implementation of CAutoTest
       
    33 //
       
    34 
       
    35 EXPORT_C CAutoTest* CAutoTest::NewL(const struct TAutoTestCase* aTestcases, TInt aNumberOfTestcases, const TDesC& aName, RTest& aTest)
       
    36 /**
       
    37  * 2 phase constructor
       
    38  *
       
    39  * @param aTestcases         Pointer to the table with test cases
       
    40  * @param aNumberOfTestcases Number of automated test cases
       
    41  * @param aName              Name of the test report file
       
    42  * @param aTest              The RTest object owned by the client
       
    43  * @return CAutoTest*        A newly created CAutoTest object
       
    44  */
       
    45 	{
       
    46 	CAutoTest* p = new (ELeave) CAutoTest(aTestcases, aNumberOfTestcases, aName, aTest);
       
    47 	CleanupStack::PushL(p);
       
    48 	p->ConstructL();
       
    49 	CleanupStack::Pop();
       
    50 	return p;
       
    51 	}
       
    52 
       
    53 
       
    54 CAutoTest::~CAutoTest()
       
    55 /**
       
    56  * D'tor
       
    57  */
       
    58 	{
       
    59 	// close file handles
       
    60 	iTestReport.Close();
       
    61 	iFileServer.Close();
       
    62 	
       
    63 	delete iCommandLine;
       
    64 	delete iTestResults;
       
    65 	delete iSkipList;
       
    66 	iTestCases = NULL;
       
    67 	}
       
    68 
       
    69 
       
    70 EXPORT_C TInt CAutoTest::ExecuteL()
       
    71 /**
       
    72  * Execute the test suite. 
       
    73  *
       
    74  * @return test result, KErrNone if all tests passed
       
    75  */
       
    76 	{
       
    77 	(void)User::LeaveIfError(iTestReport.Write(_L8("--- test report start---\r\n")));
       
    78 
       
    79 	//
       
    80 	// machine info
       
    81 	//
       
    82 	MachineInfoL();
       
    83 
       
    84 	//
       
    85 	// date & time info
       
    86 	//
       
    87 	(void)User::LeaveIfError(iTestReport.Write(_L8("Time started: ")));
       
    88 	LogTimeL();
       
    89 
       
    90 	//
       
    91 	// component under test info (optional)
       
    92 	//
       
    93 	if(iCompInfo.Length())
       
    94 		{
       
    95 		(void)User::LeaveIfError(iTestReport.Write(_L8("Component info: ")));
       
    96 		(void)User::LeaveIfError(iTestReport.Write(iCompInfo));
       
    97 		(void)User::LeaveIfError(iTestReport.Write(_L8("\r\n")));
       
    98 		}
       
    99 
       
   100 	
       
   101 	// decide to run the menu or the complete test
       
   102 	if(iKeepGoing)
       
   103 		RunAllTestsL();
       
   104 	else
       
   105 		StartMenuL();
       
   106 
       
   107 	// date & time info
       
   108 	(void)User::LeaveIfError(iTestReport.Write(_L8("Time finished: ")));
       
   109 	LogTimeL();
       
   110 
       
   111 	(void)User::LeaveIfError(iTestReport.Write(_L8("--- test report end---\r\n")));
       
   112 
       
   113 	return iTestSuiteFailed ? 84 : KErrNone;
       
   114 
       
   115 	}
       
   116 
       
   117 EXPORT_C void CAutoTest::TestCheckPointCompareL(TInt aVal,TInt aExpectedVal, const TDesC& aText, char* aFile,TInt aLine)
       
   118 	{
       
   119 	if(aVal == aExpectedVal)
       
   120 		return;
       
   121 
       
   122 	TBuf<200> temp;
       
   123 	temp.Copy(TPtrC8((TText8*)aFile));
       
   124 
       
   125 	iRTest.Printf(_L("FAILED test %d : Val = %d Exp Val = %d file %S, line %d\n")
       
   126 		, iTestCase+1, aVal, aExpectedVal, &temp, aLine);
       
   127 
       
   128 	//
       
   129 	// Log failure to log file, even if iKeepGoing is EFalse.
       
   130 	// The code used to only log the failure to the file if iKeepGoing was ETrue.
       
   131 	// If a filaure occurs it needs to be written to log regardless of iKeepGoing.
       
   132 	TBuf8<256> stringBuf;
       
   133 	stringBuf.AppendFormat(_L8("FAILED test %d : Val = %d Exp Val = %d file %s, line %d : "),iTestCase+1,aVal,aExpectedVal, aFile, aLine);
       
   134 	stringBuf.Append(aText);
       
   135 	stringBuf.AppendFormat(_L8("\r\n"));
       
   136 	(void)User::LeaveIfError(iTestReport.Write(stringBuf));
       
   137 	iTestSuiteFailed = ETrue;
       
   138 
       
   139 	User::Leave(aVal);
       
   140 	}
       
   141 
       
   142 
       
   143 EXPORT_C void CAutoTest::TestCheckPointCodeL(TInt aCase, char* aFile, TInt aLine)
       
   144 /**
       
   145  * hidden by the macro GLOBAL_CHECKPOINT_CODE. Used to validate return values etc.
       
   146  * If the 'keepgoing' command line option is specified, the test program * will not stop, but just print a warning in the test report, including
       
   147  * which file and line where the test failed. Then it will leave the test
       
   148  * case and do the next one. 
       
   149  *
       
   150  * @param aCase 0 no error or the error code
       
   151  * @param aFile name of the file involved here
       
   152  * @param aLine the line of the file involved here
       
   153  */
       
   154 	{
       
   155 	if(!aCase)
       
   156 		return;
       
   157 
       
   158 	// Convert to unicode for log to console
       
   159 	TBuf<200> temp;
       
   160 	temp.Copy(TPtrC8((TText8*)aFile));
       
   161 
       
   162 	iRTest.Printf(_L("FAILED test %d : Code = %d file %S, line %d\n"), iTestCase+1, aCase, &temp, aLine);
       
   163 
       
   164 	//
       
   165 	// Log failure to log file, even if iKeepGoing is EFalse.
       
   166 	// The code used to only log the failure to the file if iKeepGoing was ETrue.
       
   167 	// If a filaure occurs it needs to be written to log regardless of iKeepGoing.
       
   168 	TBuf8<256> stringBuf;
       
   169 	stringBuf.AppendFormat(_L8("FAILED test %d : Code = %d file %s, line %d\r\n"),iTestCase+1, aCase, aFile, aLine);
       
   170 	(void)User::LeaveIfError(iTestReport.Write(stringBuf));
       
   171 	iTestSuiteFailed = ETrue;
       
   172 
       
   173 	User::Leave(aCase);
       
   174 	}
       
   175 
       
   176 EXPORT_C void CAutoTest::TestCheckPointL(TBool aCase, char* aFile, TInt aLine)
       
   177 /**
       
   178  * hidden by the macro GLOBAL_CHECKPOINT. Used to validate return values etc.
       
   179  * If the 'keepgoing' option is specified, the test program
       
   180  * will not stop, but just print a warning in the test report, including
       
   181  * which file and line where the test failed. Then it will leave the test
       
   182  * case and do the next one. 
       
   183  *
       
   184  * @param aCase if true success, false means failed
       
   185  * @param aFile name of the file involved here
       
   186  * @param aLine the line of the file involved here
       
   187  */
       
   188 	{
       
   189 	if(aCase)
       
   190 		return;
       
   191 
       
   192 	// Convert to unicode for log to console
       
   193 	TBuf<200> temp;
       
   194 	temp.Copy(TPtrC8((TText8*)aFile));
       
   195 
       
   196 	iRTest.Printf(_L("FAILED test %d : file %S, line %d\n"),iTestCase+1, &temp, aLine);
       
   197 
       
   198 	// Log failure to log file, even if iKeepGoing is EFalse.
       
   199 	// The code used to only log the failure to the file if iKeepGoing was ETrue.
       
   200 	// If a filaure occurs it needs to be written to log regardless of iKeepGoing.
       
   201 	TBuf8<256> stringBuf;
       
   202 	stringBuf.AppendFormat(_L8("FAILED test %d : file %s, line %d\r\n"),iTestCase+1, aFile, aLine);
       
   203 	(void)User::LeaveIfError(iTestReport.Write(stringBuf));
       
   204 	iTestSuiteFailed = ETrue;
       
   205 	User::Leave(84);
       
   206 	}
       
   207 
       
   208 EXPORT_C void CAutoTest::SetCompInfo(const TDesC8& aCompInfo)
       
   209 /**
       
   210  * store information about the Component under test in the autotest object
       
   211  *
       
   212  * @param aCompInfo descriptor containin the component info
       
   213  */
       
   214 	{
       
   215 	iCompInfo = aCompInfo;
       
   216 	}
       
   217 
       
   218 //
       
   219 // protected
       
   220 //
       
   221 
       
   222 CAutoTest::CAutoTest(const struct TAutoTestCase* aTestcases, TInt aNumberOfTestcases, const TDesC& aName, RTest& aTest)
       
   223 /**
       
   224  * C'tor
       
   225  *
       
   226  * @param aTestcases         Pointer to the table with test cases
       
   227  * @param aNumberOfTestcases Number of automated test cases
       
   228  * @param aName              Name of the test report file
       
   229  * @param aTest              The RTest object owned by the client
       
   230  */
       
   231 	:iTestCases(aTestcases)
       
   232 	,iNumberOfTestcases(aNumberOfTestcases)
       
   233 	,iTestReportName(aName)
       
   234 	,iKeepGoing(EFalse)
       
   235 	,iTestSuiteFailed(ETrue)
       
   236 	,iRTest(aTest)
       
   237 	,iSkipList(NULL)
       
   238 	,iCommandLine(NULL)
       
   239 	{
       
   240 	}
       
   241 
       
   242 
       
   243 void CAutoTest::ConstructL()
       
   244 /**
       
   245  * 2nd phase of 2 phased constructor.
       
   246  *
       
   247  * create a new table for test results storing, depending on the 
       
   248  * number of test cases. Connect to the file server and open
       
   249  * and replace the test report file.
       
   250  */
       
   251 	{
       
   252 	// No serial port logging
       
   253 	iRTest.SetLogged(EFalse);
       
   254 	// Array of test result codes
       
   255 	iTestResults = new (ELeave) TInt[iNumberOfTestcases];
       
   256 	// Array of bools to determine whether a test should be skipped
       
   257 	// Set to ETrue if a test is not supported
       
   258 	iSkipList = new (ELeave) TBool[iNumberOfTestcases];
       
   259 	Mem::FillZ(iSkipList,iNumberOfTestcases * sizeof(TBool));	
       
   260 	(void)User::LeaveIfError(iFileServer.Connect());
       
   261 
       
   262 	// Read the command line or contents of config file specified on the command line,
       
   263 	// into private storage
       
   264 	GetCommandLineL();
       
   265 	// Get the name of the output log file
       
   266 	SetLogFileL();
       
   267 	// Set up the test skip options
       
   268 	GetSkipOptions();
       
   269 	// Set the keepgoing flag
       
   270 	GetKeepGoingOption();
       
   271 	}
       
   272 
       
   273 
       
   274 //
       
   275 // private
       
   276 //
       
   277 
       
   278 void CAutoTest::PrintMenu() const
       
   279 /**
       
   280  * print a menu to the console
       
   281  */
       
   282 	{
       
   283 
       
   284 	iRTest.Printf(_L("menu:\n") );
       
   285 	iRTest.Printf(_L("  !  - Run all tests\n") );
       
   286 	iRTest.Printf(_L("  ^C - Quit\n") );
       
   287 
       
   288 	for(TInt i=0;i<iNumberOfTestcases;i++)
       
   289 		{
       
   290 		iRTest.Printf(_L("%d %s \n"), i+1, iTestCases[i].iText );
       
   291 		}
       
   292 
       
   293 	}
       
   294 
       
   295 EXPORT_C void CAutoTest::Printf(TRefByValue<const TDesC> aFmt,...)
       
   296 /**
       
   297  * print to console and logfile
       
   298  */
       
   299 	{
       
   300 	VA_LIST list;
       
   301 	VA_START(list, aFmt);
       
   302 	TBuf<0x100> aBuf;
       
   303 	aBuf.AppendFormatList(aFmt, list);
       
   304 
       
   305 	// console
       
   306 	iRTest.Printf(aBuf);
       
   307 
       
   308 	// logfile
       
   309 	LogExtra((TText8*)__FILE__, __LINE__, aFmt);
       
   310 	}
       
   311 
       
   312 
       
   313 void CAutoTest::StartMenuL()
       
   314 /**
       
   315  * run the menu forever, until press Ctrl-C
       
   316  *
       
   317  * @leave this function may leave
       
   318  */
       
   319 	{
       
   320 	TInt ret;
       
   321 
       
   322 	
       
   323 	FOREVER
       
   324 		{
       
   325 		TBuf<256> inputBuf;
       
   326 		
       
   327 		PrintMenu();
       
   328 
       
   329 		TInt key = iRTest.Getch();
       
   330 		iRTest.Printf(_L("%c"), key);
       
   331 
       
   332 		switch(key)
       
   333 			{
       
   334 		case '!':
       
   335             // for the time, that there is a request in the menu to run all the
       
   336             // test cases, the iKeepGoing flag shoulg should be set and deleted
       
   337             // afterwards; because test cases behave different in automated and 
       
   338             // manual mode; and here we are definitely in the automated mode
       
   339             iKeepGoing = ETrue;
       
   340 			RunAllTestsL();
       
   341             iKeepGoing = EFalse;
       
   342 			break;
       
   343 
       
   344 		case 0x03: // Ctrl-C
       
   345 			return;
       
   346 			  
       
   347 		default:
       
   348 
       
   349 			inputBuf.Append(key);
       
   350 			GetString(*iRTest.Console(), inputBuf);
       
   351 			TLex lexer(inputBuf);
       
   352 			TInt value;
       
   353 			ret = lexer.Val(value);
       
   354 			value-=1;
       
   355 			if(ret == KErrNone)
       
   356 				{
       
   357 				iRTest.Printf(_L("Testcase: %d\n"), value+1);
       
   358 				if((value >= 0) && (value < (TInt)iNumberOfTestcases))
       
   359 					{
       
   360 					iTestCase = value;
       
   361 					ret = RunATestL();
       
   362 					}
       
   363 				else
       
   364 					break;
       
   365 
       
   366 				//
       
   367 				// Display the success or failure to the console 
       
   368 				if(ret == KErrNone)
       
   369 					iRTest.Printf(_L("SUCCESS! \n"));
       
   370 				else if(ret == KErrNotSupported)
       
   371 					iRTest.Printf(_L("NOT SUPPORTED\n"), ret);
       
   372 				else
       
   373 					iRTest.Printf(_L("FAILED! (ret=%d)\n"), ret);
       
   374 
       
   375 				//
       
   376 				// Log our success/failure in the log file
       
   377 				TBuf8<256> stringBuf8;
       
   378 				stringBuf8.AppendFormat(_L8("test %d: "), value +1 );
       
   379 
       
   380 				if(ret == KErrNone)
       
   381 					stringBuf8.Append(KTestKeywordSuccess);
       
   382 				else if(ret == KErrNotSupported)
       
   383 					stringBuf8.Append(KTestKeywordNotSupported);
       
   384 				else
       
   385 					stringBuf8.Append(KTestKeywordFailed);
       
   386 
       
   387 				stringBuf8.AppendFormat(_L8(" (return=%d) "), ret );
       
   388 				TBuf<256> buf;
       
   389 				buf.AppendFormat(_L("[%s]\r\n"), iTestCases[value].iText);
       
   390 				stringBuf8.Append(buf);
       
   391 				(void)User::LeaveIfError(iTestReport.Write(stringBuf8));
       
   392 				}
       
   393 			  
       
   394 			  break;
       
   395 
       
   396 			} // end, switch(key)
       
   397 
       
   398 		} // end, FOREVER
       
   399 	
       
   400 	}
       
   401 
       
   402 void CAutoTest::RunAllTestsL()
       
   403 /**
       
   404  * run all the tests for this test program
       
   405  */
       
   406 	{
       
   407 	TInt ret;
       
   408 	iRTest.Printf(_L("Now running all the testcases...\n") );
       
   409 	
       
   410 	for(TInt i=0;i<iNumberOfTestcases;i++)
       
   411 		{
       
   412 		iTestCase = i;
       
   413 		ret = RunATestL();
       
   414 		iTestResults[i] = ret;
       
   415 		PrintTestReportL(i);
       
   416 		}
       
   417 	}
       
   418 
       
   419 void CAutoTest::PrintThreadsToLogFile()
       
   420 // Print all the current running thread names to the log file
       
   421 	{
       
   422 	TBuf<0x1> asterisk=_L("*");
       
   423 	TName search=asterisk;
       
   424 
       
   425 	TFindThread findHb;
       
   426 	findHb.Find(search);
       
   427 	TFullName name;
       
   428 
       
   429 	while (findHb.Next(name)==KErrNone)
       
   430 		{
       
   431 		TBuf8<300> stringBuf8(_L8("\tThread Name = "));
       
   432 		stringBuf8.Append(name);
       
   433 		stringBuf8.Append(_L8("\r\n"));
       
   434 		iTestReport.Write(stringBuf8);
       
   435 		}
       
   436 	}
       
   437 
       
   438 
       
   439 TInt CAutoTest::RunATestL()// const
       
   440 /**
       
   441  * run a test and return the error code.
       
   442  * the testcase is gived in iTestCase
       
   443  *
       
   444  * @return error code for that test case
       
   445  */
       
   446 	{
       
   447 	TInt ret;
       
   448 
       
   449 	if(iSkipList[iTestCase])
       
   450 		return KErrNotSupported;
       
   451 
       
   452 	// check the index first
       
   453 	if(iTestCase < 0 || iTestCase >= (TInt)iNumberOfTestcases)
       
   454 		User::Leave(KErrNotFound);
       
   455 	
       
   456 	iRTest.Printf(_L("%d %s \n"), iTestCase+1, iTestCases[iTestCase].iText );
       
   457 
       
   458 	// get number of outstanding requetsts on thread before we run the test
       
   459 	TInt reqsAtStart = RThread().RequestCount();
       
   460 	if(reqsAtStart!=0)
       
   461 		{
       
   462 		TBuf8<256> stringBuf8;
       
   463 		stringBuf8.AppendFormat(_L8("Warning: thread had %d oustanding requests before starting test %d!\r\n"),reqsAtStart,iTestCase+1);
       
   464 		iTestReport.Write(stringBuf8);
       
   465 		}
       
   466 			
       
   467 	// get number of Handles *before* we start the program
       
   468 	TInt processHandleCountBefore;
       
   469 	TInt threadHandleCountBefore;
       
   470 	RThread().HandleCount(processHandleCountBefore, threadHandleCountBefore);
       
   471 
       
   472 	// ------------------------------------------
       
   473 	void (*fn)(void) = iTestCases[iTestCase].iFunc;
       
   474 	TRAP(ret, fn() );
       
   475 	// ------------------------------------------
       
   476 
       
   477 	//
       
   478 	// if the test case failed then we dont bother
       
   479 	// with checking the outstanding requests etc.
       
   480 	//
       
   481 	if(ret == KErrNone)
       
   482 		{
       
   483 		// get number of Handles *after* the program is finished
       
   484 		TInt processHandleCountAfter;
       
   485 		TInt threadHandleCountAfter;
       
   486 		RThread().HandleCount(processHandleCountAfter, threadHandleCountAfter);
       
   487 
       
   488 		// check that we are closing all the handles
       
   489 		if(threadHandleCountBefore<threadHandleCountAfter)
       
   490 			{
       
   491 
       
   492 			
       
   493 			TBuf8<256> stringBuf8;
       
   494 			stringBuf8.AppendFormat(_L8("%d handles left open after test %d returned!\r\n"),threadHandleCountAfter-threadHandleCountBefore,iTestCase+1);
       
   495 			iTestReport.Write(stringBuf8);
       
   496 			
       
   497 			PrintThreadsToLogFile();
       
   498 
       
   499 			return KErrGeneral;
       
   500 			}
       
   501 
       
   502 		// check that number of oustanding requests on thread has not increased
       
   503 		const TInt reqsNow=RThread().RequestCount();
       
   504 		if(reqsNow>reqsAtStart)
       
   505 			{
       
   506 			TBuf8<256> stringBuf8;
       
   507 			stringBuf8.AppendFormat(_L8("%d requests were left outstanding after test %d returned!\r\n"),reqsNow,iTestCase+1);
       
   508 			iTestReport.Write(stringBuf8);
       
   509 			return KErrGeneral;
       
   510 			}
       
   511 		}
       
   512 	return ret;
       
   513 	}
       
   514 
       
   515 void CAutoTest::SetLogFileL()
       
   516 /**
       
   517  * Parse the command line buffer to see if a logfile has been specified
       
   518  * If a logfile is specified create it
       
   519  */
       
   520 	{
       
   521 	TPtr ptr = iCommandLine->Des();
       
   522 	TLex lex(ptr);
       
   523 
       
   524 	// Parse the command line for the "-log"
       
   525 	while(!lex.Eos())
       
   526 		{
       
   527 		TPtrC ptr = lex.NextToken();
       
   528 		_LIT(KLogCommand,"-log");
       
   529 		if(ptr == KLogCommand)
       
   530 			break;
       
   531 		}
       
   532 	// Read the log filename 
       
   533 	if(!lex.Eos())
       
   534 		{
       
   535 		TPtrC file = lex.NextToken();
       
   536 		iTestReportName.Copy(file);
       
   537 		}
       
   538 	// Replace if it exists and if not, create the folder then create the file
       
   539 	if(iTestReport.Replace(iFileServer, iTestReportName, EFileWrite) != KErrNone)
       
   540 		{
       
   541 		if(iTestReport.Create(iFileServer, iTestReportName, EFileWrite) == KErrPathNotFound)
       
   542 			(void)User::LeaveIfError(iFileServer.MkDirAll(iTestReportName));
       
   543 		(void)User::LeaveIfError(iTestReport.Create(iFileServer, iTestReportName, EFileWrite));
       
   544 		}
       
   545 	}
       
   546 
       
   547 void CAutoTest::GetCommandLineL()
       
   548 /**
       
   549  * Parse the command line to see if a config file has been specified: "-config afile.txt"
       
   550  * If it has, then read the contents of the file into the private command line buffer. Otherwise
       
   551  * copy the real command line into the private command line buffer
       
   552  */
       
   553 	{
       
   554 	TBuf<KMaxCmdLength> cmdLine;
       
   555 	TBuf<KMaxFileName> fileName;
       
   556 	
       
   557 	#ifndef EKA2 
       
   558 		RProcess().CommandLine(cmdLine);
       
   559 	#else
       
   560 		User::CommandLine(cmdLine);
       
   561 	#endif
       
   562 	
       
   563 	TLex lex(cmdLine);
       
   564 	// Parse the real command line for the -config option
       
   565 	while(!lex.Eos())
       
   566 		{
       
   567 		TPtrC ptr = lex.NextToken();
       
   568 		_LIT(KConfigCommand,"-config");
       
   569 		if(ptr == KConfigCommand)
       
   570 			break;
       
   571 		}
       
   572 	// Read the config filename if it's there
       
   573 	if(!lex.Eos())
       
   574 		{
       
   575 		TPtrC file = lex.NextToken();
       
   576 		fileName.Copy(file);
       
   577 		}
       
   578 	// If the filename has not been specified, set up the default
       
   579 	// This may not exist either, by the way.
       
   580 	if(!fileName.Length())
       
   581 		{
       
   582 		_LIT(KDefaultConfigFile,"c:\\autotestconfig.txt");
       
   583 		fileName = KDefaultConfigFile;
       
   584 		}
       
   585 	RFile file;
       
   586 	CleanupClosePushL(file);
       
   587 	// Try to open the config file
       
   588 	if(file.Open(iFileServer,fileName, EFileRead) == KErrNone)
       
   589 		// Config file exists
       
   590 		// read it into a local 8 bit buffer
       
   591 		{
       
   592 		TInt size;
       
   593 		// Get the size of the file
       
   594 		(void)User::LeaveIfError(file.Size(size));
       
   595 		HBufC8* buf8 = HBufC8::NewL(size);
       
   596 		CleanupStack::PushL(buf8);
       
   597 		TPtr8 ptr8 = buf8->Des();
       
   598 		// Read the file contents into the heap buffer
       
   599 		(void)User::LeaveIfError(file.Read(ptr8,size));
       
   600 		// Copy to private class unicode buffer
       
   601 		iCommandLine = HBufC::NewL(size);
       
   602 		TPtr ptr16 = iCommandLine->Des();
       
   603 		ptr16.Copy(ptr8);
       
   604 		CleanupStack::PopAndDestroy(buf8);
       
   605 		}
       
   606 	else
       
   607 		// Config file does not exist so copy the real command line buffer to the private class copy
       
   608 		{
       
   609 		iCommandLine = HBufC::NewL(cmdLine.Length());
       
   610 		TPtr ptr16 = iCommandLine->Des();
       
   611 		ptr16.Copy(cmdLine);
       
   612 		}
       
   613 	CleanupStack::PopAndDestroy(&file);
       
   614 	}
       
   615 
       
   616 void CAutoTest::GetKeepGoingOption()
       
   617 /**
       
   618  * Read the keepgoing flag from the command line bufffer
       
   619  */
       
   620 	{
       
   621 	_LIT(KKeepGoingString, "keepgoing");
       
   622 	TInt ret = iCommandLine->Find(KKeepGoingString);
       
   623 	if(ret >= KErrNone)
       
   624 		iKeepGoing = ETrue;
       
   625 	}
       
   626 
       
   627 void CAutoTest::GetSkipOptions()
       
   628 /**
       
   629  * Read the test skip options, if any, from the command line buffer
       
   630  * Usage: "-skip 1 4 5" to skip tests 1, 4 & 5 and log as NOT SUPPORTED
       
   631  */
       
   632    {
       
   633 	TPtr ptr = iCommandLine->Des();
       
   634 	TLex lex(ptr);
       
   635 	// Parse for -skip
       
   636 	while(!lex.Eos())
       
   637 		{
       
   638 		TPtrC token = lex.NextToken();
       
   639 		_LIT(KSkipCommand,"-skip");
       
   640 		if(token == KSkipCommand)
       
   641 			break;
       
   642 		}
       
   643 	// Loop through reading the test numbers to skip
       
   644 	while(!lex.Eos())
       
   645 		{
       
   646 		TInt testNum;
       
   647 		TPtrC ptr = lex.NextToken();
       
   648 		TLex lex(ptr);
       
   649 		// Read the test number as an integer
       
   650 		if(lex.Val(testNum) != KErrNone)
       
   651 			// Exit at the first token that's not a valid number
       
   652 			break;
       
   653 		if(testNum <= 0 || testNum > iNumberOfTestcases)
       
   654 			// Out of range
       
   655 			continue;
       
   656 		// Skip this test
       
   657 		iSkipList[testNum-1] = ETrue;
       
   658 		}
       
   659 	}
       
   660 
       
   661 
       
   662 void CAutoTest::PrintTestReportL(TInt aTestIndex)
       
   663 /**
       
   664  * print a test report to file and console
       
   665  */
       
   666 	{	
       
   667 	// print status
       
   668 	TBuf8<256> stringBuf8;
       
   669 	stringBuf8.AppendFormat(_L8("test %d: "), aTestIndex+1 );
       
   670 	if(iTestResults[aTestIndex] == KErrNone)
       
   671 		stringBuf8.Append(KTestKeywordSuccess);
       
   672 	else if(iTestResults[aTestIndex] == KErrNotSupported)
       
   673 		stringBuf8.Append(KTestKeywordNotSupported);
       
   674 	else
       
   675 		stringBuf8.Append(KTestKeywordFailed);
       
   676 	stringBuf8.AppendFormat(_L8(" (return=%d) "), iTestResults[aTestIndex] );
       
   677 	TBuf<256> buf;
       
   678 	buf.AppendFormat(_L("[%s]\r\n"), iTestCases[aTestIndex].iText);
       
   679 	stringBuf8.Append(buf);
       
   680 	(void)User::LeaveIfError(iTestReport.Write(stringBuf8));
       
   681 	TBuf<256> stringBuf;
       
   682 	stringBuf.Copy(stringBuf8);
       
   683 	iRTest.Printf(stringBuf);
       
   684 	}
       
   685 
       
   686 
       
   687 EXPORT_C void CAutoTest::GetString(CConsoleBase& aConsole, TDes& aString) const
       
   688 /**
       
   689  * This function re-invents the wheel (once again...)
       
   690  * It reads a string from the keyboard. Uses Getch() to get keys and does not
       
   691  * return until ENTER is pressed. 
       
   692  *
       
   693  * @param aConsole const reference to the console
       
   694  * @param aString reference to the string to be read into
       
   695  */
       
   696     {
       
   697 	TKeyCode code;
       
   698 	TBuf<1> kjar;
       
   699 
       
   700 	FOREVER
       
   701 		{
       
   702 		code = aConsole.Getch();
       
   703 		kjar.SetLength(0);
       
   704 		kjar.Append(code);
       
   705 
       
   706 		aConsole.Printf(_L("%S"),&kjar);
       
   707 	
       
   708 		// If <CR> finish editing string
       
   709 		if (code == '\r')
       
   710 			break;
       
   711 		
       
   712 		// if <BS> remove last character
       
   713 		if ((code == 0x08) && (aString.Length() != 0))
       
   714 			aString.SetLength((aString.Length()-1));
       
   715 		else
       
   716 			aString.Append(code);
       
   717 		}
       
   718 	aConsole.Printf(_L("\n"));
       
   719     }
       
   720 
       
   721 
       
   722 void CAutoTest::LogTimeL()
       
   723 /*
       
   724  * write date&time info to log file
       
   725  */
       
   726 	{
       
   727 	TBuf8<64> buf8;
       
   728 	TTime now;
       
   729 	now.HomeTime();
       
   730 	TDateTime dateTime;
       
   731 	dateTime = now.DateTime();
       
   732 	buf8.Format(_L8("%02d/%02d/%04d %02d:%02d.%02d \r\n"), dateTime.Day()+1, dateTime.Month()+1, dateTime.Year(), 
       
   733 				dateTime.Hour(), dateTime.Minute(), dateTime.Second() );
       
   734 	(void)User::LeaveIfError(iTestReport.Write(buf8));
       
   735 	}
       
   736 
       
   737 EXPORT_C TBool CAutoTest::KeepGoing(void)
       
   738 // For external visibility
       
   739 // Handy if someone wants to use defaults instead of taking keyboard input
       
   740 	{
       
   741 	return iKeepGoing;
       
   742 	}
       
   743 
       
   744 
       
   745 EXPORT_C void CAutoTest::LogExtra(const TText8* aFile, TInt aLine, TRefByValue<const TDesC> aFmt,...)
       
   746 /**
       
   747  * Write a free formatted string to a second log file and to the console.
       
   748  * The second log files name is the same as the main log file plus '.EXTRA'.
       
   749  */
       
   750 	{
       
   751 	VA_LIST list;
       
   752 	VA_START(list,aFmt);
       
   753 	//
       
   754 	// Assemble file name for second log file
       
   755 	_LIT(KExtra,".EXTRA");
       
   756 	TBuf<KMaxCmdLength+6> logFileName;		// +6 to hold the text ".EXTRA"
       
   757 	logFileName.Copy(iTestReportName);
       
   758 	logFileName.Append(KExtra);
       
   759 
       
   760 	// 
       
   761 	// Assemble string to be written to second log
       
   762 	TBuf<256> buf;				 
       
   763 	{		// Braces used to scope lifetime of TBuf objects
       
   764 	TPtrC8 fileName8(aFile);
       
   765 	TBuf<128> fileName;
       
   766 	fileName.Copy(fileName8);
       
   767 	buf.Format(_L("\t%S\t%d\t"), &fileName, aLine);
       
   768 	
       
   769 	buf.AppendFormatList(aFmt,list);
       
   770 	}
       
   771 
       
   772 	//
       
   773 	// (1) Open/create log file.
       
   774 	// (2) Write text to log file (RFileLogger adds a time stamp for us)
       
   775 	// (3) Close log
       
   776 	_LIT(KLogFolder,"autotest");
       
   777 	RFileLogger log;
       
   778 	if(log.Connect()==KErrNone)
       
   779 		{
       
   780 		log.CreateLog(KLogFolder,logFileName,EFileLoggingModeAppend);
       
   781 		log.Write(buf);
       
   782 		log.CloseLog();
       
   783 		log.Close();
       
   784 		}
       
   785 
       
   786 	//
       
   787 	// Also write the text to the console (with a new line after)
       
   788 	buf.Zero();
       
   789 	buf.AppendFormatList(aFmt,list);
       
   790 	iRTest.Printf(_L("%S\n"),&buf);
       
   791 	}
       
   792 
       
   793 
       
   794 void CAutoTest::MachineInfoL()
       
   795 /*
       
   796  * write machine info to log file
       
   797  */
       
   798 	{
       
   799 	TBuf8<256> buf8;
       
   800 	buf8.AppendFormat(_L8("Machine info: \r\n"));
       
   801 	//
       
   802 	// platform
       
   803 	//
       
   804 #if defined(__WINS__)
       
   805 	_LIT8(KPlatform, "WINS");
       
   806 #elif defined(__MARM_ARMI__)
       
   807 	_LIT8(KPlatform, "ARMI");
       
   808 #elif defined(__MARM_ARM4__)
       
   809 	_LIT8(KPlatform, "ARM4");
       
   810 #elif defined(__MARM_THUMB__)
       
   811 	_LIT8(KPlatform, "THUMB");
       
   812 #else
       
   813 	_LIT8(KPlatform, "unknown");
       
   814 #endif
       
   815 
       
   816 #if defined (_DEBUG)
       
   817 	_LIT8(KDebugRelease, "Debug");
       
   818 #else
       
   819 	_LIT8(KDebugRelease, "Release");
       
   820 #endif
       
   821 
       
   822 	buf8.AppendFormat(_L8("  Platform:    %S %S\r\n"), &KPlatform, &KDebugRelease );
       
   823 
       
   824 	//
       
   825 	// machine info from Hal9000
       
   826 	//
       
   827 	TMachineInfoV1Buf machine;
       
   828 	UserHal::MachineInfo(machine);
       
   829 
       
   830 	TVersion romver = machine().iRomVersion;
       
   831 	TInt64 uid = machine().iMachineUniqueId;
       
   832     TInt khz = machine().iProcessorClockInKHz;
       
   833 
       
   834 	buf8.AppendFormat(_L8("  Rom version: %d.%d.%d\r\n"), romver.iMajor, romver.iMinor, romver.iBuild );
       
   835 	buf8.AppendFormat(_L8("  Unique ID:   0x%016x\r\n"), uid );
       
   836 	buf8.AppendFormat(_L8("  CPU Speed:   %d kHz\r\n"), khz );
       
   837 
       
   838 	User::LeaveIfError(iTestReport.Write(buf8));
       
   839 	}
       
   840 
       
   841 #ifndef EKA2
       
   842 GLDEF_C TInt E32Dll(TDllReason /*aReason*/)
       
   843 //
       
   844 // DLL entry point
       
   845 //
       
   846 	{
       
   847 	return(KErrNone);
       
   848 	}
       
   849 #endif
       
   850 // EOF - AUTOTEST.CPP