sl@0: // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\euser\us_test.cpp sl@0: // sl@0: // sl@0: sl@0: #include "us_std.h" sl@0: #include sl@0: sl@0: #if defined(test) sl@0: #undef test sl@0: #endif sl@0: sl@0: #include sl@0: sl@0: void RTest::CheckConsoleCreated() sl@0: { sl@0: // Check that the console has been created. sl@0: if (iConsole == NULL) sl@0: { sl@0: TRAPD(r, iConsole = Console::NewL(iTitle, TSize(KConsFullScreen, KConsFullScreen))) sl@0: __ASSERT_ALWAYS(r == KErrNone, ::Panic(ERTestCreateConsole)); sl@0: } sl@0: } sl@0: sl@0: void RTest::DisplayLevel() sl@0: { sl@0: // Display the current level string. sl@0: TBuf<0x100> aBuf(_L("RTEST: Level ")); sl@0: for (TInt ii = 1; ii < iLevel; ii++) sl@0: { sl@0: if (ii > 1) sl@0: { sl@0: aBuf.AppendFormat(_L(".%02d"), iStack[ii]); sl@0: } sl@0: else sl@0: { sl@0: aBuf.AppendFormat(_L(" %03d"), iStack[ii]); sl@0: } sl@0: } sl@0: if (iLevel > 1) sl@0: { sl@0: aBuf.AppendFormat(_L(".%02d "), iTest); sl@0: } sl@0: else sl@0: { sl@0: aBuf.AppendFormat(_L(" %03d "), iTest); sl@0: } sl@0: sl@0: Printf(aBuf); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Constructor. sl@0: sl@0: @param aTitle A title describing this use of RTest. sl@0: This is also referred to as the console title. sl@0: @param aThrowaway Not used. sl@0: @param anOtherThrowaway Not used. sl@0: */ sl@0: EXPORT_C RTest::RTest(const TDesC &aTitle,TInt /* aThrowaway */,const TText* /* anOtherThrowaway */) sl@0: : iTest(0), iLevel(0), iLogging(ETrue), iConsole(NULL), iTitle(aTitle) sl@0: // Constructor sl@0: // There is a #define test(x) test(x, __LINE__) in e32test.h to pass on line info of failing tests, sl@0: // This depends upon the user naming their RTest object test, but if they do this then an extra sl@0: // parameter aThrowaway must be added to the constructor sl@0: {} sl@0: sl@0: sl@0: sl@0: /** sl@0: Constructor. sl@0: sl@0: @param aTitle A title describing this use of RTest. sl@0: This is also referred to as the console title. sl@0: @param aThrowaway Not used. sl@0: */ sl@0: EXPORT_C RTest::RTest(const TDesC &aTitle, TInt /* athrowaway */) sl@0: : iTest(0), iLevel(0), iLogging(ETrue), iConsole(NULL), iTitle(aTitle) sl@0: // Constructor sl@0: // There is a #define test(x) test(x, __LINE__) in e32test.h to pass on line info of failing tests, sl@0: // This depends upon the user naming their RTest object test, but if they do this then an extra sl@0: // parameter aThrowaway must be added to the constructor sl@0: {} sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Constructor. sl@0: sl@0: @param aTitle A title describing this use of RTest. sl@0: This is also referred to as the console title. sl@0: */ sl@0: EXPORT_C RTest::RTest(const TDesC &aTitle) sl@0: : iTest(0), iLevel(0), iLogging(ETrue), iConsole(NULL), iTitle(aTitle) sl@0: // Constructor sl@0: {} sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Closes the console and frees any resources acquired. sl@0: */ sl@0: EXPORT_C void RTest::Close() sl@0: { sl@0: // Close the console. sl@0: delete iConsole; sl@0: iConsole=NULL; sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Prints out the console title and version number. sl@0: sl@0: The format of the text is: sl@0: sl@0: @code sl@0: RTEST TITLE: XXX YYY sl@0: Epoc/32 YYY sl@0: @endcode sl@0: sl@0: where XXX is the console title, and YYY is the version number, sl@0: formatted as described by TVersion::Name(). sl@0: sl@0: @see TVersion::Name() sl@0: @see RTest::Printf() sl@0: */ sl@0: EXPORT_C void RTest::Title() sl@0: { sl@0: // Print out the program title and version number. sl@0: TVersion v(KE32MajorVersionNumber, KE32MinorVersionNumber, KE32BuildVersionNumber); sl@0: TBuf<16> vName=v.Name(); sl@0: Printf(_L("RTEST TITLE: %S %S\n"), &iTitle, &vName); sl@0: vName=User::Version().Name(); sl@0: Printf(_L("Epoc/32 %S\n"), &vName); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Marks the start of a set of tests. sl@0: sl@0: Note that sets of tests can be nested. sl@0: sl@0: A call to this function must be matched by a call to RTest::End() to mark sl@0: the end of this set of tests. sl@0: sl@0: @param aHeading A heading describing the set of tests; this is sl@0: printed at the console. sl@0: sl@0: @see RTest::End() sl@0: */ sl@0: EXPORT_C void RTest::Start(const TDesC &aHeading) sl@0: { sl@0: // Print out the heading and nest the level. sl@0: Push(); sl@0: Next(aHeading); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Marks the start of the next test. sl@0: sl@0: @param aHeading A heading describing the test; this sl@0: is printed at the console. This function is also sl@0: called by Start(), which passes the text that describes sl@0: the set of tests. sl@0: sl@0: @see RTest::Start() sl@0: */ sl@0: EXPORT_C void RTest::Next(const TDesC &aHeading) sl@0: { sl@0: // Print out the heading and nest the level. sl@0: iTest++; sl@0: iCheck = 0; sl@0: DisplayLevel(); sl@0: Printf(_L("Next test - %S\n"), &aHeading); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Checks the result of a condition and, if this is false, prints sl@0: a failure message at the console and raises a panic. sl@0: sl@0: Before checking the condition passed in, the operator increments sl@0: a check number. This is a value that is set to zero at the start of a test sl@0: and is incremented by this operator (and by all variants of it). It identifies sl@0: the check being made within the current test. sl@0: This value is printed on a failure message. sl@0: sl@0: Typically, the operator is called, passing a test condition, for example: sl@0: sl@0: @code sl@0: RTest test(... heading text...,line number... file name) sl@0: TInt r; sl@0: ...some operation to be tested that returns a value in r... sl@0: test(r==KErrNone); sl@0: @endcode sl@0: sl@0: The failure message has the format: sl@0: sl@0: @code sl@0: : FAIL : XXX failed check N in FFF at line Number: M sl@0: RTEST: Checkpoint-fail sl@0: @endcode sl@0: sl@0: where XXX is the console title, N is the check number, FFF is the filename, sl@0: and M is the line number passed in. sl@0: sl@0: @param aResult The condition being tested. sl@0: This is interpreted as a true or false value. sl@0: @param aLineNum A line number that is printed in the failure message if sl@0: the condition being tested is false. sl@0: @param aFileName A file name that is printed in the failure message if sl@0: the condition being tested is false. sl@0: sl@0: @panic USER 84 if the condition being tested is false. sl@0: sl@0: @see RTest::Next() sl@0: @see RTest::Start() sl@0: */ sl@0: EXPORT_C void RTest::operator()(TInt aResult, TInt aLineNum, const TText* aFileName) sl@0: { sl@0: // Test a condition. sl@0: iCheck++; sl@0: if (!aResult) sl@0: { sl@0: RDebug::Printf(": FAILING : failed check at line number %d", aLineNum); sl@0: DisplayLevel(); sl@0: Printf(_L(": FAIL : %S failed check %d in %s at line number %d\n"), sl@0: &iTitle, iCheck, aFileName, aLineNum); sl@0: Panic(_L("Checkpoint-fail\n")); sl@0: if (!iLogging) sl@0: Getch(); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Checks the result of a condition and, if this is false, prints sl@0: a failure message at the console and raises a panic. sl@0: sl@0: Before checking the condition passed in, the operator increments sl@0: a check number. This is a value that is set to zero at the start of a test sl@0: and is incremented by this operator (and by all variants of it). It identifies sl@0: the check being made within the current test. sl@0: This value is printed on the failure message. sl@0: sl@0: Typically, the operator is called, passing a test condition, for example: sl@0: sl@0: @code sl@0: RTest test(... heading text...,line number) sl@0: TInt r; sl@0: ...some operation to be tested that returns a value in r... sl@0: test(r==KErrNone); sl@0: @endcode sl@0: sl@0: The failure message has the format: sl@0: sl@0: @code sl@0: : FAIL : XXX failed check N at line Number: M sl@0: RTEST: Checkpoint-fail sl@0: @endcode sl@0: sl@0: where XXX is the console title, N is the check number, and M is sl@0: the line number passed in. sl@0: sl@0: @param aResult The condition being tested. sl@0: This is interpreted as a true or false value. sl@0: @param aLineNum A line number that is printed in the failure message if sl@0: the condition being tested is false. sl@0: sl@0: @panic USER 84 if the condition being tested is false. sl@0: sl@0: @see RTest::Next() sl@0: @see RTest::Start() sl@0: */ sl@0: EXPORT_C void RTest::operator()(TInt aResult,TInt aLineNum) sl@0: { sl@0: // Test a condition. sl@0: iCheck++; sl@0: if (!aResult) sl@0: { sl@0: RDebug::Printf(": FAILING : failed check at line Number: %d", aLineNum); sl@0: DisplayLevel(); sl@0: Printf(_L(": FAIL : %S failed check %d at line Number: %d\n"), &iTitle, iCheck, aLineNum); sl@0: Panic(_L("Checkpoint-fail\n")); sl@0: if (!iLogging) sl@0: Getch(); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Checks the result of a condition and, if this is false, prints sl@0: a failure message at the console and raises a panic. sl@0: sl@0: Before checking the condition passed in, the operator increments sl@0: a check number. This is a value that is set to zero at the start of a test sl@0: and is incremented by this operator (and by all variants of it). It identifies sl@0: the check being made within the current test. sl@0: This value is printed on the failure message. sl@0: sl@0: Typically, the operator is called, passing a test condition, for example: sl@0: sl@0: @code sl@0: RTest test(... heading text...) sl@0: TInt r; sl@0: ...some operation to be tested that returns a value in r... sl@0: test(r==KErrNone); sl@0: @endcode sl@0: sl@0: The failure message has the format: sl@0: sl@0: @code sl@0: : FAIL : XXX failed check N sl@0: RTEST: Checkpoint-fail sl@0: @endcode sl@0: sl@0: where XXX is the console title, and N is the check number. sl@0: sl@0: @param aResult The condition being tested. sl@0: This is interpreted as a true or false value. sl@0: sl@0: @panic USER 84 if the condition being tested is false. sl@0: sl@0: @see RTest::Next() sl@0: @see RTest::Start() sl@0: */ sl@0: EXPORT_C void RTest::operator()(TInt aResult) sl@0: { sl@0: // Test a condition. sl@0: iCheck++; sl@0: if (!aResult) sl@0: { sl@0: RDebug::Printf(": FAILING : failed check\n"); sl@0: DisplayLevel(); sl@0: Printf(_L(": FAIL : %S failed check %d\n"), &iTitle, iCheck); sl@0: Panic(_L("Checkpoint-fail\n")); sl@0: if (!iLogging) sl@0: Getch(); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Ends the current set of tests. sl@0: sl@0: If this set of tests is not nested within another set, sl@0: then a message reporting success is written to sl@0: the console. sl@0: sl@0: @panic USER 84 if there was no matching call to RTest::Start(), sl@0: i.e. more calls to End() have been made than calls to Start(). sl@0: sl@0: @see RTest::Start() sl@0: */ sl@0: EXPORT_C void RTest::End() sl@0: { sl@0: // End the current level of tests. sl@0: if (TInt(iLevel-1) < 0) sl@0: { sl@0: Panic(_L("End() without matching Start()\n")); sl@0: } sl@0: sl@0: Pop(); sl@0: sl@0: if (iLevel == 0) sl@0: { sl@0: Printf(_L("RTEST: SUCCESS : %S test completed O.K.\n"), &iTitle); sl@0: if (!iLogging) sl@0: Getch(); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Prints an error message and an error code, sl@0: and raises a USER 84 panic. sl@0: sl@0: @param anError The error code. sl@0: @param aFmt A format list. sl@0: @param ... A variable number of parameters. sl@0: */ sl@0: EXPORT_C void RTest::Panic(TInt anError,TRefByValue aFmt,...) sl@0: { sl@0: // Print an error message, an error and then panic. sl@0: TestOverflowTruncate overflow; sl@0: VA_LIST list; sl@0: VA_START(list, aFmt); sl@0: TBuf<0x100> aBuf; sl@0: aBuf.AppendFormat(_L("RTEST: ")); sl@0: // coverity[uninit_use_in_call] sl@0: aBuf.AppendFormatList(aFmt, list, &overflow); sl@0: aBuf.AppendFormat(_L(" Failed with error %d\n"), anError); sl@0: Printf(aBuf); sl@0: if (!iLogging) sl@0: Getch(); sl@0: ::Panic(ERTestFailed); sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: /** sl@0: Prints an error message, and raises a USER 84 panic. sl@0: sl@0: @param aFmt A format list. sl@0: @param ... A variable number of parameters. sl@0: */ sl@0: EXPORT_C void RTest::Panic(TRefByValue aFmt,...) sl@0: { sl@0: // Print an error message and then panic. sl@0: TestOverflowTruncate overflow; sl@0: VA_LIST list; sl@0: VA_START(list, aFmt); sl@0: TBuf<0x100> aBuf; sl@0: aBuf.AppendFormat(_L("RTEST: ")); sl@0: // coverity[uninit_use_in_call] sl@0: aBuf.AppendFormatList(aFmt, list, &overflow); sl@0: Printf(aBuf); sl@0: if (!iLogging) sl@0: Getch(); sl@0: ::Panic(ERTestFailed); sl@0: } sl@0: sl@0: sl@0: sl@0: _LIT(KLitNL, "\n"); sl@0: _LIT(KLitCRNL, "\r\n"); sl@0: /** sl@0: Prints text to the console. sl@0: sl@0: If the logging flag is set, the string sl@0: is also written to the debug output as represented by an RDebug object. sl@0: sl@0: @param aFmt A format list. sl@0: @param ... A variable number of parameters. sl@0: sl@0: @see RTest::SetLogged() sl@0: @see Rtest::Logged() sl@0: @see RDebug sl@0: */ sl@0: EXPORT_C void RTest::Printf(TRefByValue aFmt,...) sl@0: { sl@0: // Print to a console screen. sl@0: TestOverflowTruncate overflow; sl@0: VA_LIST list; sl@0: VA_START(list, aFmt); sl@0: TBuf<0x100> buf; sl@0: // coverity[uninit_use_in_call] sl@0: buf.AppendFormatList(aFmt, list, &overflow); sl@0: CheckConsoleCreated(); sl@0: iConsole->Write(buf); sl@0: sl@0: if (iLogging) sl@0: { sl@0: TPtrC ptr(buf); sl@0: TInt newline; sl@0: while ((newline = ptr.Locate('\n')) != KErrNotFound) sl@0: { sl@0: RDebug::RawPrint(ptr.Left(newline)); sl@0: if (newline==0 || ptr[newline-1]!='\r') sl@0: RDebug::RawPrint(KLitCRNL); // bare nl, replace with crnl sl@0: else sl@0: RDebug::RawPrint(KLitNL); // crnl, already printed cr sl@0: if (newline+1Getch()); sl@0: } sl@0: sl@0: sl@0: sl@0: EXPORT_C TInt RTest::CloseHandleAndWaitForDestruction(RHandleBase& aH) sl@0: { sl@0: TRequestStatus s; sl@0: aH.NotifyDestruction(s); sl@0: aH.Close(); sl@0: TUint32 initial = User::NTickCount(); sl@0: TInt r = KErrNone; sl@0: if (s == KErrNoMemory) sl@0: r = KErrNoMemory; sl@0: TInt factor = UserSvr::HalFunction(EHalGroupVariant, EVariantHalTimeoutExpansion, 0, 0); sl@0: if (factor<=0) sl@0: factor = 1; sl@0: if (factor>1024) sl@0: factor = 1024; sl@0: TUint32 timeout = 5000 * (TUint32)factor; sl@0: TUint32 period = 1000 * (TUint32)factor; sl@0: while (s == KRequestPending) sl@0: { sl@0: TUint32 now = User::NTickCount(); sl@0: if ((now - initial) > timeout) sl@0: { sl@0: User::CancelMiscNotifier(s); sl@0: r = KErrTimedOut; sl@0: break; sl@0: } sl@0: User::AfterHighRes(period); sl@0: } sl@0: User::WaitForRequest(s); sl@0: return r; sl@0: } sl@0: sl@0: