--- /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;
+ }