symbianunittestfw/sutfw/sutfwcore/sutfwframework/src/symbianunittest.cpp
branchRCL_3
changeset 3 9397a16b6eb8
parent 1 6edeef394eb7
equal deleted inserted replaced
1:6edeef394eb7 3:9397a16b6eb8
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 #include "symbianunittestresult.h"
       
    19 #include "symbianunittestobserver.h"
       
    20 #include "symbianunittestfailure.h"
       
    21 #include "sutlogger.h"
       
    22 #include <symbianunittest.h>
       
    23 #include <e32math.h>
       
    24 #include <utf.h>
       
    25 #include <e32debug.h>
       
    26 
       
    27 // Assertion failure message formats:
       
    28 _LIT8( KIntsNotEqualFormat, "Asserted: expected=%d, actual=%d" );
       
    29 _LIT8( KDesCsNotEqualFormat, "Asserted: expected='%S', actual='%S'" );
       
    30 _LIT8( KAssertLeaveFormat1, "'%S' expected to leave: expected=%d, actual=%d" );
       
    31 _LIT8( KAssertLeaveFormat2, "'%S' expected to leave but did not leave" );
       
    32 
       
    33 const TInt KMaxSizeOfTwoIntsAsText = 80;
       
    34 const TInt KErrSymbianUnitTestAssertionFailed = -99999999;
       
    35 _LIT( KTestThreadName, "SymbianUnitTestThread" );
       
    36 const TInt KTestThreadMaxHeapSize = 0x400000; // 4 MB
       
    37 _LIT8( KDoubleColon8, "::" );
       
    38 _LIT( KDoubleColon16, "::" );
       
    39 
       
    40 // -----------------------------------------------------------------------------
       
    41 //
       
    42 // -----------------------------------------------------------------------------
       
    43 //
       
    44 EXPORT_C void CSymbianUnitTest::ConstructL( const TDesC8& aName )
       
    45     {    
       
    46     TInt doubleColonPos( aName.FindF( KDoubleColon8 ) );
       
    47     TPtrC8 classNamePtr( aName );
       
    48     if ( doubleColonPos > 0 )
       
    49         {
       
    50         classNamePtr.Set( aName.Left( doubleColonPos ) );
       
    51         }
       
    52     
       
    53     iName = CnvUtfConverter::ConvertToUnicodeFromUtf8L( classNamePtr ); 
       
    54     
       
    55     SUT_LOG_FORMAT(_L("enter CSymbianUnitTest::ConstructL -- aName : [%S]"), iName );
       
    56     
       
    57     // unify the same name for armv5 & winscw. 
       
    58     // on winscw, the function name is abc, 
       
    59     // on armv5,  the function name is void abc. 
       
    60     // unify to abc. 
       
    61     TChar chSpace( ' ' );
       
    62     TChar chTab( '\t' );
       
    63     TChar chAsterisk( '*' );
       
    64     TChar chAnd( '&' );
       
    65     TBuf<100> strTmp( *iName ); 
       
    66     strTmp.Trim();
       
    67     TInt pos;
       
    68     
       
    69     // "char * & abc" => abc
       
    70     pos = strTmp.LocateReverse( chAnd );
       
    71     if( KErrNotFound != pos ) 
       
    72     	{
       
    73     	TPtrC ptr = strTmp.Right( strTmp.Length() - pos - 1 );
       
    74     	strTmp = ptr;
       
    75     	strTmp.Trim();
       
    76     	}
       
    77     // "void * abc" => abc
       
    78     pos = strTmp.LocateReverse( chAsterisk );
       
    79     if( KErrNotFound != pos ) 
       
    80     	{
       
    81     	TPtrC ptr = strTmp.Right( strTmp.Length() - pos - 1 );
       
    82     	strTmp = ptr;
       
    83     	strTmp.Trim();
       
    84     	}
       
    85     // "void abc"
       
    86     pos = strTmp.LocateReverse( chSpace );
       
    87     if( KErrNotFound != pos ) 
       
    88     	{
       
    89     	TPtrC ptr = strTmp.Right( strTmp.Length() - pos - 1 );
       
    90     	strTmp = ptr;
       
    91     	strTmp.Trim();
       
    92     	}
       
    93     // "void 	abc"
       
    94     pos = strTmp.LocateReverse( chTab );
       
    95     if( KErrNotFound != pos ) 
       
    96     	{
       
    97     	TPtrC ptr = strTmp.Right( strTmp.Length() - pos - 1 );
       
    98     	strTmp = ptr;
       
    99     	strTmp.Trim();
       
   100     	}
       
   101     	
       
   102     *iName = strTmp;
       
   103     
       
   104     SUT_LOG_FORMAT(_L("exit CSymbianUnitTest::ConstructL -- aName : [%S]"), iName );
       
   105     }
       
   106 
       
   107 // -----------------------------------------------------------------------------
       
   108 //
       
   109 // -----------------------------------------------------------------------------
       
   110 //
       
   111 EXPORT_C CSymbianUnitTest::CSymbianUnitTest()
       
   112  : iAllocFailureType( RHeap::ENone ),
       
   113    iAllocFailureRate( 0 )
       
   114     {
       
   115     }
       
   116 
       
   117 // -----------------------------------------------------------------------------
       
   118 //
       
   119 // -----------------------------------------------------------------------------
       
   120 //
       
   121 EXPORT_C CSymbianUnitTest::~CSymbianUnitTest() 
       
   122     { 
       
   123     delete iName;
       
   124     iTestCases.ResetAndDestroy();
       
   125     }
       
   126 
       
   127 // -----------------------------------------------------------------------------
       
   128 // From MSymbianUnitTestInterface
       
   129 // -----------------------------------------------------------------------------
       
   130 //
       
   131 EXPORT_C void CSymbianUnitTest::ExecuteL(
       
   132     MSymbianUnitTestObserver& aObserver,
       
   133     CSymbianUnitTestResult& aResult,
       
   134     MSymbianUnitTestInterface::TFailureSimulation aFailureSimulation,
       
   135     const CDesCArray& aTestCaseNames,
       
   136     TInt aTimeout )
       
   137     {
       
   138     if ( aFailureSimulation == EMemAllocFailureSimulation )
       
   139         {
       
   140         iAllocFailureType = RHeap::EDeterministic;
       
   141         }
       
   142     else
       
   143         {
       
   144         iAllocFailureType = RHeap::ENone;
       
   145         }      
       
   146     SUT_LOG_FORMAT(_L("start testing, total test cases[%d]"), iTestCases.Count());
       
   147     //print the test cases name in the log
       
   148     for ( TInt i = iTestCases.Count() -1; i >=0 ; i-- )
       
   149         {
       
   150         CSymbianUnitTestCase& testCase = *( iTestCases[ i ] );
       
   151 	//check the specified test case list if any
       
   152 	if ( aTestCaseNames.Count() > 0 )
       
   153 	    {
       
   154 	    TInt index=0;
       
   155 	    TInt ret = aTestCaseNames.Find(testCase.Name(), index );
       
   156 	    if (ret != 0)
       
   157 	        {
       
   158 		    //the case isn't in the specified test case names, skip it
       
   159             SUT_LOG_FORMAT(_L("skip test case[%S]"), &testCase.Name());
       
   160 		    delete iTestCases[i];
       
   161             iTestCases.Remove(i);
       
   162             continue;
       
   163 	        }
       
   164 	    }
       
   165 	SUT_LOG_FORMAT(_L("TestCase[%S]"), &testCase.Name());
       
   166         }
       
   167 
       
   168     for ( TInt i = 0; i < iTestCases.Count(); i++ )
       
   169         {
       
   170         CSymbianUnitTestCase& testCase = *( iTestCases[ i ] );
       
   171 
       
   172         aResult.StartTestL( testCase.Name() );
       
   173         ExecuteTestCaseInThreadL( testCase, aResult, aTimeout );
       
   174         aResult.EndTestL();
       
   175 
       
   176         if (aResult.CurrentResult())
       
   177             {
       
   178             aObserver.TestPass(iCurrentTestCase->Name());
       
   179             }
       
   180         else
       
   181             {
       
   182             CSymbianUnitTestFailure* failure = aResult.Failures()[
       
   183                 aResult.Failures().Count()-1];
       
   184             aObserver.TestFailed(iCurrentTestCase->Name(), failure->FailureMessage());
       
   185             }
       
   186         }
       
   187     SUT_LOG_FORMAT(_L("testing finished, total passed test cases[%d]"), aResult.PassedTestCount());
       
   188     }
       
   189 
       
   190 // -----------------------------------------------------------------------------
       
   191 // From MSymbianUnitTestInterface
       
   192 // -----------------------------------------------------------------------------
       
   193 //
       
   194 EXPORT_C TInt CSymbianUnitTest::TestCaseCount()
       
   195     {
       
   196     return iTestCases.Count();
       
   197     }
       
   198 
       
   199 // -----------------------------------------------------------------------------
       
   200 // From MSymbianUnitTestInterface
       
   201 // -----------------------------------------------------------------------------
       
   202 //
       
   203 EXPORT_C const TDesC& CSymbianUnitTest::Name() const
       
   204     {
       
   205     if ( iName )
       
   206         {
       
   207         return *iName;
       
   208         }
       
   209     return KNullDesC;
       
   210     }
       
   211 
       
   212 // -----------------------------------------------------------------------------
       
   213 // From MSymbianUnitTestInterface
       
   214 // -----------------------------------------------------------------------------
       
   215 //
       
   216 EXPORT_C void CSymbianUnitTest::TestCaseNamesL(CDesCArray& aTestCaseNames)
       
   217     {
       
   218     for ( TInt i = iTestCases.Count() -1; i >=0 ; i-- )
       
   219         {
       
   220         CSymbianUnitTestCase& testCase = *( iTestCases[ i ] );
       
   221         aTestCaseNames.AppendL(testCase.Name());
       
   222         }
       
   223     }
       
   224 
       
   225 // -----------------------------------------------------------------------------
       
   226 //
       
   227 // -----------------------------------------------------------------------------
       
   228 //
       
   229 EXPORT_C void CSymbianUnitTest::SetupL()
       
   230     {
       
   231     // The default implementation is no operation
       
   232     }
       
   233 
       
   234 // -----------------------------------------------------------------------------
       
   235 //
       
   236 // -----------------------------------------------------------------------------
       
   237 //
       
   238 EXPORT_C void CSymbianUnitTest::Teardown()
       
   239     {
       
   240     // The default implementation is no operation
       
   241     }
       
   242 
       
   243 // -----------------------------------------------------------------------------
       
   244 //
       
   245 // -----------------------------------------------------------------------------
       
   246 //
       
   247 EXPORT_C TBool CSymbianUnitTest::IsMemoryAllocationFailureSimulationUsed() const
       
   248     {
       
   249     return ( iAllocFailureType == RHeap::EDeterministic );
       
   250     }
       
   251 
       
   252 // -----------------------------------------------------------------------------
       
   253 //
       
   254 // -----------------------------------------------------------------------------
       
   255 //
       
   256 EXPORT_C void CSymbianUnitTest::AddTestCaseL( 
       
   257     const TDesC& aName,
       
   258     FunctionPtr aSetupFunction,
       
   259     FunctionPtr aTestFunction,
       
   260     FunctionPtr aTeardownFunction )
       
   261     {
       
   262     const TInt KTestCaseNameLength = 
       
   263         Name().Length() + KDoubleColon16().Length() + aName.Length(); 
       
   264     HBufC* name = HBufC::NewLC( KTestCaseNameLength );
       
   265     name->Des().Append( Name() );
       
   266     name->Des().Append( KDoubleColon16 );
       
   267     name->Des().Append( aName ); 
       
   268     CSymbianUnitTestCase* testCase = 
       
   269         CSymbianUnitTestCase::NewL( 
       
   270             *name, aSetupFunction, aTestFunction, aTeardownFunction );
       
   271     CleanupStack::PopAndDestroy( name );
       
   272     CleanupStack::PushL( testCase );
       
   273     iTestCases.AppendL( testCase );
       
   274     CleanupStack::Pop( testCase );
       
   275     }
       
   276 
       
   277 // -----------------------------------------------------------------------------
       
   278 //
       
   279 // -----------------------------------------------------------------------------
       
   280 //
       
   281 EXPORT_C void CSymbianUnitTest::AssertEqualsL(
       
   282     TInt aExpectedValue, 
       
   283     TInt aActualValue, 
       
   284     TInt aLineNumber,
       
   285     const TDesC8& aFileName )
       
   286     {
       
   287     if ( aExpectedValue != aActualValue )
       
   288         {
       
   289         StopAllocFailureSimulation();
       
   290         HBufC8* msg = HBufC8::NewLC( 
       
   291             KIntsNotEqualFormat().Size() + KMaxSizeOfTwoIntsAsText );
       
   292         msg->Des().Format( KIntsNotEqualFormat, aExpectedValue, aActualValue );
       
   293         AssertionFailedL( *msg, aLineNumber, aFileName );
       
   294         }
       
   295     }
       
   296 
       
   297 // -----------------------------------------------------------------------------
       
   298 //
       
   299 // -----------------------------------------------------------------------------
       
   300 //
       
   301 EXPORT_C void CSymbianUnitTest::AssertEqualsL(
       
   302     const TDesC8& aExpectedValue,
       
   303     const TDesC8& aActualValue,
       
   304     TInt aLineNumber,
       
   305     const TDesC8& aFileName )
       
   306     {
       
   307     if ( aExpectedValue.Compare( aActualValue ) != 0 )
       
   308         {
       
   309         StopAllocFailureSimulation();
       
   310         TInt size = 
       
   311             KDesCsNotEqualFormat().Size() + 
       
   312             aExpectedValue.Size() + 
       
   313             aActualValue.Size();
       
   314         HBufC8 *msg = HBufC8::NewLC( size );
       
   315         msg->Des().Format( KDesCsNotEqualFormat, 
       
   316                            &aExpectedValue, 
       
   317                            &aActualValue );
       
   318         AssertionFailedL( *msg, aLineNumber, aFileName );
       
   319         }
       
   320     }
       
   321 
       
   322 // -----------------------------------------------------------------------------
       
   323 //
       
   324 // -----------------------------------------------------------------------------
       
   325 //
       
   326 EXPORT_C void CSymbianUnitTest::AssertEqualsL(
       
   327     const TDesC16& aExpectedValue,
       
   328     const TDesC16& aActualValue,
       
   329     TInt aLineNumber,
       
   330     const TDesC8& aFileName )
       
   331     {
       
   332     if ( aExpectedValue.Compare( aActualValue ) != 0 )
       
   333         {
       
   334         StopAllocFailureSimulation();
       
   335         HBufC8* msg = NotEqualsMessageLC( aExpectedValue, aActualValue );
       
   336         AssertionFailedL( *msg, aLineNumber, aFileName );
       
   337         }
       
   338     }
       
   339 
       
   340 // -----------------------------------------------------------------------------
       
   341 //
       
   342 // -----------------------------------------------------------------------------
       
   343 //
       
   344 EXPORT_C void CSymbianUnitTest::AssertLeaveL(
       
   345     const TDesC8& aStatement,
       
   346     TInt aActualLeaveCode,
       
   347     TInt aExpectedLeaveCode,
       
   348     TInt aLineNumber,
       
   349     const TDesC8& aFileName )
       
   350     {
       
   351     if ( aActualLeaveCode == KErrNoMemory &&
       
   352          aExpectedLeaveCode != KErrNoMemory &&
       
   353          iAllocFailureType == RHeap::EDeterministic )
       
   354         {
       
   355         User::Leave( KErrNoMemory );
       
   356         }   
       
   357     if ( aActualLeaveCode != aExpectedLeaveCode )
       
   358         {
       
   359         StopAllocFailureSimulation();
       
   360         HBufC8* msg = HBufC8::NewLC( 
       
   361             KAssertLeaveFormat1().Size() + 
       
   362             aStatement.Size() + 
       
   363             KMaxSizeOfTwoIntsAsText );
       
   364         msg->Des().Format( KAssertLeaveFormat2, &aStatement, 
       
   365                            aExpectedLeaveCode, aActualLeaveCode );        
       
   366         AssertionFailedL( *msg, aLineNumber, aFileName );
       
   367         }
       
   368     }
       
   369 
       
   370 // -----------------------------------------------------------------------------
       
   371 //
       
   372 // -----------------------------------------------------------------------------
       
   373 //
       
   374 EXPORT_C void CSymbianUnitTest::RecordNoLeaveFromStatementL(
       
   375     const TDesC8& aStatement,
       
   376     TInt aLineNumber,
       
   377     const TDesC8& aFileName )
       
   378     {
       
   379     StopAllocFailureSimulation();
       
   380     HBufC8* msg = 
       
   381         HBufC8::NewLC( KAssertLeaveFormat1().Size() + aStatement.Size() );
       
   382     msg->Des().Format( KAssertLeaveFormat1, &aStatement );        
       
   383     AssertionFailedL( *msg, aLineNumber, aFileName );
       
   384     }
       
   385 
       
   386 // -----------------------------------------------------------------------------
       
   387 //
       
   388 // -----------------------------------------------------------------------------
       
   389 //
       
   390 EXPORT_C void CSymbianUnitTest::AssertionFailedL(
       
   391     const TDesC8& aFailureMessage,
       
   392     TInt aLineNumber,
       
   393     const TDesC8& aFileName )
       
   394     {
       
   395     TInt dummy( 0 );
       
   396     TInt heapCellsBeforeAddingTheFailure( User::Heap().AllocSize( dummy ) );
       
   397     
       
   398     if ( iTestResult )
       
   399         {
       
   400         User::LeaveIfError( iTestResult->AddAssertFailure( 
       
   401             aFailureMessage, aLineNumber, aFileName ) );
       
   402         }
       
   403         
       
   404     TInt heapCellsAfterAddingTheFailure( User::Heap().AllocSize( dummy ) );
       
   405     iHeapCellsReservedByAssertFailure = 
       
   406         heapCellsAfterAddingTheFailure - heapCellsBeforeAddingTheFailure;
       
   407     User::Leave( KErrSymbianUnitTestAssertionFailed );
       
   408     }
       
   409 
       
   410 
       
   411 // -----------------------------------------------------------------------------
       
   412 //
       
   413 // -----------------------------------------------------------------------------
       
   414 //
       
   415 EXPORT_C void CSymbianUnitTest::AssertEqualsL(
       
   416     TInt aExpectedValue, 
       
   417     TInt aActualValue, 
       
   418     TInt aLineNumber,
       
   419     const TDesC8& aFileName,
       
   420     const TDesC8& aFailureMessage )
       
   421     {
       
   422     if ( aExpectedValue != aActualValue )
       
   423         {
       
   424         StopAllocFailureSimulation();
       
   425         AssertionFailedL( aFailureMessage, aLineNumber, aFileName );
       
   426         }
       
   427     }
       
   428 
       
   429 // -----------------------------------------------------------------------------
       
   430 //
       
   431 // -----------------------------------------------------------------------------
       
   432 //
       
   433 EXPORT_C void CSymbianUnitTest::AssertEqualsL(
       
   434     const TDesC8& aExpectedValue,
       
   435     const TDesC8& aActualValue,
       
   436     TInt aLineNumber,
       
   437     const TDesC8& aFileName,
       
   438     const TDesC8& aFailureMessage )
       
   439     {
       
   440     if ( aExpectedValue.Compare( aActualValue ) != 0 )
       
   441         {
       
   442         StopAllocFailureSimulation();
       
   443         AssertionFailedL( aFailureMessage, aLineNumber, aFileName );
       
   444         }
       
   445     }
       
   446 
       
   447 // -----------------------------------------------------------------------------
       
   448 //
       
   449 // -----------------------------------------------------------------------------
       
   450 //
       
   451 EXPORT_C void CSymbianUnitTest::AssertEqualsL(
       
   452     const TDesC16& aExpectedValue,
       
   453     const TDesC16& aActualValue,
       
   454     TInt aLineNumber,
       
   455     const TDesC8& aFileName,
       
   456     const TDesC8& aFailureMessage )
       
   457     {
       
   458     if ( aExpectedValue.Compare( aActualValue ) != 0 )
       
   459         {
       
   460         StopAllocFailureSimulation();
       
   461         AssertionFailedL( aFailureMessage, aLineNumber, aFileName );
       
   462         }
       
   463     }
       
   464 
       
   465 // -----------------------------------------------------------------------------
       
   466 //
       
   467 // -----------------------------------------------------------------------------
       
   468 //
       
   469 CSymbianUnitTest::CSymbianUnitTestCase* 
       
   470 CSymbianUnitTest::CSymbianUnitTestCase::NewL( 
       
   471     const TDesC& aName,
       
   472     FunctionPtr aSetupFunction,
       
   473     FunctionPtr aTestFunction,
       
   474     FunctionPtr aTeardownFunction )
       
   475     {
       
   476     CSymbianUnitTestCase* self = 
       
   477         new( ELeave )CSymbianUnitTestCase( 
       
   478             aSetupFunction, aTestFunction, aTeardownFunction );
       
   479     CleanupStack::PushL( self );
       
   480     self->ConstructL( aName );
       
   481     CleanupStack::Pop( self );
       
   482     return self;    
       
   483     }
       
   484 
       
   485 // -----------------------------------------------------------------------------
       
   486 //
       
   487 // -----------------------------------------------------------------------------
       
   488 //
       
   489 CSymbianUnitTest::CSymbianUnitTestCase::CSymbianUnitTestCase( 
       
   490     FunctionPtr aSetupFunction,
       
   491     FunctionPtr aTestFunction,
       
   492     FunctionPtr aTeardownFunction ) :
       
   493     iSetupFunction( aSetupFunction ),
       
   494     iTestFunction( aTestFunction ),
       
   495     iTeardownFunction( aTeardownFunction )
       
   496     {
       
   497     }
       
   498 
       
   499 // -----------------------------------------------------------------------------
       
   500 //
       
   501 // -----------------------------------------------------------------------------
       
   502 //
       
   503 void CSymbianUnitTest::CSymbianUnitTestCase::ConstructL( const TDesC& aName )
       
   504     {
       
   505     iName = aName.AllocL();
       
   506     }
       
   507 
       
   508 // -----------------------------------------------------------------------------
       
   509 //
       
   510 // -----------------------------------------------------------------------------
       
   511 //
       
   512 CSymbianUnitTest::CSymbianUnitTestCase::~CSymbianUnitTestCase()
       
   513     {
       
   514     delete iName;
       
   515     }
       
   516 
       
   517 // -----------------------------------------------------------------------------
       
   518 //
       
   519 // -----------------------------------------------------------------------------
       
   520 //
       
   521 const TDesC& CSymbianUnitTest::CSymbianUnitTestCase::Name() const
       
   522     {
       
   523     return *iName;
       
   524     }
       
   525 
       
   526 // -----------------------------------------------------------------------------
       
   527 //
       
   528 // -----------------------------------------------------------------------------
       
   529 //
       
   530 HBufC8* CSymbianUnitTest::NotEqualsMessageLC(
       
   531     const TDesC16& aExpectedValue,
       
   532     const TDesC16& aActualValue )
       
   533     {
       
   534     TInt length = 
       
   535         KDesCsNotEqualFormat().Length() + 
       
   536         aExpectedValue.Length() + 
       
   537         aActualValue.Length();
       
   538     HBufC8* msg = HBufC8::NewLC( length );
       
   539 
       
   540     HBufC8* expected = 
       
   541         CnvUtfConverter::ConvertFromUnicodeToUtf8L( aExpectedValue );
       
   542     CleanupStack::PushL( expected );
       
   543 
       
   544     HBufC8* actual = CnvUtfConverter::ConvertFromUnicodeToUtf8L( aActualValue );
       
   545     CleanupStack::PushL( actual );
       
   546 
       
   547     msg->Des().Format( KDesCsNotEqualFormat, expected, actual );
       
   548 
       
   549     CleanupStack::PopAndDestroy( actual );
       
   550     CleanupStack::PopAndDestroy( expected );
       
   551     
       
   552     return msg;
       
   553     }
       
   554     
       
   555 // -----------------------------------------------------------------------------
       
   556 //
       
   557 // -----------------------------------------------------------------------------
       
   558 //
       
   559 void CSymbianUnitTest::ExecuteTestCaseInThreadL(
       
   560     CSymbianUnitTestCase& aTestCase,
       
   561     CSymbianUnitTestResult& aResult,
       
   562     TInt aTimeout )
       
   563     {
       
   564     iCurrentTestCase = &aTestCase;
       
   565     iTestResult = &aResult;
       
   566 
       
   567     //create exec thread
       
   568     TName threadName( KTestThreadName );
       
   569     // Append a random number to make the name unique
       
   570     const TInt KThreadIdWidth = 10;
       
   571     threadName.AppendNumFixedWidthUC( Math::Random(), EHex, KThreadIdWidth );
       
   572     RThread execThread;
       
   573     TInt err = execThread.Create( threadName,
       
   574                               TestThreadEntryFunction,
       
   575                               KDefaultStackSize,
       
   576                               KMinHeapSize,
       
   577                               KTestThreadMaxHeapSize,
       
   578                               this );
       
   579     User::LeaveIfError( err );
       
   580     CleanupClosePushL( execThread );
       
   581     
       
   582 
       
   583     //start exec thread
       
   584     TRequestStatus status = KRequestPending;
       
   585     execThread.Logon( status );
       
   586     execThread.Resume();
       
   587     
       
   588     TBool timedOut = EFalse;
       
   589     if (aTimeout > 0)
       
   590         {    
       
   591 	    SUT_LOG_DEBUGF(_L("run test case with timeout %d"), aTimeout);
       
   592 	    //run test case with timeout control
       
   593 	    TRequestStatus waitStatus = KRequestPending;
       
   594         RTimer timer;
       
   595         User::LeaveIfError(timer.CreateLocal());
       
   596         CleanupClosePushL(timer);
       
   597         timer.After(waitStatus, aTimeout*1000000);
       
   598         User::WaitForRequest( status, waitStatus );
       
   599         if (waitStatus.Int() == KRequestPending)
       
   600             {
       
   601             timer.Cancel();
       
   602             timer.Close();
       
   603             User::WaitForRequest( waitStatus );
       
   604             }
       
   605 
       
   606         if (status.Int() == KRequestPending)
       
   607             {
       
   608     	    //test case did not complete in time
       
   609     	    //terminate the exec thread
       
   610     	    SUT_LOG_DEBUG(" test case timed out, kill the exec thread");
       
   611     	    timedOut = ETrue;
       
   612     	    
       
   613     	    execThread.LogonCancel( status );
       
   614     	    User::WaitForRequest(status);
       
   615     	    
       
   616             execThread.Kill(KErrTimedOut);
       
   617     	    aResult.AddTimeOutErrorL( aTimeout );
       
   618             } 
       
   619         CleanupStack::PopAndDestroy( &timer );
       
   620 	}
       
   621     else 
       
   622         {
       
   623     	SUT_LOG_DEBUG(" run test case without timeout");
       
   624     	//exec test case without timeout control
       
   625         User::WaitForRequest(status);
       
   626         }
       
   627     if (status.Int() != KErrNone && !timedOut)
       
   628         {
       
   629         SUT_LOG_DEBUG("testcase exec thread panic");
       
   630         aResult.AddPanicInfoL( 
       
   631             execThread.ExitCategory(), 
       
   632             execThread.ExitReason(),
       
   633             iAllocFailureRate );
       
   634         }
       
   635     CleanupStack::PopAndDestroy( &execThread );
       
   636     }
       
   637 
       
   638 // -----------------------------------------------------------------------------
       
   639 //
       
   640 // -----------------------------------------------------------------------------
       
   641 //
       
   642 TInt CSymbianUnitTest::TestThreadEntryFunction( TAny* aPtr )
       
   643     {
       
   644     CSymbianUnitTest* self = reinterpret_cast< CSymbianUnitTest* >( aPtr );
       
   645     TInt err = KErrNoMemory;
       
   646     CTrapCleanup* cleanupStack = CTrapCleanup::New();
       
   647     if ( cleanupStack )
       
   648         {
       
   649         // Operator new used without ELeave on purpose to avoid using TRAP.
       
   650         CActiveScheduler* scheduler = new CActiveScheduler;
       
   651         if ( scheduler )
       
   652             {
       
   653             CActiveScheduler::Install( scheduler );
       
   654             TRAP( err, self->ExecuteTestCaseL() )
       
   655             delete scheduler;
       
   656             }
       
   657         }
       
   658     delete cleanupStack;
       
   659     return err;
       
   660     }    
       
   661 
       
   662 // -----------------------------------------------------------------------------
       
   663 //
       
   664 // -----------------------------------------------------------------------------
       
   665 //
       
   666 void CSymbianUnitTest::ExecuteTestCaseL()
       
   667     {    
       
   668     __ASSERT_ALWAYS( iTestResult, User::Leave( KErrNotFound ) );
       
   669     __ASSERT_ALWAYS( iCurrentTestCase, User::Leave( KErrNotFound ) );
       
   670     iAllocFailureRate = 0;
       
   671     iLeakedMemory = 0;
       
   672     iLeakedResource = 0;
       
   673     iLeakedRequest = 0;
       
   674     TInt leaveCodeFromTest( KErrNoMemory );
       
   675     if ( iAllocFailureType == RHeap::EDeterministic )
       
   676         {
       
   677         TUint counter( 1 );
       
   678         while ( leaveCodeFromTest == KErrNoMemory )
       
   679             {
       
   680             iAllocFailureRate = counter;
       
   681             DoExecuteTestCaseL( leaveCodeFromTest );
       
   682             counter++;
       
   683             }
       
   684         }
       
   685     else
       
   686         {
       
   687         DoExecuteTestCaseL( leaveCodeFromTest );
       
   688         }
       
   689     // Add the possible failure or memory leak to the results
       
   690     if ( leaveCodeFromTest == KErrNone )
       
   691         {
       
   692         if ( iLeakedMemory > 0 )
       
   693             {
       
   694             iTestResult->AddMemoryLeakInfoL( iLeakedMemory, iAllocFailureRate );
       
   695             }
       
   696         if ( iLeakedResource > 0 )
       
   697             {
       
   698             iTestResult->AddResourceLeakInfoL( iLeakedResource, iAllocFailureRate );
       
   699             }
       
   700         if ( iLeakedRequest > 0 )
       
   701             {
       
   702             iTestResult->AddRequestLeakInfoL( iLeakedRequest, iAllocFailureRate );
       
   703             }
       
   704         }
       
   705     else if ( leaveCodeFromTest != KErrSymbianUnitTestAssertionFailed )
       
   706         {
       
   707         iTestResult->AddLeaveFromTestL( leaveCodeFromTest, iAllocFailureRate );
       
   708         }
       
   709     else
       
   710         {
       
   711         // No operation here. 
       
   712         // Assertion failure has happened and it has been added to the results.
       
   713         }
       
   714     }
       
   715 
       
   716 // -----------------------------------------------------------------------------
       
   717 //
       
   718 // -----------------------------------------------------------------------------
       
   719 //
       
   720 void CSymbianUnitTest::DoExecuteTestCaseL( TInt& aLeaveCodeFromTest )
       
   721     {
       
   722     __ASSERT_ALWAYS( iTestResult, User::Leave( KErrNotFound ) );
       
   723     __ASSERT_ALWAYS( iCurrentTestCase, User::Leave( KErrNotFound ) );
       
   724     aLeaveCodeFromTest = KErrNone;
       
   725     iHeapCellsReservedByAssertFailure = 0;
       
   726     TInt memoryBeforeTest( 0 ); 
       
   727     TInt heapCellsBeforeTest( User::Heap().AllocSize( memoryBeforeTest ) );
       
   728     TInt resourceInThreadBeforeTest, resourceInProcessBeforeTest;
       
   729     RThread().HandleCount( resourceInProcessBeforeTest, resourceInThreadBeforeTest );
       
   730     TInt requestBeforeTest = RThread().RequestCount();
       
   731     TRAPD( err, ( this->*iCurrentTestCase->iSetupFunction )() )
       
   732     if ( err != KErrNone )
       
   733         {       
       
   734         ( this->*iCurrentTestCase->iTeardownFunction )();
       
   735         iTestResult->AddSetupErrorL( err );
       
   736         return;
       
   737         }
       
   738     StartAllocFailureSimulation();
       
   739     TRAP( aLeaveCodeFromTest, ( this->*iCurrentTestCase->iTestFunction )() );
       
   740     StopAllocFailureSimulation();
       
   741        
       
   742     ( this->*iCurrentTestCase->iTeardownFunction )();
       
   743 
       
   744     TInt memoryAfterTest( 0 );
       
   745     TInt heapCellsAfterTest( User::Heap().AllocSize( memoryAfterTest ) );
       
   746     TInt leakedHeapCells = 
       
   747         heapCellsAfterTest - 
       
   748             ( heapCellsBeforeTest + iHeapCellsReservedByAssertFailure );
       
   749     if ( leakedHeapCells > 0 )
       
   750         {
       
   751         iLeakedMemory = memoryAfterTest - memoryBeforeTest;
       
   752         }
       
   753         
       
   754     TInt resourceInThreadAfterTest, resourceInProcessAfterTest;
       
   755     RThread().HandleCount( resourceInProcessAfterTest, resourceInThreadAfterTest );
       
   756     iLeakedResource = resourceInThreadAfterTest - resourceInThreadBeforeTest;
       
   757     TInt requestAfterTest = RThread().RequestCount();
       
   758     iLeakedRequest = requestAfterTest - requestBeforeTest;
       
   759     }
       
   760 
       
   761 // -----------------------------------------------------------------------------
       
   762 //
       
   763 // -----------------------------------------------------------------------------
       
   764 //
       
   765 void CSymbianUnitTest::StartAllocFailureSimulation()
       
   766     {
       
   767     __UHEAP_SETFAIL( iAllocFailureType, iAllocFailureRate );
       
   768     }
       
   769 
       
   770 // -----------------------------------------------------------------------------
       
   771 //
       
   772 // -----------------------------------------------------------------------------
       
   773 //
       
   774 void CSymbianUnitTest::StopAllocFailureSimulation()
       
   775     {
       
   776     __UHEAP_RESET;
       
   777     }