applayerprotocols/httptransportfw/Test/t_utils/HttpTestCore.cpp
changeset 0 b16258d2340f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/applayerprotocols/httptransportfw/Test/t_utils/HttpTestCore.cpp	Tue Feb 02 01:09:52 2010 +0200
@@ -0,0 +1,510 @@
+// Copyright (c) 2001-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:
+//
+    
+#include "HttpTestCore.h"
+
+_LIT(KTextFailure,"Test failed with error %d.\n");
+_LIT(KTextFailedTest,"TEST %S FAILED\n");
+_LIT(KTextPassedTest,"TEST %S PASSED\n");
+_LIT(KTextInterruptTest, "TEST %S INTERRUPTED\n");
+
+// Dummy POST body provided in test base should a specific test not want to generate its own
+_LIT8(KTestPostBody, "a=10\r\n");
+
+// format for output of data/time values
+_LIT(KDateFormat,"%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3");
+
+
+// Test harness requirements:
+// Uses an active object state machine to run tests.
+
+
+//##ModelId=3A76DDA701A2
+EXPORT_C void CTestScheduler::Error(TInt anError) const
+	{
+	_LIT(KTestPanic,"CTestScheduler RunL leave");
+	User::Panic(KTestPanic,anError);
+	}
+
+// CHttpTestEngine
+
+EXPORT_C void CHttpTestEngine::SetCurrentStatusCode(TInt aStatusCode)
+	{
+	iCurrentStatusCode=aStatusCode;
+	}
+
+
+void CHttpTestEngine::DoCancel()
+	{
+	// cancel the current test
+	if (iCurrentTest)
+		iCurrentTest->Cancel();
+	}
+
+void CHttpTestEngine::RunL()
+	{
+	switch (iState)
+		{
+	case EIdle:
+		{
+		TRAPD(err,RunNextTestL())
+		if (err!=KErrNone)
+			{
+			Console().Printf(KTextFailure, err);
+			}
+		}
+		break;
+	case ERunningTest:
+	case ESingleTestCaseFailed:
+		break;
+	case EShuttingDown:
+		CActiveScheduler::Stop();
+		break;
+		}
+	}
+
+
+EXPORT_C void CHttpTestEngine::PressAnyKey()
+	{
+	if (iDetectKeyPress)
+		iDetectKeyPress->Cancel();
+
+	iUtils->PressAnyKey();
+	
+	if (iDetectKeyPress)
+		iDetectKeyPress->RequestKey();
+
+	}
+
+void CHttpTestEngine::TestInteractionDetectedL(TTestInteraction aTestInteraction)
+	{
+	if (aTestInteraction == EStopCurrentTest)
+		{
+		iCurrentTest->Cancel();
+		TestCompleted(KErrTestInterrupted);
+		}
+	}
+
+
+/**
+ * Static factory function for a new test engine
+ */
+EXPORT_C CHttpTestEngine* CHttpTestEngine::NewL(const TDesC& aTestTitle, TBool aSilent)
+	{
+	CHttpTestEngine* self = new(ELeave) CHttpTestEngine(aSilent);
+	CleanupStack::PushL(self);
+	self->ConstructL(aTestTitle);
+	CleanupStack::Pop(self); 
+	return self;
+	}
+
+CHttpTestEngine::CHttpTestEngine(TBool aSilent)
+	: CActive(CActive::EPriorityUserInput), iSilent(aSilent)
+	{
+	}
+
+/**
+ * Constructor for the test engine
+ * Creates a console and sets itself active
+ */
+void CHttpTestEngine::ConstructL(const TDesC& aTestTitle)
+	{
+	iUtils = CHTTPTestUtils::NewL(aTestTitle);
+	iUtils->SetSilent(iSilent);
+	iDetectKeyPress = CDetectKeyPress::NewLC(*(iUtils->Test().Console()),*this);
+	CleanupStack::Pop(iDetectKeyPress);
+	CActiveScheduler::Add(this);
+	SetActive();
+	TRequestStatus* stat = &iStatus;
+	User::RequestComplete(stat,KErrNone);
+	}
+
+/** 
+ * Destructor for CHttpTestEngine
+ * Cancels any outstanding requests and deletes member variables
+ */
+EXPORT_C CHttpTestEngine::~CHttpTestEngine()
+	{
+	Cancel();
+	iTestSet.Close();
+	iTestResults.Close();
+	delete iDetectKeyPress;
+	delete iUtils;
+	}
+
+/** 
+ * Configure the set of tests to be done in this run of the test engine.
+ */
+EXPORT_C void CHttpTestEngine::ConfigureTestSet(RPointerArray<CHttpTestBase> aTestSet)
+	{
+	iTestSet = aTestSet;
+	}
+
+/**
+ * This should be called by tests to indicate that they have 
+ * completed and whether they were sucessful or not 
+ */
+EXPORT_C void CHttpTestEngine::TestCompleted(TInt aResult)
+	{
+	// Log test result.  Override silence to ensure something gets displayed
+	TBool wasSilent = iUtils->IsSilent();
+	iUtils->SetSilent(EFalse);
+	// An expected status code of 0 is used if the test doesn't care about a status code to pass
+	if (aResult == 0) 
+		{
+		iUtils->LogIt(KTextPassedTest, &(iCurrentTest->TestName()));
+		iTestResults.Append(ETrue);
+		}
+	else if (aResult == KErrTestInterrupted)
+		{
+		iUtils->LogIt(KTextInterruptTest, &(iCurrentTest->TestName()));
+		iTestResults.Append(EFalse);
+		}
+	else
+		{
+		iUtils->LogIt(KTextFailedTest, &(iCurrentTest->TestName()));
+		iTestResults.Append(EFalse);
+		}
+	iUtils->SetSilent(wasSilent);
+
+	// Inform test utils that this test is over
+	iUtils->EndTest(aResult);
+
+	// Switch state so the engine can point at the next test, then set the engine active again 
+	iState=EIdle;
+	TRequestStatus* stat = &iStatus;
+	User::RequestComplete(stat,KErrNone);
+	SetActive();
+	}
+
+
+/** 
+ * Run the next test
+ * The switch statement lists all tests to be run
+ * 
+ */
+void CHttpTestEngine::RunNextTestL()
+	{
+	// delete the test previously run
+	
+	delete iCurrentTest;
+	iCurrentTest=NULL;
+
+	// Advance to the next test
+
+	iTestIndex++;
+	if (iTestIndex <= iTestSet.Count())
+		{
+		// still going...
+		iCurrentTest = iTestSet[iTestIndex - 1];
+		iCurrentTest->SetEngine(this);
+ 		iUtils->StartTestL(iCurrentTest->TestName());
+		iState = ERunningTest;
+		iCurrentTest->BeginTest();
+		}
+	else
+		{
+		// finished testing - set status to shut down and complete our own request
+		SetPriority(EPriorityIdle);
+		iState = EShuttingDown;
+		int a,b;
+		TestSummary(a,b);
+		TRequestStatus* stat = &iStatus;
+		User::RequestComplete(stat,KErrNone);
+		SetActive();
+		return;
+		}
+	}
+
+/**
+ * return a reference to the console used by the test harness
+ */
+EXPORT_C CConsoleBase& CHttpTestEngine::Console() const 
+	{
+	return *(iUtils->Test().Console());
+	}
+
+/**
+ * return a reference to the test harness utilities
+ */
+EXPORT_C CHTTPTestUtils& CHttpTestEngine::Utils() const 
+	{
+	return *iUtils;
+	}
+
+
+EXPORT_C void CHttpTestEngine::TestSummary(TInt& aNumPasses, TInt& aNumFailures) const
+	{
+	aNumPasses = 0;
+	aNumFailures = 0;
+	for (TInt ii = 0; ii < iTestResults.Count(); ii++)
+		iTestResults[ii]?(aNumPasses++):(aNumFailures++);
+	}
+
+
+//-----CHttpTestBase------------------------------------------------------------------
+
+EXPORT_C CHttpTestBase::CHttpTestBase() : CActive(CActive::EPriorityStandard) 
+	{
+	iExpectedStatusCode= 200;
+	iTestFail=0;
+	}
+
+EXPORT_C  TInt CHttpTestBase::ExpectedStatusCode()
+	{
+	return iExpectedStatusCode;
+	}
+
+EXPORT_C void CHttpTestBase::BeginTest()
+	{
+	CActiveScheduler::Add(this);
+	SetActive();
+	TRequestStatus* stat = &iStatus;
+	User::RequestComplete(stat,KErrNone);
+	}
+
+EXPORT_C void CHttpTestBase::RunL()
+	{
+	// Either do leak tests or regular tests
+	TInt err = KErrNone;
+	if (iLeakTests > 0)
+		{
+		TRAP(err,DoLeakTestsL());
+		}
+	else
+		{
+		TRAP(err,DoRunL());
+		}
+
+	switch(err)
+		{
+	case KErrNone:
+		{
+		iEngine->Utils().LogIt(_L("\nTest case finished"));
+		if (!iEngine->IsSilent())
+			iEngine->PressAnyKey();
+		}
+		break;
+	default:// any error
+		{
+		iEngine->Utils().LogIt(_L("Test case failed (caught a Leave) ... skipping to the next test case"));
+		}
+		break;
+		}
+	iEngine->TestCompleted(err);
+	}
+
+
+void CHttpTestBase::DoLeakTestsL()
+	{
+	for (TInt ii = iFirstLeakIteration; ii < iLeakTests; ++ii)
+		{
+		iEngine->Utils().LogIt(_L("Memory Leak Testing on allocation %d\n"), ii);
+
+		TInt err = KErrNoMemory;
+		
+		__UHEAP_MARK;
+		__UHEAP_FAILNEXT(ii);
+		TRAP(err,DoRunL());
+		__UHEAP_MARKEND;
+		User::Heap().Check();
+		__UHEAP_RESET;
+
+		// Break out if the test passes successfully; allow only memory failure or test failure codes to proceed.
+		if (err == KErrNone)
+			return;
+		else if (err != KErrNoMemory && err != KErrTestFailed)
+			User::Leave(err);
+		}
+	}
+	
+EXPORT_C TInt CHttpTestBase::RunError(TInt aErr)
+	{
+	iEngine->Utils().LogIt(_L("\nTest failed with error code %d\n"), aErr);
+	return KErrNone;	
+	}
+
+EXPORT_C void CHttpTestBase::CompleteOwnRequest()
+	{
+	TRequestStatus* stat = &iStatus;
+	User::RequestComplete(stat,KErrNone);	
+	if (!IsActive())
+		SetActive();
+	}
+
+
+//-----CHttpTestTransBase------------------------------------------------------------------
+
+EXPORT_C CHttpTestTransBase::CHttpTestTransBase() : CHttpTestBase() 
+	{
+	}
+
+EXPORT_C TBool CHttpTestTransBase::GetNextDataPart(TPtrC8& aDataChunk)
+	{
+	//add a body 
+	aDataChunk.Set(KTestPostBody);
+	return ETrue;
+	}
+
+EXPORT_C void CHttpTestTransBase::ReleaseData() 
+	{
+	}
+	
+EXPORT_C TInt CHttpTestTransBase::OverallDataSize()
+	{
+	return KTestPostBody().Length();
+	}
+
+EXPORT_C void CHttpTestTransBase::DumpResponseBody(RHTTPTransaction& aTrans)
+//dump all the body's chunks 
+	{
+	MHTTPDataSupplier* body = aTrans.Response().Body();
+	TPtrC8 dataChunk;
+	TBool isLast = body->GetNextDataPart(dataChunk);
+	iEngine->Utils().DumpData(dataChunk);
+	if (isLast && !iEngine->IsSilent())
+		iEngine->Utils().LogIt(_L("Got last data chunk.\n"));
+	body->ReleaseData();
+	}
+
+EXPORT_C void CHttpTestTransBase::DumpRespHeaders(RHTTPTransaction& aTrans)
+//dump the message's headers
+	{
+	//dump the message's headers
+	RHTTPResponse resp = aTrans.Response();
+	TInt status = resp.StatusCode();
+	if (!iEngine->IsSilent())
+		iEngine->Utils().LogIt(_L("Status code = %d\n"), status);
+
+	RStringPool strP = aTrans.Session().StringPool();
+	RHTTPHeaders hdr = resp.GetHeaderCollection();
+	THTTPHdrFieldIter it = hdr.Fields();
+
+	TBuf<32>  fieldName16;
+	TBuf<128> fieldVal16;
+
+	while (it.AtEnd() == EFalse)
+		{
+		RStringTokenF fieldNameTk = it();
+		RStringF fieldName = strP.StringF(fieldNameTk);
+		THTTPHdrVal hVal;
+		if (hdr.GetField(fieldName,0,hVal) == KErrNone)
+			{
+			TPtrC8 fieldNameStr(strP.StringF(fieldName).DesC());
+			if (fieldNameStr.Length() > 32)
+				fieldNameStr.Set(fieldNameStr.Left(32));
+
+			fieldName16.Copy(fieldNameStr);
+
+			THTTPHdrVal fieldVal;
+			hdr.GetField(fieldName,0,fieldVal);
+			switch (fieldVal.Type())
+				{
+				case THTTPHdrVal::KTIntVal:
+					{
+					iEngine->Utils().LogIt(_L("%S: %d\n"), &fieldName16, fieldVal.Int());
+					} break;
+				case THTTPHdrVal::KStrVal:
+				case THTTPHdrVal::KStrFVal:
+					{
+					TPtrC8 fieldValStr(strP.StringF(fieldVal.StrF()).DesC());
+					if (fieldValStr.Length() > 128)
+						fieldValStr.Set(fieldValStr.Left(128));
+
+					fieldVal16.Copy(fieldValStr);
+					iEngine->Utils().LogIt(_L("%S: %S\n"), &fieldName16, &fieldVal16);
+					} break;
+				case THTTPHdrVal::KDateVal:
+					{
+					TDateTime date = fieldVal.DateTime();
+					TTime t(date);
+					TBuf<128> dateTimeString;
+					TRAPD(err,t.FormatL(dateTimeString,KDateFormat));
+					if (err == KErrNone)
+						iEngine->Utils().LogIt(_L("%S: %S\n"), &fieldName16, &dateTimeString);
+					} break;
+				default:
+					{
+					iEngine->Utils().LogIt(_L("%S: <unrecognised value type>\n"), &fieldName16);
+					}
+				}
+			}
+		++it;
+		}
+	}
+
+EXPORT_C TInt CHttpTestTransBase::MHFRunError(TInt aError, 
+										RHTTPTransaction /*aTransaction*/,
+										const THTTPEvent& /*aEvent*/)
+	{
+	iEngine->Utils().LogIt(_L("\nTest failed with error code %d\n"), aError);
+	return KErrNone;
+	}
+
+EXPORT_C void CHttpTestTransBase::MHFRunL(RHTTPTransaction aTransaction,
+						 const THTTPEvent& aEvent)
+	{
+	switch (aEvent.iStatus)
+		{
+	case THTTPEvent::EGotResponseHeaders:
+		{
+		// HTTP response headers have been received
+		iEngine->Utils().LogIt(_L("<EGotResponseHeaders>\n"));
+		DumpRespHeaders(aTransaction);
+		iEngine->SetCurrentStatusCode(aTransaction.Response().StatusCode());
+		} break;
+	case THTTPEvent::EGotResponseBodyData:
+		{
+		// Some (more) body data has been received (in the HTTP response)
+		iEngine->Utils().LogIt(_L("<EGotResponseBodyData received>\n"));
+		// for each chunk of data received we have to empty the buffer before to be able to receive 
+		MHTTPDataSupplier* body = aTransaction.Response().Body();
+		body->ReleaseData();
+		} break;
+	case THTTPEvent::EResponseComplete:
+		{
+		// The transaction's response is complete
+		iEngine->Utils().LogIt(_L("<EResponseComplete received >\n"));
+		} break;
+	case THTTPEvent::ESucceeded:
+		{
+		iEngine->Utils().LogIt(_L("<ESucceeded received from the VF>\n"));
+		CActiveScheduler::Stop();
+		} break;
+	case THTTPEvent::EFailed:
+		{
+		iEngine->Utils().LogIt(_L("<EFailed received from the VF>\n"));
+		CActiveScheduler::Stop();
+		} break;
+	default:
+		{
+		iEngine->Utils().LogIt(_L("<unrecognised event>\n %d"),aEvent.iStatus);
+		iEngine->Utils().LogIt(_L("Test Failed\n"));
+		iEngine->PressAnyKey();
+		CActiveScheduler::Stop();
+		} 
+		break;
+		}
+	}
+
+EXPORT_C void CHttpTestEngine::SetSilent(TBool aSilent)
+	{
+	iUtils->SetSilent(aSilent);
+	}
+
+EXPORT_C  TInt CHttpTestTransBase::Reset()
+	{
+	return KErrNone;
+	}