applayerprotocols/httptransportfw/Test/t_utils/HttpTestCore.cpp
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15     
       
    16 #include "HttpTestCore.h"
       
    17 
       
    18 _LIT(KTextFailure,"Test failed with error %d.\n");
       
    19 _LIT(KTextFailedTest,"TEST %S FAILED\n");
       
    20 _LIT(KTextPassedTest,"TEST %S PASSED\n");
       
    21 _LIT(KTextInterruptTest, "TEST %S INTERRUPTED\n");
       
    22 
       
    23 // Dummy POST body provided in test base should a specific test not want to generate its own
       
    24 _LIT8(KTestPostBody, "a=10\r\n");
       
    25 
       
    26 // format for output of data/time values
       
    27 _LIT(KDateFormat,"%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3");
       
    28 
       
    29 
       
    30 // Test harness requirements:
       
    31 // Uses an active object state machine to run tests.
       
    32 
       
    33 
       
    34 //##ModelId=3A76DDA701A2
       
    35 EXPORT_C void CTestScheduler::Error(TInt anError) const
       
    36 	{
       
    37 	_LIT(KTestPanic,"CTestScheduler RunL leave");
       
    38 	User::Panic(KTestPanic,anError);
       
    39 	}
       
    40 
       
    41 // CHttpTestEngine
       
    42 
       
    43 EXPORT_C void CHttpTestEngine::SetCurrentStatusCode(TInt aStatusCode)
       
    44 	{
       
    45 	iCurrentStatusCode=aStatusCode;
       
    46 	}
       
    47 
       
    48 
       
    49 void CHttpTestEngine::DoCancel()
       
    50 	{
       
    51 	// cancel the current test
       
    52 	if (iCurrentTest)
       
    53 		iCurrentTest->Cancel();
       
    54 	}
       
    55 
       
    56 void CHttpTestEngine::RunL()
       
    57 	{
       
    58 	switch (iState)
       
    59 		{
       
    60 	case EIdle:
       
    61 		{
       
    62 		TRAPD(err,RunNextTestL())
       
    63 		if (err!=KErrNone)
       
    64 			{
       
    65 			Console().Printf(KTextFailure, err);
       
    66 			}
       
    67 		}
       
    68 		break;
       
    69 	case ERunningTest:
       
    70 	case ESingleTestCaseFailed:
       
    71 		break;
       
    72 	case EShuttingDown:
       
    73 		CActiveScheduler::Stop();
       
    74 		break;
       
    75 		}
       
    76 	}
       
    77 
       
    78 
       
    79 EXPORT_C void CHttpTestEngine::PressAnyKey()
       
    80 	{
       
    81 	if (iDetectKeyPress)
       
    82 		iDetectKeyPress->Cancel();
       
    83 
       
    84 	iUtils->PressAnyKey();
       
    85 	
       
    86 	if (iDetectKeyPress)
       
    87 		iDetectKeyPress->RequestKey();
       
    88 
       
    89 	}
       
    90 
       
    91 void CHttpTestEngine::TestInteractionDetectedL(TTestInteraction aTestInteraction)
       
    92 	{
       
    93 	if (aTestInteraction == EStopCurrentTest)
       
    94 		{
       
    95 		iCurrentTest->Cancel();
       
    96 		TestCompleted(KErrTestInterrupted);
       
    97 		}
       
    98 	}
       
    99 
       
   100 
       
   101 /**
       
   102  * Static factory function for a new test engine
       
   103  */
       
   104 EXPORT_C CHttpTestEngine* CHttpTestEngine::NewL(const TDesC& aTestTitle, TBool aSilent)
       
   105 	{
       
   106 	CHttpTestEngine* self = new(ELeave) CHttpTestEngine(aSilent);
       
   107 	CleanupStack::PushL(self);
       
   108 	self->ConstructL(aTestTitle);
       
   109 	CleanupStack::Pop(self); 
       
   110 	return self;
       
   111 	}
       
   112 
       
   113 CHttpTestEngine::CHttpTestEngine(TBool aSilent)
       
   114 	: CActive(CActive::EPriorityUserInput), iSilent(aSilent)
       
   115 	{
       
   116 	}
       
   117 
       
   118 /**
       
   119  * Constructor for the test engine
       
   120  * Creates a console and sets itself active
       
   121  */
       
   122 void CHttpTestEngine::ConstructL(const TDesC& aTestTitle)
       
   123 	{
       
   124 	iUtils = CHTTPTestUtils::NewL(aTestTitle);
       
   125 	iUtils->SetSilent(iSilent);
       
   126 	iDetectKeyPress = CDetectKeyPress::NewLC(*(iUtils->Test().Console()),*this);
       
   127 	CleanupStack::Pop(iDetectKeyPress);
       
   128 	CActiveScheduler::Add(this);
       
   129 	SetActive();
       
   130 	TRequestStatus* stat = &iStatus;
       
   131 	User::RequestComplete(stat,KErrNone);
       
   132 	}
       
   133 
       
   134 /** 
       
   135  * Destructor for CHttpTestEngine
       
   136  * Cancels any outstanding requests and deletes member variables
       
   137  */
       
   138 EXPORT_C CHttpTestEngine::~CHttpTestEngine()
       
   139 	{
       
   140 	Cancel();
       
   141 	iTestSet.Close();
       
   142 	iTestResults.Close();
       
   143 	delete iDetectKeyPress;
       
   144 	delete iUtils;
       
   145 	}
       
   146 
       
   147 /** 
       
   148  * Configure the set of tests to be done in this run of the test engine.
       
   149  */
       
   150 EXPORT_C void CHttpTestEngine::ConfigureTestSet(RPointerArray<CHttpTestBase> aTestSet)
       
   151 	{
       
   152 	iTestSet = aTestSet;
       
   153 	}
       
   154 
       
   155 /**
       
   156  * This should be called by tests to indicate that they have 
       
   157  * completed and whether they were sucessful or not 
       
   158  */
       
   159 EXPORT_C void CHttpTestEngine::TestCompleted(TInt aResult)
       
   160 	{
       
   161 	// Log test result.  Override silence to ensure something gets displayed
       
   162 	TBool wasSilent = iUtils->IsSilent();
       
   163 	iUtils->SetSilent(EFalse);
       
   164 	// An expected status code of 0 is used if the test doesn't care about a status code to pass
       
   165 	if (aResult == 0) 
       
   166 		{
       
   167 		iUtils->LogIt(KTextPassedTest, &(iCurrentTest->TestName()));
       
   168 		iTestResults.Append(ETrue);
       
   169 		}
       
   170 	else if (aResult == KErrTestInterrupted)
       
   171 		{
       
   172 		iUtils->LogIt(KTextInterruptTest, &(iCurrentTest->TestName()));
       
   173 		iTestResults.Append(EFalse);
       
   174 		}
       
   175 	else
       
   176 		{
       
   177 		iUtils->LogIt(KTextFailedTest, &(iCurrentTest->TestName()));
       
   178 		iTestResults.Append(EFalse);
       
   179 		}
       
   180 	iUtils->SetSilent(wasSilent);
       
   181 
       
   182 	// Inform test utils that this test is over
       
   183 	iUtils->EndTest(aResult);
       
   184 
       
   185 	// Switch state so the engine can point at the next test, then set the engine active again 
       
   186 	iState=EIdle;
       
   187 	TRequestStatus* stat = &iStatus;
       
   188 	User::RequestComplete(stat,KErrNone);
       
   189 	SetActive();
       
   190 	}
       
   191 
       
   192 
       
   193 /** 
       
   194  * Run the next test
       
   195  * The switch statement lists all tests to be run
       
   196  * 
       
   197  */
       
   198 void CHttpTestEngine::RunNextTestL()
       
   199 	{
       
   200 	// delete the test previously run
       
   201 	
       
   202 	delete iCurrentTest;
       
   203 	iCurrentTest=NULL;
       
   204 
       
   205 	// Advance to the next test
       
   206 
       
   207 	iTestIndex++;
       
   208 	if (iTestIndex <= iTestSet.Count())
       
   209 		{
       
   210 		// still going...
       
   211 		iCurrentTest = iTestSet[iTestIndex - 1];
       
   212 		iCurrentTest->SetEngine(this);
       
   213  		iUtils->StartTestL(iCurrentTest->TestName());
       
   214 		iState = ERunningTest;
       
   215 		iCurrentTest->BeginTest();
       
   216 		}
       
   217 	else
       
   218 		{
       
   219 		// finished testing - set status to shut down and complete our own request
       
   220 		SetPriority(EPriorityIdle);
       
   221 		iState = EShuttingDown;
       
   222 		int a,b;
       
   223 		TestSummary(a,b);
       
   224 		TRequestStatus* stat = &iStatus;
       
   225 		User::RequestComplete(stat,KErrNone);
       
   226 		SetActive();
       
   227 		return;
       
   228 		}
       
   229 	}
       
   230 
       
   231 /**
       
   232  * return a reference to the console used by the test harness
       
   233  */
       
   234 EXPORT_C CConsoleBase& CHttpTestEngine::Console() const 
       
   235 	{
       
   236 	return *(iUtils->Test().Console());
       
   237 	}
       
   238 
       
   239 /**
       
   240  * return a reference to the test harness utilities
       
   241  */
       
   242 EXPORT_C CHTTPTestUtils& CHttpTestEngine::Utils() const 
       
   243 	{
       
   244 	return *iUtils;
       
   245 	}
       
   246 
       
   247 
       
   248 EXPORT_C void CHttpTestEngine::TestSummary(TInt& aNumPasses, TInt& aNumFailures) const
       
   249 	{
       
   250 	aNumPasses = 0;
       
   251 	aNumFailures = 0;
       
   252 	for (TInt ii = 0; ii < iTestResults.Count(); ii++)
       
   253 		iTestResults[ii]?(aNumPasses++):(aNumFailures++);
       
   254 	}
       
   255 
       
   256 
       
   257 //-----CHttpTestBase------------------------------------------------------------------
       
   258 
       
   259 EXPORT_C CHttpTestBase::CHttpTestBase() : CActive(CActive::EPriorityStandard) 
       
   260 	{
       
   261 	iExpectedStatusCode= 200;
       
   262 	iTestFail=0;
       
   263 	}
       
   264 
       
   265 EXPORT_C  TInt CHttpTestBase::ExpectedStatusCode()
       
   266 	{
       
   267 	return iExpectedStatusCode;
       
   268 	}
       
   269 
       
   270 EXPORT_C void CHttpTestBase::BeginTest()
       
   271 	{
       
   272 	CActiveScheduler::Add(this);
       
   273 	SetActive();
       
   274 	TRequestStatus* stat = &iStatus;
       
   275 	User::RequestComplete(stat,KErrNone);
       
   276 	}
       
   277 
       
   278 EXPORT_C void CHttpTestBase::RunL()
       
   279 	{
       
   280 	// Either do leak tests or regular tests
       
   281 	TInt err = KErrNone;
       
   282 	if (iLeakTests > 0)
       
   283 		{
       
   284 		TRAP(err,DoLeakTestsL());
       
   285 		}
       
   286 	else
       
   287 		{
       
   288 		TRAP(err,DoRunL());
       
   289 		}
       
   290 
       
   291 	switch(err)
       
   292 		{
       
   293 	case KErrNone:
       
   294 		{
       
   295 		iEngine->Utils().LogIt(_L("\nTest case finished"));
       
   296 		if (!iEngine->IsSilent())
       
   297 			iEngine->PressAnyKey();
       
   298 		}
       
   299 		break;
       
   300 	default:// any error
       
   301 		{
       
   302 		iEngine->Utils().LogIt(_L("Test case failed (caught a Leave) ... skipping to the next test case"));
       
   303 		}
       
   304 		break;
       
   305 		}
       
   306 	iEngine->TestCompleted(err);
       
   307 	}
       
   308 
       
   309 
       
   310 void CHttpTestBase::DoLeakTestsL()
       
   311 	{
       
   312 	for (TInt ii = iFirstLeakIteration; ii < iLeakTests; ++ii)
       
   313 		{
       
   314 		iEngine->Utils().LogIt(_L("Memory Leak Testing on allocation %d\n"), ii);
       
   315 
       
   316 		TInt err = KErrNoMemory;
       
   317 		
       
   318 		__UHEAP_MARK;
       
   319 		__UHEAP_FAILNEXT(ii);
       
   320 		TRAP(err,DoRunL());
       
   321 		__UHEAP_MARKEND;
       
   322 		User::Heap().Check();
       
   323 		__UHEAP_RESET;
       
   324 
       
   325 		// Break out if the test passes successfully; allow only memory failure or test failure codes to proceed.
       
   326 		if (err == KErrNone)
       
   327 			return;
       
   328 		else if (err != KErrNoMemory && err != KErrTestFailed)
       
   329 			User::Leave(err);
       
   330 		}
       
   331 	}
       
   332 	
       
   333 EXPORT_C TInt CHttpTestBase::RunError(TInt aErr)
       
   334 	{
       
   335 	iEngine->Utils().LogIt(_L("\nTest failed with error code %d\n"), aErr);
       
   336 	return KErrNone;	
       
   337 	}
       
   338 
       
   339 EXPORT_C void CHttpTestBase::CompleteOwnRequest()
       
   340 	{
       
   341 	TRequestStatus* stat = &iStatus;
       
   342 	User::RequestComplete(stat,KErrNone);	
       
   343 	if (!IsActive())
       
   344 		SetActive();
       
   345 	}
       
   346 
       
   347 
       
   348 //-----CHttpTestTransBase------------------------------------------------------------------
       
   349 
       
   350 EXPORT_C CHttpTestTransBase::CHttpTestTransBase() : CHttpTestBase() 
       
   351 	{
       
   352 	}
       
   353 
       
   354 EXPORT_C TBool CHttpTestTransBase::GetNextDataPart(TPtrC8& aDataChunk)
       
   355 	{
       
   356 	//add a body 
       
   357 	aDataChunk.Set(KTestPostBody);
       
   358 	return ETrue;
       
   359 	}
       
   360 
       
   361 EXPORT_C void CHttpTestTransBase::ReleaseData() 
       
   362 	{
       
   363 	}
       
   364 	
       
   365 EXPORT_C TInt CHttpTestTransBase::OverallDataSize()
       
   366 	{
       
   367 	return KTestPostBody().Length();
       
   368 	}
       
   369 
       
   370 EXPORT_C void CHttpTestTransBase::DumpResponseBody(RHTTPTransaction& aTrans)
       
   371 //dump all the body's chunks 
       
   372 	{
       
   373 	MHTTPDataSupplier* body = aTrans.Response().Body();
       
   374 	TPtrC8 dataChunk;
       
   375 	TBool isLast = body->GetNextDataPart(dataChunk);
       
   376 	iEngine->Utils().DumpData(dataChunk);
       
   377 	if (isLast && !iEngine->IsSilent())
       
   378 		iEngine->Utils().LogIt(_L("Got last data chunk.\n"));
       
   379 	body->ReleaseData();
       
   380 	}
       
   381 
       
   382 EXPORT_C void CHttpTestTransBase::DumpRespHeaders(RHTTPTransaction& aTrans)
       
   383 //dump the message's headers
       
   384 	{
       
   385 	//dump the message's headers
       
   386 	RHTTPResponse resp = aTrans.Response();
       
   387 	TInt status = resp.StatusCode();
       
   388 	if (!iEngine->IsSilent())
       
   389 		iEngine->Utils().LogIt(_L("Status code = %d\n"), status);
       
   390 
       
   391 	RStringPool strP = aTrans.Session().StringPool();
       
   392 	RHTTPHeaders hdr = resp.GetHeaderCollection();
       
   393 	THTTPHdrFieldIter it = hdr.Fields();
       
   394 
       
   395 	TBuf<32>  fieldName16;
       
   396 	TBuf<128> fieldVal16;
       
   397 
       
   398 	while (it.AtEnd() == EFalse)
       
   399 		{
       
   400 		RStringTokenF fieldNameTk = it();
       
   401 		RStringF fieldName = strP.StringF(fieldNameTk);
       
   402 		THTTPHdrVal hVal;
       
   403 		if (hdr.GetField(fieldName,0,hVal) == KErrNone)
       
   404 			{
       
   405 			TPtrC8 fieldNameStr(strP.StringF(fieldName).DesC());
       
   406 			if (fieldNameStr.Length() > 32)
       
   407 				fieldNameStr.Set(fieldNameStr.Left(32));
       
   408 
       
   409 			fieldName16.Copy(fieldNameStr);
       
   410 
       
   411 			THTTPHdrVal fieldVal;
       
   412 			hdr.GetField(fieldName,0,fieldVal);
       
   413 			switch (fieldVal.Type())
       
   414 				{
       
   415 				case THTTPHdrVal::KTIntVal:
       
   416 					{
       
   417 					iEngine->Utils().LogIt(_L("%S: %d\n"), &fieldName16, fieldVal.Int());
       
   418 					} break;
       
   419 				case THTTPHdrVal::KStrVal:
       
   420 				case THTTPHdrVal::KStrFVal:
       
   421 					{
       
   422 					TPtrC8 fieldValStr(strP.StringF(fieldVal.StrF()).DesC());
       
   423 					if (fieldValStr.Length() > 128)
       
   424 						fieldValStr.Set(fieldValStr.Left(128));
       
   425 
       
   426 					fieldVal16.Copy(fieldValStr);
       
   427 					iEngine->Utils().LogIt(_L("%S: %S\n"), &fieldName16, &fieldVal16);
       
   428 					} break;
       
   429 				case THTTPHdrVal::KDateVal:
       
   430 					{
       
   431 					TDateTime date = fieldVal.DateTime();
       
   432 					TTime t(date);
       
   433 					TBuf<128> dateTimeString;
       
   434 					TRAPD(err,t.FormatL(dateTimeString,KDateFormat));
       
   435 					if (err == KErrNone)
       
   436 						iEngine->Utils().LogIt(_L("%S: %S\n"), &fieldName16, &dateTimeString);
       
   437 					} break;
       
   438 				default:
       
   439 					{
       
   440 					iEngine->Utils().LogIt(_L("%S: <unrecognised value type>\n"), &fieldName16);
       
   441 					}
       
   442 				}
       
   443 			}
       
   444 		++it;
       
   445 		}
       
   446 	}
       
   447 
       
   448 EXPORT_C TInt CHttpTestTransBase::MHFRunError(TInt aError, 
       
   449 										RHTTPTransaction /*aTransaction*/,
       
   450 										const THTTPEvent& /*aEvent*/)
       
   451 	{
       
   452 	iEngine->Utils().LogIt(_L("\nTest failed with error code %d\n"), aError);
       
   453 	return KErrNone;
       
   454 	}
       
   455 
       
   456 EXPORT_C void CHttpTestTransBase::MHFRunL(RHTTPTransaction aTransaction,
       
   457 						 const THTTPEvent& aEvent)
       
   458 	{
       
   459 	switch (aEvent.iStatus)
       
   460 		{
       
   461 	case THTTPEvent::EGotResponseHeaders:
       
   462 		{
       
   463 		// HTTP response headers have been received
       
   464 		iEngine->Utils().LogIt(_L("<EGotResponseHeaders>\n"));
       
   465 		DumpRespHeaders(aTransaction);
       
   466 		iEngine->SetCurrentStatusCode(aTransaction.Response().StatusCode());
       
   467 		} break;
       
   468 	case THTTPEvent::EGotResponseBodyData:
       
   469 		{
       
   470 		// Some (more) body data has been received (in the HTTP response)
       
   471 		iEngine->Utils().LogIt(_L("<EGotResponseBodyData received>\n"));
       
   472 		// for each chunk of data received we have to empty the buffer before to be able to receive 
       
   473 		MHTTPDataSupplier* body = aTransaction.Response().Body();
       
   474 		body->ReleaseData();
       
   475 		} break;
       
   476 	case THTTPEvent::EResponseComplete:
       
   477 		{
       
   478 		// The transaction's response is complete
       
   479 		iEngine->Utils().LogIt(_L("<EResponseComplete received >\n"));
       
   480 		} break;
       
   481 	case THTTPEvent::ESucceeded:
       
   482 		{
       
   483 		iEngine->Utils().LogIt(_L("<ESucceeded received from the VF>\n"));
       
   484 		CActiveScheduler::Stop();
       
   485 		} break;
       
   486 	case THTTPEvent::EFailed:
       
   487 		{
       
   488 		iEngine->Utils().LogIt(_L("<EFailed received from the VF>\n"));
       
   489 		CActiveScheduler::Stop();
       
   490 		} break;
       
   491 	default:
       
   492 		{
       
   493 		iEngine->Utils().LogIt(_L("<unrecognised event>\n %d"),aEvent.iStatus);
       
   494 		iEngine->Utils().LogIt(_L("Test Failed\n"));
       
   495 		iEngine->PressAnyKey();
       
   496 		CActiveScheduler::Stop();
       
   497 		} 
       
   498 		break;
       
   499 		}
       
   500 	}
       
   501 
       
   502 EXPORT_C void CHttpTestEngine::SetSilent(TBool aSilent)
       
   503 	{
       
   504 	iUtils->SetSilent(aSilent);
       
   505 	}
       
   506 
       
   507 EXPORT_C  TInt CHttpTestTransBase::Reset()
       
   508 	{
       
   509 	return KErrNone;
       
   510 	}