diff -r 000000000000 -r e4d67989cc36 genericservices/httputils/Test/IpuTestUtils/IpuTestHarness.cpp --- /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 (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 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 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 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 aFmt, ...) +// +// Messages to the front end emulator and to the Inu log + { + VA_LIST list; + VA_START(list,aFmt); + + TBuf 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_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 logLine; + TBuf anEntry; + while (pos < aData.Length()) + { + anEntry.Format(TRefByValue_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_L("%02x "), nextByte); + logLine.Append(anEntry); + } + else + { + anEntry.Format(TRefByValue_L(" ")); + logLine.Append(anEntry); + } + } + anEntry.Format(TRefByValue_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_L("%c"), nextByte); + logLine.Append(anEntry); + } + else + { + anEntry.Format(TRefByValue_L(".")); + logLine.Append(anEntry); + } + } + else + { + anEntry.Format(TRefByValue_L(" ")); + logLine.Append(anEntry); + } + } + if (logIt) + { + LogIt(TRefByValue_L("%S"), &logLine); + } + else + { + iTest.Printf(TRefByValue_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 ourLine; + TBuf 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 buf; + buf.Format(KTestHarnessFailed, iFailedTests->Count()); + WriteComment(buf); + // Log fialed tests' information + for (TInt ii=0; iiCount(); ++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; + }