testexecfw/stf/stffw/testsrv/src/TestExecutionThread.cpp
changeset 2 8bb370ba6d1d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testexecfw/stf/stffw/testsrv/src/TestExecutionThread.cpp	Fri Apr 09 10:46:28 2010 +0800
@@ -0,0 +1,2936 @@
+/*
+* Copyright (c) 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: This module contains implementation of 
+* CTestThreadContainer class implementation. These functions are 
+* called from the context of the test execution thread.
+*
+*/
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <e32svr.h>
+#include <e32uid.h>
+#include <StifTestModule.h>
+#include "ThreadLogging.h"
+#include "TestEngineClient.h"
+#include <stifinternal/TestServerClient.h>
+#include "TestServer.h"
+#include "TestThreadContainer.h"
+#include "TestServerCommon.h"
+#include "TestServerModuleIf.h"
+#include "TestServerEvent.h"
+#include "TestThreadContainerRunner.h"
+#include <stifinternal/TestThreadContainerRunnerFactory.h>
+#include <stfeventsystem.h>
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+
+// MACROS
+#ifdef THREADLOGGER
+#undef THREADLOGGER
+#endif
+#define THREADLOGGER iThreadLogger 
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ==================== LOCAL FUNCTIONS =======================================
+
+// None
+
+// ================= MEMBER FUNCTIONS =========================================
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: NewL
+
+    Description: Returns new CTestThreadContainer instance.
+
+    Parameters: None
+
+    Return Values: CTestThreadContainer*            New instance
+
+    Errors/Exceptions: Function leaves if memory allocation fails or
+                       CTestThreadContainer ConstructL leaves.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestThreadContainer* CTestThreadContainer::NewL( 
+    CTestModuleContainer* aModuleContainer,
+    TThreadId aServerThreadId )
+    {
+
+    CTestThreadContainer* self = 
+        new ( ELeave ) CTestThreadContainer( aModuleContainer );
+    CleanupStack::PushL( self );
+    self->ConstructL( aServerThreadId );
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: ConstructL
+
+    Description: Second level constructor.
+
+    Parameters: None
+
+    Return Values: CTestThreadContainer*            New instance
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::ConstructL( TThreadId aServerThreadId )
+    {
+    
+    User::LeaveIfError( iServerThread.Open( aServerThreadId ) );
+    
+    iErrorPrintSem.SetHandle( ModuleContainer().ErrorPrintSemHandle() );
+    User::LeaveIfError( iErrorPrintSem.Duplicate( iServerThread ) );
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: CTestThreadContainer
+
+    Description: Constructor.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+CTestThreadContainer::CTestThreadContainer( 
+    CTestModuleContainer* aModuleContainer ):
+    iModuleContainer( aModuleContainer ),
+    iCheckResourceFlags( 0 )
+    {
+   
+    ModuleContainer().SetThreadContainer( this );
+    
+    StifMacroErrorInit(); // Initialization
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: ~CTestThreadContainer
+
+    Description: Destructor
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestThreadContainer::~CTestThreadContainer()
+    {
+
+    // Close mutexes
+    if ( iPrintMutex.Handle() != 0 ) iPrintMutex.Close();
+    if ( iEventMutex.Handle() != 0 ) iEventMutex.Close();
+    if ( iSndMutex.Handle() != 0 ) iSndMutex.Close();
+    if ( iRcvMutex.Handle() != 0 ) iRcvMutex.Close();
+    if ( iInterferenceMutex.Handle() != 0 ) iInterferenceMutex.Close();
+    if ( iMeasurementMutex.Handle() != 0 ) iMeasurementMutex.Close();
+    if ( iCommandMutex.Handle() != 0 ) iCommandMutex.Close();
+
+    // Mutex for testcomplete and cancel operations. Close duplicate mutex
+    if ( iTestThreadMutex.Handle() != 0 ) iTestThreadMutex.Close();
+
+    // Close semaphores
+    if ( iPrintSem.Handle() != 0 ) iPrintSem.Close();
+    if ( iErrorPrintSem.Handle() != 0 ) iErrorPrintSem.Close();
+    if ( iEventSem.Handle() != 0 ) iEventSem.Close();
+    if ( iSndSem.Handle() != 0 ) iSndSem.Close();
+    if ( iRcvSem.Handle() != 0 ) iRcvSem.Close();
+    if ( iInterferenceSem.Handle() != 0 ) iInterferenceSem.Close();
+    if ( iMeasurementSem.Handle() != 0 ) iMeasurementSem.Close();
+    //if ( iReceiverSem.Handle() != 0 ) iReceiverSem.Close();
+    if ( iCommandSem.Handle() != 0) iCommandSem.Close();
+    
+    iServerThread.Close();
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: InitializeModule
+
+    Description: Initialize test module.
+
+    Function obtains pointer to the first exported function of the test module,
+    and calls that function to obtain an instance of CTestModuleBase derived
+    object. After that the "Init()"-method is called. If some operation fails,
+    module will be deleted and error code is returned.
+
+    This function is a static member function, which is intented to be called
+    from the context of the test module thread.
+
+    Parameters: RLibrary& aModule                 :in: Module to be loaded
+    
+    Return Values: TInt                                Error code from module
+                                                       or memory allocation.
+
+    Errors/Exceptions: None.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::InitializeModuleInThread ( RLibrary& aModule )
+    {        
+        
+    __TRACEI ( KInit, ( _L("Starting test module initialization") ) );
+    __TRACEI ( KInit, ( CStifLogger::EBold,  _L("Module name \"%S\""), 
+        &ModuleContainer().OperationName() ) );
+    ModuleContainer().OperationText() = _L("E32DLL");
+
+    TFileName moduleName;
+    TFileName tmpBuffer;
+
+    TInt r( KErrNone );
+    TFileName newNameBuffer;
+    TInt check = CheckModuleName( ModuleContainer().OperationName(), newNameBuffer );
+    if( check == KErrNone )
+        {
+        // Load the module(TestScripter)
+        r = aModule.Load( newNameBuffer );
+        }
+    else
+        {
+        // Load the module(Others)
+        RemoveOptionalIndex(ModuleContainer().OperationName(), newNameBuffer);
+        __TRACEI(KInit, (_L( "Valid module name is [%S] (extracted from [%S])"), &newNameBuffer, &ModuleContainer().OperationName()));
+        r = aModule.Load(newNameBuffer);
+        }
+    
+    if ( r != KErrNone )
+        {
+        __TRACEI (KError, ( CStifLogger::EError, _L("Can't initialize test module code = %d"), r));
+
+        // Set error codes
+        ModuleContainer().OperationErrorResult() = r;
+        return r;
+        }
+    else
+        {
+        // Print module name
+        moduleName = aModule.FileName();    
+        __TRACEI (KInit, (  _L("Loaded test module[%S]"), &moduleName ) );
+        }
+
+   
+    // Get pointer to first exported function
+    ModuleContainer().OperationText() = _L("1st EXPORTED function");
+    CTestInterfaceFactory libEntry;
+    libEntry = (CTestInterfaceFactory) aModule.Lookup(1);
+    if ( libEntry == NULL )
+        {
+        // New instance can't be created
+        __TRACEI (KError, ( CStifLogger::EError, _L("Can't initialize test module, NULL libEntry")));
+
+        // Set error codes
+        ModuleContainer().OperationErrorResult() = KErrNoMemory;
+        return KErrNoMemory;
+        }
+    else
+        {
+        __TRACEI ( KInit, ( _L("Pointer to 1st exported received")));
+        }
+
+    // initialize test module
+    __TRACEI ( KVerbose, (_L("Calling 1st exported at 0x%x"), (TUint32) libEntry ));
+    TRAPD ( err, iTestModule =  (*libEntry)() );
+
+     // Handle leave from test module
+    if ( err != KErrNone )
+        {
+        __TRACEI (KError, ( CStifLogger::EError, _L("Leave when calling 1st exported function, code %d"), err));
+        tmpBuffer = _L("Leave from test module 1st EXPORTED function");        
+        ErrorPrint( 1, tmpBuffer );        
+        delete iTestModule;
+        iTestModule = NULL;
+
+        // Set error codes
+        ModuleContainer().OperationErrorResult() = err;
+        return err;
+        }
+    else if ( iTestModule == NULL )     // Handle NULL from test module init
+        {
+        __TRACEI (KError, ( CStifLogger::EError, _L("NULL pointer received when constructing test module")));
+        tmpBuffer = _L("Test module 1st EXPORTED function returned NULL");        
+        ErrorPrint( 1, tmpBuffer );        
+        delete iTestModule;
+        iTestModule = NULL;
+
+        // Set error codes
+        ModuleContainer().OperationErrorResult() = KErrNoMemory;
+        return KErrNoMemory;
+        }
+    else
+        {
+        __TRACEI (KInit, (_L("Entrypoint successfully called, test module instance at 0x%x"), (TUint32)iTestModule ) );
+        }
+
+    // Verify version number.
+    ModuleContainer().OperationText() = _L("Version");
+    TVersion moduleAPIVersion(0,0,0);
+    TVersion myOldAPIVersion( KOldTestModuleAPIMajor, KOldTestModuleAPIMinor, KOldTestModuleAPIBuild );
+    TVersion myAPIVersion( KTestModuleAPIMajor, KTestModuleAPIMinor, KTestModuleAPIBuild );
+    TRAP ( err,  moduleAPIVersion = iTestModule->Version() );
+
+    if ( err != KErrNone ||  (( myOldAPIVersion.iMajor !=  moduleAPIVersion.iMajor ||
+                                myOldAPIVersion.iMinor !=  moduleAPIVersion.iMinor  )
+                                &&
+                              ( myAPIVersion.iMajor != moduleAPIVersion.iMajor ||
+                              	myAPIVersion.iMinor != moduleAPIVersion.iMinor ))
+        )
+        {
+        tmpBuffer = moduleAPIVersion.Name();
+        __TRACEI (KError, ( CStifLogger::EError, _L("Incorrect test module version. Module version %S"), &tmpBuffer ) );        
+        tmpBuffer = myOldAPIVersion.Name();
+        __TRACEI (KError, ( CStifLogger::EError, _L("Required version %S"), &tmpBuffer  ) );
+                
+        tmpBuffer.Format(_L("Invalid version in [%S]"), &moduleName );
+        ErrorPrint( 1, tmpBuffer );        
+
+         // Set error codes
+        ModuleContainer().OperationErrorResult() = KErrNotSupported;
+        return KErrNotSupported;
+        }
+
+   
+    ModuleContainer().OperationText() = _L("InitL");
+    // Initialize test module
+    TInt initResult = KErrNone;
+    TRAP ( err, 
+        CTestModuleIf::NewL( NULL, iTestModule );
+        TFileName tmp = ModuleContainer().TestModuleIniFile();
+        initResult = iTestModule->InitL( tmp, ModuleContainer().OperationIntBuffer() );
+    );
+
+    // Handle leave from test module
+    if ( err != KErrNone )
+        {
+        __TRACEI (KError, ( CStifLogger::EError, _L("Leave when initializing test module code %d"), err));
+        tmpBuffer = _L("Leave from test module InitL");        
+        ErrorPrint( 1, tmpBuffer );   
+        ModuleContainer().OperationText() = _L("DESTRUCTOR");
+        delete iTestModule;
+        iTestModule = NULL;
+        ModuleContainer().OperationText() = _L("");
+
+        // Set error codes
+        ModuleContainer().OperationErrorResult() = err;
+        return err;
+        }      
+    else if ( initResult != KErrNone ) 
+        {     // Handle failed initialisation of test module
+        __TRACEI (KError, ( CStifLogger::EError, _L("Can't initialize test module, code %d"), initResult));
+        ModuleContainer().OperationText() = _L("DESTRUCTOR");
+        delete iTestModule;
+        iTestModule = NULL;
+        ModuleContainer().OperationText() = _L("");
+        
+        // Set error code
+        ModuleContainer().ModuleResult() = initResult;
+        return initResult;
+        }
+    ModuleContainer().OperationText() = _L("");
+
+    __TRACEI (KInit, ( CStifLogger::EBold, _L("Test module initialization done")));     
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: EnumerateInThread
+
+    Description: Enumerate test cases. Function calls GetTestCases method
+    from the test module.
+
+    This function is a static member function, which is intented to be called
+    from the context of the test module thread.
+        
+    Parameters: None
+    
+    Return Values: TInt                           Error code.
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::EnumerateInThread()
+    {
+
+    TInt err = KErrNone;
+    __TRACEI ( KInit, ( CStifLogger::EBold, _L("Calling GetTestCasesL") ) );
+
+    if ( iCases == NULL )
+        {
+        iCases = new RPointerArray<TTestCaseInfo>;
+        if ( iCases == NULL )
+            {
+            ModuleContainer().OperationErrorResult() = KErrNoMemory;
+            __TRACEI ( KError, ( _L("Can't create pointer array for cases") ) );
+            return ModuleContainer().OperationErrorResult();
+            }
+        }
+
+    // Thread ID logging(For error situations) !!!!! ----------
+    /*
+    RThread t;
+    RDebug::Print(_L("XXXXXXXXXXXXXXXXXXXXXX CurrentThread=[%d]"), t.Id() );
+    t.Open( t.Id() );   
+    RDebug::Print(_L("XXXXXXXXXXXXXXXXXXXXXX Real id=[%d]"), t.Id() );
+    t.Close();
+    */
+    // --------------------------------------------------------
+
+    ModuleContainer().OperationText() = _L("GetTestCasesL");
+    TRAPD (r, err = iTestModule->GetTestCasesL( 
+                        ModuleContainer().OperationName(),
+                        *iCases ) );
+    ModuleContainer().OperationText() = _L("");
+
+    // Leave
+    if ( r != KErrNone )
+        {
+        __TRACEI ( KError, ( CStifLogger::ERed, _L("GetTestCasesL leave code %d"), r ) );
+        TName tmpBuffer = _L("Leave from test module GetTestCasesL");        
+        ErrorPrint( 1, tmpBuffer );        
+        FreeEnumerationDataInThread();
+
+        ModuleContainer().OperationErrorResult() = r;
+        return r;
+        }
+        
+    // Error originating from test module
+    if ( err != KErrNone )
+        {
+        __TRACEI ( KError, ( CStifLogger::ERed, _L("GetTestCasesL returned error %d"), err ) );
+        FreeEnumerationDataInThread();
+
+        ModuleContainer().ModuleResult() = err;
+        return err;
+        }
+
+    __TRACEI ( KInit, ( _L("GetTestCasesL successfully called") ) );
+
+    // All ok.
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: FreeEnumerationDataInThread
+
+    Description: Frees the enumeration data. This function is called, when
+    the enumeration data is read from execution thread heap to server thread
+    heap. If cases have not been enumerated function does nothing.
+    
+    Function is intented to be called from the context of the test module thread.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::FreeEnumerationDataInThread()
+    {
+
+    __TRACEI ( KInit, ( _L("Freeing test case array") ) );
+
+    if ( iCases )
+        {
+        iCases->ResetAndDestroy();
+        delete iCases;
+        iCases = NULL;
+        }
+    
+    __TRACEI ( KInit, ( _L("Freeing test case array done") ) );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: ExecuteTestCaseInThread
+
+    Description: Execute test case. This function calls either RunTestCase or 
+    ExecuteOOMTestCase to execute and report the results.
+
+    This function is a static member function, which is intented to be called
+    from the context of the test module thread.
+
+    Parameters: None
+
+    Return Values: TInt: Error code
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::ExecuteTestCaseInThread()
+    {        
+    TVersion moduleAPIVersion;
+    moduleAPIVersion = iTestModule->Version(); 
+
+    __TRACEI ( KInit, 
+        ( CStifLogger::EBold, _L("Executing test case file=[%S] case=%d"), 
+            &ModuleContainer().OperationName(), 
+            ModuleContainer().OperationIntBuffer() ) );
+
+    TInt r = KErrNone;
+    
+    // Thread handle
+    RThread thisRt;
+    r = DuplicateMutexHandles( thisRt );
+       
+    // Result from RunTestCase       
+    TTestResult caseResult; 
+    
+    // Execution result from RunTestCase
+    TInt err = KErrNone;
+
+    // Fill in initial values
+    TestExecution().FullResult().iCaseExecutionResultType = 
+        TFullTestResult::ECaseExecuted;
+    TestExecution().FullResult().iCaseExecutionResultCode = KErrNone;            
+    TestExecution().FullResult().iStartTime.HomeTime();
+    TestExecution().TestThreadFailure() = CTestExecution::ETestThreadOk;
+
+    // Set handle to test execution
+    TRAP( r, CTestModuleIf::NewL( this,
+                                  iTestModule ) );
+
+    ModuleContainer().OperationText() =_L("RunTestCaseL");
+    
+    // Do resource checks before starting test case
+    iCheckResourceFlags = 0;        
+    
+    TInt tmp;
+    TInt threadHandleCountBeforeTest;
+
+    // Request count check
+    TInt requestCountBeforeTest = thisRt.RequestCount();
+    // Handle count check, not checking process handles
+    thisRt.HandleCount( tmp, threadHandleCountBeforeTest );
+
+    // If handle ok, then execute test          
+    if( r == KErrNone )
+        {       
+        TInt testCaseNumber = ModuleContainer().OperationIntBuffer();
+
+        // Do the test
+        __TRACEI ( KInit, ( _L("About to call RunTestCaseL. If nothing in log \
+            after line \"Calling RunTestCaseL\", check testserver log file.") ) );        
+                    
+        TInt firstMemFailure = 0; 
+        TInt lastMemFailure = 0;        
+        // Store the OOM test type
+        CTestModuleBase::TOOMFailureType failureType;
+                
+        // Check if the current test case is supposed to be run using OOM
+        if( iTestModule->OOMTestQueryL( ModuleContainer().OperationName(), 
+                                        testCaseNumber, 
+                                        failureType,
+                                        firstMemFailure, 
+                                        lastMemFailure ) )
+            {
+            //  Run the test case in OOM conditions      
+            r = ExecuteOOMTestCase( testCaseNumber, 
+                                    firstMemFailure, 
+                                    lastMemFailure, 
+                                    err, 
+                                    caseResult );
+            }
+        else
+            {
+            // Run the test case the old way, without OOM testing           
+            __TRACEI ( KInit, ( _L("Calling RunTestCaseL - \
+                OOM condition is not set") ) );
+            TRAP( r, err = iTestModule->RunTestCaseL( 
+                                            testCaseNumber,
+                                            ModuleContainer().OperationName(),
+                                            caseResult ) );
+            }
+        }        
+     
+    // Do resource checks after test case execution
+    // Handle count check
+    TInt threadHandleCountAfterTest;
+    thisRt.HandleCount( tmp, threadHandleCountAfterTest );
+    threadHandleCountAfterTest -= iTestModule->TestModuleIf().iNumberInGlbDict;
+    // Request count check
+    TInt requestCountAfterTest = thisRt.RequestCount();           
+          
+    ModuleContainer().OperationText() =_L("");
+
+    // Store end time
+    TestExecution().FullResult().iEndTime.HomeTime();   
+    // Remove handle to testexecution 
+    TRAPD( rr, CTestModuleIf::NewL( NULL, iTestModule ) );
+    
+
+    if ( rr != KErrNone )
+        {        
+        __TRACEI ( KError, ( _L("Memory low in executionthread.") ) );        
+        // Do not actually handle error
+        }
+  
+    // Report test result. Parts of this will be overwritten if error
+    // is detected
+    TestExecution().FullResult().iTestResult = caseResult;
+
+    // Get target exit reasons
+    CTestModuleIf::TExitReason allowedExitReason;
+    TInt allowedExitCode = KErrNone;
+    ExitReason( allowedExitReason, allowedExitCode );
+    
+    TBool returnLeakCheckFail = EFalse;
+
+    // Check are STIF macros used
+    if( iTestMacroInfo.iIndication ) 
+        {
+        // STIF macros are used. Set description info, test case to
+        // ECaseExecuted state and case execution result code to KErrNone
+        // to get test case to failed category.
+        TName tmpResultDes;
+        __TRACEI ( KError, ( CStifLogger::ERed, _L("Leave from RunTestCaseL(STIF TF's macro is used)" ) ) );
+        // Set result description
+        tmpResultDes.Copy( _L( "FILE[") );
+        tmpResultDes.Append( iTestMacroInfo.iFileDes );
+        tmpResultDes.Append( _L( "] FUNCTION[" ) );
+        tmpResultDes.Append( iTestMacroInfo.iFunctionDes );
+        tmpResultDes.Append( _L( "] LINE[" ) );
+        tmpResultDes.AppendNum( iTestMacroInfo.iLine );
+        tmpResultDes.Append( _L( "]" ) );
+        // Other result information
+        TestExecution().FullResult().iTestResult.iResult =
+                                            iTestMacroInfo.iReceivedError;
+        TestExecution().FullResult().iTestResult.iResultDes = tmpResultDes;
+        TestExecution().FullResult().iCaseExecutionResultType = 
+                                            TFullTestResult::ECaseExecuted;
+        // Set category to failed cases
+        TestExecution().FullResult().iCaseExecutionResultCode = KErrNone;
+        StifMacroErrorInit(); // Initialization back to default
+        }
+    else if( r != KErrNone )
+        {   // Case has left, overwrite normal result description string
+        __TRACEI ( KError, ( CStifLogger::ERed, _L("Leave from RunTestCaseL, code %d"), r ) );
+        // Set result description
+        TName tmpResultDes = _L("Leave during case:");
+        // Check if there was already some description passed to result object
+        if(caseResult.iResultDes.Length() > 0)
+            {
+            tmpResultDes.Format(_L("Leave during case [%S]:"), &caseResult.iResultDes);
+            if(tmpResultDes.Length() > KStifMaxResultDes)
+                {
+                tmpResultDes.SetLength(KStifMaxResultDes);
+                }
+            }
+        // Other result information
+        TestExecution().FullResult().iTestResult.iResult = KErrGeneral;
+        TestExecution().FullResult().iTestResult.iResultDes = tmpResultDes;
+        TestExecution().FullResult().iCaseExecutionResultType = 
+            TFullTestResult::ECaseLeave;
+        TestExecution().FullResult().iCaseExecutionResultCode = r;
+        }    
+    else if ( err != KErrNone )
+        {   
+        // Case has returned error (e.g. case not found )       
+        __TRACEI ( KError, ( CStifLogger::ERed, _L("RunTestCaseL returned error %d"), err ) ); 
+        TestExecution().FullResult().iCaseExecutionResultType = 
+            TFullTestResult::ECaseErrorFromModule;
+        TestExecution().FullResult().iCaseExecutionResultCode = err;
+        }
+    else if ( allowedExitReason != CTestModuleIf::ENormal )
+        {
+        // Test is failed, because it should end to panic or exception.
+        __TRACEI ( KInit, ( _L("Case ended normally even if it should end to panic/exception") ) ); 
+        TestExecution().FullResult().iTestResult.iResult = KErrGeneral;
+        TestExecution().FullResult().iTestResult.iResultDes = 
+            _L("Case did not ended to panic/exception");
+        }
+    // If test case is passed, check memory leak, handles etc...    
+    else if( caseResult.iResult == KErrNone )
+        {
+        returnLeakCheckFail = ETrue;
+        }
+   
+   // Test case leak checks
+    // In EKA2 heap size cannot be measured because THeapWalk is no longer supported    
+    LeakChecksForTestCase( returnLeakCheckFail, 
+                           threadHandleCountBeforeTest,
+                           threadHandleCountAfterTest,
+                           requestCountBeforeTest,
+                           requestCountAfterTest );
+
+    // Close execution specific handles
+
+    iPrintMutex.Close();
+    iEventMutex.Close();
+    iSndMutex.Close();
+    iRcvMutex.Close();
+    iInterferenceMutex.Close();
+    iMeasurementMutex.Close();
+    iCommandMutex.Close();
+    
+    // The Wait operation is performed to let the message from TestServer 
+    // to TestEngine achieve TestEngine or TestCombiner.   
+    iCommandSem.Wait();
+    
+    // Note: iTestThreadMutex.iClose() mutex will be used later, close in destructor.
+    
+    iPrintSem.Close();
+    iEventSem.Close();
+    iSndSem.Close();
+    iRcvSem.Close();
+    iInterferenceSem.Close();
+    iMeasurementSem.Close();
+    iCommandSem.Close();
+
+    // Close thread handle 
+    thisRt.Close();
+
+    __TRACEI ( KVerbose, ( _L("ExecuteTestCase out") ) );
+
+    // continues from CTestModuleContainer::RunL
+        
+    return KErrNone;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: DuplicateMutexHandles
+
+    Description: Duplicates mutex handles
+
+    Parameters: None
+
+    Return Values: TInt
+
+    Errors/Exceptions: Panic if duplication fails
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::DuplicateMutexHandles( RThread& aThread )
+    {
+    // For duplicating mutexes
+    iPrintMutex.SetHandle( TestExecution().PrintMutexHandle() );
+    iEventMutex.SetHandle( TestExecution().EventMutexHandle() );
+    iSndMutex.SetHandle( TestExecution().SndMutexHandle() );
+    iRcvMutex.SetHandle( TestExecution().RcvMutexHandle() );
+    iInterferenceMutex.SetHandle( TestExecution().InterferenceMutexHandle() );
+    iMeasurementMutex.SetHandle( TestExecution().MeasurementMutexHandle() );
+    iCommandMutex.SetHandle(TestExecution().CommandMutexHandle());
+
+    // Mutex for testcomplete and cancel operations. For duplicating mutex
+    iTestThreadMutex.SetHandle( TestExecution().TestThreadMutexHandle() );
+
+    // For duplicating semaphores
+    iPrintSem.SetHandle( TestExecution().PrintSemHandle() );
+    iEventSem.SetHandle( TestExecution().EventSemHandle() );
+    iSndSem.SetHandle( TestExecution().SndSemHandle() );
+    iRcvSem.SetHandle( TestExecution().RcvSemHandle() );
+    iInterferenceSem.SetHandle( TestExecution().InterferenceSemHandle() );
+    iMeasurementSem.SetHandle( TestExecution().MeasurementSemHandle() );
+    iCommandSem.SetHandle(TestExecution().CommandSemHandle());
+    
+    // Store thread id for later use
+    TestExecution().SetTestThread( aThread.Id() );
+    
+    // Duplicate handles from server thread
+    TRAPD( r,
+        User::LeaveIfError( iPrintMutex.Duplicate( iServerThread ) );
+        User::LeaveIfError( iEventMutex.Duplicate( iServerThread ) );
+        User::LeaveIfError( iSndMutex.Duplicate( iServerThread ) );
+        User::LeaveIfError( iRcvMutex.Duplicate( iServerThread ) );
+        User::LeaveIfError( iInterferenceMutex.Duplicate( iServerThread ) );
+        User::LeaveIfError( iMeasurementMutex.Duplicate( iServerThread ) );
+        User::LeaveIfError( iCommandMutex.Duplicate( iServerThread ) );
+        
+        User::LeaveIfError( iTestThreadMutex.Duplicate( iServerThread ) );
+
+        User::LeaveIfError( iPrintSem.Duplicate( iServerThread ) );
+        User::LeaveIfError( iEventSem.Duplicate( iServerThread ) );
+        User::LeaveIfError( iSndSem.Duplicate( iServerThread ) );
+        User::LeaveIfError( iRcvSem.Duplicate( iServerThread ) );
+        User::LeaveIfError( iInterferenceSem.Duplicate( iServerThread ) );
+        User::LeaveIfError( iMeasurementSem.Duplicate( iServerThread ) );
+        User::LeaveIfError( iCommandSem.Duplicate( iServerThread ) );
+        );
+
+    // Raise panic if duplications failed        
+    if( r != KErrNone )
+        {
+        Panic( EDuplicateFail );
+        }
+    
+    // Return the result, no error occurred
+    return KErrNone;            
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: ExecuteOOMTestCase
+
+    Description: Executes OOM test case
+
+    Parameters: None
+
+    Return Values: TInt
+
+    Errors/Exceptions: Panic if EOOMDisableLeakChecks is not set and test case
+    leaks memory.                       
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::ExecuteOOMTestCase( TInt aTestCaseNumber,
+                                               TInt aFirst, 
+                                               TInt aLast, 
+                                               TInt& aResult, 
+                                               TTestResult& caseResult )
+    {
+    TBool OOMwarning = EFalse;  
+    __TRACEI ( KInit, ( _L("CTestThreadContainer::ExecuteOOMTestCase") ) );            
+    __TRACEI ( KInit, ( _L("Executing test case #%d using OOM"), aTestCaseNumber ) );               
+    
+    // OOM test environment initialization
+    TRAPD( r, iTestModule->OOMTestInitializeL( 
+                                ModuleContainer().OperationName(),
+                                aTestCaseNumber ); );               
+    
+    for( TInt i=aFirst; i<aLast; i++ )
+        {   
+        // Fail the i:nth heap allocation
+        User::__DbgSetAllocFail( RHeap::EUser, RHeap::EFailNext, i  );
+        
+        //__TRACEI ( KInit, ( _L("Setting %d:nth heap allocation to fail"), i  ) );             
+                
+        // Intersection of iCheckResourceFlags and 
+        // EDisableMemoryLeakChecksInOOM to check if memory leak checks are to 
+        // be used with OOM testing.        
+        if( !( iCheckResourceFlags & CTestModuleIf::EOOMDisableLeakChecks ) )
+            {
+            User::__DbgMarkStart( RHeap::EUser );
+            }
+            
+        TRAP( r, aResult = iTestModule->RunTestCaseL( 
+                        aTestCaseNumber,
+                        ModuleContainer().OperationName(),
+                        caseResult ) );
+        
+        // Raise panic if test case leaks memory and EOOMDisableLeakChecks is not
+        // set        
+        if( !( iCheckResourceFlags & CTestModuleIf::EOOMDisableLeakChecks ) )
+            {
+            User::__DbgMarkEnd( RHeap::EUser, 0 );
+            }
+        
+        // If no error occurred, fake a memory error to make sure that this is
+        // the last test. If this last allocation goes wrong, it proves that 
+        // either the FAILNEXT() macro has reached its limit or that somewhere
+        // in the code some object TRAPped the OOM exception and did not leave.     
+        if( ( r != KErrNoMemory ) && ( aResult != KErrNoMemory  )
+            && ( caseResult.iResult != KErrNoMemory ) )
+            {
+            TInt* dummy = new TInt;
+            OOMwarning = ( dummy != NULL );
+            delete dummy;
+            }
+
+        // Cancel the simulated heap allocation failure
+        User::__DbgSetAllocFail( RHeap::EUser, RHeap::ENone, 1 );
+    
+        if( ( r != KErrNoMemory ) && !OOMwarning && ( aResult != KErrNoMemory )
+            && ( caseResult.iResult != KErrNoMemory ) )
+            {
+            // If we get here test was executed properly (= no memory error
+            // and no warning)
+            break;
+            }
+
+        if( OOMwarning )
+            {            
+            // It is possible that during testing some components TRAP the OOM
+            // exception and continue to run (do not leave) or they return an 
+            // error other than KErrNoMemory. These situations are making the
+            // OOM testing really difficult, so they should be detected and 
+            // make the tester aware.
+             
+            // Since each test case might have a specific oppinion on handling
+            // this situation, it is left up to the tester to handle it by 
+            // implementing the OOMHandleWarningL method. STIF will log a
+            // warning and call OOMHandleWarningL method.
+
+            // Print the OOM error message
+            __TRACEI ( KInit, ( _L("Possible trapped or non-leaving allocation in test case #%d"), i  ) );                          
+
+            iTestModule->OOMHandleWarningL( ModuleContainer().OperationName(), aTestCaseNumber, i );
+
+            // Clear the warning flag
+            OOMwarning = EFalse;
+            }
+        }
+        
+    // OOM test environment finalization                    
+    __TRACEI ( KInit, ( _L("Calling OOMTestFinalizeL") ) ); 
+    TRAPD( fres, iTestModule->OOMTestFinalizeL( 
+                                    ModuleContainer().OperationName(), 
+                                    aTestCaseNumber ); );
+    // Check the result
+    if( fres != KErrNone )
+        {
+        __TRACEI ( KInit, ( _L("OOMTestFinalizeL execution failed with error %d"), fres ) );                            
+        }
+                
+    return r;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: LeakChecksForTestCase
+
+    Description: Checks test case for memory, handle and request leaks
+
+    Parameters: None    
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::LeakChecksForTestCase( TBool aReturnLeakCheckFail,
+                                                  TInt aThreadHandleCountBeforeTest,
+                                                  TInt aThreadHandleCountAfterTest,
+                                                  TInt aRequestCountBeforeTest, 
+                                                  TInt aRequestCountAfterTest )
+                                                
+    {      
+    __TRACEI ( KInit, ( _L("CTestThreadContainer::LeakChecksForTestCase") ) );                          
+
+    // Note: Request leaks detection is disabled in UI components testing
+    if( !( iCheckResourceFlags & CTestModuleIf::ETestLeaksRequests ) && 
+             ( aRequestCountBeforeTest != aRequestCountAfterTest ) &&
+             ( !( iModuleContainer->GetTestModule()->GetTestServer()->IsUiTestingSupported() 
+                     && iModuleContainer->GetTestModule()->UiTesting() )))
+        {
+        // Test is failed, because it should end to panic or exception.
+        __TRACEI ( KError, ( CStifLogger::ERed, 
+            _L("Asynchronous request leak from test module. Request count before:[%d] and after:[%d] test."),
+            aRequestCountBeforeTest, aRequestCountAfterTest ) );
+            
+        // Set failure status    
+        TestExecution().TestThreadFailure() |= CTestExecution::ETestRequestLeak;
+        if( aReturnLeakCheckFail )
+            {
+            aReturnLeakCheckFail = EFalse;   // return first fail   
+#ifndef STIF_DISABLE_LEAK_CHECK 
+            // Testcase set to failed when request leak occurred
+            TestExecution().FullResult().iTestResult.iResult = KErrGeneral;
+#endif
+            TestExecution().FullResult().iTestResult.iResultDes = 
+                _L("Asynchronous request leak from testmodule");
+            TestExecution().FullResult().iTestResult.iResultDes.
+                AppendNum( aRequestCountAfterTest );
+            }
+        }
+    // Note: Handle leaks detection is disabled in UI components testing
+    if( !( iCheckResourceFlags & CTestModuleIf::ETestLeaksHandles ) && 
+             ( aThreadHandleCountBeforeTest != aThreadHandleCountAfterTest ) &&
+             ( !( iModuleContainer->GetTestModule()->GetTestServer()->IsUiTestingSupported() 
+                     && iModuleContainer->GetTestModule()->UiTesting() )) )
+        {
+        // Test is failed, because it should end to panic or exception.
+        __TRACEI ( KError, ( CStifLogger::ERed, 
+            _L("Thread handle leak from test module. Handle count before:[%d] and after:[%d] test."),
+            aThreadHandleCountBeforeTest, aThreadHandleCountAfterTest ) ); 
+            
+        // Set failure status
+        TestExecution().TestThreadFailure() |= CTestExecution::ETestHandleLeak;    
+        if( aReturnLeakCheckFail )
+            {
+            aReturnLeakCheckFail = EFalse;   // return first fail   
+#ifndef STIF_DISABLE_LEAK_CHECK 
+            // Testcase is set to failed yet when handle leak occurred
+            TestExecution().FullResult().iTestResult.iResult = KErrGeneral;
+#endif
+            TestExecution().FullResult().iTestResult.iResultDes = 
+                _L("Thread handle leak from testmodule");
+            TestExecution().FullResult().iTestResult.iResultDes.
+                AppendNum( aRequestCountAfterTest );
+            }
+        }       
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: DeleteTestModule
+
+    Description: Deletes a test module
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::DeleteTestModule()
+    {
+
+    __TRACEI ( KInit, ( _L("Deleting test module instance at 0x%x"), iTestModule ) );
+    // Delete the test module
+    ModuleContainer().OperationText() = _L("DESTRUCTOR");
+    TRAPD( r, delete iTestModule );
+    ModuleContainer().OperationText() = _L("");
+    iTestModule = NULL;
+
+    if ( r )
+        {
+        __TRACEI ( KError, ( _L("Leave when deleting test module, code %d"), r ) );
+        }
+
+    __TRACEI ( KInit, ( _L("Test module instance deleted") ) );
+
+    }
+    
+    /*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: TestCases
+
+    Description: Returns constant pointer to test case array
+
+    Parameters: None
+    
+    Return Values: const RPointerArray<TTestCaseInfo>*  Test cases
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+const RPointerArray<TTestCaseInfo>* CTestThreadContainer::TestCases() const
+    {
+    
+    return iCases;
+
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: ErrorPrint
+
+    Description: Prints error
+
+    Parameters: const TInt aPriority :in: Priority
+                TPtrC aError: in: Error
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::ErrorPrint( const TInt aPriority, 
+                                       TPtrC aError )
+    {
+    
+    // Get access to print stuff
+    iErrorPrintSem.Wait();
+    
+    // Get status variable from server
+    TRequestStatus* status = 
+        ModuleContainer().GetRequest( CTestModuleContainer::ERqErrorPrint );
+    
+    if( status == NULL )
+        {
+        Panic( ENullRequest );
+        return;
+        }
+    
+    // Fill in progress
+    TErrorNotification& progress = ModuleContainer().ErrorNotification();
+    progress.iPriority = aPriority;
+    progress.iText = aError;
+    
+    // Complete action to server
+    iServerThread.RequestComplete( status, KErrNone );
+    
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: DoNotifyPrint
+
+    Description: If print notification available, notification is copied to
+                    client memory space and request is completed.
+                 Else new print queue item is created and appended to print 
+                    queue. If queue is full or memory can't be allocated,
+                    then message will be discarded.
+        
+    Parameters: const TInt aPriority  :       :in:  Priority
+                const TStifInfoName& aDes         :in:  Description
+                const TName& aBuffer          :in:  Value
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::DoNotifyPrint( const TInt aPriority,
+                                    const TStifInfoName& aDes,
+                                    const TName& aBuffer )
+    {    
+    // Get access to print stuff
+    iPrintSem.Wait();
+    
+    iPrintMutex.Wait(); // Take mutex to get access to server thread.
+                        // Between Wait and Signal is critical section and this
+                        // verifies that iPrintSem and RequestComplete is done
+                        // successfully.
+    
+    // Get status variable from server
+    TRequestStatus* status = 
+        TestExecution().GetRq( CTestExecution::ERqPrint );
+    
+    if( status == NULL )
+        {
+        iPrintMutex.Signal();
+        Panic( ENullRequest );
+        return;
+        }
+
+    if( *status != KRequestPending )
+        {
+        // CPrintHandler::DoCancel called before getting here, just return
+        iPrintMutex.Signal();
+        return;    
+        }
+    // Fill in progress
+    TTestProgress& progress = TestExecution().TestProgress();
+    progress.iPosition = aPriority;
+    progress.iDescription = aDes;
+    progress.iText = aBuffer;
+    
+    // Complete action to server
+    iServerThread.RequestComplete( status, KErrNone );
+
+    iPrintMutex.Signal();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: DoNotifyEvent
+
+    Description: Forward event request.
+        
+    Parameters: const TEventIf: in: Event definition
+                TRequestStatus* aStatus: in: TRequestStatus to complete 
+    
+    Return Values: None
+
+    Errors/Exceptions: Panics if event array can't be created
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::DoNotifyEvent( TEventIf& aEvent, 
+                                          TRequestStatus* aStatus )
+    {
+    RDebug::Print(_L("STF [ES]: CTestThreadContainer::DoNotifyEvent() aStatus=[%x]"), aStatus);
+
+    REventSystem es;
+    TInt ret = KErrNone;
+
+    // Handle all events right here (except for asynchronous wait, which
+    // must be handled on server side.
+    // Asynchronous wait    
+    if(aEvent.Type() == TEventIf::EWaitEvent && aStatus)
+        {
+        RDebug::Print(_L("STF [ES]: CTestThreadContainer::DoNotifyEvent() handling asynchronous wait"));
+        SetEventReq(TEventDef::EEventCmd, aEvent, aStatus);
+        //return KErrNotSupported; // to be forwarded to Server and handled there
+        }
+    // Synchronous wait
+    else if(aEvent.Type() == TEventIf::EWaitEvent)
+        {
+        RDebug::Print(_L("STF [ES]: CTestThreadContainer::DoNotifyEvent() handling wait event"));
+        TRAP(ret, es.WaitEventL(aEvent.Name(), reinterpret_cast<TInt>(iModuleContainer->TestExecution())));
+        }
+    // Set indication
+    else if(aEvent.Type() == TEventIf::ESetEvent && aEvent.EventType() == TEventIf::EIndication)
+        {
+        RDebug::Print(_L("STF [ES]: CTestThreadContainer::DoNotifyEvent() handling set indication event"));
+        TRAP(ret, es.SetIndicationEventL(aEvent.Name(), aStatus));
+        }
+    // Set state
+    else if(aEvent.Type() == TEventIf::ESetEvent && aEvent.EventType() == TEventIf::EState)
+        {
+        RDebug::Print(_L("STF [ES]: CTestThreadContainer::DoNotifyEvent() handling set state event"));
+        TRAP(ret, es.SetEventL(aEvent.Name(), aStatus));
+        }
+    // Unset state
+    else if(aEvent.Type() == TEventIf::EUnsetEvent)
+        {
+        RDebug::Print(_L("STF [ES]: CTestThreadContainer::DoNotifyEvent() handling unset event"));
+        TRAP(ret, es.UnsetEventL(aEvent.Name(), aStatus));
+        }
+    // Request
+    else if(aEvent.Type() == TEventIf::EReqEvent)
+        {
+        RDebug::Print(_L("STF [ES]: CTestThreadContainer::DoNotifyEvent() handling request event"));
+        TRAP(ret, es.RequestEventL(aEvent.Name(), reinterpret_cast<TInt>(iModuleContainer->TestExecution())));
+        }
+    // Release
+    else if(aEvent.Type() == TEventIf::ERelEvent)
+        {
+        RDebug::Print(_L("STF [ES]: CTestThreadContainer::DoNotifyEvent() handling release event"));
+        TRAP(ret, es.ReleaseEventL(aEvent.Name(), reinterpret_cast<TInt>(iModuleContainer->TestExecution())));
+        }
+    // Unknown
+    else
+        {
+        RDebug::Print(_L("STF [ES]: CTestThreadContainer::DoNotifyEvent() Unknown event type [%d] [%d]"), aEvent.Type(), aEvent.EventType());
+        ret = KErrNotSupported;
+        }
+
+    return ret;
+    
+    /* - old implementation    
+    TInt ret = KErrNone;
+    
+    // Send event req
+    SetEventReq( TEventDef::EEventCmd, aEvent, aStatus );
+    
+    if( aStatus == NULL )
+        {
+        // Synchronous Event command used ->
+        // Block until completed with ECmdComplete from NotifyEvent
+        // Cannot be done before ERelEvent, 
+        // because Unset may be blocking the server  
+        User::WaitForRequest( iReqStatus ); 
+        
+        User::After( 1 );// workaround found for STIF 347 
+        
+        // Return result from engine 
+        ret = iReqStatus.Int();
+        
+        }    
+    
+    return ret;
+    */
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: CancelEvent
+
+    Description: Cancels pending event request.
+        
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+    
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::CancelEvent( TEventIf& aEvent, 
+                                        TRequestStatus* aStatus )
+    {
+    RDebug::Print(_L("STF [ES]: CTestThreadContainer::CancelEvent()"));
+
+    __TRACEI( KMessage, ( _L( "CTestThreadContainer::CancelEvent(%d): %S [%p]" ), 
+            aEvent.Type(), &aEvent.Name(), aStatus ) );
+            
+    // Send event req
+    SetEventReq( TEventDef::EEventCmdCancel, aEvent, aStatus );
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: SetExitReason
+
+    Description: Set exit reason
+        
+    Parameters: const TExitReason aExitReason in: Exit reason
+                const TInt aExitCode in: Exit code
+
+    Return Values: None
+    
+    Errors/Exceptions: None
+
+    
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::SetExitReason( const CTestModuleIf::TExitReason aExitReason, 
+                                    const TInt aExitCode )
+    {
+    
+    TInt exitCode = aExitCode;
+    
+    if( ( aExitReason == CTestModuleIf::ENormal ) &&
+        ( aExitCode != KErrNone ) )
+        {
+        __TRACEI( KError, 
+            ( _L( "SetExitReason: Exit type normal uses always exit code 0 (given %d is not used)" ), 
+                exitCode ) );
+        exitCode = KErrNone;
+        }
+
+    ModuleContainer().AllowedExitReason() = aExitReason;
+    ModuleContainer().AllowedExitCode() = exitCode;              
+        
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: SetBehavior
+
+    Description: Set test behaviour.
+        
+    Parameters:  const CTestModuleIf::TTestBehavior aType: in: behaviour type 
+                 TAny* aPtr: in: data
+
+    Return Values: Symbian OS error code.
+    
+    Errors/Exceptions: None
+    
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::SetBehavior( const CTestModuleIf::TTestBehavior aType, 
+                                        TAny* /*aPtr*/ )
+    {
+    
+    if( aType & CTestModuleIf::ETestLeaksMem )
+        {
+        iCheckResourceFlags |= CTestModuleIf::ETestLeaksMem;
+        }
+    if( aType & CTestModuleIf::ETestLeaksRequests )
+        {
+        iCheckResourceFlags |= CTestModuleIf::ETestLeaksRequests;
+        } 
+    if( aType & CTestModuleIf::ETestLeaksHandles )
+        {
+        iCheckResourceFlags |= CTestModuleIf::ETestLeaksHandles;
+        }
+    // For OOM testing
+    if( aType & CTestModuleIf::EOOMDisableLeakChecks )
+        {
+        iCheckResourceFlags |= CTestModuleIf::EOOMDisableLeakChecks;
+        }                
+    if( !( aType & iCheckResourceFlags ) )
+        {
+        return KErrNotFound;
+        }
+        
+    return KErrNone;
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: ExitReason
+
+    Description: Gets exit reason
+        
+    Parameters: TExitReason& aExitReason out: Exit reason
+                TInt& aExitCode out: Exit code
+
+    Return Values: None
+    
+    Errors/Exceptions: None
+    
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::ExitReason( CTestModuleIf::TExitReason& aExitReason, 
+                                   TInt& aExitCode )
+    {
+
+    aExitReason = ModuleContainer().AllowedExitReason();
+    aExitCode = ModuleContainer().AllowedExitCode();
+          
+        
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: SetEventReq 
+
+    Description: Sets asynchronous event request.
+        
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+    
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::SetEventReq( TEventDef::TEventCmdType aType, 
+                                        TEventIf& aEvent, 
+                                        TRequestStatus* aStatus )
+    {
+    RDebug::Print(_L("STF [ES]: CTestThreadContainer::SetEventReq()"));
+    // Get access to event stuff
+    iEventSem.Wait();
+
+    iEventMutex.Wait(); // Take mutex to get access to server thread.
+                        // Between Wait and Signal is critical section and this
+                        // verifies that iPrintSem and RequestComplete is done
+                        // successfully.
+    
+    // Get status variable from server
+    TRequestStatus* status = 
+        TestExecution().GetRq( CTestExecution::ERqEvent );
+    
+    if( status == NULL )
+        {
+        iEventMutex.Signal();
+        Panic( ENullRequest );
+        return;
+        }
+    if( *status != KRequestPending )
+        {
+        // CEventHandler::DoCancel called before getting here, just return
+        iEventMutex.Signal();
+        return;    
+        }
+    
+    // Fill in event on server thread
+    TEventDef& event = TestExecution().EventDef();
+    event.iType = aType;
+    event.iEvent.Copy( aEvent );
+
+    if( aStatus )
+        {
+        // Store TRequestStatus which is completed when next EEnable comes in
+        event.iStatus = aStatus;
+        } 
+    else
+        {
+        iReqStatus = KRequestPending;
+        event.iStatus = &iReqStatus;
+        }   
+
+    __TRACEI( KMessage ,(_L("SetReq Stat %d, %x"), this, aStatus ));
+    
+    // Complete action to server
+    iServerThread.RequestComplete( status, KErrNone );
+    
+    iEventMutex.Signal();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: DoRemoteReceive
+
+    Description: Enable remote receive and send.
+    
+    Parameters: 
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::DoRemoteReceive( TStifCommand aRemoteCommand,
+                                            TParams aParams,
+                                            TInt aLen,
+                                            TRequestStatus& aStatus )
+    {    
+    
+    switch( aRemoteCommand )
+        {
+        case EStifCmdSend:             // "Send"
+        case EStifCmdReboot:           // "Send"
+        case EStifCmdStoreState:       // "Send"
+        case EStifCmdGetStoredState:   // "Receive, this must be done with two phase"
+        case EStifCmdMeasurement:      // "Receive"
+            {
+            __TRACEI( KMessage, ( _L( "CTestThreadContainer::DoRemoteReceive Wait SndSem" ) ) );
+            
+            // Get access to sender 
+            // (for receive, used for securing access to shared memory)
+            iSndSem.Wait();
+
+            iSndMutex.Wait();   // Take mutex to get access to server thread.
+                                // Between Wait and Signal is critical section and this
+                                // verifies that iPrintSem and RequestComplete is done
+                                // successfully.
+
+            // Get status variable from server
+            TRequestStatus* status = 
+                TestExecution().GetRq( CTestExecution::ERqSnd );
+
+            if( status == NULL )
+                {
+                iSndMutex.Signal();
+                Panic( ENullRequest );
+                return;
+                }
+            if( *status != KRequestPending )
+                {
+                // CSndHandler::DoCancel called before getting here, just return
+                iSndMutex.Signal();
+                return;    
+                }                
+
+            // Fill in information
+            TCmdDef& aDef = TestExecution().SndInfo();
+            aDef.iCommand = aRemoteCommand;
+            aDef.iParam = aParams;
+            aDef.iLen = aLen;
+            aDef.iStatus = &aStatus;
+            
+            __TRACEI( KMessage ,
+                (_L("CTestThreadContainer::DoRemoteReceive Complete request 0x%x"),
+                    status ));
+            // Complete action to server
+            iServerThread.RequestComplete( status, KErrNone );  
+
+            iSndMutex.Signal();
+            }
+            break;
+        case EStifCmdReceive:          // "Receive"
+             {
+            __TRACEI( KMessage, ( _L( "CTestThreadContainer::DoRemoteReceive Wait RcvSem" ) ) );
+
+            // Get access to receive handler 
+            iRcvSem.Wait();
+
+            iRcvMutex.Wait();   // Take mutex to get access to server thread.
+                                // Between Wait and Signal is critical section and this
+                                // verifies that iPrintSem and RequestComplete is done
+                                // successfully.
+
+            // Get status variable from server
+            TRequestStatus* status = 
+                TestExecution().GetRq( CTestExecution::ERqRcv );
+
+            if( status == NULL )
+                {
+                iRcvMutex.Signal();
+                Panic( ENullRequest );
+                return;
+                }
+            if( *status != KRequestPending )
+                {
+                // CRcvHandler::DoCancel called before getting here, just return
+                iRcvMutex.Signal();
+                return;    
+                }                
+
+            // Fill in information
+            TCmdDef& aDef = TestExecution().RcvInfo();
+            aDef.iCommand = aRemoteCommand;
+            aDef.iParam = aParams;
+            aDef.iLen = aLen;
+            aDef.iStatus = &aStatus;
+            
+            __TRACEI( KMessage ,
+                (_L("CTestThreadContainer::DoRemoteReceive Complete request 0x%x"),
+                    status ));
+            __TRACEI( KMessage, ( _L( "CTestThreadContainer::DoRemoteReceive signal RcvSem" ) ) );
+            //iReceiverSem.Signal();
+
+            // Complete action to server
+            iServerThread.RequestComplete( status, KErrNone );  
+
+            iRcvMutex.Signal();
+            
+            }
+            break;
+
+        default:
+            TRequestStatus* rs = &aStatus;
+            User::RequestComplete( rs, KErrNotSupported );
+            break;
+        }
+        
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: DoRemoteReceiveCancel
+
+    Description: Cancel DoRemoteReceive
+    
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::DoRemoteReceiveCancel()
+    {   
+           
+    // Get access to receive handler
+    iRcvSem.Wait();
+
+    iRcvMutex.Wait();   // Take mutex to get access to server thread.
+                        // Between Wait and Signal is critical section and this
+                        // verifies that iPrintSem and RequestComplete is done
+                        // successfully. 
+
+    // Get status variable from server
+    TRequestStatus* status = 
+        TestExecution().GetRq( CTestExecution::ERqRcv );
+
+    if( status == NULL )
+        {
+        iRcvMutex.Signal();
+        return KErrNotFound;
+        }
+        
+    if( *status != KRequestPending )
+        {
+        // CRcvHandler::DoCancel called before getting here, just return
+        iRcvMutex.Signal();
+        Panic( ENullRequest );
+        return KErrNone;    
+        }        
+
+    // Fill in information
+    TCmdDef& aDef = TestExecution().RcvInfo();
+    aDef.iCommand = EStifCmdReceiveCancel;
+    // Complete action to server
+    iServerThread.RequestComplete( status, KErrNone );  
+    
+    iRcvMutex.Signal();
+
+    return KErrNone;
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: TestComplete
+
+    Description: Complete test operation: Get test case, run test case,
+                 complete test case, etc.
+        
+    Parameters: TInt aCompletionCode: in: completion code.
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::TestComplete( TInt aCompletionCode )
+    {    
+    
+    // Get status variable from server
+    TRequestStatus* status = 
+        ModuleContainer().GetRequest( CTestModuleContainer::ERqTestCase );
+    
+    if( status == NULL )
+        {
+        Panic( ENullRequest );
+        return;
+        }
+        
+    // Complete action to server
+    if( iTestThreadMutex.Handle() == 0 )
+        {
+        // Actual test case is not started yet. Inititialization phase is ongoing.
+        // Before the completion check if the status was not already completed
+        // from other thread in CTestModuleContainer::DoCancel().
+        // For details see Jira STIF-564
+        if(*status == KRequestPending)
+            iServerThread.RequestComplete( status, aCompletionCode );
+        }
+    else
+        {
+        // Test case execution is started. Test is ongoing.
+        // Before the completion check if the status was not already completed
+        // from other thread in CTestModuleContainer::DoCancel().
+        // For details see Jira STIF-564
+        if(*status == KRequestPending)
+            {
+            iTestThreadMutex.Wait(); // Block that complete and cancel do not
+                                     // executed at the same time.
+            iServerThread.RequestComplete( status, aCompletionCode );
+            iTestThreadMutex.Signal();
+            }            
+        }
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: UIExecutionThread
+
+    Description: This is the test module execution thread "main" function".
+    All test module function calls are executed in context of this execution
+    thread.
+
+    When the thread is resumed first time, function goes to wait a semaphore.
+    Operations are initiated by setting operation and signaling the semaphore.
+    If operation is synchronous, then end of operation is signaled by using
+    OperationCompleted -Semaphore. When operation is done, function (and thread)
+    are going to wait OperationSemaphore.
+
+    Function exist either when operation does fatal error, or operation type
+    is "Exit". The thread function exist from it's main loop and the thread
+    will be terminated.
+
+    Parameters: TAny* aParams:                :in:  Pointer to CTestModuleContainer
+    
+    Return Values: TInt                        KErrNone
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::UIExecutionThread( TAny* aParams )
+	{
+	
+    CTestModuleContainer* moduleContainer = 
+    	(CTestModuleContainer*) aParams;
+    
+    CTestModule* module = moduleContainer->GetTestModule();
+    CTestServer* testServer = module->GetTestServer();
+    CTestThreadContainerRunnerFactory* factory = testServer->GetTestThreadContainerRunnerFactory();    
+    
+    RThread server;
+    // Duplicate handles from server thread
+    TInt ret = server.Open( moduleContainer->ServerThreadId() );
+    if( ret != KErrNone )
+    	{
+    	Panic( EThreadHandleOpenFail );
+    	}
+    RSemaphore OperationStartSemaphore;
+    OperationStartSemaphore.SetHandle( 
+    		moduleContainer->OperationStartSemHandle() );
+    if( OperationStartSemaphore.Duplicate( server ) != KErrNone )
+        {
+        Panic( EDuplicateFail );
+        }        
+    RSemaphore OperationChangeSemaphore;
+    OperationChangeSemaphore.SetHandle( 
+    		moduleContainer->OperationChangeSemHandle() );
+    if( OperationChangeSemaphore.Duplicate( server ) != KErrNone )
+        {
+        Panic( EDuplicateFail );
+        }
+    server.Close();
+    
+    CTestThreadContainerRunner* runner = factory->CreateL();
+    
+    runner->Setup( moduleContainer );
+    
+    while ( runner->IsReusable() )
+        {
+        // Thread is going to suspend        
+        runner->CheckSignalFromSuspend();
+        
+        // Wait next operation
+        OperationStartSemaphore.Wait();
+
+        // Get operation semaphore
+        OperationChangeSemaphore.Wait();    
+    
+        // Run and wait active object
+        runner->RunOneIteration();
+        
+        OperationChangeSemaphore.Signal();        
+        }
+        
+    OperationStartSemaphore.Close();
+    OperationChangeSemaphore.Close();        
+        
+    runner->TeareDown();
+    
+    runner->Deque();
+    
+    factory->DeleteL( runner );    
+    
+    return KErrNone;    
+	}
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: ExecutionThread
+
+    Description: This is the test module execution thread "main" function".
+    All test module function calls are executed in context of this execution
+    thread.
+
+    When the thread is resumed first time, function goes to wait a semaphore.
+    Operations are initiated by setting operation and signaling the semaphore.
+    If operation is synchronous, then end of operation is signaled by using
+    OperationCompleted -Semaphore. When operation is done, function (and thread)
+    are going to wait OperationSemaphore.
+
+    Function exist either when operation does fatal error, or operation type
+    is "Exit". The thread function exist from it's main loop and the thread
+    will be terminated.
+
+    Parameters: TAny* aParams:                :in:  Pointer to CTestModuleContainer
+    
+    Return Values: TInt                        KErrNone
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::ExecutionThread( TAny* aParams )
+    {
+    TInt error( KErrNone );
+    
+    const TUint32 KAll = 0xFFFFFFFF;
+#ifndef __HIDE_IPC_V1__ // e.g. 7.0s, 8.0a
+    RThread currentThread;
+    currentThread.SetExceptionHandler( ExceptionHandler, KAll );
+#else // PlatSec used. Thread exception management is part of the User class.
+    User::SetExceptionHandler( ExceptionHandler, KAll );
+#endif // __HIDE_IPC_V1__
+
+     // Check parameters
+    __ASSERT_ALWAYS( aParams, Panic( EInvalidCTestThreadContainer ) );
+
+    CTestModuleContainer* moduleContainer = 
+        (CTestModuleContainer*) aParams;
+       
+    // Create cleanup stack
+    CTrapCleanup* tc = CTrapCleanup::New();
+    __ASSERT_ALWAYS( tc, Panic( ECreateTrapCleanup ) );
+
+    CTestThreadContainer* exec = NULL;    
+    TRAPD( err,
+        exec = CTestThreadContainer::NewL( moduleContainer, 
+                                           moduleContainer->ServerThreadId() );
+        );    
+    if( err != KErrNone )
+        {
+        Panic( ENullTestThreadContainer );
+        }
+
+    // Construct the logger
+    TName path = _L("C:\\logs\\testframework\\testserver\\");
+    TFileName name = _L("testserver_thread_");  
+    name.Append( moduleContainer->TestModuleName() );
+
+    // Create logger, in Wins use HTML in HW default logger
+    TLoggerSettings loggerSettings;
+
+    // Directory must create by hand if test server log wanted
+    loggerSettings.iCreateLogDirectories = EFalse;
+
+    loggerSettings.iOverwrite = ETrue;
+    loggerSettings.iTimeStamp = ETrue;
+    loggerSettings.iLineBreak = ETrue;
+    loggerSettings.iEventRanking = EFalse;
+    loggerSettings.iThreadId = EFalse;
+    loggerSettings.iHardwareFormat = CStifLogger::ETxt;
+#ifndef FORCE_STIF_INTERNAL_LOGGING_TO_RDEBUG
+    loggerSettings.iEmulatorFormat = CStifLogger::EHtml;
+    loggerSettings.iHardwareOutput = CStifLogger::EFile;
+    loggerSettings.iEmulatorOutput = CStifLogger::EFile;
+#else
+    RDebug::Print( _L( "STIF Test Server's thread logging forced to RDebug" ) );
+    loggerSettings.iEmulatorFormat = CStifLogger::ETxt;
+    loggerSettings.iHardwareOutput = CStifLogger::ERDebug;
+    loggerSettings.iEmulatorOutput = CStifLogger::ERDebug;
+#endif
+    loggerSettings.iUnicode = EFalse;
+    loggerSettings.iAddTestCaseTitle = EFalse;
+
+    TRAP ( error, exec->iThreadLogger = CStifLogger::NewL( path, name,
+                                                            loggerSettings ) );
+
+    RLibrary module;                    // Handle to test module library
+    TBool reusable = ETrue;             // Is test module reusable?
+    TBool initialized = EFalse;         // Is module initialized?
+    TBool signalFromSuspend = EFalse;   // Send signal from suspend state?
+
+    RThread server;
+    // Duplicate handles from server thread
+    TInt ret = server.Open( moduleContainer->ServerThreadId() );
+    if( ret != KErrNone )
+    	{
+    	Panic( EThreadHandleOpenFail );
+    	}
+    RSemaphore OperationStartSemaphore;
+    OperationStartSemaphore.SetHandle( 
+        exec->ModuleContainer().OperationStartSemHandle() );
+    if( OperationStartSemaphore.Duplicate( server ) != KErrNone )
+        {
+        Panic( EDuplicateFail );
+        }        
+    RSemaphore OperationChangeSemaphore;
+    OperationChangeSemaphore.SetHandle( 
+        exec->ModuleContainer().OperationChangeSemHandle() );
+    if( OperationChangeSemaphore.Duplicate( server ) != KErrNone )
+        {
+        Panic( EDuplicateFail );
+        }
+    server.Close();
+   
+    
+    ret = KErrNone;
+
+    // The test module thread will stay in this loop until it either
+    // dies or is exited nicely.
+    while ( reusable )
+        {
+        // Thread is going to suspend
+        
+        if ( signalFromSuspend )
+            {
+            signalFromSuspend = EFalse;
+            exec->TestComplete( ret );
+            }
+        ret = KErrNone;
+        
+        // Wait next operation
+        OperationStartSemaphore.Wait();
+
+        // Get operation semaphore
+        OperationChangeSemaphore.Wait();
+        switch ( moduleContainer->OperationType() )
+            {
+
+            // Test module initialisation
+            case CTestModuleContainer::EInitializeModule:
+                {
+                __ASSERT_ALWAYS ( !initialized,
+                                  Panic( EReInitializingTestModule ) );
+
+                // Initialize module
+                if ( exec->InitializeModuleInThread( module ) == KErrNone )
+                    {
+                    initialized = ETrue;
+                    }
+
+                signalFromSuspend = ETrue;
+                break;
+                }
+
+            // Test case enumeration
+            case CTestModuleContainer::EEnumerateInThread:
+                {
+                __ASSERT_ALWAYS ( initialized,
+                                  Panic( ETestModuleNotInitialized ) );
+                ret = exec->EnumerateInThread();
+
+                signalFromSuspend = ETrue;
+                break;
+                }
+
+            // Free test case enumeration data
+            case CTestModuleContainer::EFreeEnumerationData:
+                {
+                __ASSERT_ALWAYS ( initialized,
+                                  Panic( ETestModuleNotInitialized ) );
+                exec->FreeEnumerationDataInThread ();
+                
+                signalFromSuspend = ETrue;
+                break;
+                }
+
+            // Execute test case
+            case CTestModuleContainer::EExecuteTestInThread:
+                {
+                __ASSERT_ALWAYS ( initialized,
+                                  Panic( ETestModuleNotInitialized ) );
+                ret = exec->ExecuteTestCaseInThread ();
+
+                signalFromSuspend = ETrue;
+                break;
+                }
+
+            // Exiting (i.e test server is unloading)
+            case CTestModuleContainer::EExit:
+                {
+                reusable = EFalse;
+                break;
+                }
+
+            // Illegal state
+            default:
+                {
+                Panic( EInvalidTestModuleOperation );
+                }
+            }
+            OperationChangeSemaphore.Signal();
+        
+        }
+        
+    OperationStartSemaphore.Close();
+    OperationChangeSemaphore.Close();
+
+    exec->DeleteTestModule();
+
+    // Close handle to module. No function calls to test
+    // module are possible after this line.
+    module.Close();
+
+    // Delete logger    
+    delete exec->iThreadLogger;
+    exec->iThreadLogger = NULL;
+
+    // Delete clean-up stack.
+    delete tc;
+    tc = NULL;
+
+    // Operation completed ( = Exit completed )
+    exec->TestComplete( KErrNone );
+    
+    delete exec;
+    
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: Panic
+
+    Description: Panicing function for test thread.
+
+    Parameters: TPanicReason aReason: in: Reason code
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::Panic( TPanicReason aReason )
+    {
+    
+    RDebug::Print( _L("CTestThreadContainer::Panic %d"), aReason );
+    
+    User::Panic( _L("CTestThreadContainer::Panic"), aReason );
+    
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: ServerAlive
+
+    Description: Check that server is alive.
+
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: Panics thread if server has died.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::IsServerAlive()
+    {
+        
+    if( iServerThread.ExitType() != EExitPending ) 
+        {
+        // Server thread has died
+        __RDEBUG( ( _L( "Server died" ) ) );
+        Panic( EServerDied );
+        }
+        
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: TestExecution
+
+    Description: Return CTestExecution handle to "parent" i.e. server.
+
+    Parameters: None
+    
+    Return Values: CTestExecution&
+
+    Errors/Exceptions: Panics thread if server has died.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestExecution& CTestThreadContainer::TestExecution()
+    { 
+    
+    IsServerAlive();
+    CTestExecution* execution = iModuleContainer->TestExecution();
+    if( execution == NULL )
+        {
+        Panic( ENullExecution );
+        }
+    return *execution;
+    
+    };
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: TestExecution
+
+    Description: Return CTestExecution handle to "parent" i.e. server.
+
+    Parameters: None
+    
+    Return Values: CTestExecution&
+
+    Errors/Exceptions: Panics thread if server has died.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestModuleContainer& CTestThreadContainer::ModuleContainer()
+    { 
+    
+    IsServerAlive();
+    return *iModuleContainer; 
+    
+    };
+ 
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: ExceptionHandler
+
+    Description: Test execution thread exception handler
+
+    Just kill thread. Undertaker handles rest.
+
+    Parameters: TExcType: in: Exception type
+    
+    Return Values: None
+
+    Errors/Exceptions: This function kills the thread where it is executed in.
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::ExceptionHandler ( TExcType aType )
+    {
+
+    // Kill the current thread, undertaker handles rest
+    RThread current;
+    current.Kill( aType );
+
+    // This line is never executed, because thread has been killed.
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: StifMacroErrorInit
+
+    Description: STIF TF's macro. Initialized TTestMacro.
+
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::StifMacroErrorInit()
+    {
+    iTestMacroInfo.iIndication = EFalse;
+    iTestMacroInfo.iFileDes = KNullDesC;
+    iTestMacroInfo.iFunctionDes = KNullDesC;
+    iTestMacroInfo.iLine = 0;
+    iTestMacroInfo.iReceivedError = 0;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: StifMacroError
+
+    Description: STIF TF's macros. Saves information for later use.
+
+    Parameters: TInt aMacroType: in: Macro type(0:TL, 1:T1L, 2:T2L, etc.)
+                TDesC& aFile: in: Modified file information.
+                TDesC& aFunction: in: Modified function information.
+                TInt aLine: in: Line information.
+                TInt aResult: in: Received result.
+                TInt aExpected1: in: Expected result from user.
+                TInt aExpected2: in: Expected result from user.
+                TInt aExpected3: in: Expected result from user.
+                TInt aExpected4: in: Expected result from user.
+                TInt aExpected5: in: Expected result from user.
+    
+    Return Values: Symbian OS error code
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::StifMacroError( TInt aMacroType,
+                                           const TText8* aFile,
+                                           const char* aFunction,
+                                           TInt aLine,
+                                           TInt aResult,
+                                           TInt aExpected1,
+                                           TInt aExpected2,
+                                           TInt aExpected3,
+                                           TInt aExpected4,
+                                           TInt aExpected5 )
+    {
+    TStifMacroDes file;
+    TStifMacroDes function;
+
+    // Modifies aFile and aFunction lengths if nesessarily.
+    // File and function maximun length is KStifMacroMax.
+    SetMacroInformation( KStifMacroMax, KStifMacroMax, 
+                            aFile, aFunction, file, function );
+
+    // Log more information to file and rdebug
+    switch( aMacroType )
+        {
+        case 0: // TL macro
+            {
+            __TRACEI( KError, ( CStifLogger::ERed, 
+                _L( "FAIL: STIF TF's macro. FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                &file, &function, aLine ) );
+            RDebug::Print( 
+                _L( "FAIL: STIF TF's macro. FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                &file, &function, aLine );
+            break;
+            }
+       case 1: // T1L macro
+            {
+           __TRACEI( KError, ( CStifLogger::ERed,
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, &file, &function, aLine ) );
+            RDebug::Print( 
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, &file, &function, aLine );
+            break;
+            }
+       case 2: // T2L macro
+            {
+            __TRACEI( KError, ( CStifLogger::ERed,
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, aExpected2, &file, &function, aLine ) );
+            RDebug::Print( 
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, aExpected2, &file, &function, aLine );
+            break;
+            }
+       case 3: // T3L macro
+            {
+            __TRACEI( KError, ( CStifLogger::ERed,
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, aExpected2, aExpected3, &file, &function, aLine ) );
+            RDebug::Print( 
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, aExpected2, aExpected3, &file, &function, aLine );
+            break;
+            }
+       case 4: // T4L macro
+            {
+            __TRACEI( KError, ( CStifLogger::ERed,
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, aExpected2, aExpected3, aExpected4, &file, &function, aLine ) );
+            RDebug::Print( 
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, aExpected2, aExpected3, aExpected4, &file, &function, aLine );
+            break;
+            }
+       case 5: // T5L macro
+            {
+            __TRACEI( KError, ( CStifLogger::ERed,
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, aExpected2, aExpected3, aExpected4, aExpected5, &file, &function, aLine ) );
+            RDebug::Print( 
+                _L( "FAIL: STIF TF's macro. RECEIVED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], EXPECTED[%d], FILE[%S], FUNCTION[%S], LINE[%d]" ),
+                aResult, aExpected1, aExpected2, aExpected3, aExpected4, aExpected5, &file, &function, aLine );
+            break;
+            }
+        default: // default, faulty handling
+            {
+            __TRACEI( KError, ( CStifLogger::EError,
+                _L( "CTestThreadContainer::StifMacroError(): Macro faulty handling(Macro type is incorrect)" ) ) );
+            RDebug::Print( 
+                _L( "ERROR: CTestThreadContainer::StifMacroError(): Macro faulty handling(Macro type is incorrect)" ) );
+            return KErrArgument; // Test case goes to crashed category
+            }        
+        }
+
+    // Modifies aFile and aFunction lengths if nesessarily.
+    // File maximun length is KStifMacroMaxFile.
+    // Function maximun length is KStifMacroMaxFunction.
+    SetMacroInformation( KStifMacroMaxFile, KStifMacroMaxFunction, 
+                            aFile, aFunction, file, function );
+
+    // Set information for later use(this information is
+    // limited and can be seen in UI)
+    iTestMacroInfo.iIndication = ETrue;
+    iTestMacroInfo.iFileDes = file;
+    iTestMacroInfo.iFunctionDes = function;
+    iTestMacroInfo.iLine = aLine;
+    if( aResult == KErrNone )
+        {
+        // aResult is KErrNone. TL macro is used or expected result(s) are/is
+        // negative value(s). Received error code is mapped to KErrArgument
+        // because this is erronous case.
+        iTestMacroInfo.iReceivedError = KErrArgument;
+        }
+    else
+        {
+        iTestMacroInfo.iReceivedError = aResult;
+        }
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: SetMacroInformation
+
+    Description: Modifies aRecFile and aRecFunction lengths if nesessarily.
+
+    Parameters: TInt aMaxLength: in: Maximum length of file information.
+                TInt aMaxLength: in: Maximum length of function information.
+                const TText8* aRecFile: in: Received file information.
+                char* aRecFunction: in: Received function information.
+                TDes& aFile: inout: Modified file.
+                TDes& aFunction: inout: Modified function.
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::SetMacroInformation( TInt aFileMaxLength,
+                                                TInt aFuntionMaxLength,
+                                                const TText8* aRecFile,
+                                                const char* aRecFunction,
+                                                TDes& aFile,
+                                                TDes& aFunction )
+    {
+    // Create 8 to 16
+    TPtrC8 buf_file;
+    buf_file.Set( aRecFile );
+    // File description length is limited. Extracts the rightmost part of the
+    // data.
+    aFile.Copy( buf_file.Right( aFileMaxLength ) );
+    aFile.LowerCase();
+
+    if( aRecFunction )
+        {
+        // Create 8 to 16
+        TPtrC8 buf_func;
+        buf_func.Set( (const unsigned char*)aRecFunction );
+        // Function description length is limited. Extracts the leftmost part
+        // of the data.
+        aFunction.Copy( buf_func.Left( aFuntionMaxLength ) );
+        aFunction.LowerCase();
+        }
+    else
+        {
+        // Function is not given(WINS)
+        aFunction.Copy( _L( "-" ) );
+        }
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: AddInterferenceThread
+
+    Description: With this can be store information about test interference
+                 thread to client space.
+
+    Parameters: RThread aSTIFTestInterference: in: Thread information to store
+
+    Return Values: TInt: Symbian OS error code.
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::AddInterferenceThread( 
+                                RThread aSTIFTestInterference )
+    {
+    // Get access to test interference stuff
+    iInterferenceSem.Wait();
+    
+    iInterferenceMutex.Wait();  // Take mutex to get access to server thread.
+                                // Between Wait and Signal is critical section
+                                // and this verifies that iInterferenceSem and
+                                // RequestComplete is done successfully.
+    
+    // Get status variable from server
+    TRequestStatus* status = 
+        TestExecution().GetRq( CTestExecution::ERqInterference );
+    
+    if( status == NULL )
+        {
+        iInterferenceMutex.Signal();
+        Panic( ENullRequest );
+        return KErrNone;
+        }
+
+    if( *status != KRequestPending )
+        {
+        // CInterferenceHandler::DoCancel called before getting here,
+        // just return
+        iInterferenceMutex.Signal();
+        return KErrNone;    
+        }
+
+    // Add thread to Array. Via array can handle test interference thread's
+    // kill in panic etc. cases
+    TTestInterference& testInterface = TestExecution().TestInterference();
+    testInterface.iThreadId = aSTIFTestInterference.Id();    
+    testInterface.iOperation = TTestInterference::EAppend;
+
+    // Complete action to server
+    iServerThread.RequestComplete( status, KErrNone );
+    // Goes to CInterferenceHandler::RunL()
+
+    iInterferenceMutex.Signal();
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: RemoveInterferenceThread
+
+    Description: With this can be remove information about test interference
+                 thread from client space.
+
+    Parameters:  RThread aSTIFTestInterference: in: Thread information to store
+
+    Return Values: TInt: Symbian OS error code.
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::RemoveInterferenceThread( 
+                                RThread aSTIFTestInterference )
+    {
+    // Get access to test interference stuff
+    iInterferenceSem.Wait();
+    
+    iInterferenceMutex.Wait();  // Take mutex to get access to server thread.
+                                // Between Wait and Signal is critical section
+                                // and this verifies that iInterferenceSem and
+                                // RequestComplete is done successfully.
+    
+    // Get status variable from server
+    TRequestStatus* status = 
+        TestExecution().GetRq( CTestExecution::ERqInterference );
+    
+    if( status == NULL )
+        {
+        iInterferenceMutex.Signal();
+        Panic( ENullRequest );
+        return KErrNone;
+        }
+
+    if( *status != KRequestPending )
+        {
+        // CInterferenceHandler::DoCancel called before getting here, just return
+        iInterferenceMutex.Signal();
+        return KErrNone;    
+        }
+
+    // Add thread to Array. Via array can handle test interference thread's
+    // kill in panic etc. cases
+    TTestInterference& testInterface = TestExecution().TestInterference();
+    testInterface.iThreadId = aSTIFTestInterference.Id();    
+    testInterface.iOperation = TTestInterference::ERemove;
+
+    // Complete action to server
+    iServerThread.RequestComplete( status, KErrNone );
+    // Goes to CInterferenceHandler::RunL()
+
+    iInterferenceMutex.Signal();
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: HandleMeasurementProcess
+
+    Description: With this can be stored information about test measurement
+                 to TestServer space.
+
+    Parameters: CSTIFTestMeasurement::TMeasurement aSTIFMeasurementInfo: in:
+                Struct for measurement information.
+
+    Return Values: TInt: Symbian OS error code.
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestThreadContainer::HandleMeasurementProcess( 
+            CSTIFTestMeasurement::TStifMeasurementStruct aSTIFMeasurementInfo )
+    {
+    // Get access to test measurement stuff
+
+    // This is syncronous operation and other request cannot executed at the
+    // same time. In this case iMeasurementSem is not signaled in StarL().
+    // So iMeasurementSem.Wait(); is not needed in this case.
+
+    iMeasurementMutex.Wait();   // Take mutex to get access to server thread.
+                                // Between Wait and Signal is critical section
+                                // and this verifies that iMeasurementSem and
+                                // RequestComplete is done successfully.
+
+    // Get status variable from server
+    TRequestStatus* status = 
+        TestExecution().GetRq( CTestExecution::ERqMeasurement );
+
+    if( status == NULL )
+        {
+        iMeasurementMutex.Signal();
+        Panic( ENullRequest );
+        return KErrNone;
+        }
+
+    if( *status != KRequestPending )
+        {
+        // CMeasurementHandler::DoCancel called before getting here,
+        // just return
+        iMeasurementMutex.Signal();
+        return KErrNone;
+        }
+
+    TTestMeasurement& testmeasurement = TestExecution().TestMeasurement();
+    testmeasurement.iMeasurementStruct = aSTIFMeasurementInfo;
+
+    // Complete action to server
+    iServerThread.RequestComplete( status, KErrNone );
+    // Goes to CMeasurementHandler::RunL()
+
+    // Make this synchronous and block until needed operations are done.
+    iMeasurementSem.Wait();
+    // This continue here when iMeasurementSem.Signal is said in 
+    // CMeasurementHandler::RunL(). So when measurement operations are done.
+
+    // Error code from measurement related operations
+    TInt ret( testmeasurement.iMeasurementStruct.iOperationResult );
+
+    iMeasurementMutex.Signal();
+
+    return ret;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: SetEventReq
+
+    Description: Sets asynchronous event request.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::DoNotifyCommand(TCommand aCommand, const TDesC8& aParamsPckg)
+    {
+    // Get access to command stuff
+    iCommandSem.Wait();
+
+    iCommandMutex.Wait(); // Take mutex to get access to server thread.
+                          // Between Wait and Signal is critical section and this
+                          // verifies that iCommandSem and RequestComplete is done
+                          // successfully.
+
+    // Get status variable from server
+    TRequestStatus* status = TestExecution().GetRq(CTestExecution::ERqCommand);
+
+    if(status == NULL)
+        {
+        iCommandMutex.Signal();
+        Panic(ENullRequest);
+        return;
+        }
+    if(*status != KRequestPending)
+        {
+        iCommandMutex.Signal();
+        return;
+        }
+
+    // Fill in information
+    CCommandDef& aDef = TestExecution().CommandDef();
+    aDef.iCommand = aCommand;
+    aDef.iParamsPckg.Copy(aParamsPckg);
+
+    // Complete action to server
+    iServerThread.RequestComplete(status, KErrNone);
+
+    iCommandMutex.Signal();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: GetTestCaseTitleL
+
+    Description: Gets title of currently running test.
+
+    Parameters: aTestCaseTitle: OUT: test case title descriptor
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::GetTestCaseTitleL(TDes& aTestCaseTitle)
+    {
+    ModuleContainer().GetTestCaseTitleL(aTestCaseTitle); 
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: SetThreadLogger
+
+    Description: Sets thread logger.
+
+    Parameters: CStifLogger* aThreadLogger: in: Pointer to thread logger.
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestThreadContainer::SetThreadLogger( CStifLogger* aThreadLogger )
+	{
+	
+	iThreadLogger = aThreadLogger;
+	}
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: SetThreadLogger
+
+    Description: Gets thread logger.
+
+    Parameters: None
+
+    Return Values: Pointer to CStifLogger. 
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CStifLogger* CTestThreadContainer::GetThreadLogger()
+	{
+	
+	return iThreadLogger;
+	}
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: UITesting
+
+    Description: Gets information if testserver supports UI testing.
+
+    Parameters: None
+
+    Return Values: True if testserver supports UI testing, False if testserver
+    			   doesn't support UI testing. 
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+EXPORT_C TBool CTestThreadContainer::UITesting()
+	{
+	return iModuleContainer->GetTestModule()->GetTestServer()->IsUiTestingSupported() &&
+            iModuleContainer->GetTestModule()->UiTesting();	
+	}
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestThreadContainer
+
+    Method: GetUiEnvProxy
+
+    Description: Gets UIEnvProxy.
+
+    Parameters: None
+
+    Return Values: Pointer to UIEnvProxy 
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+EXPORT_C CUiEnvProxy* CTestThreadContainer::GetUiEnvProxy()
+	{
+	return iModuleContainer->GetTestModule()->GetTestServer()->GetUiEnvProxy();
+	}
+
+EXPORT_C TBool CTestThreadContainer::SeperateProcesses()
+    {
+    return iModuleContainer->GetTestModule()->SeperateProcesses();
+    }
+
+//  End of File