sl@0: // Copyright (c) 2002-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 "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: // This contains CTestSuite which is the base class for all the TestSuite DLLs sl@0: // sl@0: // sl@0: sl@0: // EPOC includes sl@0: #include sl@0: sl@0: // Test system includes sl@0: #include sl@0: sl@0: // do not export if Unit Testing sl@0: #if defined (__TSU_TESTFRAMEWORK__) sl@0: #undef EXPORT_C sl@0: #define EXPORT_C sl@0: #endif sl@0: sl@0: /** sl@0: * sl@0: * Default test suite version string sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: _LIT(KTxtVersion,"?.?"); sl@0: sl@0: /** sl@0: * sl@0: * Test suite destructor sl@0: * This destroys all the test steps contained in this class and sl@0: * in classes derived from it sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C CTestSuite::~CTestSuite() sl@0: { sl@0: // free all test steps sl@0: if (iArrayTestSteps) sl@0: iArrayTestSteps->ResetAndDestroy(); sl@0: sl@0: // free the dynamic array used for test steps sl@0: delete iArrayTestSteps; sl@0: sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Test suite constructor (second phase) sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::ConstructL() sl@0: { sl@0: // create a new Array to store the test steps in sl@0: iArrayTestSteps = new(ELeave) CArrayPtrFlat(1); sl@0: sl@0: // default severity sl@0: SetSeverity(ESevrAll); sl@0: iLogger = NULL; sl@0: sl@0: // initialise the derived test suites sl@0: InitialiseL(); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Get test suite version. sl@0: * sl@0: * NOTE : this function is not pure virtual i.e. a test suite sl@0: * does not have to provide a version string - however this sl@0: * may change. It is strongly recommended that a test suite DLL sl@0: * overrides this method. sl@0: * sl@0: * @return "TPtrC" sl@0: * The version string. sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C TPtrC CTestSuite::GetVersion() const sl@0: { sl@0: return KTxtVersion(); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Add a test step into the suite sl@0: * sl@0: * @param "RTestStep* aTestStep" sl@0: * The test step to add. sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::AddTestStepL(RTestStep* aTestStep) sl@0: { sl@0: __ASSERT_ALWAYS(aTestStep, User::Panic(_L("CTestSuite::AddTestStepL"), KErrArgument)); sl@0: // test steps contain a pointer back to the suite which owns them sl@0: aTestStep->SetSuite(this); sl@0: // add the step; order is not important, so add it at position 1 sl@0: iArrayTestSteps->AppendL(aTestStep, 1); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * sl@0: * Perform a test step. sl@0: * sl@0: * @param "const TDesC& aStep" sl@0: * The test step to run. sl@0: * sl@0: * @param "const TDesC& aConfig" sl@0: * The configuration file name. sl@0: * sl@0: * @return "TVerdict" sl@0: * Result of the test. sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C TVerdict CTestSuite::DoTestStep(const TDesC& aStep, const TDesC& aConfig, const TDesC& aParamSet) sl@0: { sl@0: // This function traps leaves in the test steps, so should never leave sl@0: sl@0: // get the number of tests available in this suite sl@0: TInt noOfTests = iArrayTestSteps->Count(); sl@0: sl@0: // search the available test steps for the required one sl@0: for (TInt i = 0; i < noOfTests; i++) sl@0: { sl@0: RTestStep* theStep = iArrayTestSteps->At(i); sl@0: if (theStep->StepName().MatchF(aStep) != KErrNotFound) sl@0: { sl@0: sl@0: // found required test so initialise to PASS sl@0: theStep->SetResult(EPass); sl@0: sl@0: // set the param set to use sl@0: theStep->SetDefaultParamSet(aParamSet); sl@0: sl@0: // pass the config file info into the test step sl@0: theStep->LoadConfig(aConfig); sl@0: sl@0: // assume it's going to work sl@0: TVerdict result = EPass; sl@0: sl@0: // set step status sl@0: iStepStatus = EStepStatusStart; sl@0: sl@0: // execute pre-preamble (cleanup stack growth) sl@0: TRAPD(rPreOpen, theStep->PreOpenL()); sl@0: sl@0: if (rPreOpen != KErrNone) sl@0: { sl@0: WARN_PRINTF4(_L("Warning: Test step:%S PreOpenL in suite:%S left, error %d"), &aStep, &iSuiteName, rPreOpen); sl@0: result = EInconclusive; sl@0: } sl@0: else sl@0: { sl@0: // execute test step preamble (if any) inside a trap sl@0: TRAPD(rPreAmble, result = theStep->OpenL()); sl@0: sl@0: if (result != EPass) sl@0: { sl@0: WARN_PRINTF3(_L("Warning: Test step:%S preamble in suite:%S failed"), &aStep, &iSuiteName); sl@0: // here : call to virtual cleanup function in test step, if it exists... sl@0: theStep->CleanupAfterOpenFail(); sl@0: result = EInconclusive; sl@0: } sl@0: else if (rPreAmble != KErrNone) sl@0: { sl@0: WARN_PRINTF4(_L("Warning: Test step:%S preamble in suite:%S left, error %d"), &aStep, &iSuiteName, rPreAmble); sl@0: // here : call to virtual cleanup function in test step, if it exists... sl@0: theStep->CleanupAfterOpenFail(); sl@0: result = EInconclusive; sl@0: } sl@0: } sl@0: sl@0: // only continue if the preamble passed sl@0: if (result == EPass) sl@0: { sl@0: sl@0: // set step status sl@0: iStepStatus = EStepStatusPreamble; sl@0: sl@0: // now execute test step inside a trap sl@0: TRAPD(r, result = theStep->DoTestStepL()); sl@0: sl@0: if (r!= KErrNone) sl@0: { sl@0: WARN_PRINTF4(_L("Warning: Test step:%S in suite:%S left, error %d"), &aStep, &iSuiteName, r); sl@0: result = EFail; sl@0: } sl@0: sl@0: // set step status sl@0: iStepStatus = EStepStatusTest; sl@0: sl@0: // execute test step postamble sl@0: // NB - postamble does not leave, but may panic sl@0: theStep->Close(); sl@0: sl@0: // set step status sl@0: iStepStatus = EStepStatusFinished; sl@0: } sl@0: sl@0: // *** TO DO - check if there are problems when the preamble leaves. sl@0: // In this case the postamble is not called - there may be memory leaks. sl@0: // (Preambles may allocate memory, call __UHEAP_MARK, etc.) sl@0: // If so, move Close() to this point, and check again. sl@0: sl@0: // clean up Config data object sl@0: theStep->UnloadConfig(); sl@0: sl@0: return result; sl@0: sl@0: } sl@0: } sl@0: sl@0: // suite has been searched but test step not found, so error. sl@0: ERR_PRINTF3(_L("Failed to find test step:%S in suite:%S"), &aStep, &iSuiteName); sl@0: sl@0: return ETestSuiteError; sl@0: sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Gets a step's heap and stack size. sl@0: * sl@0: * @param "const TDesC& aStep" sl@0: * The step name sl@0: * @param "TInt* aHeapSize" sl@0: * Returns the step's heap size sl@0: * @param "TInt* aStackSize" sl@0: * Returns the step's stack size sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::GetHeapAndStackSize(const TDesC& aStep, TInt* aHeapSize, TInt* aStackSize) sl@0: { sl@0: //get the number of tests available in this suite sl@0: TInt noOfTests = iArrayTestSteps->Count(); sl@0: sl@0: // search the available test steps for the required one sl@0: for (TInt i = 0; i < noOfTests; i++) sl@0: { sl@0: RTestStep* theStep = iArrayTestSteps->At(i); sl@0: if (theStep->StepName().MatchF(aStep) != KErrNotFound) sl@0: { sl@0: sl@0: // found required test, so get the stack and heap size sl@0: *aHeapSize = theStep->HeapSize(); sl@0: *aStackSize = theStep->StackSize(); sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * General logging function for test suites. sl@0: * sl@0: * @param "TRefByValue aFmt" sl@0: * Printf-style format. sl@0: * sl@0: * @param "..." sl@0: * Variable print parameters sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::Log(TRefByValue aFmt, ...) sl@0: { sl@0: sl@0: VA_LIST aList; sl@0: VA_START(aList, aFmt); sl@0: sl@0: if(iLogger) sl@0: iLogger->Log(aFmt, aList); sl@0: sl@0: VA_END(aList); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * General logging function for test suites, with severity. sl@0: * sl@0: * @param "TInt aSeverity" sl@0: * Severity level required to log sl@0: * sl@0: * @param "TRefByValue aFmt" sl@0: * Printf-style format. sl@0: * sl@0: * @param "..." sl@0: * Variable print parameters sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::Log(TInt aSeverity, TRefByValue aFmt, ...) sl@0: { sl@0: VA_LIST aList; sl@0: VA_START(aList, aFmt); sl@0: sl@0: if(LogSeverity::IsActive(aSeverity, Severity())) sl@0: { sl@0: if(iLogger) sl@0: iLogger->Log(aFmt, aList); sl@0: } sl@0: sl@0: VA_END(aList); sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Traceable logging function for test suites. sl@0: * sl@0: * @param "const TText8* aFile" sl@0: * Source code file name sl@0: * sl@0: * @param "TInt aLine" sl@0: * Source code line sl@0: * sl@0: * @param "TInt aSeverity" sl@0: * Severity level required to log sl@0: * sl@0: * @param "TRefByValue aFmt" sl@0: * Printf-style format. sl@0: * sl@0: * @param "..." sl@0: * Variable print parameters sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::LogExtra(const TText8* aFile, TInt aLine, TInt aSeverity, sl@0: TRefByValue aFmt,...) sl@0: { sl@0: VA_LIST aList; sl@0: VA_START(aList, aFmt); sl@0: sl@0: if(LogSeverity::IsActive(aSeverity, Severity())) sl@0: { sl@0: if(iLogger) sl@0: { sl@0: iLogger->LogExtra(aFile, aLine, aSeverity, aFmt, aList); sl@0: } sl@0: } sl@0: sl@0: VA_END(aList); sl@0: } sl@0: sl@0: sl@0: /** sl@0: * sl@0: * Traceable Boolean condition tester. sl@0: * sl@0: * @param "TBool aCondition" sl@0: * Condition to be checked sl@0: * sl@0: * @param "const TText8* aFile" sl@0: * Source code file name sl@0: * sl@0: * @param "TInt aLine" sl@0: * Source code line sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::TestBooleanTrueL(TBool aCondition, const TText8* aFile, TInt aLine) sl@0: { sl@0: sl@0: // check condition sl@0: if (aCondition) sl@0: return; sl@0: sl@0: // convert filename for log sl@0: TBuf fileName; sl@0: TPtrC8 fileName8(aFile); sl@0: fileName.Copy(fileName8); // TText8->TBuf16 sl@0: sl@0: // display a log message sl@0: ERR_PRINTF3(_L("Test Failed in file:%S line:%d"), &fileName, aLine); sl@0: sl@0: // leave with error code sl@0: User::Leave(KTestErrorCode); sl@0: sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Set log severity. sl@0: * sl@0: * @param "TInt aSeverity" sl@0: * The required severity sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::SetSeverity(TInt aSeverity) sl@0: { sl@0: iSeverity = aSeverity; sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Get log severity. sl@0: * sl@0: * @return "TInt" sl@0: * The current severity sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C TInt CTestSuite::Severity() const sl@0: { sl@0: return iSeverity; sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Set logging system. sl@0: * sl@0: * @param "CLog *aLogger" sl@0: * The log to use. sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::SetLogSystem(CLog* aLogger) sl@0: { sl@0: iLogger = aLogger; sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Get logging system. sl@0: * sl@0: * @return "CLog*" sl@0: * The log the test suite is currently using. sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C CLog* CTestSuite::LogSystem() const sl@0: { sl@0: return iLogger; sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Set step status. sl@0: * sl@0: * @param "TTestStepStatus aStatus" sl@0: * The status to set. sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C void CTestSuite::SetStepStatus(TTestStepStatus aStatus) sl@0: { sl@0: iStepStatus = aStatus; sl@0: } sl@0: sl@0: /** sl@0: * sl@0: * Get step status. sl@0: * sl@0: * @return "TTestStepStatus" sl@0: * The step status. sl@0: * sl@0: * @xxxx sl@0: * sl@0: */ sl@0: EXPORT_C TTestStepStatus CTestSuite::StepStatus() const sl@0: { sl@0: return iStepStatus; sl@0: }