lowlevellibsandfws/pluginfw/Test_Bed/test_bed/UnitTest.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lowlevellibsandfws/pluginfw/Test_Bed/test_bed/UnitTest.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,336 @@
+// Copyright (c) 1997-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:
+// Implementation of the CUnitTest base class.
+// 
+//
+
+#include <ecom/test_bed/unittest.h>
+#include <ecom/test_bed/transition.h>
+#include <ecom/test_bed/datalogger.h>
+#include <ecom/test_bed/testbeddefinitions.h>
+
+
+EXPORT_C CUnitTest::~CUnitTest()
+	{
+	Cancel();
+
+	// Delete any outstanding asynchronous transitions
+	if(iOutstandingTransitions)
+		{
+		iOutstandingTransitions->Reset();
+		delete iOutstandingTransitions;
+		}
+
+	if(iTransitions)
+		{
+		iTransitions->ResetAndDestroy();
+		delete iTransitions;
+		}
+
+	iLeaveErrorArray.Reset();
+
+	delete iFileMan;
+	iFs.Close();
+	}
+
+EXPORT_C void CUnitTest::UnitTestConstructL()
+	{
+	User::LeaveIfError(iFs.Connect());
+	iFileMan = CFileMan::NewL(iFs);
+	CTimer::ConstructL();
+	iTransitions = new(ELeave) RPointerArray<CTransition>;
+	iOutstandingTransitions = new(ELeave) RPointerArray<CTransition>;
+	_LIT(KConstructingUnitTestMsg, "Constructed Unit Test named %S");
+	iDataLogger.LogInformationWithParameters(KConstructingUnitTestMsg, &iUnitTestName);
+	}
+
+
+CUnitTestInfo* CUnitTest::TransitionSetL() const
+	{
+	CUnitTestInfo* transitionSet = CUnitTestInfo::NewL(iUnitTestName);
+	return transitionSet;
+	}
+
+
+EXPORT_C void CUnitTest::RunTest(TTimeIntervalMicroSeconds32 aTimeAfter /*= 0*/)
+	{
+	After(aTimeAfter);
+	_LIT(KTxtSeparator, "-----------------------------------------------------------------------------------");
+	_LIT(KStartingUnitTest, "Beginning Unit Test named %S");
+	iDataLogger.LogInformation(KTxtSeparator);
+	iDataLogger.LogInformationWithParameters(KStartingUnitTest, &iUnitTestName);
+	iDataLogger.ReportInformationWithParameters(KStartingUnitTest, &iUnitTestName);
+	}
+
+EXPORT_C void CUnitTest::RunL()
+	{
+	_LIT(KUnitTestRunLPanic, "CUnitTest::RunL");
+
+	TInt status = iStatus.Int();
+	switch(status)
+		{
+		case (KTestBedRepeatTest):			/* A stub has requested repeat of the last test */
+			// Go back one so that we repeat the last test
+			--iNextTransitionIndex;
+			break;
+
+		case (KTestBedTestLeft):				/* The last transition's RunL left */
+		case (KTestBedTestCancel):				/* The last transition was cancelled */
+		case (KTestBedLeakTestLoopDetected):	/* A leak test detected an infinite loop */
+		case (KTestBedFailedPreConditions):		/* The last transition failed it's pre conditions */
+		case (KTestBedFailedPostConditions):	/* The last transition failed it's post conditions */
+			// Go to the end of the test so that it finishes
+			iNextTransitionIndex = iTransitions->Count();
+			break;
+
+		case (KTestBedAsynchronousTransition):	/* The last transition started an async request */
+			// Remember that we have an outstanding request and then carry on
+			iOutstandingTransitions->Append((*iTransitions)[iNextTransitionIndex - 1]);
+			break;
+
+		case (KErrNone):
+			break;
+
+		default:
+			User::Panic(KUnitTestRunLPanic, KTestBedInvalidStatus);
+		}
+
+	// If we still have more transitions to run
+	if(iNextTransitionIndex < iTransitions->Count())
+		{
+		iStatus = KRequestPending;
+		SetActive();
+
+		// If the next transition is a blocking one then wait for all outstanding async
+		// requests to complete.  Otherwise just run the next transition
+		if(((*iTransitions)[iNextTransitionIndex]->IsBlockingTransition()) && 
+			(iOutstandingTransitions->Count() > 0))
+			{
+			iWaitingForCompletion = ETrue;
+			}
+		else
+			{
+			(*iTransitions)[iNextTransitionIndex]->RunTransition(&iStatus);
+			++iNextTransitionIndex;
+			}
+		}
+	else
+		{
+		// If we still have outstanding async requests then wait for these to complete
+		// otherwise we have finished this test
+		if(iOutstandingTransitions->Count() > 0)
+			{
+			iWaitingForCompletion = ETrue;
+			iStatus = KRequestPending;
+			SetActive();
+			}
+		else
+			{
+			iUnitTestObserver.Complete(this);
+
+			_LIT(KInfoPrintFailed, "Failed: Unit Test");
+			_LIT(KTestLeft, "Failed: Unit Test %S left");
+			_LIT(KTestLeftWithUnexpectedError, "Failed: Test %S left with unexpected error");
+			_LIT(KTestFailed, "Failed: Unit Test %S failed a pre/post condition validation check");
+			_LIT(KTestLeftWithExpectedError, "Test %S left with an anticipated error");
+			_LIT(KTestCancelled, "Cancelled: Unit Test Transition %S was cancelled");
+			_LIT(KTestEnteredInfiniteLoop, "Unit Test Transition %S aborted (infinitely looping)");
+			_LIT(KEndingUnitTest, "Successfully completed Unit Test %S");
+			// We use RTest if it is present in the framework to validate
+			// status codes for errors. Note: not all non KErrNone code mean 
+			// there was an error and so we need to selective over which 
+			// cases below we use RTest().
+			switch(status)
+				{
+				case (KTestBedTestLeft):
+					{
+					TInt leaveCode = iCurrentlyExecutingTransition->GetErrorCode();
+					//Check to see if the leave code is NOT on the list of known leaving codes
+					if(iLeaveErrorArray.Find(leaveCode) == KErrNotFound)
+						{
+						iDataLogger.LogInformationWithParameters(KTestLeft, &iUnitTestName);
+						iDataLogger.ReportInformationWithParameters(KTestLeft, &iUnitTestName);
+						if(iRTest) 
+							{
+							(*iRTest)(status==KErrNone);
+							}
+						}
+					else	//Leave code is on the list 
+						{
+						TInt count = iTransitions->Count();
+						//Check transition number and if it is the last transition then this is an expected error
+						CTransition* lastTransition = (*iTransitions)[count-1];
+						if(iCurrentlyExecutingTransition == lastTransition)
+							{
+							iDataLogger.LogInformationWithParameters(KTestLeftWithExpectedError, &iUnitTestName);
+							iDataLogger.ReportInformationWithParameters(KEndingUnitTest, &iUnitTestName);
+							}
+						else	//Otherwise, if not the last transition, the test failed with an unexpected error
+							{
+							User::InfoPrint(KInfoPrintFailed);
+							User::InfoPrint(iUnitTestName);
+							iDataLogger.LogInformationWithParameters(KTestLeftWithUnexpectedError, &iUnitTestName);
+							iDataLogger.ReportInformationWithParameters(KTestLeftWithUnexpectedError, &iUnitTestName);
+							if(iRTest) 
+								{
+								(*iRTest)(status==KErrNone);
+								}
+							}
+						}
+					}
+					break;
+
+				case (KTestBedFailedPreConditions):
+				case (KTestBedFailedPostConditions):
+					{
+					User::InfoPrint(KInfoPrintFailed);
+					User::InfoPrint(iUnitTestName);
+					iDataLogger.LogInformationWithParameters(KTestFailed, &iUnitTestName);
+					iDataLogger.ReportInformationWithParameters(KTestFailed, &iUnitTestName);
+					if(iRTest) 
+						{
+						(*iRTest)(status==KErrNone);
+						}
+					}
+					break;
+
+				case (KTestBedTestCancel):
+					iDataLogger.LogInformationWithParameters(KTestCancelled, &iUnitTestName);
+					iDataLogger.ReportInformationWithParameters(KTestCancelled, &iUnitTestName);
+					if(iRTest) 
+						{
+						(*iRTest)(status==KErrNone);
+						}
+					break;
+
+				case (KTestBedLeakTestLoopDetected):
+					iDataLogger.LogInformationWithParameters(KTestEnteredInfiniteLoop, &iUnitTestName);
+					iDataLogger.ReportInformationWithParameters(KTestEnteredInfiniteLoop, &iUnitTestName);
+					if(iRTest) 
+						{
+						(*iRTest)(status==KErrNone);
+						}
+					break;
+
+				case (KErrNone):
+					iDataLogger.LogInformationWithParameters(KEndingUnitTest, &iUnitTestName);
+					iDataLogger.ReportInformationWithParameters(KEndingUnitTest, &iUnitTestName);
+					break;
+
+				default:
+					User::Panic(KUnitTestRunLPanic, KTestBedInvalidStatus);
+				}
+			}
+		}
+	}
+
+EXPORT_C void CUnitTest::AddTransitionL(CTransition* aTransition)
+	{
+	__ASSERT_DEBUG(aTransition, User::Panic(_L("CUnitTest"), KErrTestBedInvalidTransition));
+	CleanupStack::PushL(aTransition);
+	User::LeaveIfError(iTransitions->Append(aTransition));
+	CleanupStack::Pop(aTransition);
+	}
+
+EXPORT_C void CUnitTest::AddBlockingTransitionL(CTransition* aTransition)
+	{
+	__ASSERT_DEBUG(aTransition, User::Panic(_L("CUnitTest"), KErrTestBedInvalidTransition));
+	aTransition->SetBlockingTransition(ETrue);
+	CleanupStack::PushL(aTransition);
+	User::LeaveIfError(iTransitions->Append(aTransition));
+	CleanupStack::Pop(aTransition);
+	}
+
+EXPORT_C void CUnitTest::AddLeaveErrorCodeL(TInt aLeaveErrorCode)
+	{
+	User::LeaveIfError(iLeaveErrorArray.Append(aLeaveErrorCode));
+	}
+
+EXPORT_C CTransition& CUnitTest::GetCurrentTransition() const
+	{
+	// Check fror a stray stub call
+	// We will always have a valid pointer here IF called
+	// from a stub in response to that transition's call 
+	// on the stub's methods.
+	__ASSERT_DEBUG(iCurrentlyExecutingTransition, User::Invariant());
+	return *iCurrentlyExecutingTransition;
+	}
+
+EXPORT_C void CUnitTest::SetCurrentTransition(CTransition& aTransition)
+	{
+	iCurrentlyExecutingTransition = &aTransition;
+	}
+
+EXPORT_C void CUnitTest::Complete(CTransition& aTransition, TInt aAsyncPostCheckError)
+	{
+	// Should never be NULL at this point
+	__ASSERT_DEBUG(iCurrentlyExecutingTransition, User::Invariant());
+	if(iCurrentlyExecutingTransition == &aTransition)
+		iCurrentlyExecutingTransition = NULL;	// Clear the current transition
+
+	// Oops the code will crash if this is ever false
+	__ASSERT_DEBUG(iOutstandingTransitions, User::Invariant());
+
+	// Look-up the transition passed in...
+	TInt index = iOutstandingTransitions->Find(&aTransition);
+	if(index != KErrNotFound)
+		{
+		// ... and remove from the set of outstanding ones.
+		iOutstandingTransitions->Remove(index);
+
+		// Did we fail a second-phase post-condition validation on an asynchronous transition?
+		// Or was it a normal transition completion?  Regardless, we go for another iteration 
+		// of the AO, passing through the error code.
+		TBool completeIt = (aAsyncPostCheckError != KErrNone);
+		if(iWaitingForCompletion && (iOutstandingTransitions->Count() == 0))
+			completeIt = ETrue;
+
+		if (completeIt)
+			{
+			TRequestStatus* status = &iStatus;
+			User::RequestComplete(status, aAsyncPostCheckError);
+			}
+		}
+	else
+		{
+		__ASSERT_DEBUG(ETrue, 
+			User::Panic(_L("CUnitTest"), KErrTestBedInvalidTransition));
+		}
+	}
+
+EXPORT_C void CUnitTest::SetParametersL(TAny* /*aParams*/)
+	{
+	// Do nothing
+	}
+
+EXPORT_C void CUnitTest::DoCancel()
+	{
+	CTimer::DoCancel();
+
+	if(iCurrentlyExecutingTransition)
+		iCurrentlyExecutingTransition->Cancel();
+
+	// Cancel any outstanding asynchronous transitions
+	if(iOutstandingTransitions)
+		{
+		TInt count = iOutstandingTransitions->Count();
+		for(TInt index = 0; index < count; ++index)
+			{
+			(*iOutstandingTransitions)[index]->Cancel();
+			}
+		}
+
+	iUnitTestObserver.Complete(this);
+	}
+