os/security/authorisation/userpromptservice/database/test/dumpupsdb/source/dumpupsdb.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 * Implements a tool to export/import UPS Decision Database
    16 *
    17 */
    18 
    19 
    20  
    21 #include "dumpupsdb.h"
    22 
    23 using namespace UserPromptService;
    24 
    25 //
    26 //CPrinter
    27 //
    28 
    29 CPrinter::CPrinter(CConsoleBase* aConsole):iConsole(aConsole)
    30 /** Constructor */
    31 	{
    32 	
    33 	}
    34 	
    35 CPrinter::~CPrinter()
    36 /** Destructor */
    37 	{
    38 	iReader.Close();
    39 	iFile.Close();
    40 	}
    41 	
    42 
    43 CPrinter* CPrinter::NewLC(CConsoleBase* aConsole)
    44 /**
    45 	Creates a new printer object and places the pointer on the cleanup stack.
    46 	@param	aConsole The console object to print text to.
    47 	@return A pointer to the new printer object.
    48 */
    49 	{
    50 	CPrinter *self = new(ELeave)CPrinter(aConsole);
    51 	CleanupStack::PushL(self);
    52 	return self;
    53 	}
    54 	
    55 CPrinter* CPrinter::NewLC(CConsoleBase* aConsole, RFile& aFile)
    56 /**
    57 	Creates a new printer object and places the pointer on the cleanup stack.
    58 	@param	aConsole	The console object to print text to.
    59 	@param	aFile		A handle to a file to write the text to. The handle is duplicated internally.					
    60 	@return A pointer to the new printer object.
    61 */
    62 	{
    63 	CPrinter *self = CPrinter::NewLC(aConsole);
    64 	self->ConstructL(aFile);
    65 	return self;
    66 	}
    67 
    68 
    69 void CPrinter::ConstructL(RFile& aFile)
    70 /** Second phase constructor*/
    71 	{
    72 	User::LeaveIfError(iFile.Duplicate(aFile));
    73 	iLogToFile = ETrue;
    74 	//iReader.Set(iFile);
    75 	iReader.Attach(aFile);
    76 	}
    77 
    78 void CPrinter::PrintfL(TRefByValue<const TDesC16> aFormat, ...)
    79 /**
    80 	Formats and writes 16-bit text to the console and/or file
    81 	@param aFormat The 16-bit non-modifiable descriptor containing the format string.
    82  */
    83 	{
    84 	VA_LIST list;
    85 	VA_START (list, aFormat);
    86 	
    87 	iBuffer.Zero();
    88 	iBuffer.AppendFormatList(aFormat, list);
    89 	
    90 	iConsole->Printf(iBuffer);
    91 	
    92 	if(iLogToFile)
    93 		{
    94 		HBufC8* utf8 = CnvUtfConverter::ConvertFromUnicodeToUtf8L(iBuffer);
    95 		CleanupStack::PushL(utf8);
    96 		User::LeaveIfError(iFile.Write(*utf8));
    97 		CleanupStack::PopAndDestroy(utf8);
    98 		}
    99 		
   100 	VA_END(list);
   101 	}
   102 
   103 
   104 void CPrinter::Printf8L(TRefByValue<const TDesC8> aFormat, ...)
   105 /**
   106 	Formats and writes 8-bit text to the console and/or file
   107 	@param aFormat The 8-bit non-modifiable descriptor containing the format string.
   108  */
   109 	{
   110 	VA_LIST list;
   111 	VA_START (list, aFormat);
   112 	
   113 	iBuffer8.Zero();
   114 	iBuffer8.AppendFormatList(aFormat, list);
   115 	iBuffer.Copy(iBuffer8);
   116 	iConsole->Printf(iBuffer);
   117 	
   118 	if(iLogToFile)
   119 		{
   120 		User::LeaveIfError(iFile.Write(iBuffer8));
   121 		}
   122 	
   123 	VA_END(list);
   124 	}
   125 
   126 void CPrinter::PrintOnlyConsoleL(const TDesC& aFormat, ...)
   127 /**
   128 	Formats and writes 16-bit text to the console.
   129 	@param aFormat The 16-bit non-modifiable descriptor containing the format string.
   130  */
   131 	{
   132 	TBool temp;
   133 	temp = iLogToFile;
   134 	iLogToFile = EFalse;
   135 	
   136 	PrintfL(aFormat);
   137 	
   138 	iLogToFile = temp;
   139 	}
   140 	
   141 	
   142 void CPrinter::Usage(CConsoleBase* aConsole)
   143 /**
   144 	Prints how to use DumpUpsDb Tool.
   145 	@param	aConsole A pointer to the console object
   146  */
   147 	{
   148 	aConsole->Printf(_L("DUMPUPSDB Version 1, 0\n"));
   149 	aConsole->Printf(_L("A utility for importing and exporting UPS Decision Database.\n"));
   150 	aConsole->Printf(_L("Copyright (c) 2007 Symbian Ltd.  All rights reserved.\n\n"));
   151 	aConsole->Printf(_L("error: wrong number of arguments\n"));
   152 	aConsole->Printf(_L("Usage: DumpUpsDb [-h] [-i] [-e] [-b] -db dbpath [-f filepath]\n\n"));
   153 	aConsole->Printf(_L("Options : -h  Show help page\n"));
   154 	aConsole->Printf(_L("Options : -i  Import an exported database\n"));
   155 	aConsole->Printf(_L("Options : -e  Export the database\n"));
   156 	aConsole->Printf(_L("Options : -db Database file\n"));
   157 	aConsole->Printf(_L("Options : -f  Output/Input file\n"));
   158 	aConsole->Printf(_L("Options : -b  Import/export Client Entity as binary\n\n"));
   159 	aConsole->Printf(_L("Press any key to continue\r\n"));
   160 	aConsole->Getch();
   161 	}
   162 
   163 void CPrinter::Wait()
   164 /**
   165 	If no output file is specified then pause after finishing because the console 
   166 	will vanish when it is closed.
   167  */
   168 	{
   169 	iConsole->Printf(_L("Press any key to continue\r\n"));
   170 	iConsole->Getch();
   171 	}
   172 	
   173 
   174 void CPrinter::ReadNextLineL(TDes8& aLine)
   175 	{
   176 	TChar achar = '\n';
   177 	iReader.ReadL(aLine, achar);
   178 	}
   179 
   180 TInt CPrinter::FileSizeL()
   181 	{
   182 	return iReader.Source()->SizeL();
   183 	}
   184 //
   185 //CDatabase
   186 //
   187 
   188 CDatabase::CDatabase(TBool aImport):iImport(aImport)
   189 /** Constructor */
   190 	{
   191 	
   192 	}
   193 	
   194 CDatabase::~CDatabase()
   195 /** Destructor */
   196 	{
   197 	delete iPrinter;
   198 	delete iUpsDb;
   199 	}
   200 	
   201 
   202 CDatabase* CDatabase::NewLC(CConsoleBase* aConsole, RFs& aFs, TBool aImport, const TDesC& aDb, const TDesC& aFile)
   203 /**
   204 	Creates a new database object and places the pointer on the cleanup stack.
   205 	
   206 	@param aConsole Pointer to the console object
   207 	@param aFs Handle to the file server
   208 	@param aImport Whether the operation type is import
   209 	@param aDb The fully qualified path of the decision database
   210 	@param aFile The fully qualified path of the dump file
   211 	@return A pointer to the newly created database object
   212  */
   213 	{
   214 	CDatabase *self = new(ELeave)CDatabase(aImport);
   215 	CleanupStack::PushL(self);
   216 	self->ConstructL(aConsole, aFs, aDb, aFile);
   217 	return self;
   218 	}
   219 	
   220 
   221 void CDatabase::ConstructL(CConsoleBase* aConsole, RFs& aFs, const TDesC& aDb, const TDesC& aFile)
   222 /**
   223 	Second phase constructor for database object
   224  */
   225 	{
   226 	if(aFile.Length() > 0)
   227 		{
   228 		if(iImport)
   229 			{
   230 			User::LeaveIfError(iFile.Open(aFs, aFile, EFileWrite|EFileShareExclusive));
   231 			}
   232 		else
   233 			{
   234 			User::LeaveIfError(iFile.Replace(aFs, aFile, EFileWrite|EFileShareExclusive));
   235 			}
   236 		
   237 		iPrinter = CPrinter::NewLC(aConsole, iFile);
   238 		}
   239 	else
   240 		{
   241 		iPrinter = CPrinter::NewLC(aConsole);
   242 		}
   243 	
   244 	CleanupStack::Pop(iPrinter);
   245 	
   246 	iUpsDb = CDecisionDbW::NewL(aDb, aFs);
   247 	
   248 	}
   249 
   250 void CDatabase::DumpL()
   251 	{
   252 	if(!iImport)
   253 		{//Dump database to the console and files
   254 		//Create an empty filter to get all decisions in the table
   255 		CDecisionFilter *filter = CDecisionFilter::NewLC();
   256 		
   257 		//Create a view object
   258 		CDecisionView *dbView = iUpsDb->CreateViewL(*filter);
   259 		CleanupStack::PushL(dbView);
   260 		
   261 		CActiveWaiter *waiter = new(ELeave)CActiveWaiter();
   262 		CleanupStack::PushL(waiter);
   263 		
   264 		//Fill the decisions into the view object
   265 		dbView->EvaluateView(waiter->iStatus);
   266 		waiter->WaitActiveL(KErrNone);	
   267 		if(iFlag & EAppendTestResults)
   268 			{
   269 			PrintTestHeaderL();
   270 			}
   271 		PrintHeaderL();
   272 		
   273 		CDecisionRecord *record = NULL;
   274 		while((record = dbView->NextDecisionL()) != NULL)
   275 			{
   276 			CleanupStack::PushL(record);
   277 			PrintDecisionL(*record);
   278 			CleanupStack::PopAndDestroy(record);
   279 			}
   280 		
   281 		CleanupStack::PopAndDestroy(3, filter);
   282 		iPrinter->PrintOnlyConsoleL(_L("Exported successfully!\n"));
   283 		if(iFlag & EAppendTestResults)
   284 			{
   285 			PrintTestResultsL();
   286 			}
   287 		}
   288 	else
   289 		{//Import an exported decision file to the decision database
   290 		TInt fileSize;
   291 		fileSize = iPrinter->FileSizeL();
   292 		TInt readSize=0;
   293 		TBuf8<256> buffer;
   294 		TBool skipFirstLine = ETrue;
   295 		CDecisionRecord *record = NULL;
   296 		do
   297 			{
   298 			iPrinter->ReadNextLineL(buffer);
   299 			readSize +=buffer.Length();
   300 			if(skipFirstLine)
   301 				{
   302 				skipFirstLine = EFalse;
   303 				}
   304 			else
   305 				{
   306 				record = ParseAndCreateRecordLC(buffer);
   307 				iUpsDb->CreateDecisionL(*record);
   308 				CleanupStack::PopAndDestroy(record);
   309 				}
   310 		
   311 			buffer.Zero();
   312 			}while(readSize < fileSize);
   313 			
   314 		iPrinter->PrintOnlyConsoleL(_L("Imported successfully!\n"));
   315 		}
   316 	//If both of the flags are not set, wait.
   317 	if(!(iFlag & EAppendTestResults || iFlag & EDoNotStop))
   318 		{
   319 		iPrinter->Wait();
   320 		}
   321 	}
   322 
   323 
   324 void CDatabase::PrintDecisionL(CDecisionRecord& aRecord)
   325 	{
   326 	_LIT(KDelimiter,	";");
   327 	_LIT(KWriteId,		"\"%08x\"");
   328 	_LIT(KWriteString,	"\"%S\"");
   329 	_LIT8(KWriteString8,"\"%S\"");
   330 	_LIT8(KWriteHex8,	"%02x");
   331 
   332 	
   333 	iPrinter->PrintfL(KWriteId,aRecord.iClientSid.iId);
   334 	iPrinter->PrintfL(KDelimiter);
   335 	iPrinter->PrintfL(KWriteId,aRecord.iEvaluatorId.iUid);
   336 	iPrinter->PrintfL(KDelimiter);
   337 	iPrinter->PrintfL(KWriteId,aRecord.iServiceId.iUid);
   338 	iPrinter->PrintfL(KDelimiter);
   339 	iPrinter->PrintfL(KWriteId,aRecord.iServerSid.iId);
   340 	iPrinter->PrintfL(KDelimiter);
   341 	
   342 	TBuf8<KUpsMaxFingerprintLength*2> hexdump;
   343 	TUint8 *ptr = (TUint8 *)aRecord.iFingerprint.Ptr();
   344 	TInt i;
   345 	TInt len = aRecord.iFingerprint.Length();
   346 
   347 	for(i=0; i<len; ++i)
   348 		{
   349 		hexdump.AppendFormat(KWriteHex8,ptr[i]);
   350 		}
   351 	iPrinter->Printf8L(KWriteString8,&hexdump);
   352 	iPrinter->PrintfL(KDelimiter);
   353 		
   354 	if(iFlag & EPrintBinary)
   355 		{
   356 		iPrinter->Printf8L(KWriteString8,&aRecord.iClientEntity);
   357 		iPrinter->PrintfL(KDelimiter);
   358 		}
   359 	else
   360 		{
   361 		hexdump.Zero();
   362 		ptr = (TUint8 *)aRecord.iClientEntity.Ptr();
   363 		len = aRecord.iClientEntity.Length();
   364 		for(i=0; i<len; ++i)
   365 			{
   366 			hexdump.AppendFormat(KWriteHex8,ptr[i]);
   367 			}
   368 		iPrinter->Printf8L(KWriteString8,&hexdump);
   369 		iPrinter->PrintfL(KDelimiter);
   370 		}	
   371 		
   372 	iPrinter->PrintfL(KWriteString,&aRecord.iDescription);
   373 	iPrinter->PrintfL(KDelimiter);
   374 	
   375 	iPrinter->PrintfL(KWriteId,aRecord.iResult);
   376 	iPrinter->PrintfL(KDelimiter);
   377 	iPrinter->PrintfL(KWriteId,aRecord.iEvaluatorInfo);
   378 	iPrinter->PrintfL(KDelimiter);
   379 	iPrinter->PrintfL(KWriteId,aRecord.iMajorPolicyVersion);
   380 	iPrinter->PrintfL(KDelimiter);
   381 	iPrinter->PrintfL(KWriteId,aRecord.iRecordId);
   382 	
   383 	iPrinter->Printf8L(_L8("\n"));
   384 	}
   385 
   386 
   387 void CDatabase::PrintHeaderL()
   388 	{
   389 	_LIT(KDelimiter,	";");
   390 	_LIT(KWriteString,	"\"%S\"");
   391 	
   392 	iPrinter->PrintfL(KWriteString,&KColClientSid);
   393 	iPrinter->PrintfL(KDelimiter);
   394 	iPrinter->PrintfL(KWriteString,&KColEvaluatorId);
   395 	iPrinter->PrintfL(KDelimiter);
   396 	iPrinter->PrintfL(KWriteString,&KColServiceId);
   397 	iPrinter->PrintfL(KDelimiter);
   398 	iPrinter->PrintfL(KWriteString,&KColServerSid);
   399 	iPrinter->PrintfL(KDelimiter);
   400 	iPrinter->PrintfL(KWriteString,&KColFingerprint);
   401 	iPrinter->PrintfL(KDelimiter);
   402 	iPrinter->PrintfL(KWriteString,&KColClientEntity);
   403 	iPrinter->PrintfL(KDelimiter);
   404 	iPrinter->PrintfL(KWriteString,&KColDescription);
   405 	iPrinter->PrintfL(KDelimiter);
   406 	iPrinter->PrintfL(KWriteString,&KColResult);
   407 	iPrinter->PrintfL(KDelimiter);
   408 	iPrinter->PrintfL(KWriteString,&KColEvaluatorInfo);
   409 	iPrinter->PrintfL(KDelimiter);
   410 	iPrinter->PrintfL(KWriteString,&KColMajorPolicyVersion);
   411 	iPrinter->PrintfL(KDelimiter);
   412 	iPrinter->PrintfL(KWriteString,&KColRecordId);
   413 	iPrinter->Printf8L(_L8("\n"));
   414 	}
   415 	
   416 CDecisionRecord* CDatabase::ParseAndCreateRecordLC(TDesC8& aLine)
   417 /**
   418 	Parse a line and create a decision record from the parsed values
   419 	@param aLine A line containing a decision record values quoted with double quotes and separated by semi-colon
   420 	@return A newly created decision record
   421  */
   422 	{
   423 	CDecisionRecord* record = NULL;
   424 	
   425 	TLex8 parser(aLine);
   426 	TChar achar;
   427 	TBool start = ETrue;
   428 	
   429 	TUint16 flag = 0x078F;
   430 	TUint16 pos	 = 0x0001;
   431 	
   432 	TInt32 value=0; 
   433 	TUint32 hexVal = 0;
   434 	
   435 	TSecureId clientSid(0);
   436 	TSecureId serverSid(0);
   437 	TUid serviceId = TUid::Null();
   438 	TUid evaluatorId = TUid::Null();
   439 	TBuf8<KUpsMaxFingerprintLength*2> fingerprint;
   440 	TBuf8<KUpsMaxClientEntityLength*2> clientEntity;
   441 	RBuf description;
   442 	TUint8 result=0;
   443 	TUint32 evaluatorInfo=0;
   444 	TUint16 policyVer=0;
   445 	TUint32 recordId=0;
   446 	
   447 	while(!parser.Eos())
   448 		{
   449 		//Get cyrrent char
   450 		achar = parser.Get();
   451 		//Skip delimiter
   452 		if(achar == ';')
   453 			{
   454 			start = ETrue;
   455 			}
   456 		//if double quote start or stop token reading	
   457 		if('\"' == achar)
   458 			{
   459 			if(start)
   460 				{
   461 				parser.Mark();
   462 				start = EFalse;
   463 				}
   464 			else
   465 				{
   466 				parser.UnGet();
   467 				
   468 				if(flag & pos)
   469 					{
   470 					TLex8 intToken(parser.MarkedToken());
   471 					switch(pos)
   472 						{
   473 						case KLocClientSid:
   474 							intToken.Val(hexVal,EHex);
   475 							clientSid.iId = hexVal;
   476 							break;
   477 						case KLocEvaluatorId:
   478 							intToken.Val(hexVal,EHex);
   479 							evaluatorId.iUid = hexVal;
   480 							break;
   481 						case KLocServiceId:
   482 							intToken.Val(hexVal,EHex);
   483 							serviceId.iUid = hexVal;
   484 							break;
   485 						case KLocServerSid:
   486 							intToken.Val(hexVal,EHex);
   487 							serverSid.iId = hexVal;
   488 							break;
   489 						case KLocResult:
   490 							intToken.Val(value);
   491 							result = (TUint8)value;
   492 							break;
   493 						case KLocEvaluatorInfo:
   494 							intToken.Val(value);
   495 							evaluatorInfo = value;
   496 							break;
   497 						case KLocMajorPolicyVersion:
   498 							intToken.Val(value);
   499 							policyVer = (TUint16)value;
   500 							break;
   501 						case KLocRecordId:
   502 							intToken.Val(value);
   503 							recordId = (TUint32)value;							
   504 							break;
   505 						default:
   506 							User::Leave(KErrGeneral);
   507 						}
   508 					}
   509 				else
   510 					{
   511 					switch(pos)
   512 						{
   513 						case KLocDescription:
   514 							{	
   515 							TPtrC8 tmpDescription = parser.MarkedToken();
   516 							description.Create(tmpDescription.Length());
   517 							description.CleanupClosePushL();
   518 							description.Copy(tmpDescription);
   519 							break;
   520 							}
   521 	
   522 						case KLocFingerprint:
   523 							{
   524 							fingerprint = parser.MarkedToken();
   525 							HexToStrL(fingerprint);	
   526 							break;						
   527 							}
   528 						case KLocClientEntity:
   529 							{
   530 							clientEntity = parser.MarkedToken();
   531 							if(!(iFlag & EPrintBinary))							
   532 								{
   533 								HexToStrL(clientEntity);
   534 								}
   535 							break;							
   536 							}
   537 							default:
   538 							User::Leave(KErrGeneral);
   539 						}
   540 					}
   541 				
   542 					
   543 				start = ETrue;
   544 				pos = pos<<1;
   545 				
   546 				}			
   547 			}
   548 		}
   549 	record = CDecisionRecord::NewL(clientSid,evaluatorId,serviceId,serverSid,fingerprint,clientEntity,description,result,policyVer,evaluatorInfo,recordId);
   550 	CleanupStack::PopAndDestroy(&description);
   551 	CleanupStack::PushL(record);
   552 	return record;
   553 	}
   554 
   555 	
   556 TUint8 CDatabase::HexToIntL(TUint8* aPtr)
   557 /**
   558 	Convert a 2-byte hexadecimal representation value to integer (Ex: C2 -> 194).
   559 	@param aPtr Pointer to source data
   560 	@return An integer value against 2-byte hexadecimal value
   561  */
   562 	{
   563 	//Save and then set third byte NULL
   564 	TUint8 temp = aPtr[2];
   565 	aPtr[2] = '\n';
   566 	//Create a lex string from first two bytes
   567 	TLex8 lex(aPtr);
   568 	//Convert two bytes hex value (ex:9F) to integer (ex:159)
   569 	TUint8 intVal;
   570 	User::LeaveIfError(lex.Val(intVal,EHex));
   571 	//Put the original value back
   572 	aPtr[2] = temp;
   573 	//return integer value of first two hex bytes
   574 	return intVal;
   575 	}
   576 
   577 	
   578 void CDatabase::HexToStrL(TDes8& aSource)
   579 /**
   580 	Convert a string containing hexadecimal representation to another string containing binary representation
   581 	@param aSource Source data containing a string
   582  */
   583 	{
   584 	TUint8 *pSource = (TUint8 *)aSource.Ptr();
   585 	TUint8 *pDest	= (TUint8 *)aSource.Ptr();
   586 	
   587 	TInt len = aSource.Length();
   588 	TInt idxSource;
   589 	TInt idxDest;
   590 	
   591 	for(idxSource=0, idxDest=0; idxSource<len; ++idxDest,idxSource+=2)
   592 		{
   593 		pDest[idxDest] = HexToIntL(pSource+idxSource);
   594 		}
   595 	
   596 	aSource.SetLength(idxDest);
   597 	}
   598 
   599 
   600 void CDatabase::PrintTestResultsL()
   601 /**
   602 	Prints dummy test results to get rid of log file parsing error in showing test results.
   603  */
   604 	{
   605 #if 1
   606 	iPrinter->PrintfL(_L("\n\n0 tests failed out of 1\n"));
   607 #else
   608 	iPrinter->PrintfL(_L("\n\nTEST STEP SUMMARY:\n"));
   609 	iPrinter->PrintfL(_L("PASS = 1\n"));
   610 	iPrinter->PrintfL(_L("FAIL = 0\n"));
   611 	iPrinter->PrintfL(_L("ABORT = 0\n"));
   612 	iPrinter->PrintfL(_L("PANIC = 0\n"));
   613 	iPrinter->PrintfL(_L("INCONCLUSIVE = 0\n"));
   614 	iPrinter->PrintfL(_L("UNKNOWN = 0\n"));
   615 	iPrinter->PrintfL(_L("UNEXECUTED = 0\n"));
   616 	iPrinter->PrintfL(_L("COMMENTED COMMAND'S = 0\n"));
   617 	iPrinter->PrintfL(_L("TEST CASE SUMMARY:\n"));
   618 	iPrinter->PrintfL(_L("PASS = 1\n"));
   619 	iPrinter->PrintfL(_L("FAIL = 0\n"));
   620 	iPrinter->PrintfL(_L("INCONCLUSIVE = 0\n"));
   621 #endif
   622 	}
   623 	
   624 void CDatabase::PrintTestHeaderL()
   625 	{
   626 	iPrinter->PrintfL(_L("TEST SYNOPSIS:\n"));
   627 	iPrinter->PrintfL(_L("TEF Version : 2.1.2004\n"));
   628 	iPrinter->PrintfL(_L("START_TESTCASE COUNT : 1\n"));
   629 	iPrinter->PrintfL(_L("RUN_TEST_STEP COUNT : 1\n"));
   630 	iPrinter->PrintfL(_L("RUN_TEST_STEP_RESULT COUNT : 1\n\n"));
   631 	}
   632