messagingfw/msgtestfw/Framework/src/CMtfTestCase.cpp
changeset 62 db3f5fa34ec7
parent 0 8e480a14352b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgtestfw/Framework/src/CMtfTestCase.cpp	Wed Nov 03 22:41:46 2010 +0530
@@ -0,0 +1,439 @@
+// Copyright (c) 2003-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:
+//
+
+/**
+ @file
+*/
+	
+#include "CMtfTestCase.h"
+#include "CMtfTestActionWait.h"
+#include "CMtfTestActionSectionComplete.h"
+#include "CMtfTestParameterStore.h"
+#include "CMtfConfigurationType.h"
+#include "CMtfTestServer.h"
+
+_LIT(KMtfTestCasePanic,"Messaging Test Case Panic");
+
+void CMtfTestCase::Panic(TMtfTestCasePanic aPanic)
+{
+	User::Panic(KMtfTestCasePanic,aPanic);
+}
+
+/** Constructor. */
+CMtfTestCase::CMtfTestCase(const CMtfTestServer& aTestServer, const TBool& aScripted,
+		const TBool& aSynchronous)
+: 	CTestStep(), iCurrentState(EMtfTestCaseInitialState),
+	iScriptedTestCase(aScripted), iSynchronous(aSynchronous), iTestServer(aTestServer) 
+{
+	SetTestStepResult(EPass);
+}
+
+/** Creates a new parameter store. */
+void CMtfTestCase::ConstructL()
+{
+	iParameterStore = CMtfTestParameterStore::NewL();
+}
+
+/** Returns a reference to the parameter store. */
+const CMtfTestParameterStore& CMtfTestCase::ParameterStore() const
+{
+	return *iParameterStore;
+}
+	
+
+CMtfTestCase::~CMtfTestCase()
+{
+	delete iParameterStore;
+	iQueuedActions.ResetAndDestroy();
+	iCurrentActions.ResetAndDestroy();
+	iCompletedActions.ResetAndDestroy();
+	iTestCaseDefaultConfigurations.ResetAndDestroy();
+	delete iScheduler;
+}
+
+/** Converts an enumerator value to its corresponding numerical value. */
+TInt CMtfTestCase::ConvertEnumeratorL(const TDesC& aEnumerator) const
+{
+	return iTestServer.ConvertEnumeratorL(aEnumerator);
+}
+
+/** Obtains the correct configuration file given a type. */
+const TDesC& CMtfTestCase::GetConfigurationFileL(const CMtfConfigurationType::TMtfConfigurationType& aType) const
+{
+	return GetConfigurationFileL(aType,0);
+}
+
+/** Tries to find a main script configuration first,
+then the test case default and if none of them exist then gets the default configuration. */
+const TDesC& CMtfTestCase::GetConfigurationFileL(const CMtfConfigurationType::TMtfConfigurationType& aType, TInt aIndex) const
+{
+	TInt error=KErrNone;
+	const TDesC* retval=0;
+	TRAP(error,retval=&iTestServer.GetMainScriptConfigurationFileL(aType,aIndex)); 
+
+	if (error==KErrNone)
+	{
+		return *retval;
+	}
+	
+	if (error != KErrNotFound)
+	{
+ 		// nice to print some kind of error message here !!!
+		User::Leave(error);
+	}
+	
+	// find test case default if it exists
+	
+	TInt index=0;
+	TRAP(error,index = CMtfConfigurationType::FindConfigurationL(aType,iTestCaseDefaultConfigurations));
+	
+	if (error==KErrNone)
+	{
+		// configuration found, return the required file
+		// this may leave if item aIndex does not exist
+		return iTestCaseDefaultConfigurations[index]->ConfigurationFileL(aIndex);
+	}
+	else if (error != KErrNotFound)
+	{
+ 		// nice to print some kind of error message here !!!
+		User::Leave(error);
+	}
+	
+	// go to the server and ask for default
+	// aIndex is ignored in this case
+	return iTestServer.GetDefaultConfigurationFileL(aType);
+	
+	// ISSUE: at the end of the test case check whether all configurations have been used
+}
+
+#if defined(__WINS__) && !defined(_DEBUG)
+#pragma warning( default : 4702 ) //  unreachable code
+#endif
+
+/** This function take ownership of aConfiguration immediately and therefore SHOULD NOT be 
+called with aConfiguration already on the Cleanup stack. */
+void CMtfTestCase::SetTestCaseDefaultConfigurationTypeL(CMtfConfigurationType* aConfiguration)
+{
+	CMtfConfigurationType::SetConfigurationTypeL(aConfiguration,iTestCaseDefaultConfigurations);
+}
+
+/** The function takes ownership of aParameter at the END. */
+void CMtfTestCase::StoreParameterL(CMtfTestParameter* aParameter)
+{
+	iParameterStore->StoreParameterL(aParameter);
+}
+
+const CMtfTestParameter& CMtfTestCase::ObtainParameterL(const TDesC& aName) const
+{
+	return iParameterStore->ObtainParameterL(aName);
+}
+
+void CMtfTestCase::DeleteParameterL(const TDesC& aName)
+{
+	iParameterStore->DeleteParameterL(aName);
+}
+
+/**
+ * @return - TVerdict code
+ * Override of base class virtual
+ */
+TVerdict CMtfTestCase::doTestStepPreambleL()
+{
+	return TestStepResult();
+}
+
+/** Starts the execution of the test case by executing all test actions until the first wait action is 
+encountered. This function then returns. Override of base class pure virtual.
+@return - TVerdict code */
+TVerdict CMtfTestCase::doTestStepL()
+{
+	iScheduler=new (ELeave) CActiveScheduler();
+	CActiveScheduler::Install(iScheduler);
+		
+	if (iCurrentState == EMtfTestCaseInitialState)
+	{
+		ChangeState();
+	}
+	
+	if (iScriptedTestCase == EFalse)
+	{	
+		// non-scripted test case, run the first section function which builds up the queue
+		SetupTestCaseL();
+		
+		// ISSUE: assert the state hasn't changed
+			
+		if (iQueuedActions.Count() > 0)
+		{
+			// the new test action will be owned by the test case
+			CMtfTestActionSectionComplete::NewL(*this);	
+			
+			ExecuteActionsL();
+		}
+		else if (SetupTestCaseIsSynchronous())
+		{
+			// no queued actions and synchronous
+			SectionCompletedL();
+		}
+	}	
+	else
+	{
+		ExecuteActionsL();
+	}
+		
+	if (iCurrentState != EMtfTestCaseTestCompleted)
+	{
+		// the test case contains some asynchronous test actions so we need to start
+		// the scheduler
+		iActiveSchedulerRunning = ETrue;
+		iScheduler->Start();
+	}
+
+	return TestStepResult();
+}
+
+/**
+ * @return - TVerdict code
+ * Override of base class virtual
+ */
+TVerdict CMtfTestCase::doTestStepPostambleL()
+{
+	return TestStepResult();
+}
+
+/** Add a new action to the test case. Takes ownership of the test action at the END. */
+void CMtfTestCase::QueueTestActionL(CMtfTestAction* aTestAction) 
+{
+	TBool synchronousTestCase = (iScriptedTestCase? iSynchronous: IsSynchronous());
+	
+	if (synchronousTestCase && !aTestAction->WaitAction() && !aTestAction->SectionCompleteAction())
+	{
+		// put a wait action after each test action to make it synchronous
+		CMtfTestActionWait::NewL(*this);
+		
+		// at this point we can take ownership of aTestAction by inserting it before the wait
+		User::LeaveIfError(iQueuedActions.Insert(aTestAction, iQueuedActions.Count()-1));
+	}
+	else
+	{
+		User::LeaveIfError(iQueuedActions.Append(aTestAction));
+	}
+}
+
+TBool CMtfTestCase::IsSynchronous()
+{
+	return iSynchronous;
+}
+	
+/** Handles an action completion by removing it from the list of current actions and putting it on the
+list of completed actions. */
+void CMtfTestCase::ActionCompletedL(CMtfTestAction& aAction)
+{
+	TInt index = iCurrentActions.Find(&aAction);
+	User::LeaveIfError(index);
+	User::LeaveIfError(iCompletedActions.Append(&aAction));
+	iCurrentActions.Remove(index);	
+	
+	if (aAction.CurrentlyBeingWaitedFor())
+	{
+		aAction.SetCurrentlyBeingWaitedFor(EFalse);
+		iWaitListCount--;
+	}
+	
+	if (iWaitListCount == 0)
+	{
+		// no more actions that are currently being waited for
+		ExecuteActionsL();
+	}
+}
+	
+/** Executing all queued actions until a wait action is found. */
+void CMtfTestCase::ExecuteActionsL()
+{
+	for (;;)
+	{
+		if (iQueuedActions.Count()==0)
+		{
+			break;
+		}
+		
+		CMtfTestAction& nextAction = *iQueuedActions[0];
+		
+		// remove the first action from the queue and put it on the list
+		// of current actions
+		
+		iQueuedActions.Remove(0);	
+		
+		if (!nextAction.WaitAction() && !nextAction.SectionCompleteAction())
+		{
+			User::LeaveIfError(iCurrentActions.Append(&nextAction));
+		}	
+		else
+		{
+			// two framework actions are synchronous so they complete immediately
+			User::LeaveIfError(iCompletedActions.Append(&nextAction));
+		}
+		
+		// executing an action may: 
+		//	- start off an asynchronous request in which case the action
+		//		remains on the list of currently executing actions
+		//  - start and complete a synchronous action in which case the action
+		//		signals the test case that it has completed within ExecuteActionL(), 
+		//		therefore the action must be already on iCurrentActions before
+		//		ExecuteActionL() is called. ExecuteActionL() will be called recursively
+		//		from ActionCompletedL().
+		
+		nextAction.ExecuteActionL();
+		
+		if (iWaitListCount>0)
+		{
+			// wait action was found, stop execution
+			break;
+		}
+	}
+}
+
+/** Handles a section completion. The test case changes its state to the next state. For scripted test cases it checks whether 
+the test case is finished and if it is not it simply returns. Since all test actions in a scripted test case are in the queue 
+at the beginning the remaining test actions will be executed. For a non-scripted test case this function calls the appropriate 
+function which queues more test actions for the next section. The function then attempts to start the execution of test 
+actions in the next test case section. */
+void CMtfTestCase::SectionCompletedL()
+{
+	ChangeState();
+
+	if (iCurrentState == EMtfTestCaseTestCompleted)
+	{
+		__ASSERT_ALWAYS(iQueuedActions.Count()==0,Panic(EMtfUnexpectedQueuedAction));
+		
+		if (iActiveSchedulerRunning)
+		{
+			CActiveScheduler::Stop();
+		}
+		
+		return;
+	}
+	
+	if (!iScriptedTestCase)
+	{		
+		// Non-scripted test cases queue actions as they execute each section.
+		// Therefore, actions are queued per section and when a section completes
+		// there must be no more actions in the queue, unlike the scripted test cases
+		// which queue all actions in the test case.
+		
+		__ASSERT_ALWAYS(iQueuedActions.Count()==0,Panic(EMtfUnexpectedQueuedAction));
+		
+		switch (iCurrentState)
+		{
+			case EMtfTestCaseExecutingTest:
+				ExecuteTestCaseL();
+		
+				if (iQueuedActions.Count() > 0)
+				{
+					// owned by the test case
+					CMtfTestActionSectionComplete::NewL(*this);	
+					ExecuteActionsL();
+				}
+				else if (ExecuteTestCaseIsSynchronous())
+				{
+					SectionCompletedL();
+				}	
+				break;
+			case EMtfTestCaseCheckingPostconditions:
+				CheckPostConditionsL();
+				if (iQueuedActions.Count() > 0)
+				{
+					// owned by the test case
+					CMtfTestActionSectionComplete::NewL(*this);	
+					ExecuteActionsL();
+				} 
+				else if (CheckPostconditionsIsSynchronous())
+				{
+					SectionCompletedL();
+				}
+				break;
+			default:
+				break;
+		}    	
+	}	
+}
+
+/** Sets the test case to wait for the specified action. */
+void CMtfTestCase::WaitForActionL(const TDesC& aActionId)
+{
+	TInt countCurrent = iCurrentActions.Count();
+	
+	for (TInt count=0; count<countCurrent; count++)
+	{
+		if (iCurrentActions[count]->ActionIdL() == aActionId)
+		{
+			iCurrentActions[count]->SetCurrentlyBeingWaitedFor(ETrue);
+			iWaitListCount++;
+			break;
+		}
+	}
+	
+	// ISSUE: if not found maybe log this fact
+}
+
+/** Sets the test case to wait for all currently executing actions. */
+void CMtfTestCase::WaitForAllActionsL()
+{
+	TInt numberOfCurrentActions = iCurrentActions.Count();
+	
+	for (TInt count=0; count < numberOfCurrentActions; count++)
+	{
+		iCurrentActions[count]->SetCurrentlyBeingWaitedFor(ETrue);
+		iWaitListCount++;
+	} 
+}
+
+void CMtfTestCase::ChangeState()
+{
+	switch (iCurrentState)
+	{
+		case EMtfTestCaseInitialState:
+			iCurrentState = EMtfTestCaseExecutingSetup;
+			break; 
+		case EMtfTestCaseExecutingSetup:
+			iCurrentState = EMtfTestCaseExecutingTest;
+			break; 
+		case EMtfTestCaseExecutingTest:
+			iCurrentState = EMtfTestCaseCheckingPostconditions;
+			break; 
+		case EMtfTestCaseCheckingPostconditions:
+			iCurrentState = EMtfTestCaseTestCompleted;
+			break; 
+		case EMtfTestCaseTestCompleted:
+			User::Invariant();
+			break;
+		default:
+			User::Invariant();
+	}
+}	
+
+TBool CMtfTestCase::SetupTestCaseIsSynchronous() const
+{
+	return ETrue;
+}
+
+TBool CMtfTestCase::ExecuteTestCaseIsSynchronous() const
+{
+	return ETrue;
+}
+
+TBool CMtfTestCase::CheckPostconditionsIsSynchronous() const
+{
+	return ETrue;
+}