stif/TestServer/src/Testundertaker.cpp
changeset 0 a03f92240627
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stif/TestServer/src/Testundertaker.cpp	Tue Feb 02 01:57:15 2010 +0200
@@ -0,0 +1,492 @@
+/*
+* 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 CUnderTaker 
+* class member functions. CUnderTaker is a class, which listens 
+* on Test Execution Thread death, and if that thread dies, then 
+* UnderTaker aborts the ongoing test execution request.
+*
+*/
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <e32svr.h>
+#include "TestEngineClient.h"
+#include <StifTestModule.h>
+#include <stifinternal/TestServerClient.h>
+#include "TestServer.h"
+#include "TestServerModuleIf.h"
+#include "TestServerCommon.h"
+#include "PrintQueue.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: CUnderTaker
+
+    Method: NewL
+
+    Description: Constructs a new CUnderTaker object.
+
+    Parameters: CTestModuleContainer* aContainer :in:   "Parent"
+
+    Return Values: CUnderTaker*                         New undertaker
+
+    Errors/Exceptions: Leaves if memory allocation or ConstructL leaves.
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+CUnderTaker* CUnderTaker::NewL( CTestModuleContainer* aContainer )
+    {
+
+    CUnderTaker* self = new( ELeave ) CUnderTaker();
+    CleanupStack::PushL( self );
+    self->ConstructL( aContainer );
+    CleanupStack::Pop( self );
+    return self;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CUnderTaker
+
+    Method: ConstructL
+
+    Description: Second level constructor.
+
+    Parameters: CTestModuleContainer* aExecution :in:   "Parent"
+
+    Return Values: None
+
+    Errors/Exceptions: Panics if aContainer is NULL
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CUnderTaker::ConstructL( CTestModuleContainer* aContainer )
+    {
+
+    __ASSERT_ALWAYS( aContainer, 
+                     CTestServer::PanicServer( ENullTestModuleContainer ) );
+
+    iModuleContainer = aContainer;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CUnderTaker
+
+    Method: CUnderTaker
+
+    Description: Constructor
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+CUnderTaker::CUnderTaker() :
+    CActive( CActive::EPriorityHigh+1 )
+    {
+
+    // By default in asynchronous mode
+    iSynchronousMode = EFalse;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CUnderTaker
+
+    Method: ~CUnderTaker
+
+    Description: Destructor. 
+    Cancels active request.
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+CUnderTaker::~CUnderTaker()
+    {
+
+    Cancel();
+
+    }
+
+
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CUnderTaker
+
+    Method: StartL
+
+    Description: Starts to monitor thread.
+
+    Parameters: None
+
+    Return Values: TInt                             Always KErrNone
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+TInt CUnderTaker::StartL()
+    {
+    
+    SetActive();
+    iModuleContainer->iThread.Logon( iStatus );
+    iCancelNeeded = ETrue;
+
+    return KErrNone;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CUnderTaker
+
+    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 CUnderTaker::RunL()
+    {
+
+    // Make sure that any of the test interference thread's won't stay to run.
+    iModuleContainer->KillTestinterferenceThread();
+
+    // Make sure that any of the test measurement's process won't stay to run.
+    iModuleContainer->KillTestMeasurement();
+
+    // Get the exit category
+    TName exitCategory = _L( "Crash reason:" );
+    exitCategory.Append( iModuleContainer->iThread.ExitCategory() );
+    TInt exitReason = iModuleContainer->iThread.ExitReason();
+    TFullTestResult::TCaseExecutionResult exitType = TFullTestResult::ECaseException;
+    if( iModuleContainer->iThread.ExitType() == EExitPanic )
+        {
+        exitType = TFullTestResult::ECasePanic;
+        }    
+
+    // it is not running anymore..
+    iModuleContainer->iUpAndRunning = EFalse;
+
+    // Do not monitor anymore.
+    iModuleContainer->iThread.LogonCancel( iStatus );
+    iCancelNeeded = EFalse;
+
+    __TRACE( KError,( CStifLogger::ERed, _L( "Execution thread crashed, exitReason = %d" ), exitReason ) );
+    __TRACE( KError,( CStifLogger::ERed, exitCategory ) );    
+
+    if ( iSynchronousMode )
+        {        
+
+        // Synchronous request was running. Complete that 
+          // operation.
+        __TRACE( KVerbose,( _L( "CUnderTaker::RunL Crash during synchronous operation" ) ) );
+        iModuleContainer->iErrorResult = KErrDied;
+        iModuleContainer->Cancel();
+        iModuleContainer->iUpAndRunning = EFalse;
+
+        // Print notification
+        TName operationText = _L("Test module died when calling:");
+        operationText.Append( iModuleContainer->iOperationText );
+
+        // Print to log file        
+        __TRACE( KError,( CStifLogger::ERed, operationText ) );
+        // Print to UI
+        iModuleContainer->iCTestModule->ErrorPrint ( 1, operationText );        
+
+        // Stop active scheduler.
+        CActiveScheduler::Stop();
+
+        // Execution continues from CTestModuleContainer::StartAndWaitOperation.
+
+        }
+    else
+        {// Test case was running, 
+
+        __TRACE( KError,( _L( "Test case execution aborted" ) ) );
+        __TRACE( KVerbose,( _L( "CUnderTaker::Run crash during test execution" ) ) );      
+
+        TInt caseResult = KErrGeneral;
+        
+        // Check if case have any special panic or exception codes that are "passed"
+        if ( iModuleContainer->iAllowedExitReason != 
+             CTestModuleIf::ENormal )            
+            {
+                
+            if ( iModuleContainer->iAllowedExitReason == 
+                 CTestModuleIf::EPanic &&
+                 exitType == TFullTestResult::ECasePanic &&
+                 iModuleContainer->iAllowedExitCode == exitReason )
+                {
+                exitType = TFullTestResult::ECaseExecuted;
+                caseResult = KErrNone;
+                exitCategory = _L("Allowed case panic");
+                
+                __TRACE( KError,( _L( "Test case execution panic, setting to OK" ) ) );
+                }
+
+            if ( iModuleContainer->iAllowedExitReason == 
+                 CTestModuleIf::EException &&
+                 exitType == TFullTestResult::ECaseException &&
+                 iModuleContainer->iAllowedExitCode == exitReason )
+                {
+                exitType = TFullTestResult::ECaseExecuted;
+                caseResult = KErrNone;
+                exitCategory = _L("Allowed case exception");
+
+                __TRACE( KError,( _L( "Test case execution exception, setting to OK" ) ) );
+                }
+            
+            
+            }
+
+        // This was asynchronous request, and nobody is waiting for it
+        // completion in server, so all clean-up must be done here
+
+        // Forget iTestThreadContainer pointer, memory is freed because test thread
+        // is destroyed   
+        // This is needed to prevent from accessing memory from thread that is destroyed.
+        // Do this only if test is been executed.
+        iModuleContainer->iThreadContainer = NULL;
+
+        if (iModuleContainer->iCTestExecution != NULL)
+        	{
+			// Execution thread have been killed
+			iModuleContainer->iCTestExecution->SetThreadState( CTestExecution::ECancelled );
+	
+			
+			// Cancel the request
+			iModuleContainer->iCTestExecution->CompleteTestExecution( KErrNone,
+																	  exitType,
+																	  exitReason,
+																	  caseResult,
+																	  exitCategory );
+	
+			// If the print queue is empty, and there is active print
+			// request, then cancel that request. 
+			// NOTE: Case queue not empty AND request waiting AND
+			//       thread terminated can't happen due iPrintMutex
+			iModuleContainer->iCTestExecution->CompletePrintRequestIfQueueEmpty();
+        	}
+        else
+        	{
+        	__TRACE( KError,( _L( "STIF internal error - iCTestExecution is NULL in CUnderTaker::RunL." ) ) );
+        	User::Leave(KErrGeneral);
+        	}
+        // Free the memory
+        // Remove undertaker from module container to make sure that
+        // it does not delete this.
+        iModuleContainer->iUnderTaker = NULL;
+        delete iModuleContainer;
+        iModuleContainer = NULL;
+
+        // Suicide. "Parent", i.e iModuleContainer has already died
+        // and no-one have pointer to this active object, so die.
+        delete this;
+
+        }
+       
+    }
+
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CUnderTaker
+
+    Method: DoCancel
+
+    Description: Stops thread monitoring
+
+    Parameters: None
+
+    Return Values: None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+    
+-------------------------------------------------------------------------------
+*/
+
+void CUnderTaker::DoCancel()
+    {
+
+    if( iCancelNeeded && iModuleContainer )
+        {
+        iModuleContainer->iThread.LogonCancel( iStatus );
+        }
+    else
+        {
+        // Note that iModuleContainer can be NULL if iCancelNeeded is EFalse
+        __ASSERT_ALWAYS( iModuleContainer, 
+                         CTestServer::PanicServer( ENullTestModuleContainer ) );
+        }
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CUnderTaker
+
+    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 CUnderTaker::RunError( TInt aError )
+    {
+    __TRACE( KError,( _L( "CUnderTaker::RunError" ) ) );
+
+    return aError;
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CUnderTaker
+
+    Method: Completed
+
+    Description: Is request completed
+
+    Parameters: None
+
+    Return Values:  TBool                           Completed?
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+TBool CUnderTaker::Completed()
+    {
+
+    if( iStatus == KRequestPending )
+        {
+        return EFalse;
+        }
+    else
+        {
+        return ETrue;
+        }
+
+    }
+
+/*
+-------------------------------------------------------------------------------
+
+    Class: CUnderTaker
+
+    Method: SetSynchronousMode
+
+    Description: Set or unsets local processing mode
+
+    Parameters: const TBool aMode             :in:  Mode
+
+    Return Values:  None
+
+    Errors/Exceptions: None
+
+    Status: Proposal
+
+-------------------------------------------------------------------------------
+*/
+void CUnderTaker::SetSynchronousMode( const TBool aMode )
+    {
+
+    iSynchronousMode = aMode;
+   
+    }
+
+// End of File