First public contribution.
1 // Copyright (c) 2001-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include "IpuTestUtils.h"
20 _LIT(KTestPanic, "IpuTestHarness");
21 const TInt KFailedTestsGranularity = 10;
22 const TInt KMaxLogEntrySize = 256;
27 CIpuTestHarness::CIpuTestHarness(const TDesC& aTitle)
32 LogRTestToFile(iTest);
34 iCanStartTest = ETrue;
37 CIpuTestHarness::~CIpuTestHarness()
42 endtime.UniversalTime();
44 // Do resource handle leak test?
45 if (iDoResourceLeakTest)
48 // End of tests - see if failed or ok
49 if (iFailedTests->Count())
55 TestHarnessComplete();
58 iFailedTests->ResetAndDestroy();
62 TDateTime t = endtime.DateTime();
63 LogIt(_L("Ended @ %d:%d:%d:%d"),t.Hour(),t.Minute(),t.Second(),t.MicroSecond());
64 TTime difftime(endtime.Int64() - iStartTime.Int64());
65 t = difftime.DateTime();
66 LogIt(_L("Execution time %d:%d:%d:%d"),t.Hour(),t.Minute(),t.Second(),t.MicroSecond());
68 // Close logs and test harness
71 // iTest test harness performs UHEAP MARK/UNMARK check upon creation/destruction
72 // therefore, it must be destroyed last since it is created first in
77 EXPORT_C CIpuTestHarness* CIpuTestHarness::NewLC(const TDesC& aTitle)
79 // Static factory c'tor
81 CIpuTestHarness* self = new (ELeave) CIpuTestHarness(aTitle);
82 CleanupStack::PushL(self);
83 self->ConstructL(aTitle);
87 EXPORT_C CIpuTestHarness* CIpuTestHarness::NewL(const TDesC& aTitle)
89 // Static factiry c'tor
91 CIpuTestHarness* self = CIpuTestHarness::NewLC(aTitle);
96 void CIpuTestHarness::ConstructL(const TDesC& aTitle)
100 // Create iFailedTests
101 iFailedTests = new (ELeave) CArrayPtrFlat<CTestInfo> (KFailedTestsGranularity);
103 // Start up logging server connection
104 TBuf<64> temp(aTitle);
105 DefaultLogFileName(temp);
106 CreateFlogger(temp, EFalse, EFalse);
108 iStartTime.UniversalTime();
109 TDateTime t = iStartTime.DateTime();
110 LogIt(_L("Started @ %d:%d:%d:%d"),t.Hour(),t.Minute(),t.Second(),t.MicroSecond());
112 // Find number of open resource handles
113 TInt processHandleCount=0;
114 RThread().HandleCount(processHandleCount,iStartHandleCount);
117 EXPORT_C void CIpuTestHarness::StartTestL(const TDesC& aName)
119 // Logs start of test aName
123 // - increment test count
126 if (iTestMode == ETestModeNormal) // don't add this info when we are doing memory leak testing otherwise it
130 // Add this test to failed test list - set errorcode to zero
131 CTestInfo* temp = CTestInfo::NewLC(aName, iTestCount, 0);
132 iFailedTests->AppendL(temp);
133 CleanupStack::Pop(); // temp
135 // Stop new test being started until this one has ended
137 iCanStartTest = EFalse;
141 TBuf<KMaxFileName + 4> buf;
142 buf.Format(KTestStartingWithDesc, iTestCount, &aName);
145 // Reset iStepNumber - start at 1
150 // Panic client - bad usage - not allowed to nest tests
151 Panic(EBadStartTest);
155 EXPORT_C void CIpuTestHarness::NextStep(const TDesC& aStepName)
157 // Logs the next step in a test - for informative use.
161 TBuf<KMaxFileName + 4> buf;
162 buf.Format(KNextTestStepWithDesc, iTestCount, iStepNumber, &aStepName);
164 iTest.Next(aStepName);
169 // Panic client - bad usage - test not started
170 Panic(EBadStartTest);
174 EXPORT_C void CIpuTestHarness::EndTest(TInt aErrorCode)
180 if (iTestMode == ETestModeNormal)
182 // Get ptr to this test's entry in failed list - will be the last entry
183 TBuf<KMaxFileName + 4> buf;
184 TInt index = iFailedTests->Count();
185 CTestInfo* ptr = iFailedTests->At(--index);
188 // Set the error code
189 ptr->SetErrorCode(aErrorCode);
190 buf.Format(KTestFailed, iTestCount, aErrorCode);
195 // Remove entry from list of failed tests
197 iFailedTests->Delete(index);
201 // Allow new test to start
203 iCanStartTest = ETrue;
207 if (iTestMode == ETestModeNormal)
208 // Panic client - bad usage - test not started
210 // don't panic when we are memory leak testing as EndTestL will never get called to reset the test properly
214 EXPORT_C void CIpuTestHarness::LogIt(TRefByValue<const TDesC> aFmt, ...)
216 // Messages to the front end emulator and to the Inu log
221 TBuf<KMaxFileName + 4> buf;
222 buf.Append(KTestCommentPrepend);
223 buf.AppendFormatList(aFmt,list);
229 EXPORT_C void CIpuTestHarness::operator()(TInt aResult,TInt aLineNum)
231 // Overload operator ()
233 iTest(aResult, aLineNum);
236 EXPORT_C void CIpuTestHarness::operator()(TInt aResult)
238 // Overload operator ()
243 EXPORT_C void CIpuTestHarness::PressAnyKey()
245 // Request a key press from user and wait - unless we are running a script
249 iTest.Printf(TRefByValue<const TDesC>_L("\nPress a key"));
254 EXPORT_C void CIpuTestHarness::DumpData(HBufC8& aData, TBool logIt)
256 // Do a formatted dump of binary data, optionally logging it
258 // Iterate the supplied block of data in blocks of 16 bytes
260 TBuf<KMaxLogEntrySize> logLine;
261 TBuf<KMaxLogEntrySize> anEntry;
262 while (pos < aData.Length())
264 anEntry.Format(TRefByValue<const TDesC>_L("%04x : "), pos);
265 logLine.Append(anEntry);
269 for (offset = 0; offset < 16; offset++)
271 if (pos + offset < aData.Length())
273 TInt nextByte = aData[pos + offset];
274 anEntry.Format(TRefByValue<const TDesC>_L("%02x "), nextByte);
275 logLine.Append(anEntry);
279 anEntry.Format(TRefByValue<const TDesC>_L(" "));
280 logLine.Append(anEntry);
283 anEntry.Format(TRefByValue<const TDesC>_L(": "));
284 logLine.Append(anEntry);
287 for (offset = 0; offset < 16; offset++)
289 if (pos + offset < aData.Length())
291 TInt nextByte = aData[pos + offset];
292 if ((nextByte >= 32) && (nextByte <= 127))
294 anEntry.Format(TRefByValue<const TDesC>_L("%c"), nextByte);
295 logLine.Append(anEntry);
299 anEntry.Format(TRefByValue<const TDesC>_L("."));
300 logLine.Append(anEntry);
305 anEntry.Format(TRefByValue<const TDesC>_L(" "));
306 logLine.Append(anEntry);
311 LogIt(TRefByValue<const TDesC>_L("%S"), &logLine);
315 iTest.Printf(TRefByValue<const TDesC>_L("%S\n"), &logLine);
319 // Advance to next 16 byte segment
324 EXPORT_C void CIpuTestHarness::GetAnEntry(const TDesC& ourPrompt, TDes& currentstring)
326 // Get an input string from the user, displaying a supplied prompt and default string value
328 // If we're scripting, try reading from script first
329 TInt readScriptErr = KErrNotFound;
332 readScriptErr = ReadLineFromScript(currentstring);
337 // Either not scripting, or hit end of script - continue with user input
338 TBuf16<KMaxUserEntrySize> ourLine;
339 TBuf<KMaxUserEntrySize> tempstring; //tempstring is a unicode descriptor
340 //create a temporary buffer where the
341 //unicode strings are stored in order to
344 tempstring.Copy(currentstring); //Copy current string to Unicode buffer
345 TKeyCode key = EKeyNull; //current string buffer is 8 bits wide.
346 //Unicode string bufffer (tempstring) is 16 bits wide.
349 if (ourLine.Length () == 0)
351 iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
352 iTest.Console()->Printf (_L ("%S"), &ourPrompt);
353 if (tempstring.Length () != 0) //get tempstring's number of items
354 iTest.Console()->Printf (_L (" = %S"), &tempstring); //if not zero print them to iTest.Console()
355 iTest.Console()->Printf (_L (" : "));
356 iTest.Console()->ClearToEndOfLine ();
360 if (key == EKeyBackspace)
362 if (ourLine.Length() !=0)
364 ourLine.SetLength(ourLine.Length()-1);
365 iTest.Console()->Printf (_L ("%c"), key);
366 iTest.Console()->SetPos(iTest.Console()->WhereX(),iTest.Console()->WhereY());
367 iTest.Console()->ClearToEndOfLine();
368 } // end if (ourLine.Length() !=0)
369 } // end if (key == KeyBackSpace)
372 if (key == EKeyDelete)
375 iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
376 iTest.Console()->ClearToEndOfLine ();
377 tempstring.Copy(ourLine);
381 if (key == EKeyEnter)
389 ourLine.Append (key);
390 iTest.Console()->Printf (_L ("%c"), key);
391 iTest.Console()->SetPos(iTest.Console()->WhereX(),iTest.Console()->WhereY());
392 iTest.Console()->ClearToEndOfLine();
393 if (ourLine.Length () == ourLine.MaxLength ())
395 } // end of for statement
397 if ((key == EKeyEnter) && (ourLine.Length () == 0))
398 tempstring.Copy (currentstring); //copy contents of 8 bit "ourLine" descriptor
400 iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
401 iTest.Console()->ClearToEndOfLine ();
402 iTest.Console()->Printf (_L ("%S"), &ourPrompt);
404 if ((key == EKeyEnter) && (ourLine.Length() !=0))
405 tempstring.Copy(ourLine);
406 if (tempstring.Length () != 0) //if temstring length is not zero
408 iTest.Console()->Printf (_L (" = %S\n"), &tempstring); //print the contents to iTest.Console()
409 LogIt(_L ("%S = %S\n"), &ourPrompt, &tempstring);
413 //iTest.Console()->Printf (_L (" is empty"));
414 iTest.Console()->Printf (_L ("\n"));
415 currentstring.Copy(tempstring); //copy 16 bit tempstring descriptor back
419 EXPORT_C TInt CIpuTestHarness::GetSelection(const TDesC& ourPrompt, const TDesC& validChoices)
421 // Present the user with a list of options, and get their selection
423 // If we're scripting, try reading from script first
424 TInt readScriptErr = KErrNotFound;
428 readScriptErr = ReadLineFromScript(oneCharBuf);
431 return validChoices.Locate((TChar)oneCharBuf[0]);
435 // Either not scripting, or hit end of script - continue with user input
436 TKeyCode key = EKeyNull;
437 iTest.Console()->SetPos (0, iTest.Console()->WhereY ());
438 iTest.Console()->Printf(_L("%S "), &ourPrompt);
439 iTest.Console()->Printf(_L("[%S] :"), &validChoices);
440 TInt retVal = KErrNotFound;
441 while (retVal == KErrNotFound)
445 // Check that key is in the list of valid choices
446 retVal = validChoices.Locate((TChar)key);
448 iTest.Console()->Printf(_L("%c\n\n"), key);
453 EXPORT_C void CIpuTestHarness::SetScript(RFile& scriptFile)
455 // Sets the file to be used for a test script - ie. a file that contains commands used by
456 // GetEntry() and GetSelection()
458 iScriptFile = &scriptFile;
459 iScriptRunning = ETrue;
460 LogIt(_L("***SCRIPT STARTING***\n"));
463 TInt CIpuTestHarness::ReadLineFromScript(TDes& aBuffer)
465 // Reads the next line from the script file, and sets the passed-in descriptor with its contents.
466 // Returns KErrNone if reading succeeded; KErrNotFound if the EOF was reached. When EOF is reached,
467 // the file is closed.
469 // *********************************
470 // Assume script is 8-bit text file
471 // *********************************
472 TBool isAComment = ETrue;
475 while (isAComment && !err)
478 text.Set(*iScriptFile);
483 err = iScriptFile->Read(c,1);
484 if (err && err != KErrEof)
486 iTest.Printf(_L("Error reading file: %d\n"), err);
496 if (c[0] == '\n') // break out if it is CR
498 else if (c[0] != (TUint8)(0x0d)) // otherwise append the char, _unless_ it is a LF
502 if (err == KErrNone && line.Locate('/') != 0) // comment (only works if it's the first character)
508 // The line read is not a comment, or have hit end of file
511 // copy to passed in descriptor, but do not allow an overflow
512 aBuffer.Copy(line.Left(aBuffer.MaxLength()));
513 LogIt(_L("***SCRIPT : read command '%S' ***\n"), &aBuffer);
517 iScriptFile->Close();
519 iScriptRunning = EFalse;
520 LogIt(_L("***SCRIPT ENDED***\n"));
525 void CIpuTestHarness::Panic(TInt aPanic)
527 // Panic the client program.
529 User::Panic(KTestPanic,aPanic);
532 void CIpuTestHarness::TestHarnessComplete()
534 // Test harness completed without failures
536 _LIT(KTestCompleteFormat, "Total Tests %d, Failed Tests %d");
538 text.AppendFormat(KTestCompleteFormat, iTestCount, iFailedTests->Count());
540 WriteComment(KTestHarnessCompleted);
543 void CIpuTestHarness::TestHarnessFailed()
545 // Test harness has a failure - log information
547 TBuf<KMaxFileName + 4> buf;
548 buf.Format(KTestHarnessFailed, iFailedTests->Count());
550 // Log fialed tests' information
551 for (TInt ii=0; ii<iFailedTests->Count(); ++ii)
553 CTestInfo* failed = iFailedTests->At(ii);
554 TPtrC name = failed->Name();
555 LogIt(KTestFailInfo, failed->Number(), &name, failed->ErrorCode());
559 void CIpuTestHarness::ResourceLeakTest()
561 // Creates a new test that fails if any there are any leaked resource handles
564 _LIT(KResourceTestName, "Resource Handle Leak Test");
565 TRAPD(testError, StartTestL(KResourceTestName));
566 if(testError==KErrNone)
568 // Find number of opened handles
569 TInt processHandleCount=0;
570 TInt threadHandleCount=0;
571 RThread().HandleCount(processHandleCount,threadHandleCount);
572 TInt openHandleCount = iStartHandleCount-threadHandleCount;
574 if ( openHandleCount !=0 )
577 LogIt(_L("Number leaked handles is %D"), openHandleCount);
583 _LIT(KTxtResourceTestRunError, "Unable to complete Resource Leak Test, error: %d");
584 LogIt(KTxtResourceTestRunError, testError);
592 CIpuTestHarness::CTestInfo::CTestInfo()
598 CIpuTestHarness::CTestInfo::~CTestInfo()
605 CIpuTestHarness::CTestInfo* CIpuTestHarness::CTestInfo::NewLC(const TDesC& aName, TInt aNumber, TInt aErrorCode)
607 // Static factory c'tor
609 CTestInfo* self = new (ELeave) CTestInfo();
610 CleanupStack::PushL(self);
611 self->ConstructL(aName, aNumber, aErrorCode);
615 CIpuTestHarness::CTestInfo* CIpuTestHarness::CTestInfo::NewL(const TDesC& aName, TInt aNumber, TInt aErrorCode)
617 // Static factory c'tor
619 CTestInfo* self = NewLC(aName, aNumber, aErrorCode);
620 CleanupStack::Pop(); // self
624 void CIpuTestHarness::CTestInfo::ConstructL(const TDesC& aName, TInt aNumber, TInt aErrorCode)
628 iName = aName.AllocLC();
629 CleanupStack::Pop(); // iName
632 iErrorCode = aErrorCode;
635 void CIpuTestHarness::CTestInfo::SetNameL(const TDesC& aName)
639 HBufC* temp = aName.AllocLC();
640 CleanupStack::Pop(); // temp
645 void CIpuTestHarness::CTestInfo::SetNumber(TInt aNumber)
652 void CIpuTestHarness::CTestInfo::SetErrorCode(TInt aErrorCode)
656 iErrorCode = aErrorCode;