sl@0: /* sl@0: * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include "t_testhandler.h" sl@0: #include "ttesthandlersettings.h" sl@0: #include "t_output.h" sl@0: #include "t_testaction.h" sl@0: #include "t_testsetup.h" sl@0: #include "tTestSpec.h" sl@0: #include "t_testrunner.h" sl@0: sl@0: sl@0: TTestSummary::TTestSummary() : sl@0: iTestsRun(0), iTestsFailed(0) sl@0: { sl@0: } sl@0: sl@0: void TTestSummary::PrintL(Output& aOut) sl@0: { sl@0: aOut.write(_L("%d tests failed out of %d\n"), iTestsFailed, iTestsRun); sl@0: aOut.write(_L("\r\n</pre></body></html>\r\n")); sl@0: } sl@0: sl@0: TBool TTestSummary::AllTestsPassed() sl@0: { sl@0: return iTestsRun > 0 && iTestsFailed == 0; sl@0: } sl@0: sl@0: EXPORT_C CTestHandler* CTestHandler::NewLC(RFs& aFs, sl@0: MTestSpec& aTestSpec, sl@0: CTestHandlerSettings& aSettings, sl@0: CConsoleBase* aConsole, sl@0: Output* aOut) sl@0: { sl@0: CTestHandler* self = new(ELeave) CTestHandler(aFs, aTestSpec, aConsole, aOut); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aSettings); sl@0: return self; sl@0: } sl@0: sl@0: CTestHandler::~CTestHandler() sl@0: { sl@0: delete iSettings; sl@0: delete iScheduler; sl@0: delete iSharedData; sl@0: delete iTestRunner; sl@0: delete iNextTestRunner; sl@0: sl@0: iFailedTests.Reset(); sl@0: iFailedTestNames.ResetAndDestroy(); sl@0: iKnownDefects.ResetAndDestroy(); sl@0: } sl@0: sl@0: CTestHandler::CTestHandler(RFs& aFs, sl@0: MTestSpec& aTestSpec, sl@0: CConsoleBase* aConsole, sl@0: Output* aOut) : sl@0: iFs(aFs), iConsole(aConsole), iOut(aOut), iTestSpec(aTestSpec) sl@0: { sl@0: } sl@0: sl@0: void CTestHandler::ConstructL(CTestHandlerSettings& aSettings) sl@0: { sl@0: iSettings = CTestHandlerSettings::NewL(aSettings); sl@0: iScheduler = new(ELeave) CActiveScheduler; sl@0: CActiveScheduler::Install(iScheduler); sl@0: sl@0: // Set up test handler based on command line argument sl@0: if (aSettings.iOOM) sl@0: { sl@0: SetTestRunnerL(new (ELeave) COOMTestRunner(*iOut)); sl@0: } sl@0: else if (aSettings.iCancel) sl@0: { sl@0: SetTestRunnerL(new (ELeave) CCancelTestRunner(*iOut)); sl@0: } sl@0: else sl@0: { sl@0: SetTestRunnerL(NULL); sl@0: } sl@0: } sl@0: sl@0: TTestSummary CTestHandler::Summary() sl@0: { sl@0: TTestSummary result; sl@0: result.iTestsRun = iActionCount; sl@0: result.iTestsFailed = iFailedTests.Count(); sl@0: return result; sl@0: } sl@0: sl@0: EXPORT_C void CTestHandler::RunTestsL() sl@0: { sl@0: sl@0: TBuf8<32>timeBuf; sl@0: TTime time; sl@0: time.UniversalTime(); sl@0: TDateTime dateTime = time.DateTime(); sl@0: _LIT8(KDateFormat,"%02d:%02d:%02d:%03d "); sl@0: timeBuf.AppendFormat(KDateFormat,dateTime.Hour(),dateTime.Minute(),dateTime.Second(),(dateTime.MicroSecond()/1000)); sl@0: sl@0: iActionNumber = 0; sl@0: CTestAction* action; sl@0: HBufC8* currentID=NULL; sl@0: HBufC8* previousID=NULL; sl@0: TBool testCaseResult=ETrue; sl@0: TBool isTefScript = EFalse; sl@0: while(iTestSpec.GetNextTest(action)) sl@0: { sl@0: iActionCount++; sl@0: iActionNumber++; sl@0: isTefScript = action->iTefScript; sl@0: // action->iTefScript = EFalse; sl@0: delete previousID; sl@0: previousID = currentID; sl@0: currentID = action->iNameInfo->AllocLC(); sl@0: sl@0: if ( (previousID == NULL) || (*currentID != *previousID) ) sl@0: { sl@0: if (previousID != NULL) sl@0: { sl@0: sl@0: sl@0: if(action->iTefScript) sl@0: { sl@0: iOut->writeString(timeBuf); sl@0: iOut->writeString(_L("Command = END_TESTCASE ")); sl@0: } sl@0: iOut->writeString(*previousID); sl@0: if(action->iTefScript) sl@0: { sl@0: iOut->writeString(_L(" ***TestCaseResult = ")); sl@0: } sl@0: sl@0: if (testCaseResult) sl@0: { sl@0: iOut->writeString(_L("PASS")); sl@0: } sl@0: else sl@0: { sl@0: iOut->writeString(_L("FAIL")); sl@0: } sl@0: iOut->writeString(_L("\r\n")); sl@0: iOut->writeString(_L("\r\n")); sl@0: } sl@0: sl@0: sl@0: if(action->iTefScript) sl@0: { sl@0: iOut->writeString(timeBuf); sl@0: iOut->writeString(_L("Command = START_TESTCASE ")); sl@0: } sl@0: iOut->writeString(*(currentID)); sl@0: iOut->writeString(_L("\r\n")); sl@0: testCaseResult = ETrue; sl@0: } sl@0: sl@0: TRAPD(err, RunTestL(action)); sl@0: if (!action->iResult) sl@0: { sl@0: testCaseResult = EFalse; sl@0: } sl@0: if (err != KErrNone) sl@0: { sl@0: FailTestL(action, EFailInTestHandler, err); sl@0: } sl@0: CleanupStack::Pop(currentID); sl@0: } sl@0: sl@0: if (currentID != NULL) sl@0: { sl@0: sl@0: sl@0: if(isTefScript) sl@0: { sl@0: iOut->writeString(timeBuf); sl@0: iOut->writeString(_L("Command = END_TESTCASE ")); sl@0: } sl@0: iOut->writeString(*currentID); sl@0: if(isTefScript) sl@0: { sl@0: iOut->writeString(_L(" ***TestCaseResult = ")); sl@0: } sl@0: sl@0: if (testCaseResult) sl@0: { sl@0: iOut->writeString(_L("PASS")); sl@0: } sl@0: else sl@0: { sl@0: iOut->writeString(_L("FAIL")); sl@0: } sl@0: iOut->writeString(_L("\r\n")); sl@0: iOut->writeString(_L("\r\n")); sl@0: } sl@0: delete previousID; sl@0: delete currentID; sl@0: sl@0: DisplaySummary(); sl@0: } sl@0: sl@0: sl@0: sl@0: void CTestHandler::RunTestL(CTestAction* aAction) sl@0: { sl@0: // If the last test set a new test runner, install it here sl@0: if (iNextTestRunner) sl@0: { sl@0: delete iTestRunner; sl@0: iTestRunner = iNextTestRunner; sl@0: iNextTestRunner = NULL; sl@0: } sl@0: sl@0: iOut->writeString(_L("Test ")); sl@0: iOut->writeNum(iActionNumber); sl@0: iOut->writeNewLine(); sl@0: sl@0: if (iActionNumber > 1) sl@0: { sl@0: iConsole->Printf(_L(", ")); sl@0: } sl@0: iConsole->Printf(_L("%d: "), iActionNumber); sl@0: sl@0: aAction->ReportAction(); sl@0: aAction->SetTestHandler(*this); sl@0: sl@0: TInt preErr = iTestRunner->PerformPrerequisiteL(aAction); sl@0: if ((preErr != KErrNone) && !aAction->iResult) sl@0: { sl@0: FailTestL(aAction, EFailInPrerequisite, preErr); sl@0: return; sl@0: } sl@0: TInt actionErr = 0; sl@0: if (preErr == KErrNone) sl@0: { sl@0: actionErr = iTestRunner->PerformActionL(aAction); sl@0: } sl@0: TInt postErr = iTestRunner->PerformPostrequisiteL(aAction, actionErr); sl@0: // investiage if passing actionErr would make more sense here sl@0: aAction->CheckResult(postErr); sl@0: if (!aAction->iResult) sl@0: { sl@0: FailTestL(aAction, EFailInAction, actionErr); sl@0: return; sl@0: } sl@0: sl@0: iConsole->Printf(_L("passed")); sl@0: } sl@0: sl@0: const TDesC& CTestHandler::GetFailLocationName(TTestFailLocation aLoc) sl@0: { sl@0: _LIT(KTestHandler, "test handler"); sl@0: _LIT(KPrerequisite, "prerequisite"); sl@0: _LIT(KTestAction, "test action"); sl@0: sl@0: const TDesC* result = NULL; sl@0: sl@0: switch (aLoc) sl@0: { sl@0: case EFailInTestHandler: sl@0: result = &KTestHandler; sl@0: break; sl@0: case EFailInPrerequisite: sl@0: result = &KPrerequisite; sl@0: break; sl@0: case EFailInAction: sl@0: result = &KTestAction; sl@0: break; sl@0: } sl@0: sl@0: ASSERT(result); sl@0: return *result; sl@0: } sl@0: sl@0: void CTestHandler::FailTestL(CTestAction* aAction, TTestFailLocation aLoc, TInt aErr) sl@0: { sl@0: iOut->writeString(_L("Test failed in ")); sl@0: iOut->writeString(GetFailLocationName(aLoc)); sl@0: iOut->writeString(_L(": ")); sl@0: iOut->writeNum(aErr); sl@0: iOut->writeNewLine(); sl@0: sl@0: iConsole->Printf(_L("failed")); sl@0: sl@0: AppendFailedTestL(iActionNumber, *aAction->iNameInfo); sl@0: if(aAction->ScriptError() == CTestAction::EFileNotFound) sl@0: { sl@0: TBuf<KMaxErrorSize> scriptError; sl@0: aAction->ScriptError(scriptError); sl@0: iOut->writeString(_L("File Not Found \"")); sl@0: iOut->writeString(scriptError); sl@0: iOut->writeString(_L("\" in test ")); sl@0: iOut->writeNum(iActionNumber); sl@0: iOut->writeNewLine(); sl@0: } sl@0: sl@0: if (aAction->iKnownFailure) sl@0: {// Expecting a failure because of known defect - record details sl@0: HBufC* name=HBufC::NewLC(aAction->iNameInfo->Length()); sl@0: name->Des().Copy(*(aAction->iNameInfo)); sl@0: User::LeaveIfError(iKnownDefects.Append(name)); sl@0: CleanupStack::Pop(name); sl@0: } sl@0: } sl@0: sl@0: void CTestHandler::AppendFailedTestL(TInt aIndex, const TDesC8& aName) sl@0: { sl@0: iFailedTests.Append(aIndex); sl@0: HBufC* name=HBufC::NewLC(aName.Length()); sl@0: name->Des().Copy(aName); sl@0: User::LeaveIfError(iFailedTestNames.Append(name)); sl@0: CleanupStack::Pop(name); sl@0: } sl@0: sl@0: void CTestHandler::DisplaySummary() sl@0: { sl@0: //Display the RTest information sl@0: iConsole->Printf(_L("\n")); sl@0: sl@0: // Log the details of tests that failed because of known (deferred) defects sl@0: TInt theFailCount = iKnownDefects.Count(); sl@0: if (theFailCount > 0) sl@0: { sl@0: iOut->writeNewLine(); sl@0: iOut->writeString(_L("----------------------------------------------------------------------------------")); sl@0: iOut->writeNewLine(); sl@0: iOut->writeString(_L("These tests may not pass because of known defects details of which are given below:")); sl@0: iOut->writeNewLine(); sl@0: iOut->writeNewLine(); sl@0: sl@0: TInt index = 0; sl@0: for (; index<theFailCount; index++) sl@0: { sl@0: iOut->writeString(*iKnownDefects[index]); sl@0: iOut->writeNewLine(); sl@0: } sl@0: iOut->writeString(_L("----------------------------------------------------------------------------------")); sl@0: iOut->writeNewLine(); sl@0: iOut->writeNewLine(); sl@0: } sl@0: sl@0: // Display the failed tests sl@0: TInt iEnd = iFailedTests.Count(); sl@0: if (iEnd!=0) sl@0: { sl@0: iOut->writeString(_L(" Failed tests:-")); sl@0: iOut->writeNewLine(); sl@0: for (TInt i = 0; i < iEnd; i++) sl@0: { sl@0: iOut->writeNum(iFailedTests[i]); sl@0: iOut->writeSpaces(2); sl@0: iOut->writeString(*iFailedTestNames[i]); sl@0: iOut->writeNewLine(); sl@0: } sl@0: iOut->writeNewLine(); sl@0: } sl@0: sl@0: // Summary line is now printed in CTestSetup sl@0: } sl@0: sl@0: CBase* CTestHandler::SharedData() const sl@0: { sl@0: return iSharedData; sl@0: } sl@0: sl@0: void CTestHandler::SetSharedData(CBase* aData) sl@0: { sl@0: iSharedData = aData; sl@0: } sl@0: sl@0: EXPORT_C void CTestHandler::SetTestRunnerL(CTestRunner *aTestRunner) sl@0: { sl@0: /* We can't set iTestRunner directly, as we may be called while we're inside sl@0: * one of its methods. */ sl@0: sl@0: // This method can be called twice in a row, eg if the -o option is used sl@0: if (iNextTestRunner) sl@0: { sl@0: delete iNextTestRunner; sl@0: iNextTestRunner = NULL; sl@0: } sl@0: sl@0: iNextTestRunner = aTestRunner ? aTestRunner : new (ELeave) CTestRunner(*iOut); sl@0: } sl@0: sl@0: void CTestHandler::SetHeapMark(TInt aAllocCount) sl@0: { sl@0: iHeapMark = aAllocCount; sl@0: } sl@0: sl@0: TInt CTestHandler::HeapMark() sl@0: { sl@0: return iHeapMark; sl@0: }