stif/TestEngine/src/TestModuleController.cpp
changeset 0 a03f92240627
child 10 381827f66490
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stif/TestEngine/src/TestModuleController.cpp	Tue Feb 02 01:57:15 2010 +0200
@@ -0,0 +1,3101 @@
+/*
+* 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 
+* CTestModuleController class member functions.
+*
+*/
+
+// INCLUDE FILES
+#include <e32svr.h>
+#include <stifinternal/TestServerClient.h>
+#include <StifLogger.h>
+#include "TestEngine.h"
+#include "TestModuleController.h"
+#include "Logging.h"
+
+// EXTERNAL DATA STRUCTURES
+// None
+
+// EXTERNAL FUNCTION PROTOTYPES
+// None
+
+// CONSTANTS
+// None
+
+// MACROS
+// None
+
+// LOCAL CONSTANTS AND MACROS
+// None
+
+// MODULE DATA STRUCTURES
+// None
+
+// LOCAL FUNCTION PROTOTYPES
+// None
+
+// FORWARD DECLARATIONS
+// None
+
+// ==================== LOCAL FUNCTIONS =======================================
+// None
+
+#define LOGGER iEngine->Logger()
+
+// ================= MEMBER FUNCTIONS =========================================
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: CTestModuleController
+
+    Description: Default constructor
+
+    C++ default constructor can NOT contain any code, that
+    might leave.
+
+    Parameters: CTestEngine* aEngine: in: Pointer to CTestEngine
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CTestModuleController::CTestModuleController( CTestEngine* aEngine ) :
+    CActive( CActive::EPriorityStandard ),
+    iEngine( aEngine ),
+    iState( ETestModuleIdle )
+    {
+    CActiveScheduler::Add( this );
+    iTestScripterController = NULL;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: ConstructL
+
+    Description: Symbian OS second phase constructor
+
+    Symbian OS default constructor can leave.
+
+    Parameters: const TName& aName: in: Test module name
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if memory allocation for iConfigFiles fails
+                       Leaves if memory allocation for iTestCaseArray fails
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleController::ConstructL( 
+                            const TName& aName,
+                            TBool aAfterReboot,
+                            CTestScripterController* aTestScripterController )
+    {
+    iTestScripterController = aTestScripterController;
+    iTestScripterIndicator = 0;
+    
+    iAfterReboot = aAfterReboot;
+
+    __TRACE ( KInit, ( _L( "Creating CTestModuleController [%S]" ), &aName ) );
+
+    iTestCaseArray = RPointerArray<TTestCaseArray>();
+
+    // Check aName length
+    if( aName.Length() <= 0 )
+        {
+        iEngine->LeaveWithNotifyL( KErrArgument );
+        }
+
+    // Remove optional '.DLL' from file name
+    TName name = aName;
+    name.LowerCase();
+    TParse parse;
+    parse.Set( name, NULL, NULL );
+
+    if ( parse.Ext() == _L(".dll") )
+        {
+        const TInt len = parse.Ext().Length();
+        name.Delete ( name.Length()-len, len );
+        }
+
+    iName = name.AllocL();
+
+    // HBufC to TPtrC
+    TPtrC atsName;
+
+    TFileName newNameBuffer;
+    TInt check = GenerateModuleName( iName->Des(), newNameBuffer );
+    if( check == KErrNone )
+        {
+        // Load the module(TestScripter)
+        atsName.Set( newNameBuffer );
+        }
+    else
+        {
+        // Load the module(Others)
+        atsName.Set( iName->Des() );
+        }
+
+    // Moved the implementation to a new function, ConstructASTLoggerL, due to
+    // CW 3.0 compiler error with multiple TRAPDs
+    TRAPD(err, ConstructASTLoggerL( atsName, aAfterReboot));
+
+    if( err != KErrNone )
+        {
+         __TRACE ( KError, ( _L( "CTestModuleController[%S]::ConstructL: Creation of ATS logger failed" ), iName ) );
+        iEngine->LeaveWithNotifyL( err, _L("Creation of ATS logger failed") );
+        }
+
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: ConstructASTLoggerL
+
+    Description: Construct ATS logger
+
+    Parameters: TDesC& atsName, TBool& aAfterReboot
+
+    Return Values: TInt
+
+    Errors/Exceptions: Leaves if error got from ATS logger NewL
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+
+TInt CTestModuleController::ConstructASTLoggerL( TDesC& atsName, TBool& aAfterReboot )
+    {
+    TRAPD( err, iAtsLogger = CAtsLogger::NewL( atsName, aAfterReboot ); );
+    if( err == KErrNotFound && aAfterReboot )
+        {
+        // If file does not exist, create new 
+        aAfterReboot = EFalse;
+        iAtsLogger = CAtsLogger::NewL( atsName, aAfterReboot );
+        }
+    User::LeaveIfError( err );
+    iAtsLogger->SetFullReporting( ETrue );
+    if( aAfterReboot )
+        {
+        iAtsLogger->ContinueAfterRebootL();
+        }
+    else
+        {
+        // Begin reporting
+        iAtsLogger->BeginTestReportL();
+          
+        // Begin test set
+        iAtsLogger->BeginTestSetL();
+        }
+    return KErrNone;
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: InitL
+
+    Description: Initialize test module.
+
+    Parameters: TFileName& aIniFile: in: Initialization file of Test Module
+                const TDesC& aConfigFile: in: Test case(config) file name(Used 
+                in TestScripter case).
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if error got from Test Server
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleController::InitL( TFileName& aIniFile, 
+                                    const TDesC& aConfigFile )
+    {
+    __TRACE( KInit, (_L( "Initialising test module [%S] with initialization file [%S]" ),
+        iName, &aIniFile ) );
+
+    // HBufC to TPtrC
+    TPtrC name( iName->Des() );
+
+    // Connect to server
+    TInt r = iServer.Connect( name, aConfigFile );
+
+    if ( r != KErrNone )
+        {
+        __TRACE( KError, ( CStifLogger::ERed, _L( "Can't connect to test module [%S], IniFile [%S]" ), &name, &aIniFile ) );
+        LeaveWithNotifyL( r,  _L( "Can't connect to test module" ) );
+        }
+
+    // Open session 
+    r = iModule.Open( iServer, aIniFile );
+    if ( r != KErrNone )
+        {
+        __TRACE( KError, ( CStifLogger::ERed, _L( "Can't open session to test module [%S], IniFile=[%S]" ), &name, &aIniFile ) );
+        LeaveWithNotifyL( r, _L( "Can't open session to test module" ) );
+        }
+
+    iErrorPrinter = CErrorPrinter::NewL( iEngine );
+    iErrorPrinter->StartL( iModule );
+
+    iServerStateHandler = CServerStateHandler::NewL( iEngine, this );
+    iServerStateHandler->StartL( iServer );
+    __TRACE( KInit, (_L( "Initialising test module [%S] with initialization file [%S] done" ),
+        iName, &aIniFile ) );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: NewL
+
+    Description: Two-phased constructor.
+
+    Parameters: CTestEngine* aEngine: in: CTestEngine object.
+                const TName& aName: in: module name.
+                TBool aAfterReboot: in: reboot indicator.
+                TBool aCreateTestScripterCont: in: Indications to
+                TestModule or TestScripter creation
+                CTestScripterController* aTestScripterController: in:
+                CTestEngine object.
+
+
+    Return Values: CTestModuleController* : pointer to created object
+
+    Errors/Exceptions: Leaves if called ConstructL method leaves
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestModuleController* CTestModuleController::NewL( 
+                            CTestEngine* aEngine,
+                            const TName& aName,
+                            TBool aAfterReboot,
+                            TBool aCreateTestScripterCont,
+                            CTestScripterController* aTestScripterController )
+    {
+    // Create CTestScripterController
+    if( aCreateTestScripterCont )
+        {
+        CTestScripterController* testScripterController = NULL;
+        testScripterController = CTestScripterController::NewL(
+            aEngine, aName, aAfterReboot );
+        return testScripterController;  
+        }
+
+
+    CTestModuleController* self =
+        new ( ELeave ) CTestModuleController( aEngine );
+    CleanupStack::PushL( self );
+    self->ConstructL( aName, aAfterReboot, aTestScripterController );
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: ~CTestModuleController
+
+    Description: Destructor
+
+    Deallocate all allocated resources
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CTestModuleController::~CTestModuleController()
+    {
+
+    // If CTestScripterController is created there is deleted base class(
+    // CTestModuleController) also and this has no iName.
+    if( iName )
+        {
+        __TRACE(KVerbose, (_L( "Deleting CTestModuleController [%S]" ), iName ) );
+        }
+
+    Cancel();
+
+    // If CTestScripterController is created there is deleted base class(
+    // CTestModuleController) also and this has no iAtsLogger.
+    if( iAtsLogger )
+        {
+        // End test set
+        TRAPD( err, iAtsLogger->EndTestSetL() );
+        // End AtsLogger reporting, has to be trapped in destructor
+        TRAPD( err2, iAtsLogger->EndTestReportL() );
+        if( ( err != KErrNone ) || ( err2 != KErrNone ) )
+            {
+            // Print error if error got from trap
+            __TRACE( KError, ( 
+                _L( "Destructor of CTestModuleController [%S]: XML log closing failed" ),
+                iName ) );
+            }
+        }
+
+    // Delete Atslogger
+    delete iAtsLogger;
+
+    // Stop error printer
+    delete iErrorPrinter;
+    iErrorPrinter = NULL;
+    // Delete server state handler
+    delete iServerStateHandler;
+    iServerStateHandler = NULL;
+
+    // Close RTestModule session
+    iModule.Close();
+    // Close RTestServer session
+    iServer.Close();
+
+    // Release the test case array
+    iTestCaseArray.Close();
+
+    // Release the config file array
+    iConfigFiles.Close();
+
+    // Release the config file array
+    iFailedEnumerateConfig.Reset();
+    iFailedEnumerateConfig.Close();
+    
+    // Release the children array
+    iChildrenControllers.ResetAndDestroy();
+    iChildrenControllers.Close();
+
+    delete iName;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: AddConfigFileL
+
+    Description: Add config file
+
+    Parameters: TFileName& aConfigFile: in: Config file for Test Module
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if AppendL leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleController::AddConfigFileL( TFileName& aConfigFile )
+    {
+    __TRACE( KInit,
+        ( _L( "CTestModuleController::AddConfigFileL [%S] aConfigFile=[%S]" ),
+        iName, &aConfigFile ) );
+    // Check that this config file does not already exists
+    for ( TInt i = 0; i < iConfigFiles.Count(); i++ )
+        {
+        // HBufC to TPtrC
+        TPtrC name( iConfigFiles[i]->Des() );
+        if ( KErrNone == aConfigFile.CompareF( name ) )
+            {
+            LeaveWithNotifyL( KErrAlreadyExists,  
+                _L( "Adding config file failed: Config file already exists" ) );
+            }
+        }
+    HBufC* configFile = aConfigFile.AllocLC();
+
+    User::LeaveIfError( iConfigFiles.Append( configFile ) );
+    CleanupStack::Pop( configFile );
+
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: RemoveConfigFileL
+
+    Description: Remove config file
+
+    Parameters: TFileName& aConfigFile: in: Config file name
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleController::RemoveConfigFileL( TFileName& aConfigFile )
+    {
+    __TRACE( KInit, ( 
+        _L( "CTestModuleController::RemoveConfigFileL [%S] aConfigFile=[%S]" ),
+        iName, &aConfigFile ) );
+    // Find config file
+    for ( TInt i = 0; i < iConfigFiles.Count(); i++ )
+        {
+        // HBufC to TPtrC
+        TPtrC name( iConfigFiles[i]->Des() );
+        if ( KErrNone == aConfigFile.CompareF( name ) )
+            {
+            HBufC* configFile = iConfigFiles[i];
+            iConfigFiles.Remove(i);
+            delete configFile;
+            // Cancel enumerate and free test cases
+            Cancel();
+            FreeTestCases();
+            return;
+            }
+        }
+        
+    LeaveWithNotifyL( KErrNotFound, 
+        _L( "Removing config file failed: Config file not found" ) );
+            
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: StartEnumerateL
+
+    Description: Start test case enumeration
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleController::StartEnumerateL()
+    {
+    __TRACE( KVerbose, ( 
+        _L( "CTestModuleController::StartEnumerateL [%S]" ), iName ) ); 
+    iTestCaseCount = 0;
+    iEnumerateCount = 0;
+    iFailedEnumerateCount = 0;
+    iFailedEnumerateConfig.Reset();
+    iEnumerateComplete = EFalse;
+
+    iState = ETestModuleEnumerateCases;
+
+    if ( iConfigFiles.Count() > 0 )
+        {
+        // HBufC to TPtrC
+        iEnumConfigFile.Set( iConfigFiles[0]->Des() );
+        }
+
+    __TRACE( KInit, ( 
+        _L( "Getting testcases from module [%S], test case file [%S]" ),
+        iName, &iEnumConfigFile ) );
+
+    SetActive();
+    iModule.EnumerateTestCases( iEnumConfigFile, iEnumResultPackage, iStatus );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: RunL
+
+    Description: RunL handles completed requests.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if iStatus is not KErrNone
+                       Leaves if some of called leaving methods leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleController::RunL()
+    {
+
+    // If CTestScripterController is used then move execution to the
+    // CTestScripterController size
+    if( iTestScripterController )
+        {
+        iTestScripterController->RunLEmulator( this );
+        return;
+        }
+
+    __TRACE( KVerbose, ( _L( "CTestModuleController::RunL [%S] [iStatus = %d]"),
+        iName, iStatus.Int() ) );
+
+    // Note:
+    // If test case not found there may be existing cases from previous
+    // enumerations, so those cases are valid. e.g. case: "add test case file",
+    // "add test case file that not exist" and "get test cases".
+
+    TInt ret( KErrNone );
+    // Check that request was successful
+    if( iStatus.Int() == KErrNone )
+        {
+        // Get enumerated test cases and append them to array
+        CFixedFlatArray<TTestCaseInfo>* testCases = 
+            CFixedFlatArray<TTestCaseInfo>::NewL( iEnumResultPackage() );
+        CleanupStack::PushL( testCases );
+        ret = iModule.GetTestCases( *testCases );
+        __TRACE( KInit, ( _L( "RunL()'s GetTestCases method returns: %d" ), ret ) );
+
+        iTestCaseCount += testCases->Count();
+
+        if ( testCases->Count() == 0 )
+            {
+
+            if (iConfigFiles.Count() > 0)
+                {
+                __TRACE( KInit, ( CStifLogger::EBold, 
+                    _L( "Module [%S], test case file [%S] returned 0 cases" ),
+                    iName,  iConfigFiles[iEnumerateCount] ) );
+                }
+            else
+                {
+                __TRACE( KInit, ( CStifLogger::EBold, 
+                    _L( "Module [%S] without test case file, returned 0 cases" ),
+                    iName ) );
+                }
+            iEngine->ErrorPrint( 1, _L("Someone returned 0 test cases. Check testengine log"));
+            iAtsLogger->CommentL( _L("Test module returned 0 test cases") );   
+            }
+
+        // Store test cases for later use
+        User::LeaveIfError( iTestCaseArray.Append( testCases ) );
+        CleanupStack::Pop( testCases );
+        
+        }
+    else
+        {
+        // Calculate failed enumeration count
+        iFailedEnumerateCount++;
+        // Add failed config(test case) file to array for later removing
+        if( iConfigFiles.Count() != NULL )
+            {
+            __TRACE( KError, (
+                CStifLogger::ERed, 
+                _L( "Test case[%S] enumeration fails with error: %d" ),
+                iConfigFiles[iEnumerateCount], iStatus.Int() ) );
+            // Append
+            iFailedEnumerateConfig.Append( iConfigFiles[iEnumerateCount] );
+            }
+        }
+
+    iEnumerateCount++;
+
+    if ( iEnumerateCount < iConfigFiles.Count() )
+        {
+        // Continue enumeration
+        __TRACE( KInit, ( 
+            _L( "Getting testcases from module [%S], test case file [%S]" ),
+            iName, iConfigFiles[iEnumerateCount] ) );
+        SetActive();
+        iModule.EnumerateTestCases( *iConfigFiles[iEnumerateCount],
+                                    iEnumResultPackage, iStatus );
+        }
+    else if( iTestCaseCount == 0 )
+        {
+        // Total count of succesfully enumerations
+        iEnumerateCount -= iFailedEnumerateCount;
+        User::Leave( KErrNotFound );
+        }
+    else
+        {
+        // Total count of succesfully enumerations
+        iEnumerateCount -= iFailedEnumerateCount;
+        // Remove faulty config (test case) file(s)
+        for( TInt a= 0; a < iFailedEnumerateConfig.Count(); a++ )
+            {
+            TInt index( 0 );
+            // Find removed config(test case) file
+            index = iConfigFiles.Find( iFailedEnumerateConfig[a] );
+            if( index != KErrNotFound )
+                {
+                __TRACE( KInit, ( _L( "Removing test case file[%S]" ),
+                    iConfigFiles[index] ) );
+                // Remove
+                iConfigFiles.Remove( index );
+                }
+            }
+
+        // All test cases enumerated
+        iState = ETestModuleEnumerateCasesCompleted;
+        iEnumerateComplete = ETrue;
+
+        iEngine->EnumerationCompleted( iTestCaseCount );
+        }
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: TestCasesL
+
+    Description: Return Test Cases
+
+    Parameters: None
+
+    Return Values: CFixedFlatArray<TTestInfo>* :Pointer to created array
+
+    Errors/Exceptions: Leaves if NewL leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CFixedFlatArray<TTestInfo>* CTestModuleController::TestCasesL()
+    {
+    CFixedFlatArray<TTestInfo>* testCases = 
+        CFixedFlatArray<TTestInfo>::NewL( iTestCaseCount );
+
+    CleanupStack::PushL( testCases );
+
+    // Loop through all test cases from all config files
+    TInt totalCount = 0;
+    // HBufC to TPtrC
+    TPtrC name( iName->Des() );
+    for ( TInt i = 0; i < iEnumerateCount; i++ )
+        {
+        TTestInfo tmpInfo;
+        tmpInfo.iModuleName = name;
+        if ( iConfigFiles.Count() > 0 )
+            {
+            tmpInfo.iConfig = *iConfigFiles[i];
+            }
+
+        // Get test cases from iTestCaseArray at [i]
+        //if( (iTestCaseArray)[i] )
+		if ( iTestCaseArray.Count() > 0) 
+            {
+            CFixedFlatArray<TTestCaseInfo>* tempTestCases = (iTestCaseArray)[i];
+            for ( TInt j = 0; j < tempTestCases->Count(); j++ )
+                {
+                tmpInfo.iTestCaseInfo = (*tempTestCases)[j];
+                // Set TestCaseInfo to testCases array
+                testCases->Set( totalCount, tmpInfo );
+                totalCount++;
+                }
+            }
+        }
+
+    CleanupStack::Pop( testCases );
+
+    return testCases;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: FreeTestCases
+
+    Description: Free memory used for test cases
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleController::FreeTestCases()
+    {
+    // Reset and destroy test cases
+    iTestCaseArray.ResetAndDestroy();
+    iTestCaseArray.Close();
+
+    iTestCaseCount = 0;
+    iEnumerateComplete = EFalse;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: DoCancel
+
+    Description: Cancel active request
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleController::DoCancel()
+    {
+
+    // If CTestScripterController is used then move execution to the
+    // CTestScripterController size
+    if( iTestScripterController )
+        {
+        iTestScripterController->DoCancelEmulator( this );
+        return;
+        }
+
+    __TRACE( KVerbose, ( _L( "CTestModuleController::DoCancel [%S]" ), iName ) );
+
+    switch ( iState )
+        {
+        case ETestModuleEnumerateCases:
+            iModule.CancelAsyncRequest( ETestModuleEnumerateTestCases );
+            iEnumerateComplete = ETrue;
+            // Enumeration canceled, complete with KErrCancel
+            iEngine->EnumerationCompleted( 0, KErrCancel );
+
+            // Free allocated test cases because EnumerateTestCases was
+            // canceled
+            FreeTestCases();
+            break;
+        case ETestModuleIdle:
+        case ETestModuleEnumerateCasesCompleted:
+        default:
+            // DoCancel called in wrong state => Panic
+            _LIT( KTestModuleController, "CTestModuleController" );
+            User::Panic( KTestModuleController, EDoCancelDisorder );
+            break;
+        }
+
+    iAtsLogger->ErrorL( _L("Test case enumeration cancelled") );   
+
+    iState = ETestModuleIdle;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: RunError
+
+    Description: Handle errors.
+
+    Parameters: TInt aError: in: Symbian OS error: Error code
+
+    Return Values: TInt KErrNone: Always returned KErrNone
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestModuleController::RunError( TInt aError )
+    {
+
+    // If CTestScripterController is used then move execution to the
+    // CTestScripterController size
+    if( iTestScripterController )
+        {
+        return iTestScripterController->RunErrorEmulator( aError, this );
+        }
+
+    __TRACE( KError, ( CStifLogger::ERed, 
+        _L( "CTestModuleController::RunError [%S] aError=[%d]" ),
+        iName, aError ) );
+    if( aError == KErrNoMemory )
+        {
+        __TRACE( KError, ( CStifLogger::ERed, 
+            _L( "No memory available. Test case file's size might be too big." ) ) );
+        }
+
+    iEnumerateComplete = ETrue;
+
+    iAtsLogger->ErrorL( _L("Test module did not return any test cases") );
+    
+    _LIT( KErrorText, " did not return any test cases [error: ");
+    if( KErrorText().Length() + iName->Length() + 1 < KMaxName )
+        {
+        // Enumeration failed, print warning and complete with KErrNone
+        TName error( iName->Des() );
+        error.Append( KErrorText );  
+        error.AppendNum( aError );  
+        error.Append( _L("]") );  
+        iEngine->ErrorPrint ( 0, error );
+    
+        iEngine->EnumerationCompleted( 0, KErrNone );
+        }
+    else 
+        {
+        // Cannot only print warning, complete with error
+        iEngine->EnumerationCompleted( 0, aError );
+        }        
+
+    // Free allocated test cases because EnumerateTestCases failed
+    FreeTestCases();
+    iEnumerateComplete = ETrue;
+
+    return KErrNone;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: Server
+
+    Description: Return handle to Test Server
+
+    Parameters: TTestInfo& aTestInfo: in: Test info for this test case
+
+    Return Values: RTestServer& : Reference to RTestServer
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+RTestServer& CTestModuleController::Server( TTestInfo& /*aTestInfo*/ )
+    {
+    return iServer;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: GetFreeOrCreateModuleControllerL
+
+    Description: Return pointer to module controller.
+                 Find module controller which does not run test case
+                 and if this is not possible then create new one.
+                 (Only for test scripter).
+
+    Parameters: TTestInfo& aTestInfo: in: Test info for this test case
+                TBool aUITestingSupport: in: Is UI testing mode enabled
+
+    Return Values: CTestModuleController* : pointer to module controller
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CTestModuleController* CTestModuleController::GetFreeOrCreateModuleControllerL(TTestInfo& /*aTestInfo*/, TBool /*aUItestingSupport*/)
+    {
+    return NULL;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: ModuleName
+
+    Description: Return the name of Test Module
+
+    Parameters: const TDesC& aModuleName: in Modulename
+
+    Return Values: const TDesC : Name of Test Module
+
+    Errors/Exceptions: None
+
+    Status: proposal
+
+-------------------------------------------------------------------------------
+*/
+const TDesC& CTestModuleController::ModuleName( const TDesC& /*aModuleName*/ )
+    {
+    return *iName;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: EnumerationComplete
+
+    Description: Is enumeration of test cases complete.
+
+    Parameters: None
+    
+    Return Values: TBool ETrue: Enumeration of test cases is complete
+                         EFalse: Enumeration is not complete
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TBool CTestModuleController::EnumerationComplete()
+    {
+    return iEnumerateComplete;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: LeaveWithNotifyL
+
+    Description: Print out info and leave.
+
+    Parameters: TInt aCode: in: Error code 
+                const TDesC& aText: in: Test info
+    
+    Return Values: None
+    
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CTestModuleController::LeaveWithNotifyL( TInt aCode, const TDesC& aText )
+    {
+
+    __TRACE( KError, ( CStifLogger::ERed, aText ) );
+    if( iAtsLogger )
+        {
+        iAtsLogger->ErrorL( aText );
+        }
+    iEngine->LeaveWithNotifyL( aCode );
+
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: CaseCreated
+
+    Description: Increases the value of iTestCaseCounter
+
+    Parameters: None
+    
+    Return Values: None
+    
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/  
+void CTestModuleController::CaseCreated()
+    {
+    // Number of ongoing testcases
+    iTestCaseCounter++;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: CaseFinished
+
+    Description: Decreases the value of iTestCaseCounter and deletes this pointer
+                 only in test module crash situations (KErrServerTerminated -15)
+
+    Parameters: None:
+    
+    Return Values: None
+    
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/  
+void CTestModuleController::CaseFinished()
+    {
+    // Number of ongoing testcases
+    iTestCaseCounter--;
+    
+    // iTestModuleCrashDetected tells is TestModuleController cloned or not
+    // TestModuleController is cloned only when testmodule is crashed with KErrServerTerminated -15
+    if (iTestCaseCounter == 0 && iTestModuleCrashDetected)
+       {
+       // Delete this in case where it has been replaced with it clone
+       // and no one have pointer to this. This happens only when test module
+       // crashes    
+  	   delete this;
+  	   // Mem::Fill(this, sizeof(CTestModuleController), 0xa1a1a1a1);
+       }
+       
+    }
+    
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: CloneL
+
+    Description: 
+
+    Parameters: 
+    
+    Return Values: 
+    
+    Errors/Exceptions: 
+
+    Status: 
+
+-------------------------------------------------------------------------------
+*/    
+CTestModuleController* CTestModuleController::CloneL( 
+                            CTestModuleController* aTestModuleController,
+                            TBool aAfterReset,
+                            CTestScripterController* aTestScripterController )
+    {
+    __TRACE( KInit, ( _L( "Cloning CTestModuleController" ) ) );
+   
+    
+    TName crashModuleName;
+    crashModuleName = aTestModuleController->ModuleName( crashModuleName );
+    
+    CTestModuleController* clone = CTestModuleController::NewL( iEngine, crashModuleName, aAfterReset, EFalse, aTestScripterController );
+    
+    clone->InitL( aTestModuleController->iInifile, KNullDesC );
+
+	// Give ATS logger to clone
+	clone->iAtsLogger = iAtsLogger;
+	iAtsLogger = NULL; 
+	
+    for ( TInt i = 0; i < aTestModuleController->iConfigFiles.Count(); i++ )
+	    {
+		TPtrC configFile = aTestModuleController->iConfigFiles[i]->Des();
+		TFileName config = configFile;
+   	    clone->AddConfigFileL( config );
+   	    }   
+	
+	iTestModuleCrashDetected = ETrue;       
+	
+    __TRACE( KVerbose, ( _L( "Cloning of CTestModuleController finished " ) ) );
+    return clone; 
+    }    
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: DeleteModuleController
+
+    Description: In that class this method does nothing. It is implemented
+                 in CTestScripterController.
+
+    Parameters: CTestModuleController* aRealModuleController: not used
+    
+    Return Values: None
+    
+    Errors/Exceptions: None
+
+    Status: 
+
+-------------------------------------------------------------------------------
+*/    
+void CTestModuleController::DeleteModuleController(CTestModuleController* /*aRealModuleController*/)
+    {
+    } 
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: RemoveModuleController
+
+    Description: In that class this method does nothing. It is implemented
+                 in CTestScripterController.
+
+    Parameters: CTestModuleController* aRealModuleController: not used
+    
+    Return Values: None
+    
+    Errors/Exceptions: None
+
+    Status: 
+
+-------------------------------------------------------------------------------
+*/    
+void CTestModuleController::RemoveModuleController(CTestModuleController* /*aRealModuleController*/)
+    {
+    } 
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestModuleController
+
+    Method: EnumerateSynchronously
+
+    Description: Enumerates test module controller. Used only when new
+                 test module controller is created during test case
+                 execution.
+
+    Parameters: None
+    
+    Return Values: None
+    
+    Errors/Exceptions: None
+
+    Status: 
+
+-------------------------------------------------------------------------------
+*/    
+void CTestModuleController::EnumerateSynchronously(void)
+    {
+    TInt i;
+    TInt cfgfiles = iConfigFiles.Count();
+    __TRACE(KInit, (_L("Module controller will enumerate synchronously [%d] config files"), cfgfiles));
+    
+    for(i = 0; i < cfgfiles; i++)
+        {
+        TRequestStatus status; 
+        iModule.EnumerateTestCases(*iConfigFiles[i],
+                                   iEnumResultPackage, 
+                                   status);
+        User::WaitForRequest(status);
+        }
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    DESCRIPTION
+
+    This module contains implementation of CTestScripterController class member
+    functions.
+
+-------------------------------------------------------------------------------
+*/
+#define LOGGER iEngine->Logger()
+
+// ================= MEMBER FUNCTIONS =========================================
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: CTestScripterController
+
+    Description: Default constructor
+
+    C++ default constructor can NOT contain any code, that
+    might leave.
+
+    Parameters: CTestEngine* aEngine: in: Pointer to CTestEngine
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CTestScripterController::CTestScripterController( CTestEngine* aEngine ) :
+    CTestModuleController( aEngine )
+    {
+    // None
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: ConstructL
+
+    Description: Symbian OS second phase constructor
+
+    Symbian OS default constructor can leave.
+
+    Parameters: const TName& aName: in: Test module name
+                TBool aAfterReboot: in: Reboot indication
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::ConstructL( const TName& aName,
+                                          TBool aAfterReboot )
+    {
+    __TRACE( KInit, ( 
+        _L( "NOTE: Test module is TestScripter and each test case(config) file(s) will have own server(s)" ) ) );
+
+    // Remove optional '.DLL' from file name
+    TName name = aName;
+    name.LowerCase();
+    TParse parse;
+    parse.Set( name, NULL, NULL );
+
+    if ( parse.Ext() == _L(".dll") )
+        {
+        const TInt len = parse.Ext().Length();
+        name.Delete ( name.Length()-len, len );
+        }
+
+    iName = name.AllocL();
+
+    iAfterReboot = aAfterReboot;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: InitL
+
+    Description: Initialize test module.
+
+    Parameters: TFileName& aIniFile: in: Initialization file of Test Module
+                const TDesC& aConfigFile: in: Test case(config) file name(Used 
+                in TestScripter case).
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::InitL( TFileName& aIniFile, 
+                                     const TDesC& /*aConfigFile*/ )
+    {
+    // Take initialization file of Test Module
+    iInifile = aIniFile;
+
+    // Just empty, don't create TestServer operations. TestServer
+    // creation will be do in AddTestCaseFile()-method.
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: NewL
+
+    Description: Two-phased constructor.
+
+    Parameters: CTestEngine* aEngine: in: CTestEngine object
+                const TName& aName: in: Test module name
+                TBool aAfterReboot: in: Reboot indication
+
+    Return Values: CTestScripterController* : pointer to created object
+
+    Errors/Exceptions: Leaves if called ConstructL method leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CTestScripterController* CTestScripterController::NewL( CTestEngine* aEngine,
+                                                        const TName& aName,
+                                                        TBool aAfterReboot )
+    {
+    CTestScripterController* self =
+        new ( ELeave ) CTestScripterController( aEngine );
+    CleanupStack::PushL( self );
+    self->ConstructL( aName, aAfterReboot );
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: ~CTestScripterController
+
+    Description: Destructor
+
+    Deallocate all allocated resources. Delete CTestScripterController's
+    CTestModuleController(s). After this is deleted base class also, see:
+    CTestModuleController::~CTestModuleController(). 
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CTestScripterController::~CTestScripterController()
+    {
+    // Delete CTestScripterController(s).
+    iTestScripter.ResetAndDestroy();
+    iTestScripter.Close();
+
+    // After this is deleted base class also, see:
+    // CTestModuleController::~CTestModuleController(). 
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: AddConfigFileL
+
+    Description: Add config file.
+                 - Creates CTestModuleController(Gives test case file name)
+                 - Initializes CTestModuleController( creates a server session)
+                 - Adds config file
+
+    Parameters: TFileName& aConfigFile: in: Config file for TestScripter
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if AppendL leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::AddConfigFileL( TFileName& aConfigFile )
+    {
+    // Check that this config file does not already exists
+    for(  TInt a = 0; a < iTestScripter.Count(); a++ )
+        {
+        for ( TInt i = 0; i < iTestScripter[a]->iConfigFiles.Count(); i++ )
+            {
+            // HBufC to TPtrC
+            TPtrC name( iTestScripter[a]->iConfigFiles[i]->Des() );
+            if ( KErrNone == aConfigFile.CompareF( name ) )
+                {
+                LeaveWithNotifyL( KErrAlreadyExists,  
+                    _L( "Adding config file failed: Config file already exists" ) );
+                }
+            }
+        }
+
+    __TRACE( KInit, ( 
+        _L( "CTestScripterController::AddConfigFileL aConfigFile=[%S]" ) ,
+        &aConfigFile ) );
+
+    HBufC* testScripterAndTestCaseFile = NULL; // InitL() takes TFileName
+    testScripterAndTestCaseFile = CreateTestScripterNameL( 
+                                            aConfigFile,
+                                            testScripterAndTestCaseFile );
+    // Add to cleanup stack here, because CreateTestScripterNameL needs to be
+    // trapped in other methods.
+    CleanupStack::PushL( testScripterAndTestCaseFile );
+
+    //Create server and active object(This uses CTestModuleController::InitL())
+    CTestModuleController* module = CTestModuleController::NewL( 
+                                        iEngine,
+                                        testScripterAndTestCaseFile->Des(),
+                                        iAfterReboot, EFalse, this );
+    CleanupStack::PopAndDestroy( testScripterAndTestCaseFile );
+    CleanupStack::PushL( module );
+
+    User::LeaveIfError( iTestScripter.Append( module ) );
+
+    // Now is used TestScripter so give test case file also(used
+    // in caps modifier cases). 
+    TRAPD ( err, module->InitL( iInifile, aConfigFile ) );
+    if( err != KErrNone )
+        {
+        __TRACE( KInit, ( _L( "InitL fails with error: %d" ), err ) );
+        User::Leave( err );
+        }
+
+    module->AddConfigFileL( aConfigFile );
+
+    CleanupStack::Pop( module );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: RemoveConfigFileL
+
+    Description: Remove config file
+
+    Parameters: TFileName& aConfigFile: in: Config file name
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::RemoveConfigFileL( TFileName& aConfigFile )
+    {
+     __TRACE( KInit, ( _L( "CTestScripterController::RemoveConfigFileL" ) ) );
+
+    HBufC* testScripterAndTestCaseFile = NULL;
+    testScripterAndTestCaseFile = CreateTestScripterNameL( aConfigFile,
+                                         testScripterAndTestCaseFile );
+    // Add to cleanup stack here, because CreateTestScripterNameL needs to be
+    // trapped in other methods.
+    CleanupStack::PushL( testScripterAndTestCaseFile );
+
+    // Get correct iTestScripter
+    TInt index( -1 );
+    for( TInt a = 0; a < iTestScripter.Count(); a++ )
+        {
+        if( ( iTestScripter[a]->iName->CompareF( 
+                        testScripterAndTestCaseFile->Des() ) == KErrNone ) )
+            {
+            index = a;
+            break;
+            }
+        }
+
+    CleanupStack::PopAndDestroy( testScripterAndTestCaseFile );
+
+    if( index == -1 )
+        {
+        LeaveWithNotifyL( KErrNotFound, 
+            _L( "Removing config file failed: Config file not found" ) );
+        }
+
+    __TRACE( KInit, ( 
+        _L( "CTestScripterController[%S]::RemoveConfigFileL aConfigFile=[%S]"),
+        iTestScripter[index]->iName, &aConfigFile ) );
+
+    // Find config file
+    for ( TInt i = 0; i < iTestScripter[index]->iConfigFiles.Count(); i++ )
+        {
+        // HBufC to TPtrC
+        TPtrC name( iTestScripter[index]->iConfigFiles[i]->Des() );
+        if ( KErrNone == aConfigFile.CompareF( name ) )
+            {
+            HBufC* configFile = iTestScripter[index]->iConfigFiles[i];
+            iTestScripter[index]->iConfigFiles.Remove(i);
+            delete configFile;
+            // Cancel enumerate and free test cases
+            Cancel();
+            FreeTestCases();
+            // Testcasefile(config) is found, so we can return
+            return;
+            }
+        }
+
+    LeaveWithNotifyL( KErrNotFound, 
+        _L( "Removing config file failed: Config file not found" ) );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: StartEnumerateL
+
+    Description: Start test case enumeration
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: LeaveWithNotifyL if no test case added. 
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::StartEnumerateL()
+    {
+    if( iTestScripter.Count() <= 0 )
+        {
+        RDebug::Print( 
+            _L( "There is no test case file for TestScripter registered yet. Enumeraton aborted." ) );
+        LeaveWithNotifyL( KErrNotFound,
+            _L( "There is no test case file for TestScripter registered yet. Enumeraton aborted." ) );
+        return;
+        }
+
+    for( TInt a = 0; a < iTestScripter.Count(); a++ )
+        {
+        __TRACE( KVerbose, ( 
+                _L( "CTestScripterController[%S]::StartEnumerateL" ),
+                iTestScripter[a]->iName ) );
+        iTestScripter[a]->iTestCaseCount = 0;
+        iTestScripter[a]->iEnumerateCount = 0;
+        iTestScripter[a]->iFailedEnumerateCount = 0;
+        iTestScripter[a]->iFailedEnumerateConfig.Reset();
+        iTestScripter[a]->iEnumerateComplete = EFalse;
+
+        iTestScripter[a]->iState = ETestModuleEnumerateCases;
+        
+        if ( iTestScripter[a]->iConfigFiles.Count() > 0 )
+            {
+            // HBufC to TPtrC
+            iTestScripter[a]->iEnumConfigFile.Set( 
+                                iTestScripter[a]->iConfigFiles[0]->Des() );
+            }
+
+        __TRACE( KInit, ( 
+            _L( "Getting testcases from module [%S], test case file[%S]" ),
+            iTestScripter[a]->iName, &iTestScripter[a]->iEnumConfigFile ) );
+        
+        iTestScripter[a]->SetActive();
+        iTestScripter[a]->iModule.EnumerateTestCases( 
+                                    iTestScripter[a]->iEnumConfigFile,
+                                    iTestScripter[a]->iEnumResultPackage,
+                                    iTestScripter[a]->iStatus );
+        } // End of for-loop
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: GetCurrentIndex
+
+    Description: Get current CTestScripterController.
+
+    Parameters: CTestModuleController* aTestModuleController: in:
+                Pointer current to CTestModuleController
+
+    Return Values: KErrNotFound returned if CTestModuleController not found
+                   else current index returned.
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestScripterController::GetCurrentIndex( CTestModuleController*
+                                                    aTestModuleController )
+    {
+    // Get correct iTestScripter
+    return iTestScripter.Find( aTestModuleController );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: RunL
+
+    Description: RunL handles completed requests.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::RunL()
+    {
+    // Should never come here because one TestScripter have one test case
+    // file per server session.
+    // CTestScripterController's base class is an active object but this class
+    // not used as an active object. So there not used RunL => Panic.
+
+    User::Panic( _L( "CTestScripterController::RunL()" ), KErrCorrupt );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: RunLEmulator
+
+    Description: RunLEmulator handles completed requests(Emulates RunL()).
+                 This is called from CTestModuleController::RunL.
+
+    Parameters: CTestModuleController* aTestModuleController: in: pointer to
+                CTestModuleController.
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves if some of called leaving methods leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::RunLEmulator( CTestModuleController*
+                                                    aTestModuleController )
+    {
+    iTestScripterIndicator++;
+    TInt index = GetCurrentIndex( aTestModuleController );
+    if( index < KErrNone )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    __TRACE( KVerbose, ( 
+        _L( "CTestScripterController[%S]::RunLEmulator [iStatus = %d]"),
+        iTestScripter[index]->iName, iTestScripter[index]->iStatus.Int() ) );
+
+    // Note:
+    // If test case not found there may be existing cases from previous
+    // enumerations, so those cases are valid. e.g. case: "add test case file",
+    // "add test case file that not exist" and "get test cases".
+
+    TInt ret( KErrNone );
+
+    // Check that request was successful
+    if( iTestScripter[index]->iStatus.Int() == KErrNone )
+        {
+        // Get enumerated test cases and append them to array
+        CFixedFlatArray<TTestCaseInfo>* testCases = 
+                        CFixedFlatArray<TTestCaseInfo>::NewL( 
+                        iTestScripter[index]->iEnumResultPackage() );
+        CleanupStack::PushL( testCases );
+        ret = iTestScripter[index]->iModule.GetTestCases( *testCases );
+        __TRACE( KInit, ( 
+                _L( "RunL()'s GetTestCases method returns: %d" ), ret ) );
+
+        iTestScripter[index]->iTestCaseCount += testCases->Count();
+
+        if ( testCases->Count() == 0 )
+            {
+
+            if (iTestScripter[index]->iConfigFiles.Count() > 0)
+                {
+                __TRACE( KInit, ( 
+                    CStifLogger::EBold, 
+                    _L( "Module [%S], test case file[%S] returned 0 cases" ),
+                    iTestScripter[index]->iName,
+                    iTestScripter[index]->iConfigFiles[iTestScripter[index]->iEnumerateCount] ) );
+                }
+            else
+                {
+                __TRACE( KInit, ( CStifLogger::EBold,
+                    _L("Module [%S] without test case file, returned 0 cases"),
+                    iTestScripter[index]->iName ) );
+                }
+            iTestScripter[index]->iEngine->ErrorPrint( 1,
+                _L("Someone returned 0 test cases. Check testengine log"));
+            iTestScripter[index]->iAtsLogger->CommentL( 
+                _L("Test module returned 0 test cases") );   
+            }
+
+        // Store test cases for later use
+        User::LeaveIfError( iTestScripter[index]->iTestCaseArray.Append( 
+                                                                testCases ) );
+        CleanupStack::Pop( testCases );
+        
+        }
+    else
+        {
+        // Calculate failed enumeration count
+        iTestScripter[index]->iFailedEnumerateCount++;
+        // Add failed config(test case) file to array for later removing
+        if( iTestScripter[index]->iConfigFiles.Count() != NULL )
+            {
+            __TRACE( KError, (
+                CStifLogger::ERed, 
+                _L( "Test case[%S] enumeration fails with error: %d" ),
+                iTestScripter[index]->iConfigFiles[iTestScripter[index]->iEnumerateCount],
+                iTestScripter[index]->iStatus.Int() ) );
+            // Append
+            iTestScripter[index]->iFailedEnumerateConfig.Append(
+                iTestScripter[index]->iConfigFiles[iTestScripter[index]->iEnumerateCount] );
+            }
+        }
+
+    TInt count = iTestScripter.Count();
+
+    // All TestScripter enumerations is finished for cleaning if necessarily
+    // and complete request up to engine.
+    if( count == iTestScripterIndicator )
+        {
+        TInt testCaseCount( 0 );
+        for( TInt a = 0; a < count; a++  )
+            {
+            // Remove faulty config (test case) file(s) and 
+            // iEnumerateCount not increased.
+            if( iTestScripter[a]->iTestCaseCount == 0 )
+                {
+                // Check that test case file is not allready removed.
+                if( iTestScripter[a]->iConfigFiles.Count() != 0 )
+                    {
+                    iTestScripter[a]->iConfigFiles.Remove( 0 );
+                    }
+                }
+            else
+                {
+                iTestScripter[a]->iEnumerateCount++;
+                testCaseCount += iTestScripter[a]->iTestCaseCount;
+                }
+
+            // All test cases enumerated
+            iTestScripter[a]->iState = ETestModuleEnumerateCasesCompleted;
+            iTestScripter[a]->iEnumerateComplete = ETrue;
+            }
+
+        iTestScripterIndicator = 0; // Initialization back to 0, enumerations
+                                    // are done at this run.
+        iEngine->EnumerationCompleted( testCaseCount );
+        }
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: TestCasesL
+
+    Description: Return Test Cases
+
+    Parameters: None
+
+    Return Values: CFixedFlatArray<TTestInfo>*: Pointer to created array
+
+    Errors/Exceptions: Leaves if NewL leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CFixedFlatArray<TTestInfo>* CTestScripterController::TestCasesL()
+    {
+    TInt testCaseCount( 0 );
+    for( TInt i = 0; i < iTestScripter.Count(); i++  )
+        {
+        testCaseCount += iTestScripter[i]->iTestCaseCount;
+        }
+
+    CFixedFlatArray<TTestInfo>* testCases = 
+        CFixedFlatArray<TTestInfo>::NewL( testCaseCount );
+
+    CleanupStack::PushL( testCases );
+
+    // Loop through all test cases from all config files
+    TInt totalCount = 0;
+    // HBufC to TPtrC
+    for( TInt a = 0; a < iTestScripter.Count(); a++ )
+        {
+        TPtrC name( iTestScripter[a]->iName->Des() );
+        for ( TInt i = 0; i < iTestScripter[a]->iEnumerateCount; i++ )
+            {
+            TTestInfo tmpInfo;
+            tmpInfo.iModuleName = name;
+            if ( iTestScripter[a]->iConfigFiles.Count() > 0 )
+                {
+                tmpInfo.iConfig = *iTestScripter[a]->iConfigFiles[i];
+                }
+
+            // Get test cases from iTestCaseArray at [i]
+            if( (iTestScripter[a]->iTestCaseArray)[i] )
+                {
+                CFixedFlatArray<TTestCaseInfo>* tempTestCases = 
+                                    (iTestScripter[a]->iTestCaseArray)[i];
+                for ( TInt j = 0; j < tempTestCases->Count(); j++ )
+                    {
+                    tmpInfo.iTestCaseInfo = (*tempTestCases)[j];
+                    // Set TestCaseInfo to testCases array
+                    testCases->Set( totalCount, tmpInfo );
+                    totalCount++;
+                    }
+                }
+            }
+        }
+
+    CleanupStack::Pop( testCases );
+
+    return testCases;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: FreeTestCases
+
+    Description: Free memory used for test cases
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::FreeTestCases()
+    {
+    for( TInt a = 0; a < iTestScripter.Count(); a++ )
+        {
+        // Reset and destroy test cases
+        iTestScripter[a]->iTestCaseArray.ResetAndDestroy();
+        iTestScripter[a]->iTestCaseArray.Close();
+
+        iTestScripter[a]->iTestCaseCount = 0;
+        iTestScripter[a]->iEnumerateComplete = EFalse;
+        }
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: DoCancel
+
+    Description: Cancel active request
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::DoCancel()
+    {
+    // Should never come here because one TestScripter have one test case
+    // file per server session.
+    // CTestScripterController's base class is an active object but this class
+    // not used as an active object. So there not used DoCancel => Panic.
+
+    User::Panic( _L( "CTestScripterController::DoCancel()" ), KErrCorrupt );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: DoCancelEmulator
+
+    Description: Cancel active request(Emulates DoCancel)
+                 This is called from CTestModuleController::DoCancel.
+
+    Parameters: CTestModuleController* aTestModuleController: in: pointer to
+                CTestModuleController.
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CTestScripterController::DoCancelEmulator(
+                                CTestModuleController* aTestModuleController )
+    {
+    TInt index = GetCurrentIndex( aTestModuleController );
+    if( index < KErrNone )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    __TRACE( KVerbose, ( 
+        _L( "CTestScripterController[%S]::RunDoCancelEmulator" ),
+        iTestScripter[index]->iName ) );
+
+    switch ( iTestScripter[index]->iState )
+        {
+        case ETestModuleEnumerateCases:
+            iTestScripter[index]->iModule.CancelAsyncRequest(
+                                            ETestModuleEnumerateTestCases );
+            iTestScripter[index]->iEnumerateComplete = ETrue;
+            // Enumeration canceled, complete with KErrCancel
+            iTestScripter[index]->iEngine->EnumerationCompleted(
+                                                            0, KErrCancel );
+
+            // Free allocated test cases because EnumerateTestCases was
+            // canceled
+            FreeTestCases();
+            break;
+        case ETestModuleIdle:
+        case ETestModuleEnumerateCasesCompleted:
+        default:
+            // DoCancel called in wrong state => Panic
+            _LIT( KTestModuleController, "CTestModuleController" );
+            User::Panic( KTestModuleController, EDoCancelDisorder );
+            break;
+        }
+
+    iTestScripter[index]->iAtsLogger->ErrorL( 
+                        _L("Test case enumeration cancelled") );
+    iTestScripter[index]->iState = ETestModuleIdle;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: RunError
+
+    Description: Handle errors.
+
+    Parameters: TInt aError: in: Symbian OS error: Error code
+
+    Return Values: TInt KErrNone: Always returned KErrNone
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestScripterController::RunError( TInt /*aError*/ )
+    {
+    // Should never come here because one TestScripter have one test case
+    // file per server session.
+    // CTestScripterController's base class is an active object but this class
+    // not used as an active object. So there not used RunError => Panic.
+
+    User::Panic( _L( "CTestScripterController::RunError()" ), KErrCorrupt );
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: RunErrorEmulator
+
+    Description: Handle errors(Emulates RunError).
+                 This is called from CTestModuleController::RunError.
+
+    Parameters: TInt aError: in: Symbian OS error: Error code.
+                CTestModuleController* aTestModuleController: in: pointer to
+                CTestModuleController.
+
+    Return Values: TInt KErrNone: Always returned KErrNone
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CTestScripterController::RunErrorEmulator( TInt aError,
+                                CTestModuleController* aTestModuleController )
+    {
+    TInt index = GetCurrentIndex( aTestModuleController );
+    if( index < KErrNone )
+        {
+        User::Leave( KErrNotFound );
+        }
+    
+    __TRACE( KError, ( CStifLogger::ERed,
+        _L( "CTestScripterController[%S]::RunErrorEmulator aError=[%d]" ),
+        iTestScripter[index]->iName, aError ) );
+    if( aError == KErrNoMemory )
+        {
+        __TRACE( KError, ( CStifLogger::ERed, 
+            _L( "No memory available. Test case file's size might be too big." ) ) );
+        }
+
+    iTestScripter[index]->iEnumerateComplete = ETrue;
+
+    iTestScripter[index]->iAtsLogger->ErrorL( 
+                            _L("Test module did not return any test cases") );
+    
+    _LIT( KErrorText, " did not return any test cases [error: ");
+    if( KErrorText().Length() +
+            iTestScripter[index]->iName->Length() +
+            1 < KMaxName )
+        {
+        // Enumeration failed, print warning and complete with KErrNone
+        TName error( iTestScripter[index]->iName->Des() );
+        error.Append( KErrorText );  
+        error.AppendNum( aError );  
+        error.Append( _L("]") );  
+        iEngine->ErrorPrint ( 0, error );
+    
+        iTestScripter[index]->iEngine->EnumerationCompleted( 0, KErrNone );
+        }
+    else 
+        {
+        // Cannot only print warning, complete with error
+        iTestScripter[index]->iEngine->EnumerationCompleted( 0, aError );
+        }
+
+    // Free allocated test cases because EnumerateTestCases failed
+    FreeTestCases();
+    iTestScripter[index]->iEnumerateComplete = ETrue;
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: EnumerationComplete
+
+    Description: Is enumeration of test cases complete.
+
+    Parameters: None
+    
+    Return Values: TBool ETrue: Enumeration of test cases is complete
+                         EFalse: Enumeration is not complete
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TBool CTestScripterController::EnumerationComplete()
+    {
+    for( TInt a = 0; a < iTestScripter.Count(); a++ )
+        {
+        if( !iTestScripter[a]->iEnumerateComplete )
+            {
+            return EFalse;
+            }
+        }
+    return ETrue;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: Server
+
+    Description: Return handle to Test Server
+
+    Parameters: TTestInfo& aTestInfo: in: Test info for this test case
+
+    Return Values: RTestServer& : Reference to RTestServer
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+RTestServer& CTestScripterController::Server( TTestInfo& aTestInfo )
+    {
+    HBufC* testScripterAndTestCaseFile = NULL;
+    TRAPD( ret, testScripterAndTestCaseFile = CreateTestScripterNameL( 
+                                            aTestInfo.iConfig,
+                                            testScripterAndTestCaseFile ) );
+    // Add to cleanup stack here, because CreateTestScripterNameL needs to be
+    // trapped in other methods.
+    CleanupStack::PushL( testScripterAndTestCaseFile );
+    if( ret != KErrNone )
+        {
+        User::Panic( 
+            _L( "CTestScripterController::Server(): CreateTestScripterNameL" ),
+            ret );
+        }
+
+    // Get correct handle
+    TInt index( KErrNotFound );
+    for( TInt a = 0; a < iTestScripter.Count(); a++ )
+        {
+        if( testScripterAndTestCaseFile->Des() == 
+                                            iTestScripter[a]->iName->Des() )
+            {
+            index = a;
+            break;
+            }
+        }
+
+    CleanupStack::PopAndDestroy( testScripterAndTestCaseFile );
+
+    if( index == KErrNotFound )
+        {
+        User::Panic(
+            _L( "CTestScripterController::Server(): Index not found" ),
+            KErrNotFound );
+        }
+
+    // Return handle
+    return iTestScripter[index]->iServer;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: GetFreeOrCreateModuleControllerL
+
+    Description: Return pointer to test module controller.
+                 Find controller which does not run test case
+                 and if this is not possible then create new one.
+
+    Parameters: TTestInfo& aTestInfo: in: Test info for this test case
+                TBool aUITestingSupport: in: Is UI testing mode enabled
+
+    Return Values: CTestModuleController* : pointer to controller
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CTestModuleController* CTestScripterController::GetFreeOrCreateModuleControllerL(TTestInfo& aTestInfo, TBool aUITestingSupport)
+    {
+    HBufC* testScripterAndTestCaseFile = NULL;
+    TRAPD(ret, testScripterAndTestCaseFile = CreateTestScripterNameL(aTestInfo.iConfig, testScripterAndTestCaseFile));
+
+    // Add to cleanup stack here, because CreateTestScripterNameL needs to be trapped in other methods.
+    CleanupStack::PushL(testScripterAndTestCaseFile);
+    if(ret != KErrNone)
+        {
+        User::Panic(_L("CTestScripterController::GetFreeOrCreateModuleControllerL(): CreateTestScripterNameL"), ret);
+        }
+
+    CTestModuleController* resultController = NULL;
+    CTestModuleController* parentController = NULL;
+    TInt j;
+    
+    __TRACE(KInit, (_L("Find free real module controller (or create new one)")));
+
+    // Get handle to correct "parent" module controller
+    __TRACE(KInit, (_L("Searching for parent module controller named [%S]"), testScripterAndTestCaseFile));
+    for(TInt a = 0; a < iTestScripter.Count(); a++)
+        {
+        //Check if module name matches to given name
+        if(iTestScripter[a]->iName->Des() == testScripterAndTestCaseFile->Des())
+            {
+            parentController = iTestScripter[a]; 
+            __TRACE(KInit, (_L("Parent module controller [%S] has been found. Checking its %d children"), parentController->iName, parentController->iChildrenControllers.Count()));
+            //Now check all its children and find free one
+            //In UI testing mode always create new module controller
+            if(!aUITestingSupport)
+                {
+                for(j = 0; j < parentController->iChildrenControllers.Count(); j++)
+                    {
+                    if(parentController->iChildrenControllers[j]->iTestCaseCounter == 0)
+                        {
+                        resultController = parentController->iChildrenControllers[j];
+                        __TRACE(KInit, (_L("Free real module controller found [%S]"), resultController->iName));
+                        break;
+                        }
+                    else
+                        {
+                        __TRACE(KInit, (_L("Module controller found [%S] but is not free (it runs %d test cases)"), parentController->iChildrenControllers[j]->iName, parentController->iChildrenControllers[j]->iTestCaseCounter));
+                        }
+                    }
+                }
+            else
+                {
+                __TRACE(KInit, (_L("In UITestingSupport mode new module controller will be always created")));
+                }
+            }
+        }
+
+    //Append underscore to name
+    TPtr ptr = testScripterAndTestCaseFile->Des();
+    ptr.Append(_L("@"));
+
+    //Create new module controller if free one has not been found
+    if(!resultController)
+        {
+        TBuf<10> ind;
+        ind.Format(_L("%d"), iEngine->GetIndexForNewTestModuleController());
+        TPtr ptr = testScripterAndTestCaseFile->Des();
+        ptr.Append(ind);
+        __TRACE(KInit, (_L("Free real module controller not found. Creating new one [%S]."), testScripterAndTestCaseFile));
+            
+        //Create server and active object (This uses CTestModuleController::InitL())
+        CTestModuleController* module = CTestModuleController::NewL( 
+                                            iEngine,
+                                            testScripterAndTestCaseFile->Des(),
+                                            iAfterReboot, EFalse, this);
+        CleanupStack::PushL(module);
+        parentController->iChildrenControllers.AppendL(module);
+        __TRACE(KInit, (_L("Child added to [%S] controller. Currently it has %d children:"), parentController->iName, parentController->iChildrenControllers.Count()));
+        for(j = 0; j < parentController->iChildrenControllers.Count(); j++)
+            {
+            __TRACE(KInit, (_L("    %d. [%S]"), j + 1, parentController->iChildrenControllers[j]->iName));
+            }
+
+        // Now is used TestScripter so give test case file also(used
+        // in caps modifier cases). 
+        TRAPD(err, module->InitL(iInifile, aTestInfo.iConfig));
+        if(err != KErrNone)
+            {
+            __TRACE(KVerbose, (_L("InitL fails with error: %d" ), err));
+            User::Leave(err);
+            }
+
+        module->AddConfigFileL(aTestInfo.iConfig);
+
+        __TRACE(KInit, (_L("New module controller created [%S]."), testScripterAndTestCaseFile));
+
+        //Enumerate test cases
+        module->EnumerateSynchronously();
+
+        CleanupStack::Pop(module);
+        resultController = module;
+        }
+
+    CleanupStack::PopAndDestroy(testScripterAndTestCaseFile);
+
+    // Return handle
+    return resultController;
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: ModuleName
+
+    Description: Return the name of Test Scripter
+
+    Parameters: const TDesC& aModuleName: in: Module name
+
+    Return Values: const TDesC : Name of Test Scripter
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+const TDesC& CTestScripterController::ModuleName( const TDesC& aModuleName )
+    {
+    // If test case file not added yet.
+    if( iTestScripter.Count() == 0 || aModuleName == KTestScripterName )
+        {
+        return *iName;
+        }
+
+    // Test case(s) is(are) added. Scan the name from corrent TestScripter
+    // session
+    for( TInt a = 0; a < iTestScripter.Count(); a++ )
+        {
+        if( aModuleName == iTestScripter[a]->iName->Des() )
+            {
+            return *iTestScripter[a]->iName;
+            }
+        }
+
+    return KNullDesC;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: CreateTestScripterNameL
+
+    Description: Create name according to TestScripter and Test case file.
+
+    Parameters: TFileName& aTestCaseFile: in: Test case file with path and name
+                TFileName& aCreatedName: inout: Created name
+
+    Return Values: None
+
+    Errors/Exceptions: Leaves is test case file is too long
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+HBufC* CTestScripterController::CreateTestScripterNameL( 
+                                                    TFileName& aTestCaseFile,
+                                                    HBufC* aCreatedName )
+    {
+    TParse parse;
+    parse.Set( aTestCaseFile, NULL, NULL );
+
+    TInt length( 0 );
+    length = parse.Name().Length();
+    length += ( KTestScripterNameLength + 1 );
+    length += 10; //this will be used to add unique identifier (when run test case in separate process is on)
+
+    // aCreatedName to CleanupStack
+    aCreatedName = HBufC::NewLC( length );
+    TPtr ptr = aCreatedName->Des();
+
+    // Maximum length of TestScripter's name(Max limitation from
+    // CTestModuleController creation)
+    TInt maximumLength = KMaxName - ( KTestScripterNameLength + 1 );
+
+    // Start create name. Format is testscripter_testcasefile
+    ptr.Copy( KTestScripterName );
+    ptr.Append( _L( "_" ) );
+    if( parse.Name().Length() < maximumLength )
+        {
+        ptr.Append( parse.Name() );
+        ptr.LowerCase();
+        }
+    else
+        {
+        __TRACE( KInit, ( CStifLogger::ERed,
+            _L( "TestScripter test case file(config)'s name is too long. Current length[%d], allowed max length[%d]. Cannot continue" ),
+            parse.Name().Length(), maximumLength ) );
+        User::Leave( KErrArgument );
+        }
+
+    // Pop here because this method can be trapped and trap panics with
+    // E32USER-CBase if cleap up stack is not empty.
+    CleanupStack::Pop( aCreatedName );
+
+    return aCreatedName;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: DeleteModuleController
+
+    Description: Finds specified module controller and deletes it.
+
+    Parameters: CTestModuleController* aRealModuleController: module controller
+                   to be deleted.
+    
+    Return Values: None
+    
+    Errors/Exceptions: None
+
+    Status: 
+
+-------------------------------------------------------------------------------
+*/    
+void CTestScripterController::DeleteModuleController(CTestModuleController* aRealModuleController)
+    {
+    __TRACE(KInit, (_L("Attempting to delete real module controller [%S]"), aRealModuleController->iName));
+
+    TInt i, j, k;
+    TInt children;
+    TInt subcontrollers = iTestScripter.Count();
+    
+    for(k = 0; k < subcontrollers; k++)
+        {
+        children = iTestScripter[k]->iChildrenControllers.Count();
+        __TRACE(KInit, (_L("...checking controller [%S] which has %d children"), iTestScripter[k]->iName, children));
+
+        for(i = 0; i < children; i++)
+            {
+            if(iTestScripter[k]->iChildrenControllers[i] == aRealModuleController)
+                {
+                __TRACE(KInit, (_L("Real module controller found... deleting")));
+                delete iTestScripter[k]->iChildrenControllers[i];
+                iTestScripter[k]->iChildrenControllers.Remove(i);
+    
+                __TRACE(KInit, (_L("Child removed from [%S] controller. Currently it has %d children:"), iTestScripter[k]->iName, iTestScripter[k]->iChildrenControllers.Count()));
+                for(j = 0; j < iTestScripter[k]->iChildrenControllers.Count(); j++)
+                    {
+                    __TRACE(KInit, (_L("    %d. [%S]"), j + 1, iTestScripter[k]->iChildrenControllers[j]->iName));
+                    }
+    
+                return;
+                }
+            }
+        }
+    __TRACE(KInit, (_L("Real module controller NOT found... NOT deleting")));
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CTestScripterController
+
+    Method: RemoveModuleController
+
+    Description: Finds specified module controller and removes it from children list.
+
+    Parameters: CTestModuleController* aRealModuleController: module controller
+                   to be removed.
+    
+    Return Values: None
+    
+    Errors/Exceptions: None
+
+    Status: 
+
+-------------------------------------------------------------------------------
+*/    
+void CTestScripterController::RemoveModuleController(CTestModuleController* aRealModuleController)
+    {
+    __TRACE(KInit, (_L("Attempting to remove real module controller [%x]"), aRealModuleController));
+
+    TInt i, j, k;
+    TInt children;
+    TInt subcontrollers = iTestScripter.Count();
+    
+    for(k = 0; k < subcontrollers; k++)
+        {
+        children = iTestScripter[k]->iChildrenControllers.Count();
+        __TRACE(KInit, (_L("...checking controller [%S] which has %d children"), iTestScripter[k]->iName, children));
+
+        for(i = 0; i < children; i++)
+            {
+            if(iTestScripter[k]->iChildrenControllers[i] == aRealModuleController)
+                {
+                __TRACE(KInit, (_L("Real module controller found... removing")));
+                iTestScripter[k]->iChildrenControllers.Remove(i);
+    
+                __TRACE(KInit, (_L("Child removed from [%S] controller. Currently it has %d children:"), iTestScripter[k]->iName, iTestScripter[k]->iChildrenControllers.Count()));
+                for(j = 0; j < iTestScripter[k]->iChildrenControllers.Count(); j++)
+                    {
+                    __TRACE(KInit, (_L("    %d. [%S]"), j + 1, iTestScripter[k]->iChildrenControllers[j]->iName));
+                    }
+    
+                return;
+                }
+            }
+        }
+    __TRACE(KInit, (_L("Real module controller NOT found... NOT removing")));
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    DESCRIPTION
+
+    This module contains implementation of CErrorPrinter class member
+    functions.
+
+-------------------------------------------------------------------------------
+*/
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrinter
+
+    Method: NewL
+
+    Description: Create a testcase runner.
+
+    Parameters: CTestEngine* aMain: in: Pointer to console main
+
+    Return Values: CErrorPrinter* : pointer to created object
+
+    Errors/Exceptions: Leaves if memory allocation for object fails
+                       Leaves if ConstructL leaves
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CErrorPrinter* CErrorPrinter::NewL( CTestEngine* aTestEngine )
+    {
+    CErrorPrinter* self = new ( ELeave ) CErrorPrinter();
+    CleanupStack::PushL( self );
+    self->ConstructL( aTestEngine );
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrinter
+
+    Method: ConstructL
+
+    Description: Second level constructor.
+
+    Parameters: CTestEngine* aEngine: in: Pointer to Engine
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CErrorPrinter::ConstructL( CTestEngine* aEngine )
+    {
+    iEngine = aEngine;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrinter
+
+    Method: CErrorPrinter
+
+    Description: Constructor.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CErrorPrinter::CErrorPrinter( ) : CActive( EPriorityStandard ),
+                                      iErrorPckg( iError )
+    {
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrinter
+
+    Method: ~CErrorPrinter
+
+    Description: Destructor.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+CErrorPrinter::~CErrorPrinter( )
+    {
+    Cancel();
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrinter
+
+    Method: StartL
+
+    Description: Starts a test case and sets the active object to active.
+
+    Parameters: RTestModule& aServer: in: Reference to the server object
+
+    Return Values: None
+
+    Errors/Exceptions: TInt: Return KErrNone
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CErrorPrinter::StartL( RTestModule& aServer )
+    {
+    iServer = aServer;
+
+    CActiveScheduler::Add ( this );
+
+    SetActive();
+    aServer.ErrorNotification ( iErrorPckg, iStatus );
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrinter
+
+    Method: RunL
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CErrorPrinter::RunL()
+    {
+
+    if ( iStatus.Int() != KErrNone )
+        {
+        __TRACE( KVerbose, ( _L( "In CErrorPrinter::RunL [iStatus = %d]" ), iStatus.Int() ) );
+        }
+    else
+       {
+        // Forward error print to UI and set request again active.
+        iEngine->ErrorPrint( iErrorPckg );
+        SetActive();
+        iServer.ErrorNotification ( iErrorPckg, iStatus );
+       }
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrinter
+
+    Method: DoCancel
+
+    Description: Cancels the asynchronous request
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+void CErrorPrinter::DoCancel()
+    {
+    iServer.CancelAsyncRequest ( ETestModuleErrorNotification );
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CErrorPrinter
+
+    Method: RunError
+
+    Description: Handles errors. RunL can't leave so just forward error
+    and let framework handle error.
+
+    Parameters: TInt aError: in: Error code
+
+    Return Values: TInt: Error code
+
+    Errors/Exceptions: None
+
+    Status: Approved
+
+-------------------------------------------------------------------------------
+*/
+TInt CErrorPrinter::RunError( TInt aError )
+    {
+    return aError;
+
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CServerStateHandler
+
+    Method: NewL
+
+    Description: Constructs a new CServerStateHandler object.
+
+    Parameters: CTestEngine* aMain
+
+    Return Values: CServerStateHandler*: New undertaker
+
+    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CServerStateHandler* CServerStateHandler::NewL( CTestEngine* aTestEngine, 
+                                                CTestModuleController* aTestModuleController )
+    {
+
+    CServerStateHandler* self = 
+                        new( ELeave ) CServerStateHandler( aTestEngine, aTestModuleController );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CServerStateHandler
+
+    Method: ConstructL
+
+    Description: Second level constructor.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CServerStateHandler::ConstructL()
+    {
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CServerStateHandler
+
+    Method: CServerStateHandler
+
+    Description: Constructor
+
+    Parameters: CTestEngine* aMain
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+CServerStateHandler::CServerStateHandler( CTestEngine* aTestEngine, 
+                                          CTestModuleController* aTestModuleController ) :
+    CActive( CActive::EPriorityStandard ),
+    iEngine( aTestEngine ),
+    iTestModuleController( aTestModuleController )
+    {
+    
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CServerStateHandler
+
+    Method: ~CServerStateHandler
+
+    Description: Destructor. 
+    Cancels active request.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+CServerStateHandler::~CServerStateHandler()
+    {
+    
+    Cancel();
+
+    iServerThread.Close();
+    
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CServerStateHandler
+
+    Method: StartL
+
+    Description: Starts to monitor server thread.
+
+    Parameters: RTestServer& aServer
+
+    Return Values: TInt: 
+
+    Errors/Exceptions: 
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TInt CServerStateHandler::StartL( RTestServer& aServer )
+    {
+    
+    __TRACE( KVerbose, ( _L( "CServerStateHandler::StartL" ) ) );
+     
+    TThreadId serverThreadId; 
+     
+    iStatus = KRequestPending;
+  
+    // Asks from server its thread ID value
+    User::LeaveIfError( aServer.GetServerThreadId ( serverThreadId ) ); 
+      
+    // Opens handle to thread
+    User::LeaveIfError( iServerThread.Open( serverThreadId ) );
+    
+    CActiveScheduler::Add( this );
+        
+    // Requests notification when this thread dies, normally or otherwise   
+    iServerThread.Logon( iStatus ); // Miten RThread hanska ko serveriin..
+   
+    SetActive();
+
+    return KErrNone;
+
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CServerStateHandler
+
+    Method: RunL
+
+    Description: Handles thread death.
+  
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CServerStateHandler::RunL()
+    {
+    
+    // something went badly wrong!
+    __TRACE( KInit, ( CStifLogger::ERed, 
+        _L( "Test case execution fails. Possible reason: KErrServerTerminated" ) ) );
+ 
+    RDebug::Print( _L("Test case execution fails. Possible reason: KErrServerTerminated") );     
+             
+    // Note: 
+    // More Info about STIF panic with KErrServerTerminated 
+    // will be informed to the user via testengine log and testreport    
+    // in CTestCaseController::RunL() method
+   
+    // TestModuleCrash is called for doing all needed recovering operations for enabling STIF 
+    // to continue test case execution
+    iEngine->TestModuleCrash( iTestModuleController );
+      
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CServerStateHandler
+
+    Method: DoCancel
+
+    Description: Stops listening TestServer status.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+void CServerStateHandler::DoCancel()
+    {
+
+    __TRACE( KVerbose, ( _L( "CServerStateHandler::DoCancel" ) ) );
+
+    // Cancels an outstanding request for notification of the death of this thread.
+    iServerThread.LogonCancel( iStatus );
+    
+    }
+/*
+-------------------------------------------------------------------------------
+
+    Class: CServerStateHandler
+
+    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 CServerStateHandler::RunError( TInt aError )
+    {
+    __TRACE( KError,( _L( "CServerStateHandler::RunError" ) ) );
+    return aError;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: -
+
+    Method: GenerateModuleName
+
+    Description: Check is module TestScripter. Does parsing and returns new
+                 module name and error codes(Needed operations when creating
+                 server sessions to TestScripter). 
+
+    Parameters: const 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 GenerateModuleName(const TDesC& aModuleName,
+                        TDes& aNewModuleName)
+    {
+    // 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.CompareF( KTestScripterName );
+    if( ret == KErrNone )
+        {
+        aNewModuleName.Copy( aModuleName.Mid( 0, KTestScripterNameLength ) );
+        aNewModuleName.LowerCase();
+        }
+    else
+        {
+        return KErrNotFound;
+        }
+
+    return KErrNone;
+
+    }
+
+// ================= OTHER EXPORTED FUNCTIONS =================================
+
+// None
+
+//  End of File