stif/TestServer/src/TestModuleContainer.cpp
branchRCL_3
changeset 59 8ad140f3dd41
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stif/TestServer/src/TestModuleContainer.cpp	Wed Oct 13 16:17:58 2010 +0300
@@ -0,0 +1,2364 @@
+/*
+* 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 
+* CTestModuleContainer class member functions. CTestModuleContainer 
+* class contains interface * to execute various functions in context 
+* of test execution thread.
+*
+* CTestModuleContainer is the owner of the test execution thread 
+* object and the owner of the test module instance.
+*
+*/
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <e32svr.h>
+#include <e32uid.h>
+#include "TestEngineClient.h"
+#include <StifTestModule.h>
+#include <stifinternal/TestServerClient.h>
+#include "TestServer.h"
+#include "TestServerModuleIf.h"
+#include "TestServerCommon.h"
+#include "PrintQueue.h"
+#include "TestThreadContainer.h"
+//--PYTHON-- begin
+#include "StifPython.h"
+//--PYTHON-- end
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// The test module execution thread function
+TInt ExecutionThread( TAny* aParams );
+
+// CONSTANTS
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+typedef TInt( *CTestInterfaceFactoryTestModule )( CTestModuleParam*&, TUint32& );
+
+// FORWARD DECLARATIONS
+
+// ==================== LOCAL FUNCTIONS =======================================
+
+// ================= MEMBER FUNCTIONS =========================================
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: NewL
+
+    Description: Returns new CTestModuleContainer instance.
+
+    Parameters: const TDesC& aName: in: Module name
+                CTestModule* aSession: in: "Parent"
+                const TDesC& aConfig: in: Test case (config) file name.
+
+    Return Values: CTestModuleContainer* New instance
+
+    Errors/Exceptions: Function leaves if memory allocation fails or
+                       CTestModuleContainer ConstructL leaves.
+                       Panics if aSession is NULL.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestModuleContainer* CTestModuleContainer::NewL( const TDesC& aName,
+                                                  CTestModule* aSession,
+                                                  const TDesC& aConfig )
+    {
+
+    __ASSERT_ALWAYS ( aSession, 
+                      CTestServer::PanicServer( ENullTestModule ) );
+
+    CTestModuleContainer* self = new ( ELeave ) CTestModuleContainer();
+    CleanupStack::PushL( self );
+    self->ConstructL( aName, aSession, aConfig );
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: ConstructL
+
+    Description: Second level constructor.
+
+    Function creates the execution thread, creates exception
+    handler and the thread undertaker for it and then resumes the thread.
+
+    Parameters: const TDesC& aName: in: Module name
+                CTestModule* aSession: in: "Parent"
+                const TDesC& aConfig: in: Test case (config) file name.
+
+    Return Values: CTestModuleContainer* New instance
+
+    Errors/Exceptions: Function leaves if thread creation fails,
+                       memory allocation fails or undertaker creation leaves.
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::ConstructL( const TDesC& aName,
+                                       CTestModule* aSession,
+                                       const TDesC& aConfig )
+    {
+
+    RDebug::Print( aName );
+    
+    iNestedActiveScheduler = new (ELeave) CActiveSchedulerWait;
+    
+    iCTestModule = aSession;
+
+    // Create error print handler
+    iErrorPrintHandler = CErrorPrintHandler::NewL( *this );
+    User::LeaveIfError( iErrorPrintSem.CreateLocal( 0 ) );
+
+    // Construct unique thread name
+    const TInt KAddressLen = 8;
+    const TInt KMaxName = 50;  // Something smaller than max thread name
+    TInt len = aName.Length();
+    if ( KAddressLen + len > KMaxName )
+        {
+        len = KMaxName - KAddressLen;
+        }
+    
+    // Default heap and stack sizes that may configure by user.
+    TInt heapMinSize( KTestThreadMinHeap );
+    TInt heapMaxSize( KTestThreadMaxHeap );
+    TInt stackSize( KStackSize );
+
+    // Check is user give heap or stack sizes and verify sizes.
+    GetTestModuleParams( aName, aConfig, stackSize, heapMinSize, heapMaxSize );
+
+    // Create a new thread
+    TInt ret = KErrAlreadyExists;
+    for( TInt i = 0; ret == KErrAlreadyExists; i++ )
+        {
+        TName threadName = aName.Left( len );
+        threadName.AppendFormat( _L( "%x" ), ( TUint32 ) this );
+        threadName.AppendFormat( _L( "%x" ), i );
+        //RDebug::Print( threadName );
+
+		RDebug::Print(_L("CTestModuleContainer::ConstructL create thread=[%S] stackSize=(%d)"), &threadName, stackSize);
+
+		if ( iCTestModule->GetTestServer()->UiTesting() == false )
+			{
+	        ret = iThread.Create(
+	                    threadName,                 // name of thread
+	                    CTestThreadContainer::ExecutionThread,// thread function
+	                    stackSize,                  // Stack size
+	                    heapMinSize,                // Heap sizes
+	                    heapMaxSize,
+	                    this                        // Parameter to thread function
+	                    );
+			}
+		else
+			{
+	        ret = iThread.Create(
+                    threadName,                 // name of thread
+                    CTestThreadContainer::UIExecutionThread,// thread function
+                    stackSize,                  // Stack size
+                    heapMinSize,                // Heap sizes
+                    heapMaxSize,
+                    this                        // Parameter to thread function
+                    );
+			}
+
+        // If test execution thread exist try to create new one
+        if( ret == KErrAlreadyExists )
+            {
+            RDebug::Print( _L( "Thread[%S] allready exist, creating new one" ), &threadName );
+            __TRACE ( KInit, ( CStifLogger::ERed, _L( "Thread[%S] allready exist, creating new one" ), &threadName ) );
+            }
+
+        }
+
+    // If thread creation fails, leave here.
+    if( ret != KErrNone )
+        {
+        RDebug::Print( _L( "Execution thread creation fails with: [%d]" ), ret );
+        __TRACE ( KError, ( CStifLogger::ERed, _L( "Execution thread creation fails with: [%d]" ), ret ) );
+        User::Leave( ret );
+        }
+
+    // Doing nothing
+    // ChangeOperationNoError ( ESuspend, 0 );
+    // Thread suspends always first by default
+    
+    // Construct the undertaker to get notifications about the 
+    // thread death. 
+    // This must be trapped to allow to kill just created thread
+    // nicely without a mess in destructor.
+    TRAPD ( r, 
+        iUnderTaker = CUnderTaker::NewL ( this );
+        CActiveScheduler::Add( iUnderTaker );
+        iUnderTaker->StartL();
+        );    
+
+    // Can't create or start the undertaker. Kill the thread. 
+    // Undertaker will be deleted in destructor if needed.
+    if ( r != KErrNone )
+        {
+        iThread.Kill ( r );
+        iThread.Close();
+        User::Leave( r );
+        }
+
+    // Get server thread id ( i.e current thread id )
+    RThread tmpThread;
+    iServerThreadId = tmpThread.Id();
+    
+    // Resume the thread
+    iThread.Resume();                // Start the thread
+    iUpAndRunning = ETrue;           // Thread is created 
+
+    // Add "this" container to active scheduler
+    CActiveScheduler::Add ( this );
+
+    // Start error print handler
+    iErrorPrintHandler->StartL();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: CTestModuleContainer
+
+    Description: Constructor.
+
+    Initialise semaphores.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+CTestModuleContainer::CTestModuleContainer() :
+    CActive( CActive::EPriorityStandard ),
+    iOperationName ( 0, 0 ),
+    iIsPaused( EFalse )
+    {
+
+    // Create operation start semaphore
+    iOperationStartSemaphore.CreateLocal( 0 );
+
+    // Operation can be changed without first waiting.
+    iOperationChangeSemaphore.CreateLocal( 1 );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: ~CTestModuleContainer
+
+    Description: Destructor
+
+    Delete the test execution thread, if it is up and running. Delete
+    undertaker and close handles.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestModuleContainer::~CTestModuleContainer()
+    {
+
+    __TRACE ( KThreadOperation, ( _L( "CTestModuleContainer::~CTestModuleContainer in" ) ) );
+
+    if ( iUpAndRunning )
+        {
+		if( iUnderTaker != NULL )
+			{
+			iUnderTaker->Cancel();
+			}
+
+        // Set the operation
+        ChangeOperationNoError ( EExit, 0 );
+
+        // Do operation
+        StartAndWaitOperation();
+
+        }
+    
+    delete iErrorPrintHandler;
+	iErrorPrintHandler = NULL;
+
+    // Delete heap descriptor
+    delete iModuleNameBuffer;
+    iModuleNameBuffer = NULL;
+
+    // Delete undertaker
+    delete iUnderTaker;
+    iUnderTaker = NULL;
+
+    // Close error semaphore
+    if ( iErrorPrintSem.Handle() != 0 ) iErrorPrintSem.Close();
+
+    // Close the semaphores
+    iOperationStartSemaphore.Close();
+    iOperationChangeSemaphore.Close();
+
+    // Close handle to thread
+    iThread.Close();
+
+    Cancel();
+
+    delete iNestedActiveScheduler;
+    iNestedActiveScheduler = NULL;
+
+    __TRACE ( KThreadOperation, ( _L( "CTestModuleContainer::~CTestModuleContainer out" ) ) );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: StartAndWaitOperation
+
+    Description: Signals operation and waits until operation is completed.
+
+    Function executes active scheduler locally to handle both request
+    completion from execution thread and thread undertaker operations.    
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::StartAndWaitOperation()
+    {
+
+    // Change undertaker mode to synchronous    
+    iUnderTaker->SetSynchronousMode( ETrue );
+
+    iStatus = KRequestPending;
+    // Get ready to handle operation completion
+    SetActive();
+
+    // Start operation
+    iOperationStartSemaphore.Signal();
+
+    // Start "nested" active scheduler "locally"
+    //CActiveScheduler::Start();
+    iNestedActiveScheduler->Start();
+
+    // Request completed or operation crashed, everything 
+    // is done in ModuleContainer's RunL function or in UnderTaker's RunL.
+
+    // Cancel the original request in case than it was the undertaker
+    // that stopped the active scheduler. Does not do anything if original
+    // request is already finished.
+    Cancel();
+    
+    // Undertaker back to "normal" mode
+    iUnderTaker->SetSynchronousMode ( EFalse );
+
+    return iModuleResult;
+
+    }
+
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: Initialise
+
+    Description: Initialise the test module
+
+    Initialisation is done in context of test execution thread.
+
+    Parameters: const TDesC& aName            :in:  Module name
+                TBool aFirstTime              :in:  First init?
+
+
+    Return Values: TInt                             Result from init
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::Initialize( const TFileName& aName,
+                                       TBool aFirstTime
+                                     )
+    {
+
+    __TRACE ( KInit, ( _L( "Initializing test module" ) ) );
+
+    // Set the operation
+    iErrorResult = ChangeOperation ( EInitializeModule, aName, aFirstTime );
+    iModuleResult = KErrNone;
+    
+    if ( iErrorResult == KErrNone )
+        {
+        // Wait until operation is completed
+        StartAndWaitOperation();
+        }
+    
+    if ( iErrorResult )
+        {
+        __TRACE ( KError, ( CStifLogger::ERed,  _L( "Initializing test module failed %d" ), iErrorResult ) );
+        }
+    else if ( iModuleResult )
+        {
+        __TRACE ( KError, ( CStifLogger::ERed, _L( "Initializing test module failed code from module = %d" ), iModuleResult ) );
+        } 
+    else
+        {
+        __TRACE ( KInit, ( CStifLogger::EBold, _L( "Test module initialization done" ) ) );
+        }
+
+    // Return result
+    return iModuleResult;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: EnumerateTestCases
+
+    Description: Enumerate test cases of the test module
+
+    Enumeration is done in context of test execution thread.
+
+    Parameters: const TDesC& aName            :in:  Configuration file
+
+    Return Values: TInt                             Result from enumeration
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::EnumerateTestCases( const TFileName& aName )
+    {
+
+    __TRACE ( KInit, ( CStifLogger::EBold, _L( "Enumerating test cases from [%S] (might be empty)" ), &aName ) );
+
+    // Set the operation
+    iErrorResult = ChangeOperation( EEnumerateInThread, aName, 0 );
+    iModuleResult = KErrNone;
+
+    if ( iErrorResult == KErrNone )
+        {
+        // Wait until operation is completed
+        StartAndWaitOperation();
+        }
+
+    if ( iErrorResult )
+        {
+        __TRACE ( KError, ( CStifLogger::ERed, _L( "Enumerating test cases failed %d" ), iErrorResult ) );
+        }
+    else if ( iModuleResult )
+        {
+        __TRACE ( KError, ( CStifLogger::ERed, _L( "Enumerating test cases failed, code from module = %d" ), iModuleResult ) );
+        } 
+    else
+        {
+        __TRACE ( KInit, ( _L( "Enumerating test cases done" ) ) );
+        }
+
+    // Return result
+    return iModuleResult;
+
+    }
+
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: FreeEnumerationData
+
+    Description: Frees the enumeration data
+
+    Memory deallocation is done in context of test execution thread.
+
+    Parameters: None
+
+    Return Values: TInt                             Result from operation
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+
+TInt CTestModuleContainer::FreeEnumerationData()
+    {
+
+    // Set the operation
+    ChangeOperationNoError( EFreeEnumerationData, 0 );
+    
+    // Do the operation
+    StartAndWaitOperation();
+
+    // Return result
+    return iModuleResult;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: RunTestCase
+
+    Description: Run a test case
+
+    Running a test case is done in context of test execution thread. This
+    function is asynchronous ( i.e test is not finished when this function
+    returns ).
+
+    Parameters: const TFileName& aName        :in:  Configuration file
+                TInt aCaseNumber              :in:  Case number
+                const RMessage                :in:  Handle to test msg.
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::RunTestCase ( const TFileName& aName,
+                                         const TInt aCaseNumber,
+                                         const RMessage2& aMessage
+                                       )
+    {
+
+    __TRACE ( KInit, ( CStifLogger::EBold, _L( "Running test case [%S], case [%d]" ), &aName, aCaseNumber ) );
+
+    // Set the operation    
+    iErrorResult = ChangeOperation( EExecuteTestInThread, aName, aCaseNumber );
+
+    if ( iErrorResult != KErrNone )
+        {
+        aMessage.Complete ( iErrorResult );
+        return;
+        }    
+
+    // Set data
+    iMessage = aMessage;
+
+    iStatus = KRequestPending;
+    // Get ready to handle operation completion
+    SetActive();
+
+    // Do operation
+    iOperationStartSemaphore.Signal();    
+
+    // This is asynchronous operation, 
+    // do not wait until completed.    
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: SetExecutionSubSession
+
+    Description: Set execution subsession
+
+    Sets module container test execution subsession. Execution subsession
+    is changed when a module container is reused to run another 
+    test case.
+
+    Parameters: CTestExecution* aExecution    :in:  Subsession pointer
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::SetExecutionSubSession( CTestExecution* aExecution )
+    {
+
+    iCTestExecution = aExecution;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: PauseThread
+
+    Description: Pauses the thread
+
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::PauseThread()
+    {
+    
+    if( iThread.ExitType() != EExitPending )
+        {
+        // Thread is not alive anymore
+        return KErrDied;
+        }
+
+    if(iCTestExecution != NULL)
+    	{
+		RMutex printMutex;
+		printMutex.SetHandle( iCTestExecution->PrintMutexHandle() );
+		RMutex eventMutex;
+		eventMutex.SetHandle( iCTestExecution->EventMutexHandle() );
+		RMutex sndMutex;
+		sndMutex.SetHandle( iCTestExecution->SndMutexHandle() );
+		RMutex rcvMutex;
+		rcvMutex.SetHandle( iCTestExecution->RcvMutexHandle() );
+		
+		printMutex.Wait(); // wait that print operation is done
+		eventMutex.Wait(); // wait that event operation is done        
+		sndMutex.Wait(); // wait that and operation is done
+		rcvMutex.Wait(); // wait that event operation is done        
+			
+		iThread.Suspend();
+		
+		printMutex.Signal();
+		eventMutex.Signal();
+		sndMutex.Signal();
+		rcvMutex.Signal();
+    	}
+    else
+		{
+		__TRACE( KError,( _L( "STIF internal error - iCTestExecution is NULL in CTestModuleContainer::PauseThread" ) ) );
+		User::Panic(_L("NULL pointer exception"), KErrGeneral);
+		}
+    
+    iIsPaused = ETrue;
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: ResumeThread
+
+    Description: Resumes the thread
+
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::ResumeThread()
+    {
+
+    if( iThread.ExitType() != EExitPending )
+        {
+        // Thread is not alive anymore
+        return KErrDied;
+        }
+    
+    iThread.Resume();
+
+    // Pause() - Resume() operations done successfully. 
+    iIsPaused = EFalse;
+
+    return KErrNone;
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: KillThread
+
+    Description: Kills the thread
+
+    Parameters: const TInt aCode              :in:   Kill code
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::KillThread( const TInt aCode )
+    {
+
+    iUpAndRunning = EFalse;
+    iUnderTaker->Cancel();
+    
+    if(iCTestExecution != NULL)
+    	{
+		RMutex printMutex;
+		printMutex.SetHandle( iCTestExecution->PrintMutexHandle() );
+		RMutex eventMutex;
+		eventMutex.SetHandle( iCTestExecution->EventMutexHandle() );
+		RMutex sndMutex;
+		sndMutex.SetHandle( iCTestExecution->SndMutexHandle() );
+		RMutex rcvMutex;
+		rcvMutex.SetHandle( iCTestExecution->RcvMutexHandle() );
+		
+		printMutex.Wait(); // wait that print operation is done
+		eventMutex.Wait(); // wait that event operation is done        
+		sndMutex.Wait(); // wait that snd operation is done
+		rcvMutex.Wait(); // wait that event operation is done        
+			
+		iThread.Kill ( aCode );
+		
+		printMutex.Signal();
+		eventMutex.Signal();
+		sndMutex.Signal();
+		rcvMutex.Signal();
+    	}
+    else
+		{
+		__TRACE( KError,( _L( "STIF internal error - iCTestExecution is NULL in CTestModuleContainer::KillThread" ) ) );
+		User::Panic(_L("NULL pointer exception"), KErrGeneral);
+		}
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: ChangeOperation
+
+    Description: Multithread safe way to change operation
+
+    Parameters: const TOperation aOperation   :in:  Operation type
+                const TFileName* aNameBuffer  :in:  Filename ( or NULL )
+                const TInt aInt               :in:  Operation specific int
+    
+    Return Values: TInt                             Error code
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::ChangeOperation( const TOperation aOperation,
+                                            const TFileName& aNameBuffer,
+                                            const TInt aInt )
+    {
+
+    TInt ret = KErrNone;
+
+    iOperationChangeSemaphore.Wait();
+
+    iErrorResult  = KErrNone;
+    iModuleResult = KErrNone;
+
+    TFileName newNameBuffer;
+    // Check is TestScripter
+    TInt check = CheckModuleName( aNameBuffer, newNameBuffer );
+    delete iModuleNameBuffer;
+	iModuleNameBuffer = NULL;
+    if( check == KErrNone )
+        {
+        // Construct heap buffer for configuration file
+        TRAP( ret, iModuleNameBuffer = HBufC::NewL( newNameBuffer.Length() ) );
+
+        if( ret == KErrNone )
+            {
+            iOperationName.Set ( iModuleNameBuffer->Des() );
+            iOperationName.Copy ( newNameBuffer );
+        
+            iOperationIntBuffer = aInt;
+            iOperationType = aOperation;
+            }
+        else
+            {
+            __TRACE ( KError, ( CStifLogger::ERed, _L( "CTestModuleContainer::ChangeOperation NoMemory" ) ) );
+            }   
+        }
+    else
+        {
+        // Construct heap buffer for configuration file
+        TRAP( ret, iModuleNameBuffer = HBufC::NewL( aNameBuffer.Length() ) );
+
+        if( ret == KErrNone )
+            {
+            iOperationName.Set ( iModuleNameBuffer->Des() );
+            iOperationName.Copy ( aNameBuffer );
+        
+            iOperationIntBuffer = aInt;
+            iOperationType = aOperation;
+            }
+        else
+            {
+            __TRACE ( KError, ( CStifLogger::ERed, _L( "CTestModuleContainer::ChangeOperation NoMemory" ) ) );
+            }
+        }
+
+    iOperationChangeSemaphore.Signal();
+
+    return ret;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: ChangeOperationNoError
+
+    Description: Multithread safe way to change operation. This version
+    of function can't fail.
+
+    Parameters: const TOperation aOperation   :in:  Operation type
+                const TInt aInt               :in:  Operation specific int
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::ChangeOperationNoError( const TOperation aOperation,
+                                                   const TInt aInt
+                                                 )
+    {
+
+    iOperationChangeSemaphore.Wait();
+
+    iErrorResult  = KErrNone;
+    iModuleResult = KErrNone;
+    iOperationIntBuffer = aInt;
+    iOperationType = aOperation;
+    
+    iOperationChangeSemaphore.Signal();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: Operation
+
+    Description: Multithread safe way to obtain current operation.
+
+    Parameters: None
+
+    Return Values: TBool                            Operation
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+//@spe const CTestModuleContainer::TOperation CTestModuleContainer::Operation()
+CTestModuleContainer::TOperation CTestModuleContainer::Operation()
+    {
+    TOperation operation;
+    iOperationChangeSemaphore.Wait();
+    operation = iOperationType;
+    iOperationChangeSemaphore.Signal();
+
+    return operation;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: ModuleResult
+
+    Description: Returns error code from test module
+
+    Parameters: None
+
+    Return Values: TInt                             Result code from module
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt& CTestModuleContainer::ModuleResult()
+    {
+
+    return iModuleResult;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: OperationErrorResult
+
+    Description: Returns error code from test module
+
+    Parameters: None
+
+    Return Values: TInt                             Result code from module
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt& CTestModuleContainer::OperationErrorResult()
+    {
+
+    return iModuleResult;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: TestModuleName
+
+    Description: Returns test module name.
+
+    Parameters: None
+
+    Return Values: const TDesC&: test module name
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+const TDesC& CTestModuleContainer::TestModuleName()
+    {
+    
+    return iCTestModule->Name();
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: TestModuleName
+
+    Description: Returns test module name.
+
+    Parameters: None
+
+    Return Values: const TDesC&: test module name
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+const TDesC& CTestModuleContainer::TestModuleIniFile()
+    {
+    
+    return iCTestModule->IniName();
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: ModuleResult
+
+    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>* CTestModuleContainer::TestCases() const
+    {
+    
+    if( !iUpAndRunning )
+        {
+        return NULL;
+        }
+        
+    if( iThreadContainer == NULL )
+        {
+        CTestServer::PanicServer( ENullTestThreadContainer );
+        }
+    return iThreadContainer->TestCases();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: Complete
+
+    Description: Completes operation from any thread
+
+    Parameters: const TInt aCompletionCode :in:     Completion code
+    
+    Return Values: None
+
+    Errors/Exceptions: Function panics if server's thread can't be opened.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::Complete( const TInt aCompletionCode )
+    {
+
+    TRequestStatus* req = &iStatus;
+    User::RequestComplete( req, aCompletionCode );
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: DoErrorPrint
+
+    Description: Handle error prints.
+        
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::DoErrorPrint()
+    {    
+    
+    iCTestModule->ErrorPrint( iErrorPrint.iPriority, iErrorPrint.iText );
+    
+    }
+ 
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: KillTestinterferenceThread
+
+    Description: Make sure that any of the test interference thread's won't
+                 stay to run if test case is crashed of test interference
+                 object is not deleted.
+
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::KillTestinterferenceThread()
+    {
+    if (iCTestExecution != NULL)
+    	{
+    	iCTestExecution->KillTestinterferenceThread();
+    	}
+    else
+    	{
+    	__TRACE( KError,( _L( "STIF internal error - iCTestExecution is NULL in CTestModuleContainer::KillTestinterferenceThread" ) ) );
+    	User::Panic(_L("NULL pointer exception"), KErrGeneral);
+    	}
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: KillTestMeasurement
+
+    Description: Make sure that any of the test measurement process's won't
+                 stay to run if test case is crashed of test measurement object
+                 is not deleted.
+
+    Parameters: None
+    
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+    
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::KillTestMeasurement()
+    {    
+    if (iCTestExecution != NULL)
+    	{
+    	iCTestExecution->KillTestMeasurement();
+    	}
+    else
+    	{
+    	__TRACE( KError,( _L( "STIF internal error - iCTestExecution is NULL in CTestModuleContainer::KillTestMeasurement" ) ) );
+    	User::Panic(_L("NULL pointer exception"), KErrGeneral);
+    	}
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: GetRequest
+
+    Description: Return status flags.
+        
+    Parameters: TRequestType aType: in: request type
+    
+    Return Values: TRequestStatus*: pointer to TRequestStatus
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TRequestStatus* CTestModuleContainer::GetRequest( TRequestType aType )
+    { 
+    
+    TRequestStatus* status = NULL;
+    
+    switch( aType )
+        {
+        case ERqTestCase:
+            status = &iStatus;
+            break;
+        case ERqErrorPrint:
+            status = &iErrorPrintHandler->iStatus;
+            break;
+        default: 
+            break;
+        }
+    
+    return status;
+
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: RunL
+
+    Description: Stops active scheduler when operation in another thread
+                 is completed.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::RunL()
+    {
+    
+    if( iOperationType == CTestModuleContainer::EExecuteTestInThread )
+        {
+        // Make sure that any of the test interference thread's won't stay
+        // to run.
+        KillTestinterferenceThread();
+
+        // Make sure that any of the test measurement process's won't stay
+        // to run.
+        KillTestMeasurement();
+
+        if(iCTestExecution == NULL)
+        	{
+        	__TRACE( KError,( _L( "STIF internal error - iCTestExecution is NULL in CTestModuleContainer::RunL" ) ) );
+        	User::Leave(KErrGeneral);
+        	}
+        else
+        	{
+			// Set the thread state
+			iCTestExecution->SetThreadState( CTestExecution::EFinished );
+	
+			 // If test print queue is empty, then complete request with KEof. If Queue
+			// is not empty, then do not complete. Queue will be emptied by UI.   
+			iCTestExecution->CompletePrintRequestIfQueueEmpty();
+	
+			// Event queue clean-up
+			iCTestExecution->CleanupEvents();
+			
+			// Complete the test request
+			iCTestExecution->CompleteTestExecution( iStatus.Int() );
+			
+			// Test case execution OK and test module thread's pause operation
+			// is not ongoing. Re-use old test module execution thread
+			if( iCTestExecution->TestThreadFailure() == CTestExecution::ETestThreadOk && !iIsPaused )
+				{
+				// Return this module to pool
+				__TRACE( KInit, ( _L("Freeing test module container at 0x%x"),  
+					(TUint32) this ) );
+				iCTestModule->FreeTestModule( this );
+				}
+			// Problems in test case execution. Delete this test module thread and
+			// start next test case in new test module thread.
+			else
+				{
+				if( iIsPaused )
+					{
+					// Test case is paused by user and this RunL is executed also.
+					// This RunL will make Resume() operation to fail because test
+					// case is finished. Next test case cannot complete and that is
+					// why next test case will start at the "clean table".
+					__TRACE( KInit, ( _L( "Delete test module container at 0x%x because test module thread is paused while test case is finished(Cannot Resume())" ), (TUint32) this ) );  
+					}
+				else
+					{
+					// delete test module thread if some thread problem has occurred 
+					__TRACE( KInit, ( _L("Delete test module container at 0x%x because of thread leak (0x%x)"),  
+						(TUint32) this,  iCTestExecution->TestThreadFailure() ) );
+					}
+				delete this;            
+				}
+        	}
+        }
+    else
+        {
+        // Synchronous operation is completed, stop "nested" active scheduler.
+        //CActiveScheduler::Stop();
+        iNestedActiveScheduler->AsyncStop();
+        // Execution continues from CTestModuleContainer::WaitOperation().
+        }
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: DoCancel
+
+    Description: Cancel asyncronous request.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::DoCancel()
+    {
+
+    if ( iUpAndRunning == EFalse )
+        {
+        
+        // Before the completion check if the status was not already completed
+        // from other thread in CTestThreadContainer::TestComplete().
+        // For details see Jira STIF-564
+        if(iStatus == KRequestPending)
+            Complete ( KErrCancel ); 
+
+        }
+
+    }
+
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: RunError
+
+    Description: Handle errors. 
+
+    Because RunL does not leave, one should never come here. Just forward
+    error code and let framework panic the server in case of error.
+
+    Parameters: TInt aError:                  :in:  Error code
+
+    Return Values:  TInt                            Error code
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::RunError( TInt aError )
+    {
+
+    __TRACE( KError,( _L( "CTestModuleContainer::RunError %d" ), aError ) );
+
+    return aError;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: ReadParametersFromScriptFileL
+
+    Description: Read test class parameters from script file if parameter(s)
+                 are/is set(TestScripter and TestCombiner).
+
+    Parameters: const TDesC& aConfig: in: Test case (config) file name.
+                TUint32& aStackSize: inout: Stack size.
+                TUint32& aHeapMinSize: inout: Heap's minimum size.
+                TUint32& aHeapMaxSize: inout: Heap's maximum size.
+
+    Return Values: Symbian error code.
+
+    Errors/Exceptions: Leaves if User::LeaveIfError() leaves
+                       Leaves if User::LeaveIfNull() leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::ReadParametersFromScriptFileL( 
+                                                const TDesC& aConfig,
+                                                TInt& aStackSize,
+                                                TInt& aHeapMinSize,
+                                                TInt& aHeapMaxSize )
+    {
+    // __UHEAP_MARK;
+
+    RFs fileServer;
+    RFile file;
+    TInt ret( KErrNone );
+
+    User::LeaveIfError( fileServer.Connect() );
+    CleanupClosePushL( fileServer );
+    
+    __TRACE( KInit, ( _L( "ReadParametersFromScriptFile(): Open configfile [%S]" ), &aConfig ) );
+
+    TParse parse;
+    parse.Set( aConfig, NULL, NULL );
+
+    User::LeaveIfError( fileServer.SetSessionPath( parse.DriveAndPath() ) );
+
+    User::LeaveIfError( file.Open( fileServer, aConfig, EFileRead | EFileShareAny ) );
+    CleanupClosePushL( file );
+
+    TInt size( 0 );
+    User::LeaveIfError( file.Size( size ) );
+
+    const TInt tmpSize = KMaxName; // 128
+    TInt offset( 0 ); // Offset value to parts reading
+
+    // Indications for tags
+    TBool start_tag_found( EFalse );
+    TBool end_tag_found( EFalse );
+    // Offset values for start and end position parsing
+    TInt offset_start( 0 );
+    TInt offset_end( 0 );
+
+    /* Search is combined to section that include tags. After this create new
+    combined section that include second buffer data and new buffer data.
+    Section:     1) 1+2
+                 2) 2+1
+                 2) 1+2 etc. This should ensure that all data is search.
+    */
+
+    // Construct modifiable heap-based descriptor. tmp1 to CleanupStack
+    // This for first data buffer
+    HBufC8* tmp1 = HBufC8::NewLC( tmpSize );            // 128
+    TPtr8 buf1 = tmp1->Des();
+
+    // Construct modifiable heap-based descriptor. tmp2 to CleanupStack
+    // This for second data buffer
+    HBufC8* tmp2 = HBufC8::NewLC( tmpSize );            // 128
+    TPtr8 buf2 = tmp2->Des();
+
+    // Construct modifiable heap-based descriptor. tmp3 to CleanupStack
+    // This includes both first and second data buffers
+    HBufC* tmp3 = HBufC::NewLC( tmpSize + tmpSize );    // 256
+    TPtr currentSection = tmp3->Des();
+
+    // Construct modifiable heap-based descriptor. tmp4 to CleanupStack
+    // This is for changing 8 bit to 16 bit
+    HBufC* tmp4 = HBufC::NewLC( tmpSize );              // 128
+    TPtr to16bit = tmp4->Des();
+
+    ret = KErrNone;
+
+    // Read data to buffer 1
+    // tmp4, tmp3, tmp2 and tmp1 are in CleanupStack => Leave OK
+    // CleanupClosePushL is used to fileServer and file => Leave OK
+    User::LeaveIfError( file.Read( offset, buf1, tmpSize ) );
+
+    // For next buffer reading
+    offset += tmpSize;
+
+    // Read data to buffer 2
+    // tmp4, tmp3, tmp2 and tmp1 are in CleanupStack => Leave OK
+    // CleanupClosePushL is used to fileServer and file => Leave OK
+    User::LeaveIfError( file.Read( offset, buf2, tmpSize ) );
+
+    // 8 bit to 16. Create first combined buffer 1 and buffer 2 that
+    // is used for searching.
+    to16bit.Copy( buf1 );
+    currentSection.Copy( to16bit );
+    to16bit.Copy( buf2 );
+    currentSection.Append( to16bit );
+
+    // Check if small files to be parsed(e.g. settings + one short case).
+    TInt bigsize( 0 );
+    // Check if parsed section is smaller than 256
+    if( size <  ( tmpSize + tmpSize ) )
+        {
+        bigsize = size;
+        }
+    else
+        {
+        bigsize = tmpSize + tmpSize;    // 256
+        }
+
+    do
+        {
+        // Start the next buffer reading
+        offset += tmpSize;
+
+        // Search the start tag
+        ret = currentSection.Find( KStifSettingsStartTag );
+        if( ret != KErrNotFound )
+            {
+            // Succesfully search, take the start offset
+            ret = file.Seek( ESeekCurrent, offset_start );
+            if( ret == KErrNone )
+                {
+                start_tag_found = ETrue;
+                // Current section is end so offset to beging of the 
+                // combined section.
+                offset_start = ( offset_start - ( bigsize ) );
+                }
+            }
+        // Search the end tag
+        ret = currentSection.Find( KStifSettingsEndTag );
+        if( ret != KErrNotFound )
+            {
+            // Succesfully search, take the end offset
+            ret = file.Seek( ESeekCurrent, offset_end );
+            if( ret == KErrNone )
+                {
+                end_tag_found = ETrue;
+                }
+            }
+
+        // Both start and end tags are founded, start parsing sizes.
+        if( start_tag_found && end_tag_found )
+            {
+            TInt length = ( offset_end - offset_start );
+
+            // Construct modifiable heap-based descriptor.
+            // setting_buf to CleanupStack
+            HBufC8* setting_buf = HBufC8::NewLC( length );// 8 bit for reading
+            TPtr8 setting8 = setting_buf->Des();
+
+            // Construct modifiable heap-based descriptor.
+            // setting_buf2 to CleanupStack
+            HBufC* setting_buf2 = HBufC::NewLC( length );// 16 bit for parsing
+            TPtr setting16 = setting_buf2->Des();
+
+            // Read data from the founded STIF settings sections
+            ret = KErrNone;
+            // HBufCs are in CleanupStack => Leave OK
+            // CleanupClosePushL is used to fileServer and file => Leave OK
+            User::LeaveIfError( file.Read( offset_start, setting8, length ) );
+
+            // Section 8 bit to 16.
+            setting16.Copy( setting8 );
+
+            // Start create parser for parsing heap and stack sizes.
+            // NOTE: Comments are parsed away from the section.
+            CStifParser* parser = NULL;
+            User::LeaveIfNull( parser = CStifParser::NewL( setting16,
+                                        CStifParser::ECStyleComments  ) );
+            CleanupStack::PushL(parser);
+
+            CStifSectionParser* section = NULL;
+            User::LeaveIfNull( section = parser->SectionL( KStifSettingsStartTag,
+                                                   KStifSettingsEndTag ) );
+            CleanupStack::PushL(section);
+            TInt lineRet( KErrNone );
+            TInt integer( 0 );
+
+            // Try to get stack size
+            CStifItemParser* itemLine = NULL;
+            TRAPD( parse_ret, itemLine = section->GetItemLineL(
+                                                        KUserDefStackSize ) );
+            if ( parse_ret == KErrNone && itemLine != NULL )
+                {
+                lineRet = itemLine->GetInt( KUserDefStackSize, integer );
+                if ( lineRet == KErrNone )
+                    {
+                    aStackSize = integer;
+                    }
+                }
+            delete itemLine;
+            itemLine = NULL;
+
+            // Try to get minimum heap size
+            TRAP( parse_ret, itemLine = section->GetItemLineL(
+                                                        KUserDefMinHeap ) );
+            if ( parse_ret == KErrNone && itemLine != NULL )
+                {
+                lineRet = itemLine->GetInt( KUserDefMinHeap, integer );
+                if ( lineRet == KErrNone )
+                    {
+                    aHeapMinSize = integer;
+                    }
+                }
+            delete itemLine;
+            itemLine = NULL;
+
+            // Try to get maximum heap size
+            TRAP( parse_ret, itemLine = section->GetItemLineL(
+                                                        KUserDefMaxHeap ) );
+            if ( parse_ret == KErrNone && itemLine != NULL )
+                {
+                lineRet = itemLine->GetInt( KUserDefMaxHeap, integer );
+                if ( lineRet == KErrNone )
+                    {
+                    aHeapMaxSize = integer;
+                    }
+                }
+            delete itemLine;
+
+            CleanupStack::Pop(section);
+            CleanupStack::Pop(parser);
+
+            CleanupStack::PopAndDestroy( setting_buf2 );
+            CleanupStack::PopAndDestroy( setting_buf );
+
+            delete section;
+            delete parser;
+
+            break; // Stop the do branch
+            }
+
+        // Start to create new section for search
+
+        // 8 bit to 16. Last buffer to first
+        to16bit.Copy( buf2 );
+        currentSection.Copy( to16bit );
+
+        // Read new data to buffer 1
+        ret = KErrNone;
+        User::LeaveIfError( file.Read( offset, buf1, tmpSize ) );
+
+        // 8 bit to 16. Append
+        to16bit.Copy( buf1 );
+        currentSection.Append( to16bit );
+
+        // Copy first buffer data to buffer 2. This is added to first
+        // in section in next run
+        buf2.Copy( buf1 );
+
+        } while( offset < size );
+
+    CleanupStack::PopAndDestroy( tmp4 );
+    CleanupStack::PopAndDestroy( tmp3 );
+    CleanupStack::PopAndDestroy( tmp2 );
+    CleanupStack::PopAndDestroy( tmp1 );
+
+    CleanupStack::PopAndDestroy( &file );
+    CleanupStack::PopAndDestroy( &fileServer );
+    file.Close();
+    fileServer.Close();
+
+    //__UHEAP_MARKEND;
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: ReadParametersFromTestModule
+
+    Description: Loads dynamically testmodule and calls SetRequirements()-
+                 method for test module parameter handling.
+
+    Parameters: const TDesC& aModuleName: in: Test module name
+                CTestModuleParam*& aTestModuleParam: inout: Object for handling
+                test module parameters.
+
+    Return Values: TInt: Symbian error code.
+
+    Errors/Exceptions: None.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::ReadParametersFromTestModule(
+                                const TDesC& aModuleName,
+                                CTestModuleParam*& aTestModuleParam )
+    {
+    __TRACE( KInit, (  _L( "ReadParametersFromTestModule() [%S]" ), &aModuleName ) );
+    RLibrary testModule;
+    // Load the module
+    TPtrC dllName;
+    
+    // Remove optional index appended to module name
+    TFileName validModuleName;
+    RemoveOptionalIndex(aModuleName, validModuleName);
+    __TRACE(KInit, (_L( "Valid module name is [%S] (extracted from [%S])"), &validModuleName, &aModuleName));
+    dllName.Set(validModuleName);
+    
+    // Loading should work with and without '.dll' extension.
+    TInt r = testModule.Load( dllName );
+    if ( r != KErrNone )
+        {
+        __TRACE( KError, ( CStifLogger::EError, _L("Can't initialize test module[%S], code = %d"), &dllName, r ) );
+        return KErrNotFound;
+        }
+    else
+        {
+        // Print reset module name
+        __TRACE( KInit, (  _L("Loaded test module[%S]"), &dllName ) );
+        }
+
+    
+
+    CTestInterfaceFactoryTestModule libEntry = NULL;
+    
+#if defined( __ARMCC__ )
+        {
+        // In this environment the heap and stack feature may crash if
+        // test module not include a workaround for ARM RVCT(ARMv5) compiler
+        // error. For more information see STIF user guide.
+        __TRACE ( KInit, ( _L( "Workaround for ARM RVCT(ARMv5) compiler error should be included to TestModule." ) ) );
+        }
+#endif // #if defined(__ARMCC__)
+
+    // Get pointer to second exported function
+    // Verify that there is function
+    //CTestInterfaceFactoryTestModule libEntry;
+    libEntry = (CTestInterfaceFactoryTestModule) testModule.Lookup( 2 );
+    if ( libEntry == NULL )
+        {
+        // New instance can't be created
+        __TRACE( KInit, (_L( "Test module is old version and has not SetRequirements() feature." ) ) );
+        testModule.Close();
+        return KErrNotSupported;
+        }
+    else
+        {
+        __TRACE ( KInit, ( _L("Pointer to 2st exported received")));
+        }
+
+    // Calls dynamically loaded module's second method.
+    __TRACE ( KVerbose, (_L("Calling 2st exported at 0x%x"), (TUint32) libEntry ));
+    TUint32 check = 0;
+    TInt ret =  (*libEntry)( aTestModuleParam, check  );
+    if( check != KStifTestModuleParameterChanged  )
+        {
+        // Problems in def-file definitions. Test module is old wersion
+        // and has not SetRequirements feature.
+        RDebug::Print( ( _L( "STIF TF: Test module is old version and has not SetRequirements() feature." ) ) );
+        __TRACE( KInit, (_L( "Test module is old version and has not SetRequirements() feature." ) ) );
+        testModule.Close();
+        return KErrNotSupported;
+        }
+    if( ret != KErrNone )
+        {
+        __TRACE (KInit, (_L("ReadParametersFromTestModule; SetRequirements fails with error: %d"), ret ) );
+        testModule.Close();
+        return ret;
+        }
+
+    libEntry = NULL; 
+    testModule.Close(); // After close test module's pointer is not
+                        // valid anymore.
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: GetTestModuleParams
+
+    Description: Load test module dynamically. If loading is done succesfully
+                 then set test module's parameters according to version.
+                 Verify received parameters.
+
+    Parameters: const TDesC& aModuleName: in: Test module name.
+                const TDesC& aConfig: in: Test case (config) file name.
+                TInt& aStackSize: inout: Stack size.
+                TInt& aHeapMinSize: inout: Heap's minimum size.
+                TInt& aHeapMaxSize: inout: Heap's maximum size.
+
+    Return Values: TInt: Symbian error code.
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleContainer::GetTestModuleParams( const TDesC& aModuleName,
+                                                const TDesC& aConfig,
+                                                TInt& aStackSize,
+                                                TInt& aHeapMinSize,
+                                                TInt& aHeapMaxSize )
+    {
+    TInt r( KErrNone );
+
+    // There is lower case despite what is initialization file given.
+    // Module name is without dll extension.
+    // Check is TestScripter or TestCombiner and test case (config) file
+    // name is given.
+    if( ( aModuleName.Find( KTestScripterName ) != KErrNotFound ||
+          aModuleName == _L( "testcombiner" ) ) && aConfig != KNullDesC )
+        {
+        TRAPD( ret, r = ReadParametersFromScriptFileL( aConfig, aStackSize,
+                                          aHeapMinSize, aHeapMaxSize ) );
+        if( r != KErrNone )
+            {
+            __TRACE( KInit, ( CStifLogger::ERed, _L( "Cannot set Test Class's stack or heap sizes, fail with error: %d" ), r ) );
+            __TRACE( KInit, ( _L( "Default sizes will be use(See KTestThreadMinHeap, KTestThreadMinHeap and KStackSize)" ) ) );
+            return r;
+            }
+        if( ret != KErrNone )
+            {
+            __TRACE( KInit, ( CStifLogger::ERed, _L( "Cannot set Test Class's stack or heap sizes, leaves with error: %d" ), r ) );
+            __TRACE( KInit, ( _L( "Default sizes will be use(See KTestThreadMinHeap, KTestThreadMinHeap and KStackSize)" ) ) );
+            return ret;
+            }
+        }
+    else
+        {
+        CTestModuleParam* testModuleParam = NULL;
+        //--PYTHON-- begin
+        if(aModuleName.Find(KPythonScripter) != KErrNotFound)
+            {
+			RDebug::Print(_L("CTestModuleContainer::GetTestModuleParams reading params for PythonScripter, aModuleName=[%S]"), &aModuleName);
+            TName n;
+            n.Copy(KPythonScripter);
+            r = ReadParametersFromTestModule( n, testModuleParam );
+            }
+        else
+        //--PYTHON-- end
+            r = ReadParametersFromTestModule( aModuleName, testModuleParam );
+
+        if( r != KErrNone )
+            {
+            __TRACE( KInit, ( _L( "Cannot set Test Module's stack or heap sizes, fails with: %d" ), r ) );
+            __TRACE( KInit, ( _L( "Default sizes will be use(See KTestThreadMinHeap, KTestThreadMinHeap and KStackSize)" ) ) );
+            delete testModuleParam;
+            return r;
+            }
+
+        if ( testModuleParam->Version() == 1 )
+            {
+            // Casting
+            CTestModuleParamVer01* paramVer01 = ( CTestModuleParamVer01* ) testModuleParam;
+            aStackSize = paramVer01->iTestThreadStackSize;
+            aHeapMinSize = paramVer01->iTestThreadMinHeap;
+            aHeapMaxSize = paramVer01->iTestThreadMaxHeap;
+            }
+
+        delete testModuleParam;
+        }
+
+    // Verify that sizes are valid. If problems are notices then use default 
+    // value
+
+    // 1) "The panic occurs when the value of the stack size is negative."
+    if( aStackSize < 0 )
+        {
+        RDebug::Print( ( _L("STIF TF: GetTestModuleParams() fails because value of the stack size is negative, default value is taken into use") ) );
+        __TRACE( KInit, ( CStifLogger::ERed, _L("STIF TF: GetTestModuleParams() fails because value of the stack size is negative, default value is taken into use" ) ) );
+        // Use default value
+        aStackSize = KStackSize;
+        }
+    
+    // 2) "The panic occurs if the minimum heap size specified is less
+    // than KMinHeapSize".
+    // KMinHeapSize: "Functions that require a new heap to be allocated will
+    // either panic, or will reset the required heap size to this value if a
+    // smaller heap size is specified".
+    if( aHeapMinSize < KMinHeapSize )
+        {
+        RDebug::Print( _L( "STIF TF: GetTestModuleParams() fails because test module minimum heap size is less than KMinHeapSize:[%d], default value is taken into use" ), KMinHeapSize );
+        __TRACE( KInit, ( CStifLogger::ERed, _L("STIF TF: GetTestModuleParams() fails because test module minimum heap size is less than KMinHeapSize:[%d], default value is taken into use"), KMinHeapSize ) );
+        // Use default value(Note: This is used for now on)
+        aHeapMinSize = KTestThreadMinHeap;
+        }
+
+    // 3) "The panic occurs if the minimum heap size specified is greater than
+    // the maximum size to which the heap can grow".
+    // Check this last !
+    if( aHeapMinSize > aHeapMaxSize )
+        {
+        RDebug::Print( ( _L("STIF TF: GetTestModuleParams() fails because the maximum heap size is specified less than minimum heap size, default values is taken into use" ) ) );
+        __TRACE( KInit, ( CStifLogger::ERed, _L( "STIF TF: GetTestModuleParams() fails because the maximum heap size is specified less than minimum heap size, default values is taken into use" ) ) );
+        // Use default values
+        aHeapMinSize = KTestThreadMinHeap;
+        aHeapMaxSize = KTestThreadMaxHeap;
+        }
+
+    __TRACE( KInit, ( _L( "[%S] uses:" ), &aModuleName ) );
+    __TRACE( KInit, ( _L( "Stack size: [%d]" ), aStackSize ) );
+    __TRACE( KInit, ( _L( "Minimum heap size: [%d]" ), aHeapMinSize ) );
+    __TRACE( KInit, ( _L( "Maximum heap size: [%d]" ), aHeapMaxSize ) );
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: GetTestCaseTitleL
+
+    Description: Gets title of currently running test case.
+
+    Parameters: TDes& aTestCaseTitle: out: Test case title.
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleContainer::GetTestCaseTitleL(TDes& aTestCaseTitle)
+    {
+    //currently run test case stored in the iOperationIntBuffer variable
+    iCTestModule->GetTestCaseTitleL( iOperationIntBuffer, 
+                                     iCTestExecution->GetConfigFileName(),
+                                    aTestCaseTitle);  
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleContainer
+
+    Method: GetTestModule
+
+    Description: Gets pointer to test module
+
+    Parameters: none
+
+    Return Values: CTestModule* : Pointer to test module
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestModule* CTestModuleContainer::GetTestModule()
+    {
+    
+    return iCTestModule;
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    DESCRIPTION
+
+    This module contains implementation of CPrintHandler class member functions.
+    CErrorPrintHandler listens print notifications from test thread.
+
+-------------------------------------------------------------------------------
+*/
+
+// ================= MEMBER FUNCTIONS =========================================
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrintHandler
+
+    Method: NewL
+
+    Description: Constructs a new CErrorPrintHandler object.
+
+    Parameters: CTestExecution& aExecution: in: "Parent"
+
+    Return Values: CErrorPrintHandler*: New undertaker
+
+    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CErrorPrintHandler* CErrorPrintHandler::NewL( CTestModuleContainer& aContainer )
+    {
+
+    CErrorPrintHandler* self = new( ELeave ) CErrorPrintHandler( aContainer );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrintHandler
+
+    Method: ConstructL
+
+    Description: Second level constructor.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CErrorPrintHandler::ConstructL()
+    {
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrintHandler
+
+    Method: CErrorPrintHandler
+
+    Description: Constructor
+
+    Parameters: CTestModuleContainer& aExecution :in:   "Parent"
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+CErrorPrintHandler::CErrorPrintHandler( CTestModuleContainer& aContainer ) :
+    CActive( CActive::EPriorityStandard ),
+    iContainer( aContainer )
+    {
+    
+    CActiveScheduler::Add ( this );
+        
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrintHandler
+
+    Method: ~CErrorPrintHandler
+
+    Description: Destructor. 
+    Cancels active request.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+CErrorPrintHandler::~CErrorPrintHandler()
+    {
+
+    Cancel();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrintHandler
+
+    Method: StartL
+
+    Description: Starts to monitor thread.
+
+    Parameters: None
+
+    Return Values: TInt                             Always KErrNone
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CErrorPrintHandler::StartL()
+    {
+    
+    __TRACE( KPrint, ( _L( "CErrorPrintHandler::StartL" ) ) );
+    
+    iStatus = KRequestPending;
+    SetActive();
+    
+    // Signal test thread
+    iContainer.iErrorPrintSem.Signal();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrintHandler
+
+    Method: RunL
+
+    Description: Handles thread death.
+    Function does:
+    1 ) Stops monitoring thread
+    1 ) Marks thread death
+    2 ) Completes ongoing requests
+    3 ) Cleans the memory
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CErrorPrintHandler::RunL()
+    {
+
+    __TRACE( KPrint, ( _L( "CErrorPrintHandler::RunL [%d]" ), iStatus.Int() ) );
+    
+    iContainer.DoErrorPrint();    
+    
+    // enable error print request
+    iContainer.iErrorPrintHandler->StartL();
+       
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrintHandler
+
+    Method: DoCancel
+
+    Description: Stops print notification listening.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+
+void CErrorPrintHandler::DoCancel()
+    {
+
+    __TRACE( KPrint, ( _L( "CErrorPrintHandler::DoCancel" ) ) );
+
+    // Signal test thread
+    iContainer.iErrorPrintSem.Wait();
+
+    TRequestStatus* status = &iStatus;    
+    User::RequestComplete( status, KErrCancel );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrintHandler
+
+    Method: RunError
+
+    Description: Handle errors. RunL function does not leave, so one should
+    never come here. 
+
+    Print trace and let framework handle error( i.e to do Panic )
+
+    Parameters: TInt aError:                  :in:  Error code
+
+    Return Values:  TInt                            Error code
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CErrorPrintHandler::RunError( TInt aError )
+    {
+    
+    __TRACE( KError,( _L( "CErrorPrintHandler::RunError" ) ) );
+
+    return aError;
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: -
+
+    Method: CheckModuleName
+
+    Description: Check is module TestScripter. Does parsing and returns new
+                 module name and error codes(Needed operations when creating
+                 server sessions to TestScripter).
+
+    Parameters: TFileName aModuleName: in: Module name for checking.
+                TFileName& aNewModuleName: inout: Parsed module name.
+
+    Return Values: KErrNone if TestScripter releated module.
+                   KErrNotFound if not TestScripter releated module.
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CheckModuleName( TFileName aModuleName, TFileName& aNewModuleName )
+    {
+//--PYTHON-- old code has been replaced with the new one
+/*
+    // Check that length is greated than KTestScripterNameLength
+    if( aModuleName.Length() < KTestScripterNameLength )
+        {
+        return KErrNotFound;
+        }
+    // Check is TestScripter
+    TPtrC check( aModuleName.Mid( 0, KTestScripterNameLength ) );
+    TInt ret = check.Compare( KTestScripterName );
+    if( ret == KErrNone )
+        {
+        aNewModuleName.Copy( aModuleName.Mid( 0, KTestScripterNameLength ) );
+        }
+    else
+        {
+        return KErrNotFound;
+        }
+
+    return KErrNone;
+*/
+
+	// Check that length is greated than KTestScripterNameLength
+	if( aModuleName.Length() >= KTestScripterNameLength )
+		{
+		TPtrC check( aModuleName.Mid( 0, KTestScripterNameLength ) );
+		TInt ret = check.Compare( KTestScripterName );
+		if( ret == KErrNone )
+			{
+			aNewModuleName.Copy( aModuleName.Mid( 0, KTestScripterNameLength ) );
+			return KErrNone;
+			}
+		}
+
+	// Check that length is greated than KTestScripterNameLength
+	if( aModuleName.Length() >= KPythonScripterLength )
+		{
+		TPtrC check( aModuleName.Mid( 0, KPythonScripterLength ) );
+		TInt ret = check.Compare( KPythonScripter );
+		if( ret == KErrNone )
+			{
+			aNewModuleName.Copy( aModuleName.Mid( 0, KPythonScripterLength ) );
+			return KErrNone;
+			}
+		}
+
+    return KErrNotFound;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: -
+
+    Method: RemoveOptionalIndex
+
+    Description: Remove optional index appended to module name.
+                 If it is found (@ char) then set new module name without it.
+                 This feature is used when iSeparateProcesses is set in
+                 TestEngine.
+
+    Parameters: TFileName aModuleName: in: Module name for checking.
+                TFileName& aNewModuleName: inout: Parsed module name.
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void RemoveOptionalIndex(const TDesC& aModuleName, TDes& aNewModuleName)
+    {
+    //Copy module name to destination buffer
+    aNewModuleName.Copy(aModuleName);
+    
+    //Search for @ char (it means that some index has been appended)
+    TInt index = aNewModuleName.Find(_L("@"));
+    
+    //Remove index form name (if found)
+    if(index != KErrNotFound)
+        {
+        aNewModuleName.Delete(index, aNewModuleName.Length() - index);
+        }
+    }
+
+// End of File