/*
* 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 CTestExecution 
* class member functions. CTestExecution class handles a test 
* execution subsession specific operations.
*
*/

// INCLUDE FILES
#include <e32std.h>
#include <e32svr.h>
#include "TestEngineClient.h"
#include "StifTFwIfProt.h"
#include <stifinternal/TestServerClient.h>
#include "TestServer.h"
#include "TestServerModuleIf.h"
#include "TestServerCommon.h"
#include "PrintQueue.h"
#include "TestServerEvent.h"
#include "TestThreadContainer.h"
#include "STIFMeasurement.h"

// EXTERNAL DATA STRUCTURES

// EXTERNAL FUNCTION PROTOTYPES  

// CONSTANTS

// MACROS

// LOCAL CONSTANTS AND MACROS

// MODULE DATA STRUCTURES

// LOCAL FUNCTION PROTOTYPES

// FORWARD DECLARATIONS

// ==================== LOCAL FUNCTIONS =======================================

// ================= MEMBER FUNCTIONS =========================================

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: NewL

    Description: Returns new CTestExecution instance.

    Parameters: CTestModule* aModuleSession   :in:  "Parent" module
                TInt aCaseNumber              :in:  Test case number
                const TFileName& aConfig      :in:  Configuration filename

    Return Values: CTestExecution*                  New instance

    Errors/Exceptions: Function leaves if memory allocation fails or
                       CTestExecution construction leaves.
                       Panics is aModuleSession is NULL.

    Status: Proposal

-------------------------------------------------------------------------------
*/
CTestExecution* CTestExecution::NewL( CTestModule* aModuleSession,
                                      TInt aCaseNumber, 
                                      const TFileName& aConfig )
    {

    __ASSERT_ALWAYS ( aModuleSession, 
                      CTestServer::PanicServer( ENullModuleSession ) );

    CTestExecution* self=new( ELeave ) CTestExecution;
    CleanupClosePushL( *self );
    self->ConstructL( aModuleSession, aCaseNumber, aConfig );
    CleanupStack::Pop();

    return self;

    }


/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CTestExecution

    Description: Constructor.
    Initialises member variables whose default state is not zero or NULL.

    Parameters:  None
    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CTestExecution::CTestExecution() : 
    iConfig( 0, 0 ),
    iTestThreadOpen( EFalse ),
    iTestThreadFailure( ETestThreadOk )
    {

    iPrintNotifyAvailable = EFalse;
    iThreadState = ENotStarted;
    iRemoteSendAvailable = EFalse;
    iRemoteReceiveAvailable = EFalse;
    iEventNotifyAvailable = EFalse;
    iCommandNotifyAvailable = EFalse;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: ~CTestExecution

    Description: Destructor

    Parameters: None
    
    Return Values: None

    Errors/Exceptions: Panics is threadmutex is taken.

    Status: Approved
    
-------------------------------------------------------------------------------
*/
CTestExecution::~CTestExecution()
    {
    // Thread must be stopped before CTestExecution can be deleted
    if( iThreadState == EOnGoing ) 
		{
			if( iModuleContainer != NULL )
				{
				iModuleContainer->KillThread( KErrCancel );
				}
			delete iModuleContainer;
			iModuleContainer = NULL;
			CTestServer::PanicServer( EClosingWhileTestRunning );
		}

    delete iPrintHandler;
    iPrintHandler = NULL;
    delete iEventHandler;
    iEventHandler = NULL;
    delete iSndHandler;
    iSndHandler = NULL;
    delete iRcvHandler;
    iRcvHandler = NULL;
    delete iInterferenceHandler;
    iInterferenceHandler = NULL;
    delete iMeasurementHandler;
    iMeasurementHandler = NULL;
    delete iCommandHandler;
    iCommandHandler = NULL;

    // Test interference array(Needed cases when test interference thread is
    // needed to Kill())
    iSTIFTestInterferenceArray.Reset();
    iSTIFTestInterferenceArray.Close();

    // Reset test measurement array
    iMeasurementHandlingArray.Reset();
    iMeasurementHandlingArray.Close();

    // iPrintQueue must be emptied here, because it items are allocated from server heap
    delete iPrintQueue;
    iPrintQueue = NULL;

    // Delete name buffer
    delete iConfigNameBuffer;
    iConfigNameBuffer = NULL;
    
    iStateEvents.ResetAndDestroy();
    iStateEvents.Close();

    iEventArray.ResetAndDestroy();
    iEventArray.Close();

    // Close mutexes
    if ( iPrintMutex.Handle() != 0 ) iPrintMutex.Close();
    if ( iEventMutex.Handle() != 0 ) iEventMutex.Close();
    if ( iSndMutex.Handle() != 0 ) iSndMutex.Close();
    if ( iRcvMutex.Handle() != 0 ) iRcvMutex.Close();
    if ( iInterferenceMutex.Handle() != 0 ) iInterferenceMutex.Close();
    if ( iMeasurementMutex.Handle() != 0 ) iMeasurementMutex.Close();
    if ( iCommandMutex.Handle() != 0 ) iCommandMutex.Close();

    // Mutex for testcomplete and cancel operations. Close mutex
    if ( iTestThreadMutex.Handle() != 0 ) iTestThreadMutex.Close();

    // Close semaphores
    if ( iPrintSem.Handle() != 0 ) iPrintSem.Close();
    if ( iEventSem.Handle() != 0 ) iEventSem.Close();
    if ( iSndSem.Handle() != 0 ) iSndSem.Close();
    if ( iRcvSem.Handle() != 0 ) iRcvSem.Close();
    if ( iInterferenceSem.Handle() != 0 ) iInterferenceSem.Close();
    if ( iMeasurementSem.Handle() != 0 ) iMeasurementSem.Close();
    //if ( iReceiverSem.Handle() != 0 ) iReceiverSem.Close();
    if ( iCommandSem.Handle() != 0 ) iCommandSem.Close();
    
    iMessageQueue.Close();
    
    iTestThread.Close();

    delete iCommandDef;
    iCommandDef = NULL;
    }


/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: ConstructL

    Description: Second level constructor

    Parameters: CTestModule* aModuleSession   :in:  "Parent" module
                TInt aCaseNumber ::           :in:  Test case number
                const TFileName& aConfig      :in:  Configuration filename

    Return Values: None

    Errors/Exceptions: None

    Status: Approved

-------------------------------------------------------------------------------
*/
void CTestExecution::ConstructL( CTestModule *aModuleSession,
                                 TInt aCaseNumber,
                                 const TFileName& aConfig )
    {

    // Get the parameters
    iModuleSession = aModuleSession;
    iCaseNumber = aCaseNumber;

    // Construct heap buffer for configuration file
    iConfigNameBuffer = HBufC::NewL( aConfig.Length() );
    iConfig.Set ( iConfigNameBuffer->Des() );
    iConfig.Copy ( aConfig );

    // Create mutexes
    User::LeaveIfError( iPrintMutex.CreateLocal() );
    User::LeaveIfError( iEventMutex.CreateLocal() );
    User::LeaveIfError( iSndMutex.CreateLocal() );
    User::LeaveIfError( iRcvMutex.CreateLocal() );
    User::LeaveIfError( iInterferenceMutex.CreateLocal() );
    User::LeaveIfError( iMeasurementMutex.CreateLocal() );
    User::LeaveIfError( iCommandMutex.CreateLocal() );

    // Mutex for testcomplete and cancel operations. Create mutex
    User::LeaveIfError( iTestThreadMutex.CreateLocal() );

    // Create semaphores
    User::LeaveIfError( iPrintSem.CreateLocal( 0 ) );
    User::LeaveIfError( iEventSem.CreateLocal( 0 ) );
    User::LeaveIfError( iSndSem.CreateLocal( 0 ) );
    User::LeaveIfError( iRcvSem.CreateLocal( 0 ) );
    User::LeaveIfError( iInterferenceSem.CreateLocal( 0 ) );
    User::LeaveIfError( iMeasurementSem.CreateLocal( 0 ) );
    //User::LeaveIfError( iReceiverSem.CreateLocal( 0 ) );
    User::LeaveIfError( iCommandSem.CreateLocal( 0 ) );

    // Create handlers
    iPrintHandler = CPrintHandler::NewL( *this );
    iEventHandler = CEventHandler::NewL( *this );
    iSndHandler  = CSndHandler::NewL( *this );
    iRcvHandler  = CRcvHandler::NewL( *this );
    iInterferenceHandler = CInterferenceHandler::NewL( *this );
    iMeasurementHandler = CMeasurementHandler::NewL( *this );
    iCommandHandler = CCommandHandler::NewL( *this );

    // Create print queue
    iPrintQueue = CPrintQueue::NewL();

    // Start print handler   
    iPrintHandler->StartL();
    
    // Start rcv handler
    iRcvHandler->StartL();

    // Start interference handler
    iInterferenceHandler->StartL();

    // Start measurement handler
    iMeasurementHandler->StartL();

    iCommandDef = CCommandDef::NewL();
    }


/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: RunTestCase

    Description: Starts to execute test case in separate thread.

    Parameters: const RMessage& aMessage  :in:      Message from client.

    Return Values: TInt                             Error code

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
TInt CTestExecution::RunTestCase( const RMessage2& aMessage )
    {

    __TRACE ( KInit, ( _L( "CTestExecution::RunTestCase in" ) ) );

    // Store message to be completed when case is finished
    iTestExeMessage = aMessage;

    iFullResult.iStartTime.HomeTime();

    // Get a test module, which executes the test case.
    // The test module will be freed either when the test case
    // completes, or the test case is aborted.
    TInt ret = iModuleSession->GetTestModule( iModuleContainer, iConfig );
    if ( ret != KErrNone || iModuleContainer == NULL )
        {
        _LIT(KRunError,"Can't get test module");
        __TRACE ( KError, ( CStifLogger::ERed, KRunError() ) );
        CompleteTestExecution( KErrNone,
                               TFullTestResult::ECaseException,
                               ret,
                               KErrGeneral,
                               KRunError );
        return KErrNone;
        }
    

    // Thread is created, so all thread specific operations are possible, 
    // even if thread is not yet resumed, so mark thread to be "Running"
    SetThreadState ( EOnGoing );

    // Start the test
    iModuleContainer->SetExecutionSubSession( this );
    iModuleContainer->RunTestCase( iConfig, iCaseNumber, aMessage );

    __TRACE ( KRunTestCase, ( _L( "CTestExecution::RunTestCase out. Case ongoing" ) ) );

    return KErrNone;

    }


/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: NotifyPrint

    Description: Handles print request from engine. If print queue is empty,
                 message is stored to be used later when there is something to
                 print, otherwise the first queue item is returned and request
                 completes immediately.

    Parameters: const RMessage& aMessage      :in:  Message from client.

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::NotifyPrint( const RMessage2& aMessage )
    {

    __ASSERT_ALWAYS( iPrintNotifyAvailable == EFalse, 
                     CTestServer::PanicServer( EPrintQueueBroken ) );

    // Get first item from queue
    TPrintQueueItem *item = iPrintQueue->Pop();

    if ( item == NULL )
        {

        // If thread can't print anymore, and queue is empty, then 
        // complete with Eof, because there will not be any new prints
        if ( iThreadState == EFinished || iThreadState == ECancelled )
            {
            __TRACE ( KPrint, ( _L( "CTestExecution::NotifyPrint to finished thread" ) ) );
            aMessage.Complete ( KErrEof );
            }
        else
            {
            // Print request available, do not complete request
            iNotifyPrintMessage = aMessage;
            iPrintNotifyAvailable = ETrue;
            }

        }
    else
        {
        // Construct message
        TTestProgress progress;
        progress.iPosition = item->iPriority;
        progress.iDescription = item->iData1;
        progress.iText = item->iData2;

        iNotifyPrintMessage = aMessage;
        // Write message to client space and complete request
        WritePrint( progress );

        delete item; 
        }


    return KErrNone;

    }
/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: DoNotifyPrint

    Description: If print notification available, notification is copied to
                    client memory space and request is completed.
                 Else new print queue item is created and appended to print 
                    queue. If queue is full or memory can't be allocated,
                    then message will be discarded.
        
    Parameters: None
    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::DoNotifyPrint()
    {    

    if ( iPrintNotifyAvailable )
        {
        // Write message to client space
        WritePrint( iProgress );
        }
    else
        {

        TPrintQueueItem *item = 
            new TPrintQueueItem( iProgress.iPosition, 
                                 iProgress.iDescription, 
                                 iProgress.iText );

        if ( item != NULL )
            {
            // Item constructed ok, add it to queue
            if ( iPrintQueue->Push( *item ) != KErrNone )
                { 
                // Queue is full, clean-up
                delete item;
                }
            }
        // else: Could not construct TPrintQueueItem, no free memory.
        // drop printing            
        }
    
    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: DoNotifyInterference

    Description: Handles Test Interference thread append and remove operations.
        
    Parameters: None
    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::DoNotifyInterference()
    {    
    // Information for this context => information is in this thread's heap and
    // if CUndertaker::RunL is called then test interface thread can called
    // with function call and kill() test interference thread

    // Take information from struct given in 
    // CTestThreadContainer::AddInterferenceThread or
    // CTestThreadContainer::RemoveInterferenceThread
    
    RThread thread;
    TInt ret = thread.Open ( iTestInterference.iThreadId );
    if( ret != KErrNone )
    	{
    	RDebug::Print( _L("CTestExecution::DoNotifyInterference %d"), ret );
        User::Panic( _L("CTestExecution::DoNotifyInterference"), ret );
    	}
    
    if ( iTestInterference.iOperation == TTestInterference::EAppend )
        {
        iSTIFTestInterferenceArray.Append( thread );
        }
    else if (iTestInterference.iOperation == TTestInterference::ERemove )
        {
        // Remove thread from Array.Test interference thread is stopped and killed
        // successfully
        for( TInt i = 0; i < iSTIFTestInterferenceArray.Count(); i++ )
            {
            if( iSTIFTestInterferenceArray[i].Id() == thread.Id() )
                {
                iSTIFTestInterferenceArray.Remove( i );
                break;
                }
            }
        }
    else
        {
        return;
        }

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: DoNotifyMeasurement

    Description: Handles test measurement operations: NewL, Start and Stop.
        
    Parameters: None
    
    Return Values: None

    Errors/Exceptions: None

    Status: Approved
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::DoNotifyMeasurement()
    {    
    // Information for this context => information is in this thread's heap:
    // From CUndertaker::RunL() or CTestModuleContainer::RunL() method can
    // handle stop and clean operations if these operations are not done 
    // before.
    // Erronous cases(CUndertaker::RunL will be called) or when test case is
    // executed(CTestModuleContainer::RunL() will be called) there can handle
    // test measurement stop and clean operation. 

    if( iTestMeasurement.iMeasurementStruct.iMeasurementOperation == 
                                        CSTIFTestMeasurement::KMeasurementNew)
        {
        // Check that same measurement module don't try to create several times
        // Only one measurement type per test is allowed
        for( TInt i = 0; i < iMeasurementHandlingArray.Count(); i++ )
            {
            if( iMeasurementHandlingArray[i]->iMeasurementModulePtr->MeasurementType() ==
                        iTestMeasurement.iMeasurementStruct.iMeasurementType )
                {
                return KErrAlreadyExists;
                }
            }

        TMeasurementHandling* measurementHandling = NULL;
        measurementHandling = new TMeasurementHandling();

        TBuf<KStifMeasurementTypeLength> modulename;
        if( iTestMeasurement.iMeasurementStruct.iMeasurementType == 1 )
            {
            modulename.Copy( KStifMeasurement01 );
            }
        else if( iTestMeasurement.iMeasurementStruct.iMeasurementType == 2 )
            {
            modulename.Copy( KStifMeasurement02 );
            }
        else if( iTestMeasurement.iMeasurementStruct.iMeasurementType == 3 )
            {
            modulename.Copy( KStifMeasurement03 );
            }
        else if( iTestMeasurement.iMeasurementStruct.iMeasurementType == 4 )
            {
            modulename.Copy( KStifMeasurement04 );
            }
        else if( iTestMeasurement.iMeasurementStruct.iMeasurementType == 5 )
            {
            modulename.Copy( KStifMeasurement05 );
            }
        else if( iTestMeasurement.iMeasurementStruct.iMeasurementType == 6 )
            {
            modulename.Copy( KStifMeasurementBappea );
            }
        else
            {
            __TRACE( KError, (  _L("CTestExecution::DoNotifyMeasurement(): unknown measurement type" ) ) );
            return KErrArgument;
            }

        // Loading should work with and without '.dll' extension.
        TInt r = measurementHandling->iMeasurementModule.Load( modulename );
        if ( r != KErrNone )
            {
            __TRACE( KError, ( CStifLogger::EError, _L("Can't load test measurement module[%S], code = %d"),
                &modulename, r ) );
            delete measurementHandling;
            return KErrNotFound;
            }
        else
            {
            //Print test measururement module name
            __TRACE( KInit, (  _L("Loaded test measurement module[%S]"),
                &modulename ) );
            }

        // Get pointer to first exported function
        // Verify that there is function
        measurementHandling->iMeasurementLibEntry = (CTestMeasurementFactory) measurementHandling->iMeasurementModule.Lookup( 1 );
        if ( measurementHandling->iMeasurementLibEntry == NULL )
            {
            // New instance can't be created
            __TRACE( KInit, (_L( "Test measurement module instance cannot create." ) ) );
            measurementHandling->iMeasurementModule.Close();
            delete measurementHandling;
            return KErrNotFound;
            }
        else
            {
            __TRACE ( KInit, ( _L("Pointer to 1st exported received")));
            }

        CSTIFTestMeasurementImplementation* measurement;
        measurement = NULL;

        // initialize test measurement module
        __TRACE ( KVerbose, (_L("Calling 1st exported at 0x%x"), (TUint32) measurementHandling->iMeasurementLibEntry ));
        TRAPD ( err, measurement = (*measurementHandling->iMeasurementLibEntry)( 
                            iTestMeasurement.iMeasurementStruct.iConfigurationInfo, iTestMeasurement.iMeasurementStruct.iMeasurementType ) );

         // Handle leave from test module
        if ( err != KErrNone )
            {
            __TRACE (KError, ( CStifLogger::EError, _L( "Leave when calling 1st exported function, code %d"), err ) );
            delete measurementHandling;
            return err;
            }
        else if ( measurementHandling->iMeasurementLibEntry == NULL )     // Handle NULL from test measurement
            {
            __TRACE (KError, ( CStifLogger::EError, _L( "NULL pointer received when constructing test measurement module" ) ) );
            delete measurementHandling;
            // Set error codes
            return KErrNoMemory;
            }
        else
            {
            measurementHandling->iMeasurementModulePtr = measurement;
            __TRACE (KInit, (_L("Entrypoint successfully called, Measurement module instance at 0x%x"),
                (TUint32)measurementHandling->iMeasurementLibEntry ) );
            }
        iMeasurementHandlingArray.Append( measurementHandling );
        } // End of NewL operations

    else if( iTestMeasurement.iMeasurementStruct.iMeasurementOperation == 
                                        CSTIFTestMeasurement::KMeasurementStart)
        {
        for( TInt i = 0; i < iMeasurementHandlingArray.Count(); i++ )
            {
            if( iMeasurementHandlingArray[i]->iMeasurementModulePtr->MeasurementType() == iTestMeasurement.iMeasurementStruct.iMeasurementType )
                {
                return iMeasurementHandlingArray[i]->iMeasurementModulePtr->Start();
                }
            }

        }
    else if( iTestMeasurement.iMeasurementStruct.iMeasurementOperation == 
                                        CSTIFTestMeasurement::KMeasurementStop)
        {
        for( TInt i = 0; i < iMeasurementHandlingArray.Count(); i++ )
            {
            if( iMeasurementHandlingArray[i]->iMeasurementModulePtr->MeasurementType() == iTestMeasurement.iMeasurementStruct.iMeasurementType )
                {
                TInt stop_ret = iMeasurementHandlingArray[i]->iMeasurementModulePtr->Stop();
                delete iMeasurementHandlingArray[i];
                iMeasurementHandlingArray.Remove(i);
                return stop_ret;
                }
            }
        }
    else 
        {
        __TRACE (KError, ( CStifLogger::EError, _L("CTestExecution::DoNotifyMeasurement(): Not supported operation") ) );
        return KErrNotSupported;
        }
    
    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: WritePrint

    Description: Writes print notification to client memory space.                 
        
    Parameters: const TInt aPriority          :in:  Priority
                const TStifInfoName& aDes         :in:  Description
                const TName& aBuffer          :in:  Value
    
    Return Values: TInt                             Return value from message write

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::WritePrint( TTestProgress& aProgress )
    {

    TTestProgressPckg progressPckg( aProgress );
 
    // Write message to client space    
    TRAPD( res, iNotifyPrintMessage.WriteL( 0, progressPckg ) );

    iPrintNotifyAvailable = EFalse;

    // Complete request with possible error code
    iNotifyPrintMessage.Complete( res );

    return res;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: NotifyEvent

    Description: Handles event request from engine. 

    ESetEvent and EUnsetEvent change event status. EEnable enables 
    event notify.

    Parameters: const RMessage& aMessage      :in:  Message from client.
                    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::NotifyEvent( const RMessage2& aMessage )
    {   

    TEventIf event;
    TEventIfPckg eventPckg( event );
    
    TRAPD( res, aMessage.ReadL( 0, eventPckg ) );

    if( res != KErrNone )
        {
        __TRACE( KError, ( _L( "CTestExecution::NotifyEvent: ReadL failed" ) ));
        return res;
        }
    
    switch( event.Type() )
        {
        case TEventIf::ESetEvent: 
            {
            TInt ind = 0;
            TInt count = iEventArray.Count();
            for( ind=0; ind < count; ind++ )
                {
                if( iEventArray[ind]->Name() == event.Name() )
                    {
                    __TRACE( KMessage, ( _L( "CTestExecution::NotifyEvent(%d): SetEvent %S ( count %i )" ), 
                        this, &event.Name(), count ) );
                    TEventIf::TEventType etype = TEventIf::EIndication;
                    // To get state events working with testcombiner
                    if( ( event.EventType() == TEventIf::EState ) ||                            
                        ( iEventArray[ind]->EventType() == TEventIf::EState ) )
                        {
                        etype = TEventIf::EState;
                        }
                    iEventArray[ind]->Set( etype );
                    }
                }
            }
            break;
        case TEventIf::EUnsetEvent:
            { 
            return UnsetEvent( event, aMessage );
            }
        case TEventIf::EEnable:
            {
            // Store event message
            iNotifyEventMessage = aMessage;
            iEventNotifyAvailable = ETrue;
            TInt errorFromPreviousCmd =  aMessage.Int1();

            __TRACE( KMessage, ( _L( "CTestExecution::NotifyEvent: enable (%d) notify %d" ), 
                errorFromPreviousCmd, this ) );

            // Complete previous Event command
            CompleteEvent( errorFromPreviousCmd );    
            iEventHandler->StartL();
            
            // iNotifyEventMessage is completed from DoNotifyEvent
            return KErrNone; 
            }
        
        default:
            __TRACE( KError, ( _L( "CTestExecution::NotifyEvent: Unknown command %i" ), 
                event.Type() ));
            return KErrArgument;
        }

    __TRACE( KMessage, ( _L( "CTestExecution::NotifyEvent(%d): Done" ), this ) );

    aMessage.Complete( KErrNone );
    //User::After(1000); //Stif-95 This pause is needed to let Info::TestFrameworkEngine thread
                       //get some processor time and run exactly at this moment (by calling
                       //CTestEventController::EventCallBack). When Stif is focused on the screen,
                       //there is no problem if this line is absent, however when another
                       //application (like screen saver) is focused this is required.
    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: DoNotifyEvent

    Description: Forward event request.
        
    Parameters: None
   
    Return Values: None

    Errors/Exceptions: Panics if event array can't be created

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::DoNotifyEvent()
    {
    
    TInt ret = KErrNone;
        
    switch( iEventDef.iEvent.Type() )
        {
        case TEventIf::EReqEvent:
            {
            __TRACE( KMessage, 
                ( _L( "CTestExecution::DoNotifyEvent(%d): ReqEvent %S" ), 
                    this, &iEventDef.iEvent.Name() ) );
            ret = RequestEvent( iEventDef.iEvent );
            // If error, return error, 
            // otherwise proceed with sending information to engine
            if( ret != KErrNone )
                {
                iEventHandler->StartL();
                return ret;
                }
            }
            break;
        case TEventIf::EWaitEvent:
        case TEventIf::ESetWaitPending:
            {
            __TRACE( KMessage, 
                ( _L( "CTestExecution::DoNotifyEvent(%d): WaitEvent %S" ), 
                    this, &iEventDef.iEvent.Name() ) );
            // We return from here, i.e. nothing is sent to engine
            ret = WaitEvent( iEventDef.iEvent, iEventDef.iStatus );
            iEventHandler->StartL();
            return ret;
            }
        // Add state events to internal array  
        case TEventIf::ESetEvent: 
        case TEventIf::EUnsetEvent:
            {
            __TRACE( KMessage, 
                ( _L( "CTestExecution::DoNotifyEvent(%d): Set/UnsetEvent %S" ), 
                    this, &iEventDef.iEvent.Name() ) );
            EventStateChange( iEventDef.iEvent );
            }
            break;
        case TEventIf::ERelEvent:
            // This is handled later
            __TRACE( KMessage, 
                ( _L( "CTestExecution::DoNotifyEvent(%d): RelEvent %S" ), 
                    this, &iEventDef.iEvent.Name() ) );
            break;
        default:
            iEventHandler->StartL();
            return KErrArgument;
        }
    
    // Construct message
    TEventIfPckg eventPckg( iEventDef.iEvent );

    // Write message to client space
    TRAPD( res, iNotifyEventMessage.WriteL( 0, eventPckg ) );

    if( res != KErrNone )
        {
        __TRACE( KError, ( _L( "CTestExecution::DoNotifyEvent: WriteL failed" ) ) );
        ret = res;
        }
    // Complete request
    // Complete with WriteL result
    // MUST be done before ERelEvent
    iEventNotifyAvailable = EFalse;
    iNotifyEventMessage.Complete( res );
    User::After(1000); //Stif-95 This pause is needed to let Info::TestFrameworkEngine thread
                       //get some processor time and run exactly at this moment (by calling
                       //CTestEventNotifier::RunL). When Stif is focused on the screen,
                       //there is no problem if this line is absent, however when another
                       //application (like screen saver) is focused this is required.

    if( iEventDef.iEvent.Type() == TEventIf::ERelEvent )
        {
        ret = ReleaseEvent( iEventDef.iEvent );
        if( ret != KErrNone )
            {
            // If error, return immediately
            return ret;
            }
        }

    __TRACE( KMessage, ( _L( "CTestExecution::DoNotifyEvent(%d): Done" ), this ) );

    return ret;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: RequestEvent

    Description: Handles TestModule event requests. 
        
    Parameters: const TEventIf& aEvent: in: Event requested  
    
    Return Values: TInt: Success/Error code

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/    
TInt CTestExecution::RequestEvent( TEventIf& aEvent )
    {

    // Requested events are added to iEventArray
    // There can be multiple simultaneous requests for the same event                    
    TEvent* event = new TEvent( iTestThreadId );    
    if( !event )
        {
        return KErrNoMemory;
        }
    event->Copy( aEvent );
    if( iEventArray.Append( event ) != KErrNone )
        {
        delete event;
        return KErrNoMemory;
        }
        
    __TRACE( KMessage,( _L( "CTestExecution::DoNotifyEvent: Req added %S ( count %i )" ), 
         &aEvent.Name(), iEventArray.Count() ));
    
    return KErrNone;
    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: WaitEvent

    Description: Handles TestModule event waits. Waiting is implemented here 
                and completed in NotifyEvent    

        
    Parameters: const TEventIf& aEvent: in: Event wait  
    
    Return Values: TInt: Success/Error code

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/    
TInt CTestExecution::WaitEvent( TEventIf& aEvent, TRequestStatus* aStatus )
    {
      
    // Get first "free" event entry from requested events
    TInt ind = 0;
    TInt count = iEventArray.Count();
    TEvent* event = NULL;
    for( ind=0; ind < count; ind++ )
        {
        if( ( iEventArray[ind]->Name() == aEvent.Name() ) &&
            ( iEventArray[ind]->WaitEventPending() == EFalse ) )
            {
            // Found event with correct name and one that is still free
            // i.e. nobody is waiting for it.
            event = iEventArray[ind];
            if( aEvent.Type() == TEventIf::EWaitEvent )
                {
                // For EWaitEvent we complete immediately if event is pending
                if( event->EventPending() )
                    {
                    // Event was already pending, so we may return immediately
                    if( aStatus )
                        {
                        TestThreadRequestComplete( aStatus, KErrNone );
                        }
                    return KErrNone;           
                    }
                }
            }
        }
    if( event == NULL )
        {
        // Event is not in the iEventArray, 
        // so event is not currently requested
        return KErrNotFound;
        }
        
    __TRACE( KMessage,( _L( "CTestExecution::DoNotifyEvent: Waiting %S ( count %i )" ), 
        &aEvent.Name(), count ));
    
    // Event is not pending so we have to wait for it
    // Set wait pending            
    TInt ret = event->SetWaitPending( aStatus );
    // event cannot be freed by the test module, 
    // because it is waiting the event, 

    if( ( aStatus == NULL ) &&
        ( ret == KErrNone ) &&
        ( aEvent.Type() == TEventIf::EWaitEvent ) ) 
        {
        // This is synchronous wait
        // Go waiting, completed from set event            
        event->Wait();
        }

    return ret;
    
    } 
    
/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: ReleaseEvent

    Description: Handles TestModule event releases. 
        
    Parameters: const TEventIf& aEvent: in: Event released  
    
    Return Values: TInt: Success/Error code

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/   
TInt CTestExecution::ReleaseEvent( TEventIf& aEvent )
    {
    
    // Get last event entry from requested events
    TInt ind = 0;
    TInt freeFound = 0;
    TInt eventIndex = 0;
    TInt count = iEventArray.Count();
    for( ind=0; ind < count; ind++ )
        {
        if( iEventArray[ind]->Name() == aEvent.Name() )
            {
            if( iEventArray[ind]->WaitEventPending() == EFalse )
                {
                freeFound++;
                eventIndex = ind;
                }
            }
        }

    if( freeFound == 0 )
        {
        return KErrNotFound;
        }
    __TRACE( KMessage,( 
        _L( "CTestExecution::DoNotifyEvent: Release event %S ( count %i )" ), 
            &aEvent.Name(), iEventArray.Count() ));

    TEvent* event = iEventArray[eventIndex];
    iEventArray.Remove( eventIndex );
    // Release and free event entry
    event->Release(); 

    // Delete used event entry
    delete event;
    
    return KErrNone;
}

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: UnsetEvent

    Description: Handles TestModule event unsets. 
        
    Parameters: const TEventIf& aEvent: in: Event unset  
    
    Return Values: TInt: Success/Error code

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::UnsetEvent( TEventIf& aEvent, const RMessage2& aMessage )
    {
    
    TInt ret = KErrNone;
    TInt ind = 0;
    TInt count = iEventArray.Count();
    TBool activeEventReq = EFalse;
    for( ind=0; ind < count; ind++ )
        {
        if( iEventArray[ind]->Name() == aEvent.Name() )
            {
             __TRACE( KMessage, ( 
                _L( "CTestExecution::NotifyEvent(%d): UnsetEvent %S ( count %i )" ), 
                this, &aEvent.Name(), count ) );
                
            ret = iEventArray[ind]->Unset( aMessage, this );
            if( ret == KErrNone )
                {
                activeEventReq = ETrue;
                }
            break;
            }
        }
    if( activeEventReq )
        {
        // Unset is completed by release   
        return KErrNone;
        }
        
    // No pending requests or error from unset
    aMessage.Complete( ret );
    
    return KErrNone;
    
    }
    
/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: EventStateChange

    Description: Handles event setting and unsetting. Saves status of
                state events to enable unsetting of set state events when 
                killing the testcase abnormally.
        
    Parameters: const TEventIf& aEvent: in: Event set/unset  
    
    Return Values: TInt: Success/Error code

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/   
TInt CTestExecution::EventStateChange( TEventIf& aEvent )
    {
    
    TInt ret = KErrNotFound;
    if( aEvent.EventType() == TEventIf::EState )
        {
        
        TInt count = iStateEvents.Count();
        TInt index = 0;
        for(; index < count; index++ )   
            {
            TPtrC name = *(iStateEvents[index]);
            if( name == aEvent.Name() )
                {
                break;
                }
            } 
            
                
        if( aEvent.Type() == TEventIf::ESetEvent )
            {
            if( index < count )
                {
                ret = KErrAlreadyExists;
                }
            else
                {
                // add event to iStateEvents
                HBufC* name = aEvent.Name().Alloc();
                if( name == NULL )
                    {
                    ret = KErrNoMemory;
                    }
                else if( iStateEvents.Append( name ) != KErrNone )
                    {
                    delete name;
                    ret = KErrNoMemory;
                    }
                else
                    {
                    ret = KErrNone;
                    }
                }                
            }
        else if( aEvent.Type() == TEventIf::EUnsetEvent )
            {
            if( index == count )
                {
                ret = KErrNotFound;
                }
            else
                {
                ret = KErrNone;
                delete iStateEvents[index];
                iStateEvents.Remove( index );
                }
            }
        }
    
    return ret;
    
    }
/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CancelEvent

    Description: Cancels pending event request.
        
    Parameters: None
    
    Return Values: None

    Errors/Exceptions: None
    
    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::CancelEvent()
    {
    
    TInt ret = KErrNotFound;

    __TRACE( KMessage, ( _L( "CTestThreadContainer::CancelEvent(%d): %S [%p]" ), 
            iEventDef.iEvent.Type(), &iEventDef.iEvent.Name(), iEventDef.iStatus ) );

    switch( iEventDef.iEvent.Type() )
        {
        case TEventIf::EReqEvent:
        case TEventIf::ERelEvent:
        case TEventIf::ESetEvent:
        case TEventIf::EUnsetEvent:   
            CompleteEvent( KErrCancel );  
            break;
        case TEventIf::EWaitEvent:
        case TEventIf::ESetWaitPending:
            {
            // Get waited event entry from requested events
            TInt ind = 0;
            TInt count = iEventArray.Count();
            for( ind=0; ind < count; ind++ )
                {
                if( ( iEventArray[ind]->Name() == iEventDef.iEvent.Name() ) &&
                    ( iEventArray[ind]->WaitEventPending() != EFalse ) &&
                    ( iEventArray[ind]->RequestStatus() == iEventDef.iStatus ) )
                    {
                    TEvent* event = iEventArray[ind];
                    // Found event with correct name and one that is waited.
                    event->CompletePendingWait( KErrCancel ); 
                    ret = KErrNone;
                    break;
                    }
                }
            if( ret != KErrNone )
                {
                // Request has been already completed, not handled 
                // by ActiveScheduler yet.
                // DoCancel will do the job, don't worry.
                __TRACE( KError, ( _L( "CTestThreadContainer::CancelEvent(%d): %S, not found 2" ), 
                    iEventDef.iEvent.Type(), &iEventDef.iEvent.Name() ) ); 
                }
            }
            break;
        default:
            CTestServer::PanicServer( EUnknownEventCmd );
            break;
        }
        
    // Synchonize
    iEventHandler->StartL();
        
    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: NotifyRemoteCmd

    Description: Handles the first phase of the RemoteCmd request from engine.

    Parameters: const RMessage& aMessage: in: Message from client.
                    
    Return Values: Symbian OS error code.

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::NotifyRemoteCmd( const RMessage2& aMessage )
    {   

    // Store RemoteCmd message
    // and the length buffer address
    iNotifyRemoteCmdMessage = aMessage;
    iRemoteSendAvailable = ETrue;
    iSndHandler->StartL();

    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: DoRemoteReceive

    Description: Enable remote receive.
    
    Parameters: None 
    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::DoRemoteReceive()
    {    

    switch( iRcvCmdDef.iCommand )
        {
        case EStifCmdReceive:          // "Receive"
            {
            // @js If there's pointer in array, we'll send it down
            if(iMessageQueue.Count() > 0)
                {
                HBufC8 * buf =  iMessageQueue[0];
                iRcvCmdDef.iParam.aRemoteMsgRef->Copy( iMessageQueue[0]->Des() );
                iMessageQueue.Remove(0);
                delete buf; 
                __TRACE( KMessage, 
                        (_L("CTestExecution::ReadRemoteCmdInfo: complete receive 0x%x"), 
                            iRcvCmdDef.iStatus ));
                       
                 // calls the TestCombiner's CRemoteReceiver::RunL()
                 TestThreadRequestComplete( iRcvCmdDef.iStatus, KErrNone );
                }
            else
                {
                iRemoteReceiveAvailable = ETrue;            
                }

            break;
            }
        case EStifCmdReceiveCancel:
            if( iRemoteReceiveAvailable )
                {
                iRemoteReceiveAvailable = EFalse;
                TestThreadRequestComplete( iRcvCmdDef.iStatus, KErrCancel );
                }                
            break;
        default:
            CTestServer::PanicServer( EUnknownRemoteCmd );
            break;
        }
    // Signal test thread
    iRcvHandler->StartL();

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: DoRemoteSend

    Description: Send remote messages.
    
    Parameters: None 
    
    Return Values: None

    Errors/Exceptions: None

    Status: Approved
    
-------------------------------------------------------------------------------
*/
void CTestExecution::DoRemoteSend()
    {  
    switch( iCmdDef.iCommand )
        {  
        case EStifCmdSend:             // "Send"
        case EStifCmdReboot:           // "Send"
        case EStifCmdStoreState:       // "Send"
        case EStifCmdGetStoredState:   // "Receive, this must be done with two phase"
        case EStifCmdMeasurement:      // "Receive, this must be done with two phase"
            {
            if( iRemoteSendAvailable )
                {
                TInt ret = KErrNone;
                TPckg<TStifCommand> remoteCommandPckg( iCmdDef.iCommand );

                // Start first phase of the writing message to client space
                TRAP( ret, 
                    iNotifyRemoteCmdMessage.WriteL( 0, remoteCommandPckg ) );

                if( ret != KErrNone )
                    {
                    __TRACE( KError, ( _L( "CTestExecution::DoRemoteSend: WriteL failed" ) ) );
                    }
                TPckg<TInt> lenPckg( iCmdDef.iLen );

                TRAP( ret, 
                    iNotifyRemoteCmdMessage.WriteL( 1, lenPckg ) );

                if( ret != KErrNone )
                    {
                    __TRACE( KError, ( _L( "CTestExecution::DoRemoteSend: WriteL failed" ) ) );
                    }

                // Complete request
                // Complete with WriteL result
                // CTestRemoteCmdNotifier::RunL() will called
                iRemoteSendAvailable = EFalse;
                iNotifyRemoteCmdMessage.Complete( ret );
                break;
                }
            }
            TestThreadRequestComplete( iCmdDef.iStatus, KErrNotSupported );
            break;
        default:
            CTestServer::PanicServer( EUnknownRemoteCmd );
            break;
        }

    }


/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: ReadRemoteCmdInfo

    Description: Handles the second phase of the RemoteCmd request from engine.

    Parameters: const RMessage& aMessage: in: Message from client.
                    
    Return Values: Symbian OS error code.

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::ReadRemoteCmdInfo( const RMessage2& aMessage )
    {   
    
    TInt ret( KErrNone );
    TInt completeSend = EFalse;
    TInt returnedErrorCode = KErrNone;
    TInt len = 0;
    TInt value( aMessage.Int2() );
    if( value < 0 )
        {
        returnedErrorCode = value;
        }
    else
        {
        len = value;
        }
  
    switch( aMessage.Int1() )
        {
        case EStifCmdReceive:              // "Receive"
            {

                if( len <= 0 )
                    {
                    __TRACE( KError, 
                        (_L("CTestExecution::ReadRemoteCmdInfo: empty message")));
                    ret = KErrGeneral;
                    break;
                    }
                if( iRcvCmdDef.iParam.aRemoteMsgRef->MaxLength() < len )
                    {
                    __TRACE( KError, 
                        (_L("CTestExecution::ReadRemoteCmdInfo: message overflow")));
                    ret = KErrGeneral;
                    break;
                    }

                HBufC8* buf = HBufC8::New( len );
                if( buf == NULL )
                    { 
                    ret = KErrNoMemory;
                    break;
                    }
                TPtr8 tmp = buf->Des();
                // Read message from client space
                TRAP( ret, aMessage.ReadL( 0, tmp ) );

                
                if( ret != KErrNone )
                    {
                    __TRACE( KError, 
                        (_L("CTestExecution::ReadRemoteCmdInfo: ReadL failed")));
                    break;
                    }
                    
                if( iRemoteReceiveAvailable )
                // @js Checking moved here
                    {                                   
                    iRcvCmdDef.iParam.aRemoteMsgRef->Copy( buf->Des() );
                    delete buf;
                
                    __TRACE( KMessage, 
                        (_L("CTestExecution::ReadRemoteCmdInfo: complete receive 0x%x"), 
                            iRcvCmdDef.iStatus ));
                    // calls the TestCombiner's CRemoteReceiver::RunL()
                    TestThreadRequestComplete( iRcvCmdDef.iStatus, ret );
                    
                    iRemoteReceiveAvailable = EFalse;
                    }
                else
                // @js Adding buf to RPointerArray, handling it in DoRemoteReceive function
                    {
                   iMessageQueue.Append( buf );
                    } 
                
            break;
            }
        case EStifCmdSend:                 // "Send"
            {
            HBufC8* buf = HBufC8::New( iCmdDef.iParam.aRemoteMsgConstRef->Length() );
            if( buf == NULL )
                { 
                ret = KErrNoMemory;
                break;
                }
            TPtr8 tmp = buf->Des();
            tmp.Copy( *iCmdDef.iParam.aRemoteMsgConstRef );
            // Second phase of the writing. Write information to the Engine.
            TRAP( ret, aMessage.WriteL( 0, tmp ) );

            delete buf;
            
            if( ret != KErrNone )
                {
                __TRACE( KError, ( _L( "CTestExecution::ReadRemoteCmdInfo: WriteL failed" ) ) );
                }
            completeSend = ETrue;
            break;
            }
        case EStifCmdReboot:               // "Send"
            {
            TRebootParamsPckg remoteTypePckg( *iCmdDef.iParam.aRebootType );

            // Second phase of the writing. Write information to the Engine.
            TRAP( ret, aMessage.WriteL( 0, remoteTypePckg ) );

            if( ret != KErrNone )
                {
                __TRACE( KError, ( _L( "CTestExecution::ReadRemoteCmdInfo: WriteL failed" ) ) );
                }
            // Because Reboot must block...Don't complete, so now we wait for
            // ever phone booting operation !!!!!
            break;
            }
        case EStifCmdStoreState:          // "Send"
            {
            TRebootStateParamsPckg remoteStatePckg( *iCmdDef.iParam.aRebootState );

            // Second phase of the writing. Write information to the Engine.
            TRAP( ret, aMessage.WriteL( 0, remoteStatePckg ) );

            if( ret != KErrNone )
                {
                __TRACE( KError, ( _L( "CTestExecution::ReadRemoteCmdInfo: WriteL failed" ) ) );
                }
            // Completed from EStifCmdRebootProceed
            break;
            }
        case EStifCmdMeasurement:   // "Receive"
            {
            TGetMeasurementOptions getMeasurementOptions;
            TGetMeasurementOptionsPckg measurementParamsPckg( getMeasurementOptions );

            // Read message from client space
            TRAP( ret, aMessage.ReadL( 0, measurementParamsPckg ) );

            if( ret != KErrNone )
                {
                __TRACE( KError, ( _L( "CTestExecution::ReadRemoteCmdInfo: ReadL failed" ) ) );
                }
            iCmdDef.iParam.aMeasurementOption->iOptions = getMeasurementOptions.iOptions;

            completeSend = ETrue;
            break;
            }
        case EStifCmdGetStoredState:   // "Receive"
            {
            TGetRebootStoredParams getRebootStoredParams;
            TGetRebootStoredParamsPckg rebootStoredParamsPckg( getRebootStoredParams );

            // Read message from client space
            TRAP( ret, aMessage.ReadL( 0, rebootStoredParamsPckg ) );

            if( ret != KErrNone )
                {
                __TRACE( KError, ( _L( "CTestExecution::ReadRemoteCmdInfo: ReadL failed" ) ) );
                }
            iCmdDef.iParam.aRebootStoredRef->iCode = getRebootStoredParams.aCode;
            iCmdDef.iParam.aRebootStoredRef->iName = getRebootStoredParams.aName;

            completeSend = ETrue;
            break;
            }
        case EStifCmdRebootProceed:          
            {
            completeSend = ETrue; // Complete EStifCmdStoreState
            }
            break;
        default:
            {
            iModuleSession->PanicClient( EUnknownRemoteCmd, aMessage );
            break;
            }
        }
    // Complete request with ret
    aMessage.Complete( ret ); 

    if( completeSend )
        {
        // Calls the TestCombiner's CRemoteReceiver::RunL() and
        // returns error code to test module.
        TestThreadRequestComplete( iCmdDef.iStatus, returnedErrorCode );
        }
        
    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: Pause

    Description: Pauses a test case

    Only ongoing tests can be paused. If test is not ongoing, then
    function does nothing.

    Parameters: const RMessage& aMessage      :in:  Message from client.
    
    Return Values: TInt                             Always KErrNone

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
TInt CTestExecution::Pause( const RMessage2& aMessage )
    {

    __TRACE ( KThreadOperation, ( _L( "CTestExecution::Pause" ) ) );

    TInt completionCode = KErrNone;

    // Note that it is allowed to suspend already suspended thread, so
    // there is no need for states to verify that thread is really in
    // resumed state.
    switch ( iThreadState )
        {
        case EOnGoing:
            completionCode = iModuleContainer->PauseThread();
            break;

        case ENotStarted:
            completionCode = KErrNotReady;
            break;

        case EFinished:
        case ECancelled:
            completionCode = KErrCompletion;
            break;

        default:
            CTestServer::PanicServer( EInvalidThreadState );
            break;
        }


    // Complete the request
    aMessage.Complete( completionCode );

    return KErrNone;

    }


/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: Resume

    Description: Resumes a test case. If test is not ongoing,
    then do not resume.

    Parameters: const RMessage& aMessage      :in:  Message from client.
    
    Return Values: TInt                             Always KErrNone

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
TInt CTestExecution::Resume( const RMessage2& aMessage )
    {

    __TRACE ( KThreadOperation, ( _L( "CTestExecution::Resume" ) ) );

    TInt completionCode = KErrNone;

    // Note that it is allowed to resume already resumed thread, so
    // there is no need for states to verify that thread is really in
    // suspended state.
    switch ( iThreadState )
        {
        case EOnGoing:
            completionCode = iModuleContainer->ResumeThread();
            break;

        case ENotStarted:
            completionCode = KErrNotReady;
            break;

        case EFinished:
        case ECancelled:
            completionCode = KErrCompletion;
            break;

        default:
            CTestServer::PanicServer( EInvalidThreadState );
            break;
        }


    // Complete the request
    aMessage.Complete( completionCode );

    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CloseTestExecution

    Description: Closes Test Execution subsession

    Parameters: const RMessage& aMessage      :in:  Message from client.
    
    Return Values: TInt                             Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::CloseTestExecution( const RMessage2& aMessage )
    {

    // Cancel test request
    CancelTestRequest();

    // Cancel print request
    CancelPrintRequest();
    
    // Cancel event request
    CancelEventRequest();

    // Delete this subsession
    const TUint subsession = aMessage.Int3();
    iModuleSession->DeleteTestExecution( subsession, aMessage );

    // Complete the request
    aMessage.Complete( KErrNone );

    return KErrNone;

    }


/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CancelPrintRequest

    Description: Cancel print request. Completes ongoing print request
    with KErrCancel.

    Parameters: None
    
    Return Values: TInt                             Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::CancelPrintRequest()
    {

    if ( iPrintNotifyAvailable )
        {
        iPrintHandler->Cancel();
        
        iPrintNotifyAvailable = EFalse;
        iNotifyPrintMessage.Complete ( KErrCancel );
        //@spe iPrintNotifyAvailable = EFalse;
        }

    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CancelEventRequest

    Description: Cancel event request. Completes ongoing event request
    with KErrCancel.

    Parameters: None
    
    Return Values: TInt                             Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::CancelEventRequest()
    {
    iEventHandler->Cancel();

    if( iEventNotifyAvailable )
        {
        // Cancel request
        iEventNotifyAvailable = EFalse;
        iNotifyEventMessage.Complete ( KErrCancel );
        }

    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CancelInterferenceRequest

    Description: Cancel print request. Completes ongoing print request
    with KErrCancel.

    Parameters: None

    Return Values: TInt: Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::CancelInterferenceRequest()
    {

    if ( iInterferenceNotifyAvailable )
        {
        iInterferenceHandler->Cancel();
        
        iInterferenceNotifyAvailable = EFalse;
        iNotifyInterferenceMessage.Complete ( KErrCancel );
        }

    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CancelRemoteCmdRequest

    Description: Cancel RemoteCmd request. Completes ongoing RemoteCmd request
        with KErrCancel.

    Parameters: None
    
    Return Values: TInt: Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::CancelRemoteCmdRequest()
    {
    iSndHandler->Cancel();

    // Cancel request
    if( iRemoteSendAvailable )
        {
        iRemoteSendAvailable = EFalse;
        iNotifyRemoteCmdMessage.Complete ( KErrCancel );
        }

    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: NotifyCommand

    Description: Handles the first phase of the Command request from engine.

    Parameters: const RMessage& aMessage: in: Message from client.

    Return Values: Symbian OS error code.

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
TInt CTestExecution::NotifyCommand( const RMessage2& aMessage )
    {
    iNotifyCommandMessage = aMessage;
    iCommandNotifyAvailable = ETrue;
    iCommandHandler->StartL();

    return KErrNone;
    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CancelCommandRequest

    Description: Cancel Command request. Completes ongoing Command request
        with KErrCancel.

    Parameters: None

    Return Values: TInt: Always KErrNone

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
TInt CTestExecution::CancelCommandRequest()
    {
    iCommandHandler->Cancel();

    // Cancel request
    if(iCommandNotifyAvailable)
        {
        iCommandNotifyAvailable = EFalse;
        iNotifyCommandMessage.Complete(KErrCancel);
        }

    return KErrNone;
    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CancelTestRequest

    Description: Cancel test execution request.
    If thread is not in OnGoing state, function does not do anything.

    Otherwise following operations are done:
    1 ) Obtain access to both  PrintMutex and EventMutex to make sure that
       thread can't be accessing print queue or events.
    2 ) Kill the thread
    3 ) Complete original "RunTestCase" request with KErrCancel
    4 ) If print queue is empty, complete print request
    5 ) Give up mutexes
    6 ) Delete module container

    Parameters: None
    
    Return Values: TInt: Always KErrNone

    Errors/Exceptions: None

    Status: Approved
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::CancelTestRequest()
    {
    // This mutex block and make sure that cancel operation is done succesfully
    // and test case e.g. cannot complete at the same time. Get mutex.
    iTestThreadMutex.Wait();

    // iModuleContainer is an active object, check is active.
    if ( iModuleContainer == NULL || ( iModuleContainer != NULL && !iModuleContainer->IsActive() ) )
        {
        // Test case is already ready, return.
        iTestThreadMutex.Signal();
        return KErrNone;
        }

    if ( iThreadState == EOnGoing )
        {
        // Print mutex access is required to make sure that the dying thread
        // does not have access to print queue. Same is true for event queue.

        // NOTE: iEventArrayMutex is now taken, so the ongoing thread
        // can't set any events so queue will be empty.
        iPrintHandler->Cancel();
        iEventHandler->Cancel();
        iInterferenceHandler->Cancel();
        iCommandHandler->Cancel();

        // Kill the thread
        iModuleContainer->KillThread( KErrCancel );

        // Complete the test execution request
        CompleteTestExecution( KErrCancel, TFullTestResult::ECaseCancelled, 
                               KErrCancel, KErrCancel, _L( "Cancelled" ) );
        iThreadState = ECancelled;

       
        /**        
        * Removed, because may block in certain situations. Implemented now in
        * TestCombiner instead.
        // Unset all pending state events, 
        // because we have killed the testcase abnormally
        // UnsetStateEvents();
        */
        
        // Complete print request if queue is empty
        CompletePrintRequestIfQueueEmpty();
        
        // Delete the module containter
        delete iModuleContainer;
        iModuleContainer = NULL;
        }
        
    // Relinquish mutex.
    iTestThreadMutex.Signal();

    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CancelRequestL

    Description: Cancel asynchronous request

    Parameters: const RMessage& aMessage      :in:  Message from client.
    
    Return Values: TInt                             Error code from CancelXXX-
                                                    function

    Errors/Exceptions: Function panics the client, if invalid message
                       received.

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::CancelRequestL( const RMessage2& aMessage )
    {
    TInt r = KErrNone;

    switch ( aMessage.Int0() )
        {
        case ETestExecutionRunTestCase:
            {
            r = CancelTestRequest();
            break;
            }
        case ETestExecutionNotifyProgress:
            {
            r = CancelPrintRequest();
            break;
            }
        case ETestExecutionNotifyEvent:
            {
            r = CancelEventRequest();
            break;
            }
        case ETestExecutionNotifyRemoteCmd:
            {
            r = CancelRemoteCmdRequest();
            break;
            }
        case ETestExecutionNotifyCommand:
            {
            r = CancelCommandRequest();
            break;
            }
        default:
            iModuleSession->PanicClient( EInvalidRequestCancel, aMessage );
            break;
        }

    aMessage.Complete( r );

    return r;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: SetThreadState

    Description: A multithread safe thread state modification function

    Parameters: const TTestState aState       :in:  New state
    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::SetThreadState( const TTestState aState )
    {

    iThreadState = aState;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: Complete event

    Description: Completes pending event request. Must be 
        called with iEventSem taken.
        
    Parameters: None
    
    Return Values: None

    Errors/Exceptions: None
    
    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::CompleteEvent( TInt aError )
    {
    if( iEventDef.iStatus )
        {
        __TRACE( KMessage,(_L("Comp Stat %d, %x (error %d)"), 
            this, iEventDef.iStatus, aError));
        TestThreadRequestComplete( iEventDef.iStatus, aError );
        
        iEventDef.iStatus = NULL;
        
        }
        
    }
    
/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CompletePrintRequestIfQueueEmpty

    Description: Completes print request if queue is empty.

    Parameters: None
    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::CompletePrintRequestIfQueueEmpty()
    {

    if ( iPrintNotifyAvailable &&  iPrintQueue->Count() == 0 )
        {
        iNotifyPrintMessage.Complete ( KErrEof );
        iPrintNotifyAvailable = EFalse;
        }

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CleanupEvents

    Description: Cleanups Events.

    Parameters: None
    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::CleanupEvents()
    {
    
    iEventArray.ResetAndDestroy();
    
    }
    
/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: GetRq

    Description: Get request pointers.

    Parameters: None

    Return Values: TRequestStatus*

    Errors/Exceptions: None

    Status: Approved
    
-------------------------------------------------------------------------------
*/
TRequestStatus* CTestExecution::GetRq( TRequestType aType )
    {

    TRequestStatus* status = NULL;

    switch( aType )
        {
        case ERqPrint:
            status = &iPrintHandler->iStatus;
            break;
        case ERqEvent:
            status = &iEventHandler->iStatus;
            break;
        case ERqSnd:
            status = &iSndHandler->iStatus;
            break;
        case ERqRcv:
            status = &iRcvHandler->iStatus;
            break;
        case ERqInterference:
            status = &iInterferenceHandler->iStatus;
            break;
        case ERqMeasurement:
            status = &iMeasurementHandler->iStatus;
            break;
        case ERqCommand:
            status = &iCommandHandler->iStatus;
            break;
        default:
            break;
        }

    return status;

    }


/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CompleteTestExecution

    Description: Completes test execution

    Parameters: const TInt aCompletionCode    :in:  Request completion code
                const TInt aCaseExecutionCode  in:  Case execution code
                const TFullTestResult::TCaseExecutionResult aCaseExecutionType,
                const TInt aCaseResult        :in:  Case result
                const TDesC& aText            :in:  Completion text

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CTestExecution::CompleteTestExecution( const TInt aCompletionCode,
    const TFullTestResult::TCaseExecutionResult aCaseExecutionType,
    const TInt aCaseExecutionCode,
    const TInt aCaseResult,
    const TDesC& aText )
    {
    
    TInt completionCode = aCompletionCode;
    
    if( iModuleContainer != NULL )
        {
        // Fill the description
        iFullResult.iEndTime.HomeTime();
        iFullResult.iCaseExecutionResultType = aCaseExecutionType;
        iFullResult.iCaseExecutionResultCode = aCaseExecutionCode;
        iFullResult.iTestResult.iResult = aCaseResult;
        iFullResult.iTestResult.iResultDes = aText;
        CompleteTestExecution( aCompletionCode );
        return;
        }
    else
        {   
        completionCode = KErrGeneral;
        __TRACE ( KError, ( CStifLogger::ERed, 
            _L("CTestExecution::CompleteTestExecution: ModuleContainer NULL") ) );
        }

    iTestExeMessage.Complete ( completionCode );

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CompleteTestExecution

    Description: Completes test execution

    Parameters: const TInt aCompletionCode: in: completion code
                TFullTestResult&: in: test case result

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CTestExecution::CompleteTestExecution( const TInt aCompletionCode )
    {
    
    TInt completionCode = aCompletionCode;
    
    TFullTestResultPckg fullResultPckg( iFullResult );
    TRAPD( res, iTestExeMessage.WriteL( 0, fullResultPckg ) );
    if ( res != KErrNone )
        {
        completionCode = res;
        }

    iTestExeMessage.Complete ( completionCode );
    
    // @js Now it returns completionCode, used to return res

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: UnsetStateEvents

    Description: Unsets all state events. Must be done if testcase is exited 
                abnormally (i.e. aborted by the user).

    Parameters: None
    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::UnsetStateEvents()
    {


    // Unset all state events that are set currently
    TInt count = iStateEvents.Count();
    TEventIf event;
    for( TInt i = 0; i < count; i++ )   
        {
        TPtrC name = *(iStateEvents[i]);
        event.Set( TEventIf::EUnsetEvent, name, TEventIf::EState );
        
        // Construct message
        TEventIfPckg eventPckg( event );

        // Write message to client space
        TRAPD( res, iNotifyEventMessage.WriteL( 0, eventPckg ) );

        // Complete with WriteL result
        iEventNotifyAvailable = EFalse;
        iNotifyEventMessage.Complete( res );
        if( res != KErrNone )
            {
            __TRACE( KError,( _L( "CTestExecution::UnsetStateEvents: WriteL failed" ) ));
            break;
            } 
        }
    
    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: TestThreadRequestComplete

    Description: Complete test thread request.

    Parameters: None
    
    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CTestExecution::TestThreadRequestComplete( TRequestStatus* aStatus, 
                                                TInt aCode)
    {                                        
    
    if( iThreadState != EOnGoing )
        {
        __TRACE( KError,
            ( _L( "CTestExecution::TestThreadRequestComplete: test thread killed" ) ));
        return;
        }

    if( iTestThreadOpen == EFalse )
        {        
        if( iTestThread.Open( iTestThreadId ) != KErrNone )
            {
            __TRACE( KError,
                ( _L( "CTestExecution::TestThreadRequestComplete: test thread cannot be opened" ) ));
            return;
            }
        iTestThreadOpen = ETrue;
        }
    if( iTestThread.ExitType() != EExitPending ) 
        {
        // test thread has died
        __TRACE( KError,
            ( _L( "CTestExecution::TestThreadRequestComplete: test thread has died" ) ));
        return;
        }    
     
    iTestThread.RequestComplete( aStatus, aCode );
    
    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: CancelTestExecution

    Description: Cancels test(s) execution in special cases e.g. timeout,
                 exit etc.

    Parameters: None
    
    Return Values: TInt: Symbian error code.

    Errors/Exceptions: None

    Status: Approved
    
-------------------------------------------------------------------------------
*/
TInt CTestExecution::CancelTestExecution()
    {
    TInt ret( KErrNone );
    ret = CancelTestRequest();

    return ret;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: KillTestinterferenceThread

    Description: Make sure that any of the test interference thread's won't
                 stay to run if test case is crashed of test interference
                 object is not deleted.

    Parameters: None

    Return Values: TInt: Symbian OS error code.

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
TInt CTestExecution::KillTestinterferenceThread()
    {
    for( TInt i = 0; i < iSTIFTestInterferenceArray.Count(); i++ )
        {
        RDebug::Print( 
            _L( "Test interference's thread[%x] killed by STIF" ), (TInt)iSTIFTestInterferenceArray[i].Id() );
        __TRACE( KInit,
            ( _L( "Test interference's thread[%x] killed by STIF" ), (TInt)iSTIFTestInterferenceArray[i].Id() ) );
        iSTIFTestInterferenceArray[i].Kill( KErrCancel );
        //iSTIFTestInterferenceArray.Remove( i );
        }

    iSTIFTestInterferenceArray.Reset();
    iSTIFTestInterferenceArray.Close();

    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: DoNotifyCommand

    Description: Completes command message.

    Parameters: None.

    Return Values: Symbian OS error code.

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
TInt CTestExecution::DoNotifyCommand()
    {
    if(!iCommandNotifyAvailable)
    	{
    	__TRACE(KPrint, (_L("CTestExecution::DoNotifyCommand(): unable to complete notification")))
    	return KErrNone;
    	}

    TInt ret = KErrNone;

    switch(iCommandDef->iCommand)
        {
        case EStopExecution:
            {
            //Unpack received parameters
            TStopExecutionCommandParams par;
            TStopExecutionCommandParamsPckg parPack(par);
            parPack.Copy(iCommandDef->iParamsPckg);

            //Set test case handle
            par.iTestCaseHandle = iNotifyCommandMessage.Int3();

            __TRACE(KPrint, (_L("CTestExecution::DoNotifyCommand(): command [%d] type [%d] code [%d] test handle [%d]"), TInt(iCommandDef->iCommand), TInt(par.iType), TInt(par.iCode), par.iTestCaseHandle));
            iCommandDef->iParamsPckg.Copy(parPack);
            break;
            }
        case ESendTestModuleVersion:
        	{
        	TSendTestModuleVesionCommandParams par;
        	TSendTestModuleVesionCommandParamsPckg parPack(par);
        	parPack.Copy(iCommandDef->iParamsPckg);
        	
        	__TRACE(KPrint, (_L("CTestExecution::DoNotifyCommand(): command ESendTestModuleVersion")));
        	break;
        	}
        default:
            __TRACE(KError, (_L("CTestExecution::DoNotifyCommand(): Unknown command [%d]"), TInt(iCommandDef->iCommand)));
            return KErrNotFound;
        }
    // Construct message
    TPckg<TCommand> commandPckg(iCommandDef->iCommand);

    // Start first phase of the writing message to client space
    TRAP(ret, iNotifyCommandMessage.WriteL(0, commandPckg));
    if(ret != KErrNone)
       {
       __TRACE(KError, (_L( "CTestExecution::DoNotifyCommand(): WriteL failed (0)")));
       }

    TRAP(ret, iNotifyCommandMessage.WriteL(1, iCommandDef->iParamsPckg));
    if(ret != KErrNone)
       {
       __TRACE(KError, (_L( "CTestExecution::DoNotifyCommand(): WriteL failed (1)")));
       }

    // Complete request with WriteL result
    iCommandNotifyAvailable = EFalse;
    iNotifyCommandMessage.Complete(ret);

    return KErrNone;
    }

/*
-------------------------------------------------------------------------------

    Class: CTestExecution

    Method: KillTestMeasurement

    Description: Make sure that any of the test measurement operations won't
                 stay to run if test case is crashed or test measurement object
                 is not stopped by user.

    Parameters: None

    Return Values: TInt: Symbian OS error code.

    Errors/Exceptions: None

    Status: Approved

-------------------------------------------------------------------------------
*/
TInt CTestExecution::KillTestMeasurement()
    {
    for( TInt i = 0; i < iMeasurementHandlingArray.Count(); i++ )
        {
        iMeasurementHandlingArray[i]->iMeasurementModulePtr->Stop();
        }

    iMeasurementHandlingArray.ResetAndDestroy();
    iMeasurementHandlingArray.Close();

    return KErrNone;

    }

/*
-------------------------------------------------------------------------------

    DESCRIPTION

    This module contains implementation of CPrintHandler class member functions.
    CPrintHandler listens print notifications from test thread.

-------------------------------------------------------------------------------
*/

// ================= MEMBER FUNCTIONS =========================================


/*
-------------------------------------------------------------------------------

    Class: CPrintHandler

    Method: NewL

    Description: Constructs a new CPrintHandler object.

    Parameters: CTestExecution& aExecution: in: "Parent"

    Return Values: CPrintHandler*: New undertaker

    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.

    Status: Proposal

-------------------------------------------------------------------------------
*/
CPrintHandler* CPrintHandler::NewL( CTestExecution& aExecution )
    {

    CPrintHandler* self = new( ELeave ) CPrintHandler( aExecution );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;

    }

/*
-------------------------------------------------------------------------------

    Class: CPrintHandler

    Method: ConstructL

    Description: Second level constructor.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CPrintHandler::ConstructL()
    {

    }

/*
-------------------------------------------------------------------------------

    Class: CPrintHandler

    Method: CPrintHandler

    Description: Constructor

    Parameters: CTestModuleContainer& aExecution :in:   "Parent"

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CPrintHandler::CPrintHandler( CTestExecution& aExecution ) :
    CActive( CActive::EPriorityStandard ),
    iExecution( aExecution )
    {
    
    CActiveScheduler::Add ( this );
    
    }

/*
-------------------------------------------------------------------------------

    Class: CPrintHandler

    Method: ~CPrintHandler

    Description: Destructor. 
    Cancels active request.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CPrintHandler::~CPrintHandler()
    {

    Cancel();

    }




/*
-------------------------------------------------------------------------------

    Class: CPrintHandler

    Method: StartL

    Description: Starts to monitor thread.

    Parameters: None

    Return Values: TInt                             Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CPrintHandler::StartL()
    {
    
    __TRACE( KPrint, ( _L( "CPrintHandler::StartL" ) ) );
    
    if( IsActive() ) 
        {
        CTestServer::PanicServer( EAlreadyActive );
        }

    iStatus = KRequestPending;
    SetActive();
    
    // Signal test thread
    iExecution.iPrintSem.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CPrintHandler

    Method: RunL

    Description: Handles thread death.
    Function does:
    1 ) Stops monitoring thread
    1 ) Marks thread death
    2 ) Completes ongoing requests
    3 ) Cleans the memory

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CPrintHandler::RunL()
    {

    __TRACE( KPrint, ( _L( "CPrintHandler::RunL [%d]" ), iStatus.Int() ) );
    
    iExecution.DoNotifyPrint();
    
    // enable print request
    //@speiExecution.iPrintHandler->StartL();
    StartL();
    }


/*
-------------------------------------------------------------------------------

    Class: CPrintHandler

    Method: DoCancel

    Description: Stops print notification listening.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/

void CPrintHandler::DoCancel()
    {

    __TRACE( KPrint, ( _L( "CPrintHandler::DoCancel" ) ) );

    iExecution.iPrintMutex.Wait();  // Take mutex and check test case print
                                    // operation. If pending take print semaphore
                                    // and complete
    if( iStatus == KRequestPending )
        {
        // Signal test thread
        // @remove iExecution.iPrintSem.Wait();
    
        TRequestStatus* status = &iStatus;    
        User::RequestComplete( status, KErrCancel );        
        }

    iExecution.iPrintMutex.Signal();
    }

/*
-------------------------------------------------------------------------------

    Class: CPrintHandler

    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 CPrintHandler::RunError( TInt aError )
    {
    
    __TRACE( KError,( _L( "CPrintHandler::RunError" ) ) );

    return aError;
    
    }

/*
-------------------------------------------------------------------------------

    DESCRIPTION

    This module contains implementation of CEventHandler class member functions.
    CEventHandler listens print notifications from test thread.

-------------------------------------------------------------------------------
*/

// ================= MEMBER FUNCTIONS =========================================


/*
-------------------------------------------------------------------------------

    Class: CEventHandler

    Method: NewL

    Description: Constructs a new CEventHandler object.

    Parameters: CTestExecution& aExecution: in: "Parent"

    Return Values: CEventHandler*: New undertaker

    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.

    Status: Proposal

-------------------------------------------------------------------------------
*/
CEventHandler* CEventHandler::NewL( CTestExecution& aExecution )
    {

    CEventHandler* self = new( ELeave ) CEventHandler( aExecution );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;

    }

/*
-------------------------------------------------------------------------------

    Class: CEventHandler

    Method: ConstructL

    Description: Second level constructor.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CEventHandler::ConstructL()
    {

    }

/*
-------------------------------------------------------------------------------

    Class: CEventHandler

    Method: CEventHandler

    Description: Constructor

    Parameters: CTestModuleContainer& aExecution :in:   "Parent"

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CEventHandler::CEventHandler( CTestExecution& aExecution ) :
    CActive( CActive::EPriorityStandard ),
    iExecution( aExecution )
    {
    
    CActiveScheduler::Add ( this );
    
    }

/*
-------------------------------------------------------------------------------

    Class: CEventHandler

    Method: ~CEventHandler

    Description: Destructor. 
    Cancels active request.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CEventHandler::~CEventHandler()
    {

    Cancel();

    }




/*
-------------------------------------------------------------------------------

    Class: CEventHandler

    Method: StartL

    Description: Starts to monitor thread.

    Parameters: None

    Return Values: TInt                             Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CEventHandler::StartL()
    {
    
    __TRACE( KPrint, ( _L( "CEventHandler::StartL" ) ) );

    if( IsActive() ) 
        {
        CTestServer::PanicServer( EAlreadyActive );
        }
    
    iStatus = KRequestPending;
    SetActive();
    
    // Signal test thread
    iExecution.iEventSem.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CEventHandler

    Method: RunL

    Description: Handles thread death.
    Function does:
    1 ) Stops monitoring thread
    1 ) Marks thread death
    2 ) Completes ongoing requests
    3 ) Cleans the memory

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CEventHandler::RunL()
    {

    __TRACE( KPrint, ( _L( "CEventHandler::RunL [%d]" ), iStatus.Int() ) );

    switch( iExecution.EventDef().iType )
        {
        case TEventDef::EEventCmd:
            iExecution.DoNotifyEvent();
            break;
        case TEventDef::EEventCmdCancel:
            iExecution.CancelEvent();
            break;
        default:
            CTestServer::PanicServer( EUnknownEventCmd );
            break;  
        }
         
    }


/*
-------------------------------------------------------------------------------

    Class: CEventHandler

    Method: DoCancel

    Description: Stops print notification listening.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/

void CEventHandler::DoCancel()
    {

    __TRACE( KPrint, ( _L( "CEventHandler::DoCancel" ) ) );
    
    iExecution.iEventMutex.Wait();  // Take mutex and check test case event
                                    // operation. If pending take event
                                    // semaphore and complete
    if( iStatus == KRequestPending )
        {
        // Signal test thread
        // @remove iExecution.iEventSem.Wait();

        TRequestStatus* status = &iStatus;    
        User::RequestComplete( status, KErrCancel );

        }

    iExecution.iEventMutex.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CEventHandler

    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 CEventHandler::RunError( TInt aError )
    {
    
    __TRACE( KError,( _L( "CEventHandler::RunError" ) ) );

    return aError;
    
    }

/*
-------------------------------------------------------------------------------

    DESCRIPTION

    This module contains implementation of CSndHandler class member functions.
    CSndHandler listens print notifications from test thread.

-------------------------------------------------------------------------------
*/

// ================= MEMBER FUNCTIONS =========================================


/*
-------------------------------------------------------------------------------

    Class: CSndHandler

    Method: NewL

    Description: Constructs a new CSndHandler object.

    Parameters: CTestExecution& aExecution: in: "Parent"

    Return Values: CSndHandler*: New undertaker

    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.

    Status: Proposal

-------------------------------------------------------------------------------
*/
CSndHandler* CSndHandler::NewL( CTestExecution& aExecution )
    {

    CSndHandler* self = new( ELeave ) CSndHandler( aExecution );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;

    }

/*
-------------------------------------------------------------------------------

    Class: CSndHandler

    Method: ConstructL

    Description: Second level constructor.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CSndHandler::ConstructL()
    {

    }

/*
-------------------------------------------------------------------------------

    Class: CSndHandler

    Method: CSndHandler

    Description: Constructor

    Parameters: CTestModuleContainer& aExecution :in:   "Parent"

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CSndHandler::CSndHandler( CTestExecution& aExecution ) :
    CActive( CActive::EPriorityStandard ),
    iExecution( aExecution )
    {
    
    CActiveScheduler::Add ( this );
    
    }

/*
-------------------------------------------------------------------------------

    Class: CSndHandler

    Method: ~CSndHandler

    Description: Destructor. 
    Cancels active request.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CSndHandler::~CSndHandler()
    {

    Cancel();

    }




/*
-------------------------------------------------------------------------------

    Class: CSndHandler

    Method: StartL

    Description: Starts to monitor thread.

    Parameters: None

    Return Values: TInt                             Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CSndHandler::StartL()
    {
    
    __TRACE( KPrint, ( _L( "CSndHandler::StartL" ) ) );

    if( IsActive() ) 
        {
        CTestServer::PanicServer( EAlreadyActive );
        }
    
    iStatus = KRequestPending;
    SetActive();
    
    // Signal test thread
    iExecution.iSndSem.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CSndHandler

    Method: RunL

    Description: Handles thread death.
    Function does:
    1 ) Stops monitoring thread
    1 ) Marks thread death
    2 ) Completes ongoing requests
    3 ) Cleans the memory

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CSndHandler::RunL()
    {

    __TRACE( KPrint, ( _L( "CSndHandler::RunL [%d]" ), iStatus.Int() ) );
    
    iExecution.DoRemoteSend();
       
    }


/*
-------------------------------------------------------------------------------

    Class: CSndHandler

    Method: DoCancel

    Description: Stops print notification listening.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/

void CSndHandler::DoCancel()
    {

    __TRACE( KPrint, ( _L( "CSndHandler::DoCancel" ) ) );

    iExecution.iSndMutex.Wait();  // Take mutex and check test case send
                                  // operation. If pending take send
                                  // semaphore and complete
    if( iStatus == KRequestPending )
        {
        // Signal test thread
        // @remove iExecution.iSndSem.Wait();

        TRequestStatus* status = &iStatus;    
        User::RequestComplete( status, KErrCancel );

        }

    iExecution.iSndMutex.Signal();
    
    }

/*
-------------------------------------------------------------------------------

    Class: CSndHandler

    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 CSndHandler::RunError( TInt aError )
    {
    
    __TRACE( KError,( _L( "CSndHandler::RunError" ) ) );

    return aError;
    
    }

/*
-------------------------------------------------------------------------------

    DESCRIPTION

    This module contains implementation of CSndHandler class member functions.
    CRcvHandler listens print notifications from test thread.

-------------------------------------------------------------------------------
*/

// ================= MEMBER FUNCTIONS =========================================


/*
-------------------------------------------------------------------------------

    Class: CRcvHandler

    Method: NewL

    Description: Constructs a new CRcvHandler object.

    Parameters: CTestExecution& aExecution: in: "Parent"

    Return Values: CRcvHandler*: New undertaker

    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.

    Status: Proposal

-------------------------------------------------------------------------------
*/
CRcvHandler* CRcvHandler::NewL( CTestExecution& aExecution )
    {

    CRcvHandler* self = new( ELeave ) CRcvHandler( aExecution );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;

    }

/*
-------------------------------------------------------------------------------

    Class: CRcvHandler

    Method: ConstructL

    Description: Second level constructor.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CRcvHandler::ConstructL()
    {

    }

/*
-------------------------------------------------------------------------------

    Class: CRcvHandler

    Method: CRcvHandler

    Description: Constructor

    Parameters: CTestModuleContainer& aExecution :in:   "Parent"

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CRcvHandler::CRcvHandler( CTestExecution& aExecution ) :
    CActive( CActive::EPriorityStandard ),
    iExecution( aExecution )
    {
    
    CActiveScheduler::Add ( this );
    
    }

/*
-------------------------------------------------------------------------------

    Class: CRcvHandler

    Method: ~CRcvHandler

    Description: Destructor. 
    Cancels active request.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CRcvHandler::~CRcvHandler()
    {

    Cancel();

    }




/*
-------------------------------------------------------------------------------

    Class: CRcvHandler

    Method: StartL

    Description: Starts to monitor thread.

    Parameters: None

    Return Values: TInt                             Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CRcvHandler::StartL()
    {
    
    __TRACE( KPrint, ( _L( "CRcvHandler::StartL" ) ) );
    
    if( IsActive() ) 
        {
        CTestServer::PanicServer( EAlreadyActive );
        }
    iStatus = KRequestPending;
    SetActive();
    
    // Signal test thread
    iExecution.iRcvSem.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CRcvHandler

    Method: RunL

    Description: Handles thread death.
    Function does:
    1 ) Stops monitoring thread
    1 ) Marks thread death
    2 ) Completes ongoing requests
    3 ) Cleans the memory

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CRcvHandler::RunL()
    {

    __TRACE( KPrint, ( _L( "CRcvHandler::RunL [%d]" ), iStatus.Int() ) );
    
    iExecution.DoRemoteReceive();
       
    }


/*
-------------------------------------------------------------------------------

    Class: CRcvHandler

    Method: DoCancel

    Description: Stops print notification listening.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/

void CRcvHandler::DoCancel()
    {

    __TRACE( KPrint, ( _L( "CRcvHandler::DoCancel" ) ) );

    iExecution.iRcvMutex.Wait();  // Take mutex and check test case receive
                                  // operation. If pending take reveive
                                  // semaphore and complete
    if( iStatus == KRequestPending )
        {
        // Signal test thread
        // @remove iExecution.iRcvSem.Wait();

        TRequestStatus* status = &iStatus;    
        User::RequestComplete( status, KErrCancel );
        }
        
    iExecution.iRcvMutex.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CRcvHandler

    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 CRcvHandler::RunError( TInt aError )
    {
    
    __TRACE( KError,( _L( "CRcvHandler::RunError" ) ) );

    return aError;
    
    }


/*
-------------------------------------------------------------------------------

    DESCRIPTION

    This module contains implementation of CTestInterferenceHandler class 
    member functions. CTestInterferenceHandler listens print notifications from
    test thread.

-------------------------------------------------------------------------------
*/

// ================= MEMBER FUNCTIONS =========================================


/*
-------------------------------------------------------------------------------

    Class: CInterferenceHandler

    Method: NewL

    Description: Constructs a new CInterferenceHandler object.

    Parameters: CTestExecution& aExecution: in: "Parent"

    Return Values: CInterferenceHandler*: New undertaker

    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.

    Status: Proposal

-------------------------------------------------------------------------------
*/
CInterferenceHandler* CInterferenceHandler::NewL( 
                                                CTestExecution& aExecution )
    {
    CInterferenceHandler* self = 
                        new( ELeave ) CInterferenceHandler( aExecution );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;

    }

/*
-------------------------------------------------------------------------------

    Class: CInterferenceHandler

    Method: ConstructL

    Description: Second level constructor.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CInterferenceHandler::ConstructL()
    {

    }

/*
-------------------------------------------------------------------------------

    Class: CInterferenceHandler

    Method: CInterferenceHandler

    Description: Constructor

    Parameters: CTestModuleContainer& aExecution :in: "Parent"

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CInterferenceHandler::CInterferenceHandler( CTestExecution& aExecution ) :
    CActive( CActive::EPriorityStandard ),
    iExecution( aExecution )
    {
    CActiveScheduler::Add ( this );
    
    }

/*
-------------------------------------------------------------------------------

    Class: CInterferenceHandler

    Method: ~CInterferenceHandler

    Description: Destructor. 
    Cancels active request.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
CInterferenceHandler::~CInterferenceHandler()
    {
    Cancel();

    }

/*
-------------------------------------------------------------------------------

    Class: CInterferenceHandler

    Method: StartL

    Description: Starts to monitor thread.

    Parameters: None

    Return Values: TInt: Always KErrNone

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CInterferenceHandler::StartL()
    {
    __TRACE( KPrint, ( _L( "CInterferenceHandler::StartL" ) ) );
    
    if( IsActive() ) 
        {
        CTestServer::PanicServer( EAlreadyActive );
        }

    iStatus = KRequestPending;
    SetActive();
    
    // Signal test thread, Notify test thread that operation is done.
    iExecution.iInterferenceSem.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CInterferenceHandler

    Method: RunL

    Description: Handles thread death.
    Function does:
    1 ) Stops monitoring thread
    1 ) Marks thread death
    2 ) Completes ongoing requests
    3 ) Cleans the memory

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CInterferenceHandler::RunL()
    {
    __TRACE( KPrint, ( _L( "CInterferenceHandler::RunL [%d]" ), iStatus.Int() ) );
    
    iExecution.DoNotifyInterference();
    
    StartL();

    }

/*
-------------------------------------------------------------------------------

    Class: CInterferenceHandler

    Method: DoCancel

    Description: Stops interference notification listening.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal
    
-------------------------------------------------------------------------------
*/
void CInterferenceHandler::DoCancel()
    {
    __TRACE( KPrint, ( _L( "CInterferenceHandler::DoCancel" ) ) );

    iExecution.iInterferenceMutex.Wait();   // Take mutex and check test
                                            // interference operation. If
                                            // pending take interference
                                            // semaphore and complete
    if( iStatus == KRequestPending )
        {
    
        TRequestStatus* status = &iStatus;    
        User::RequestComplete( status, KErrCancel );
        }

    iExecution.iInterferenceMutex.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CInterferenceHandler

    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 CInterferenceHandler::RunError( TInt aError )
    {
    __TRACE( KError,( _L( "CTestInterferenceHandler::RunError" ) ) );

    return aError;

    }

/*
-------------------------------------------------------------------------------

    DESCRIPTION

    This module contains implementation of CMeasurementHandler class 
    member functions. CMeasurementHandler handles test measurement operations
    that comes from test execution side to TestServer side.

-------------------------------------------------------------------------------
*/

// ================= MEMBER FUNCTIONS =========================================


/*
-------------------------------------------------------------------------------

    Class: CMeasurementHandler

    Method: NewL

    Description: Constructs a new CMeasurementHandler object.

    Parameters: CTestExecution& aExecution: in: Pointer to test execution side.

    Return Values: CMeasurementHandler*: New undertaker

    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.

    Status: Approved

-------------------------------------------------------------------------------
*/
CMeasurementHandler* CMeasurementHandler::NewL( CTestExecution& aExecution )
    {
    CMeasurementHandler* self = 
                        new( ELeave ) CMeasurementHandler( aExecution );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;

    }

/*
-------------------------------------------------------------------------------

    Class: CMeasurementHandler

    Method: ConstructL

    Description: Second level constructor.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Approved

-------------------------------------------------------------------------------
*/
void CMeasurementHandler::ConstructL()
    {

    }

/*
-------------------------------------------------------------------------------

    Class: CMeasurementHandler

    Method: CMeasurementHandler

    Description: Constructor

    Parameters: CTestModuleContainer& aExecution :in: Pointer to test
                execution side.

    Return Values: None

    Errors/Exceptions: None

    Status: Approved

-------------------------------------------------------------------------------
*/
CMeasurementHandler::CMeasurementHandler( CTestExecution& aExecution ) :
    CActive( CActive::EPriorityStandard ),
    iExecution( aExecution )
    {
    CActiveScheduler::Add ( this );

    }

/*
-------------------------------------------------------------------------------

    Class: CMeasurementHandler

    Method: ~CMeasurementHandler

    Description: Destructor. 
    Cancels active request.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Approved

-------------------------------------------------------------------------------
*/
CMeasurementHandler::~CMeasurementHandler()
    {
    Cancel();

    }

/*
-------------------------------------------------------------------------------

    Class: CMeasurementHandler

    Method: StartL

    Description: Starts to monitor thread.

    Parameters: None

    Return Values: TInt: Always KErrNone

    Errors/Exceptions: None

    Status: Approved

-------------------------------------------------------------------------------
*/
void CMeasurementHandler::StartL()
    {
    __TRACE( KPrint, ( _L( "CMeasurementHandler::StartL" ) ) );

    if( IsActive() ) 
        {
        CTestServer::PanicServer( EAlreadyActive );
        }

    iStatus = KRequestPending;
    SetActive();

    // Do not Signal here because synchronous operations will be executed and we
    // don't want to signal at first time: iExecution.iMeasurementSem.Signal();
    // Signal() operation will be handled in RunL in this case.

    }

/*
-------------------------------------------------------------------------------

    Class: CMeasurementHandler

    Method: RunL

    Description: Derived from CActive, handles test measurement execution.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Approved

-------------------------------------------------------------------------------
*/
void CMeasurementHandler::RunL()
    {
    __TRACE( KPrint, ( _L( "CMeasurementHandler::RunL [%d]" ), iStatus.Int() ) );
    
    TInt ret( 0 );
    ret = iExecution.DoNotifyMeasurement();

    // ret value is copied to struct so it can be handled later.
    iExecution.iTestMeasurement.iMeasurementStruct.iOperationResult = ret;
    
    // SetActive again
    StartL();

    // TestServer side operations are done, Signal that operation is done.
    iExecution.iMeasurementSem.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CMeasurementHandler

    Method: DoCancel

    Description: Stops measurement notification listening.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Approved
    
-------------------------------------------------------------------------------
*/
void CMeasurementHandler::DoCancel()
    {
    __TRACE( KPrint, ( _L( "CMeasurementHandler::DoCancel" ) ) );

    iExecution.iMeasurementMutex.Wait();    // Take mutex and check test
                                            // measurement operation. If
                                            // pending take measurement
                                            // semaphore and complete
    if( iStatus == KRequestPending )
        {
    
        TRequestStatus* status = &iStatus;    
        User::RequestComplete( status, KErrCancel );
        }

    iExecution.iMeasurementMutex.Signal();

    }

/*
-------------------------------------------------------------------------------

    Class: CMeasurementHandler

    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: Approved

-------------------------------------------------------------------------------
*/
TInt CMeasurementHandler::RunError( TInt aError )
    {
    __TRACE( KError,( 
        _L( "CMeasurementHandler::RunError with error: %d" ), aError ) );

    return aError;

    }

/*
-------------------------------------------------------------------------------

    DESCRIPTION

    This module contains implementation of CCommandHandler class member functions.
    CCommandHandler listens command notifications from test thread.

-------------------------------------------------------------------------------
*/

// ================= MEMBER FUNCTIONS =========================================


/*
-------------------------------------------------------------------------------

    Class: CCommandHandler

    Method: NewL

    Description: Constructs a new CCommandHandler object.

    Parameters: CTestExecution& aExecution: in: "Parent"

    Return Values: CCommandHandler*: New object

    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.

    Status: Proposal

-------------------------------------------------------------------------------
*/
CCommandHandler* CCommandHandler::NewL(CTestExecution& aExecution)
    {
    CCommandHandler* self = new (ELeave) CCommandHandler(aExecution);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }

/*
-------------------------------------------------------------------------------

    Class: CCommandHandler

    Method: ConstructL

    Description: Second level constructor.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CCommandHandler::ConstructL()
    {
    }

/*
-------------------------------------------------------------------------------

    Class: CCommandHandler

    Method: CCommandHandler

    Description: Constructor

    Parameters: CTestExecution& aExecution :in:   "Parent"

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
CCommandHandler::CCommandHandler(CTestExecution& aExecution):
    CActive(CActive::EPriorityStandard),
    iExecution(aExecution)
    {
    CActiveScheduler::Add (this);
    }

/*
-------------------------------------------------------------------------------

    Class: CCommandHandler

    Method: ~CCommandHandler

    Description: Destructor.
    Cancels active request.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
CCommandHandler::~CCommandHandler()
    {
    Cancel();
    }

/*
-------------------------------------------------------------------------------

    Class: CCommandHandler

    Method: StartL

    Description: Starts to monitor thread.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CCommandHandler::StartL()
    {
    __TRACE(KPrint, (_L( "CCommandHandler::StartL" )));

    if(IsActive())
        {
        CTestServer::PanicServer(EAlreadyActive);
        }
    iStatus = KRequestPending;
    SetActive();

    // Signal test thread
    iExecution.iCommandSem.Signal();
    }

/*
-------------------------------------------------------------------------------

    Class: CCommandHandler

    Method: RunL

    Description:

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/
void CCommandHandler::RunL()
    {
    __TRACE(KPrint, (_L( "CCommandHandler::RunL [%d]"), iStatus.Int()));

    iExecution.DoNotifyCommand();
//    StartL();
    }


/*
-------------------------------------------------------------------------------

    Class: CCommandHandler

    Method: DoCancel

    Description: Stops command notification listening.

    Parameters: None

    Return Values: None

    Errors/Exceptions: None

    Status: Proposal

-------------------------------------------------------------------------------
*/

void CCommandHandler::DoCancel()
    {
    __TRACE(KPrint, (_L("CCommandHandler::DoCancel")));

    iExecution.iCommandMutex.Wait();  // Take mutex and check test case receive
                                      // operation. If pending take reveive
                                      // semaphore and complete
    if(iStatus == KRequestPending)
        {
        TRequestStatus* status = &iStatus;
        User::RequestComplete(status, KErrCancel);
        }

    iExecution.iCommandMutex.Signal();
    }

/*
-------------------------------------------------------------------------------

    Class: CCommandHandler

    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 CCommandHandler::RunError(TInt aError)
    {
    __TRACE(KError, (_L("CCommandHandler::RunError")));

    return aError;
    }

/*
-------------------------------------------------------------------------------

    Class: CCommandDef

    Method: CCommandDef

    Description: private constructor

    Return Values:  void

-------------------------------------------------------------------------------
*/

CCommandDef::CCommandDef()
	{
	}

/*
-------------------------------------------------------------------------------

    Class: CCommandDef

    Method: ConstructL

    Description: Second phase constructor

    Return Values:  void

-------------------------------------------------------------------------------
*/

void CCommandDef::ConstructL()
	{

	}

/*
-------------------------------------------------------------------------------

    Class: CCommandDef

    Method: NewL

    Description: First phase constructor

    Return Values:  void

-------------------------------------------------------------------------------
*/

CCommandDef* CCommandDef::NewL()
	{
	CCommandDef* self = new(ELeave) CCommandDef;
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

/*
-------------------------------------------------------------------------------

    Class: CCommandDef

    Method: ~CCommandDef

    Description: destructor

-------------------------------------------------------------------------------
*/

CCommandDef::~CCommandDef()
	{

	}

//  End of File
