genericservices/httputils/Test/IpuTestUtils/IpuTestHarness.cpp
changeset 0 e4d67989cc36
child 67 a1e347446159
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericservices/httputils/Test/IpuTestUtils/IpuTestHarness.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,656 @@
+// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "IpuTestUtils.h"
+
+//
+//	Constants
+_LIT(KTestPanic, "IpuTestHarness");
+const TInt KFailedTestsGranularity = 10;
+const TInt KMaxLogEntrySize = 256;
+
+//
+//	CIpuTestHarness
+//
+CIpuTestHarness::CIpuTestHarness(const TDesC& aTitle)
+	: iTest(aTitle)
+//
+//	Default c'tor
+	{
+	iTest.Title();
+	iCanStartTest = ETrue;
+	}
+
+CIpuTestHarness::~CIpuTestHarness()
+//
+//	D'tor
+	{
+	TTime endtime;
+	endtime.UniversalTime();
+
+	// Do resource handle leak test?
+	if (iDoResourceLeakTest)
+		ResourceLeakTest();
+
+	//	End of tests - see if failed or ok
+	if (iFailedTests->Count())
+		{
+		TestHarnessFailed();
+		}
+	else
+		{
+		TestHarnessComplete();
+		}
+
+	iFailedTests->ResetAndDestroy();
+	delete iFailedTests;
+
+	//	Log finish time
+	TDateTime t = endtime.DateTime();
+	LogIt(_L("Ended @ %d:%d:%d:%d"),t.Hour(),t.Minute(),t.Second(),t.MicroSecond());
+	TTime difftime(endtime.Int64() - iStartTime.Int64());
+	t = difftime.DateTime();
+	LogIt(_L("Execution time %d:%d:%d:%d"),t.Hour(),t.Minute(),t.Second(),t.MicroSecond());
+
+	//	Close logs and test harness
+	iFlogger.CloseLog();
+	
+	// iTest test harness performs UHEAP MARK/UNMARK check upon creation/destruction
+	//   therefore, it must be destroyed last since it is created first in 
+	//   CIpuTestHarness
+	iTest.Close();
+	}
+
+EXPORT_C CIpuTestHarness* CIpuTestHarness::NewLC(const TDesC& aTitle)
+//
+//	Static factory c'tor
+	{
+	CIpuTestHarness* self = new (ELeave) CIpuTestHarness(aTitle);
+	CleanupStack::PushL(self);
+	self->ConstructL(aTitle);
+	return self;
+	}
+
+EXPORT_C CIpuTestHarness* CIpuTestHarness::NewL(const TDesC& aTitle)
+//
+//	Static factiry c'tor
+	{
+	CIpuTestHarness* self = CIpuTestHarness::NewLC(aTitle);
+	CleanupStack::Pop();
+	return self;
+	}
+
+void CIpuTestHarness::ConstructL(const TDesC& aTitle)
+//
+//	Non-trivial c'tor
+	{
+	//	Create iFailedTests
+	iFailedTests = new (ELeave) CArrayPtrFlat<CTestInfo> (KFailedTestsGranularity);
+
+	//	Start up logging server connection
+	TBuf<64> temp(aTitle);
+	DefaultLogFileName(temp);
+	CreateFlogger(temp, EFalse, EFalse);
+
+	iStartTime.UniversalTime();
+	TDateTime t = iStartTime.DateTime();
+	LogIt(_L("Started @ %d:%d:%d:%d"),t.Hour(),t.Minute(),t.Second(),t.MicroSecond());
+
+	// Find number of open resource handles
+	TInt processHandleCount=0;
+	RThread().HandleCount(processHandleCount,iStartHandleCount);
+	}
+
+EXPORT_C void CIpuTestHarness::StartTestL(const TDesC& aName)
+//
+//	Logs start of test aName
+	{
+	if (iCanStartTest)
+		{
+		//  - increment test count
+		++iTestCount;
+		
+		if (iTestMode == ETestModeNormal) // don't add this info when we are doing memory leak testing otherwise it
+										  // would get leaked!
+			{
+
+			//	Add this test to failed test list - set errorcode to zero
+			CTestInfo* temp = CTestInfo::NewLC(aName, iTestCount, 0);
+			iFailedTests->AppendL(temp);
+			CleanupStack::Pop();	//	temp
+
+			//	Stop new test being started until this one has ended
+			iTest.Start(aName);
+			iCanStartTest = EFalse;
+			}
+
+		
+		TBuf<KMaxFileName + 4> buf;
+		buf.Format(KTestStartingWithDesc, iTestCount, &aName);
+		WriteComment(buf);
+
+		// Reset iStepNumber - start at 1
+		iStepNumber = 1;
+		}
+	else
+		{
+		//	Panic client - bad usage - not allowed to nest tests
+		Panic(EBadStartTest);
+		}
+	}
+
+EXPORT_C void CIpuTestHarness::NextStep(const TDesC& aStepName)
+//
+//	Logs the next step in a test - for informative use.
+	{
+	if (!iCanStartTest)
+		{
+		TBuf<KMaxFileName + 4> buf;
+		buf.Format(KNextTestStepWithDesc, iTestCount, iStepNumber, &aStepName);
+		WriteComment(buf);
+		iTest.Next(aStepName);
+		++iStepNumber;
+		}
+	else
+		{
+		//	Panic client - bad usage - test not started
+		Panic(EBadStartTest);
+		}
+	}
+
+EXPORT_C void CIpuTestHarness::EndTest(TInt aErrorCode)
+//
+//	Logs end of test
+	{
+	if (!iCanStartTest)
+		{
+		if (iTestMode == ETestModeNormal)
+			{
+			//	Get ptr to this test's entry in failed list - will be the last entry
+			TBuf<KMaxFileName + 4> buf;
+			TInt index = iFailedTests->Count();
+			CTestInfo* ptr = iFailedTests->At(--index);
+			if (aErrorCode)
+				{
+				//	Set the error code
+				ptr->SetErrorCode(aErrorCode);
+				buf.Format(KTestFailed, iTestCount, aErrorCode);
+				WriteComment(buf);
+				}
+			else
+				{
+				//	Remove entry from list of failed tests
+				delete ptr;
+				iFailedTests->Delete(index);
+				}
+			
+			}
+		//	Allow new test to start
+		iTest.End();
+		iCanStartTest = ETrue;
+		}
+	else
+		{
+		if (iTestMode == ETestModeNormal)
+			//	Panic client - bad usage - test not started
+			Panic(EBadEndTest);
+		// don't panic when we are memory leak testing as EndTestL will never get called to reset the test properly
+		}
+	}
+
+EXPORT_C void CIpuTestHarness::LogIt(TRefByValue<const TDesC> aFmt, ...)
+//
+//	Messages to the front end emulator and to the Inu log
+	{
+	VA_LIST list;
+	VA_START(list,aFmt);
+
+	TBuf<KMaxFileName + 4> buf;
+	buf.Append(KTestCommentPrepend);
+	buf.AppendFormatList(aFmt,list);
+	VA_END(list);
+
+	WriteComment(buf);
+	}
+
+EXPORT_C void CIpuTestHarness::operator()(TInt aResult,TInt aLineNum)
+//
+//	Overload operator ()
+	{
+	iTest(aResult, aLineNum);
+	}
+
+EXPORT_C void CIpuTestHarness::operator()(TInt aResult)
+//
+//	Overload operator ()
+	{
+	iTest(aResult);
+	}
+
+EXPORT_C void CIpuTestHarness::PressAnyKey()
+//
+//	Request a key press from user and wait - unless we are running a script
+	{
+	if (!iScriptRunning)
+		{
+		iTest.Printf(TRefByValue<const TDesC>_L("\nPress a key"));	
+		iTest.Getch();
+		}
+	}
+
+EXPORT_C void CIpuTestHarness::DumpData(HBufC8& aData, TBool logIt)
+//
+//	Do a formatted dump of binary data, optionally logging it
+	{
+	// Iterate the supplied block of data in blocks of 16 bytes
+	TInt pos = 0;
+	TBuf<KMaxLogEntrySize> logLine;
+	TBuf<KMaxLogEntrySize> anEntry;
+	while (pos < aData.Length())
+		{
+		anEntry.Format(TRefByValue<const TDesC>_L("%04x : "), pos);
+		logLine.Append(anEntry);
+
+		// Hex output
+		TInt offset = 0;
+		for (offset = 0; offset < 16; offset++)
+			{
+			if (pos + offset < aData.Length())
+				{
+				TInt nextByte = aData[pos + offset];
+				anEntry.Format(TRefByValue<const TDesC>_L("%02x "), nextByte);
+				logLine.Append(anEntry);
+				}
+			else
+				{
+				anEntry.Format(TRefByValue<const TDesC>_L("   "));
+				logLine.Append(anEntry);
+				}
+			}
+			anEntry.Format(TRefByValue<const TDesC>_L(": "));
+			logLine.Append(anEntry);
+
+		// Char output
+		for (offset = 0; offset < 16; offset++)
+			{
+			if (pos + offset < aData.Length())
+				{
+				TInt nextByte = aData[pos + offset];
+				if ((nextByte >= 32) && (nextByte <= 127))
+					{
+					anEntry.Format(TRefByValue<const TDesC>_L("%c"), nextByte);
+					logLine.Append(anEntry);
+					}
+				else
+					{
+					anEntry.Format(TRefByValue<const TDesC>_L("."));
+					logLine.Append(anEntry);
+					}
+				}
+			else
+				{
+				anEntry.Format(TRefByValue<const TDesC>_L(" "));
+				logLine.Append(anEntry);
+				}
+			}
+			if (logIt)
+				{
+				LogIt(TRefByValue<const TDesC>_L("%S"), &logLine);
+				}
+			else
+				{
+				iTest.Printf(TRefByValue<const TDesC>_L("%S\n"), &logLine);	
+				}
+			logLine.Zero();
+
+		// Advance to next 16 byte segment
+		pos += 16;
+		}
+	}
+
+EXPORT_C void CIpuTestHarness::GetAnEntry(const TDesC& ourPrompt, TDes& currentstring)
+//
+//	Get an input string from the user, displaying a supplied prompt and default string value
+	{
+	// If we're scripting, try reading from script first
+	TInt readScriptErr = KErrNotFound;
+	if (iScriptRunning)
+		{
+		readScriptErr = ReadLineFromScript(currentstring);
+		}
+	if (!readScriptErr)
+		return;
+
+	// Either not scripting, or hit end of script - continue with user input
+	TBuf16<KMaxUserEntrySize> ourLine;
+	TBuf<KMaxUserEntrySize> tempstring;				//tempstring is a unicode descriptor
+										//create a temporary buffer where the
+										//unicode strings are stored in order to 
+										//be displayed
+	ourLine.Zero ();
+	tempstring.Copy(currentstring);		//Copy current string to Unicode buffer
+	TKeyCode key = EKeyNull;						//current string buffer is 8 bits wide.
+										//Unicode string bufffer (tempstring) is 16 bits wide.
+	for (;;)
+		{
+		if (ourLine.Length () == 0)
+			{
+			iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
+			iTest.Console()->Printf (_L ("%S"), &ourPrompt);
+			if (tempstring.Length () != 0)						//get tempstring's number of items
+				iTest.Console()->Printf (_L (" = %S"), &tempstring);	//if not zero print them to iTest.Console()
+			iTest.Console()->Printf (_L (" : "));
+			iTest.Console()->ClearToEndOfLine ();
+			}
+		key = iTest.Getch();
+		
+		  if (key == EKeyBackspace)
+				{
+					if (ourLine.Length() !=0)
+					{
+						ourLine.SetLength(ourLine.Length()-1);
+						iTest.Console()->Printf (_L ("%c"), key);
+						iTest.Console()->SetPos(iTest.Console()->WhereX(),iTest.Console()->WhereY());
+						iTest.Console()->ClearToEndOfLine();
+					}	// end if (ourLine.Length() !=0)
+				}	// end if (key == KeyBackSpace)
+		  
+		  		  
+		  if (key == EKeyDelete) 			
+				{
+					ourLine.Zero();
+					iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
+					iTest.Console()->ClearToEndOfLine ();
+					tempstring.Copy(ourLine);
+					break;
+				}
+		  
+		  if (key == EKeyEnter)
+			break;
+		
+		  if (key < 32)
+			{
+			continue;
+			}
+		
+		ourLine.Append (key);
+		iTest.Console()->Printf (_L ("%c"), key);
+		iTest.Console()->SetPos(iTest.Console()->WhereX(),iTest.Console()->WhereY());
+		iTest.Console()->ClearToEndOfLine();
+		if (ourLine.Length () == ourLine.MaxLength ())
+			break;
+		}	// end of for statement
+
+	if ((key == EKeyEnter) && (ourLine.Length () == 0))
+		tempstring.Copy (currentstring);				//copy contents of 8 bit "ourLine" descriptor
+	
+	iTest.Console()->SetPos (0, iTest.Console()->WhereY ());		
+	iTest.Console()->ClearToEndOfLine ();
+	iTest.Console()->Printf (_L ("%S"), &ourPrompt);
+	
+	if ((key == EKeyEnter) && (ourLine.Length() !=0))
+		tempstring.Copy(ourLine);
+	if (tempstring.Length () != 0)						//if temstring length is not zero
+		{
+		iTest.Console()->Printf (_L (" = %S\n"), &tempstring);	//print the contents to iTest.Console()
+		LogIt(_L ("%S = %S\n"), &ourPrompt, &tempstring);
+		}
+
+	else
+		//iTest.Console()->Printf (_L (" is empty"));
+	iTest.Console()->Printf (_L ("\n"));
+	currentstring.Copy(tempstring);						//copy 16 bit tempstring descriptor back 
+	}
+
+
+EXPORT_C TInt CIpuTestHarness::GetSelection(const TDesC& ourPrompt, const TDesC& validChoices)
+//
+//	Present the user with a list of options, and get their selection
+	{
+	// If we're scripting, try reading from script first
+	TInt readScriptErr = KErrNotFound;
+	if (iScriptRunning)
+		{
+		TBuf<1> oneCharBuf;
+		readScriptErr = ReadLineFromScript(oneCharBuf);
+		if (!readScriptErr)
+			{
+			return validChoices.Locate((TChar)oneCharBuf[0]);
+			}
+		}
+
+	// Either not scripting, or hit end of script - continue with user input
+	TKeyCode key = EKeyNull;
+	iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
+	iTest.Console()->Printf(_L("%S "), &ourPrompt);
+	iTest.Console()->Printf(_L("[%S] :"), &validChoices);
+	TInt retVal = KErrNotFound;
+	while (retVal == KErrNotFound)
+		{
+		key = iTest.Getch();
+
+		// Check that key is in the list of valid choices
+		retVal = validChoices.Locate((TChar)key);
+		}
+	iTest.Console()->Printf(_L("%c\n\n"), key);
+	return retVal;
+	}
+
+
+EXPORT_C void CIpuTestHarness::SetScript(RFile& scriptFile)
+//
+//	Sets the file to be used for a test script - ie. a file that contains commands used by
+//  GetEntry() and GetSelection()
+	{
+	iScriptFile = &scriptFile;
+	iScriptRunning = ETrue;
+	LogIt(_L("***SCRIPT STARTING***\n"));
+	}
+
+TInt CIpuTestHarness::ReadLineFromScript(TDes& aBuffer)
+//
+// Reads the next line from the script file, and sets the passed-in descriptor with its contents.
+// Returns KErrNone if reading succeeded; KErrNotFound if the EOF was reached. When EOF is reached,
+// the file is closed.
+	{
+	// *********************************
+	// Assume script is 8-bit text file
+	// *********************************
+	TBool isAComment = ETrue;
+	TInt err = KErrNone;
+	TBuf<512> line;
+	while (isAComment && !err)
+		{
+		TFileText text;
+		text.Set(*iScriptFile);
+		line.SetLength(0);
+		for(;;)
+			{
+			TBuf8<2> c;
+			err = iScriptFile->Read(c,1);
+			if (err && err != KErrEof)
+				{
+				iTest.Printf(_L("Error reading file: %d\n"), err);
+				break;
+				}
+			if (c.Length() == 0)
+				{
+				err = KErrEof;
+				break;
+				}
+			else
+				{
+				if (c[0] == '\n') // break out if it is CR
+					break;
+				else if (c[0] != (TUint8)(0x0d)) // otherwise append the char, _unless_ it is a LF
+					line.Append(c[0]);
+				}
+			}
+		if (err == KErrNone && line.Locate('/') != 0) // comment (only works if it's the first character)
+			{
+			isAComment = EFalse;
+			}
+		}
+
+	// The line read is not a comment, or have hit end of file
+	if (!err)
+		{
+		// copy to passed in descriptor, but do not allow an overflow
+		aBuffer.Copy(line.Left(aBuffer.MaxLength()));
+		LogIt(_L("***SCRIPT : read command '%S' ***\n"), &aBuffer);
+		}
+	else
+		{
+		iScriptFile->Close();
+		err = KErrNotFound;
+		iScriptRunning = EFalse;
+		LogIt(_L("***SCRIPT ENDED***\n"));
+		}
+	return err;
+	}
+
+void CIpuTestHarness::Panic(TInt aPanic)
+//
+//	Panic the client program.
+	{
+	User::Panic(KTestPanic,aPanic);
+	}
+
+void CIpuTestHarness::TestHarnessComplete()
+//
+//	Test harness completed without failures
+	{
+	_LIT(KTestCompleteFormat, "Total Tests %d, Failed Tests %d");
+	TBuf<50> text;
+	text.AppendFormat(KTestCompleteFormat, iTestCount, iFailedTests->Count()); 
+	WriteComment(text);
+	WriteComment(KTestHarnessCompleted);
+	}
+
+void CIpuTestHarness::TestHarnessFailed()
+//
+//	Test harness has a failure - log information
+	{
+	TBuf<KMaxFileName + 4> buf;
+	buf.Format(KTestHarnessFailed, iFailedTests->Count());
+	WriteComment(buf);
+	//	Log fialed tests' information
+	for (TInt ii=0; ii<iFailedTests->Count(); ++ii)
+		{
+		CTestInfo* failed = iFailedTests->At(ii);
+		TPtrC name = failed->Name();
+		LogIt(KTestFailInfo, failed->Number(), &name, failed->ErrorCode());
+		}
+	}
+
+void CIpuTestHarness::ResourceLeakTest()
+//
+// Creates a new test that fails if any there are any leaked resource handles
+	{
+	// Start new test
+	_LIT(KResourceTestName, "Resource Handle Leak Test");
+	TRAPD(testError, StartTestL(KResourceTestName));
+	if(testError==KErrNone)
+		{
+		//	Find number of opened handles
+		TInt processHandleCount=0;
+		TInt threadHandleCount=0;
+		RThread().HandleCount(processHandleCount,threadHandleCount);
+		TInt openHandleCount = iStartHandleCount-threadHandleCount;
+		TInt err = KErrNone;
+		if ( openHandleCount !=0 )
+			{
+			err = KErrGeneral;
+			LogIt(_L("Number leaked handles is %D"), openHandleCount);
+			}
+		EndTest(err);
+		}
+	else
+		{
+		_LIT(KTxtResourceTestRunError, "Unable to complete Resource Leak Test, error: %d");
+		LogIt(KTxtResourceTestRunError, testError);
+		EndTest(testError);
+		}
+	}
+
+//
+//	CTestInfo
+//
+CIpuTestHarness::CTestInfo::CTestInfo()
+//
+//	Default c'tor
+	{
+	}
+
+CIpuTestHarness::CTestInfo::~CTestInfo()
+//
+//	D'tor
+	{
+	delete iName;
+	}
+
+CIpuTestHarness::CTestInfo* CIpuTestHarness::CTestInfo::NewLC(const TDesC& aName, TInt aNumber, TInt aErrorCode)
+//
+//	Static factory c'tor
+	{
+	CTestInfo* self = new (ELeave) CTestInfo();
+	CleanupStack::PushL(self);
+	self->ConstructL(aName, aNumber, aErrorCode);
+	return self;
+	}
+
+CIpuTestHarness::CTestInfo* CIpuTestHarness::CTestInfo::NewL(const TDesC& aName, TInt aNumber, TInt aErrorCode)
+//
+//	Static factory c'tor
+	{
+	CTestInfo* self = NewLC(aName, aNumber, aErrorCode);
+	CleanupStack::Pop();	//	self
+	return self;
+	}
+
+void CIpuTestHarness::CTestInfo::ConstructL(const TDesC& aName, TInt aNumber, TInt aErrorCode)
+//
+//	Non-trivial c'tor
+	{
+	iName = aName.AllocLC();
+	CleanupStack::Pop();	//	iName
+
+	iNumber = aNumber;
+	iErrorCode = aErrorCode;
+	}
+
+void CIpuTestHarness::CTestInfo::SetNameL(const TDesC& aName)
+//
+//	Sets iName
+	{
+	HBufC* temp = aName.AllocLC();
+	CleanupStack::Pop();	//	temp
+	delete iName;
+	iName = temp;
+	}
+
+void CIpuTestHarness::CTestInfo::SetNumber(TInt aNumber)
+//
+//	Sets iNumber
+	{
+	iNumber = aNumber;
+	}
+
+void CIpuTestHarness::CTestInfo::SetErrorCode(TInt aErrorCode)
+//
+//	Sets iErrorCode
+	{
+	iErrorCode = aErrorCode;
+	}