diff -r 14460bf2a402 -r f50f4094acd7 cbsref/csyrefplugins/csy27010/test/unit_test_base/unitTestBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cbsref/csyrefplugins/csy27010/test/unit_test_base/unitTestBase.cpp Tue Jul 06 15:36:38 2010 +0300 @@ -0,0 +1,1266 @@ +// +// * Copyright 2004 Neusoft America Inc. +// * All rights reserved. +// * This component and the accompanying materials are made available +// * under the terms of the Eclipse Public License v1.0 +// * which accompanies this distribution, and is available +// * at the URL "http://www.eclipse.org/legal/epl-v10.html". +// * +// * Contributors: +// * Keith Collins (Neusoft America Inc.) original software development and additional code and modifications. +// * Thomas Gahagen (Neusoft America Inc.) additional code and modifications. +// * Zhen Yuan (Neusoft America Inc.) additional code and modifications. +// * +// * Description: This file contains the implementation for the base class from +// * which all unit test classes are derived. +// + +// UnitTestBase.cpp + +/** @file UnitTestBase.cpp + * + */ + +#include "unitTestBase.h" + +// This indicates that the CSY is loaded by the TSY +#define LOADED_BY_TSY 1 + +// +// CUnitTestBase +// + +// These methods can be overwritten + +TBool CUnitTestBase::HasTestRangesDefined() + { + return EFalse; + } + + +void CUnitTestBase::ConstructL() +/** + * + * + */ + { + //LOGTEXT(">>ConstructL"); + + User::LeaveIfError(iFs.Connect()); + User::LeaveIfError(iFs.SetSessionPath(KTestSessionPath)); + + TInt err=iLogFile.Open(iFs,iLogFileName, EFileWrite); + + if (err==KErrNotFound) // file does not exist - create it + { + err = iLogFile.Create(iFs, iLogFileName, EFileWrite); + } + // In simultaneous tests, someone else may have created it between our + // calls to Open and Create, so no 'else' here. + if ( err == KErrInUse || err == KErrAlreadyExists ) + { + //LOGTEXT("Distinct logging required"); + + // Same filename already open by someone else. In order to run more + // than one test in, say, BasicCall at once AND have logging that + // works, create distinct log files when required. + TInt n = 0; + while ( err == KErrInUse || err == KErrAlreadyExists ) + { + TName newLogFileName(iLogFileName); + n++; + newLogFileName.AppendFormat(_L("%d"),n); + err = iLogFile.Open(iFs, newLogFileName, EFileWrite); + if (! err) + { + TInt pos = 0; + iLogFile.Seek(ESeekEnd, pos); + } + if ( err == KErrNotFound ) + { + err = iLogFile.Create(iFs, newLogFileName, EFileWrite); + break; + } + } + } + + if (err) + { + iTest.Printf(_L("Couldn't open log file (%d). Does the %S path exist?\n"), err, &KTestSessionPath); + User::After(4000000); + User::Leave(err); + } + TInt pos = 0; + iLogFile.Seek(ESeekEnd, pos); + + err = iLogFile.Write(_L8("#------------------------Test Run Start-------------------------\r\n")); + iLogFile.Flush(); + + } + +CUnitTestBase::CUnitTestBase(const TDesC& aUnitTestName, + const TDesC& aLogFileName, + const TDesC& aTestSpecName, + const TDesC& aTestScriptName) +/** + * + * + */ + :iTest(aUnitTestName), + iUnitTestName(aUnitTestName), + iLogFileName(aLogFileName), + iTestScriptName(aTestScriptName), + iTestSpecName(aTestSpecName) + { +#ifndef __WINS__ + iTest.SetLogged(EFalse); +#endif // __WINS__ + } + +CUnitTestBase::~CUnitTestBase() +/** + * + * + */ + { + iFailedTests.Close(); + + if (iLogFile.SubSessionHandle()) + { + iLogFile.Write(_L8("#------------------------Test Run End-------------------------\r\n")); + iLogFile.Flush(); + } + iLogFile.Close(); + iFs.Close(); + iTest.Close(); + } + +void CUnitTestBase::ResizeConsoleL(const TDesC& aName, TInt aXOrg, TInt aYOrg, TInt aXSize, TInt aYSize) + { +#if defined (__WINS__) + CConsoleBase* cons = iTest.Console(); + CConsoleBase* newCon = NULL; + + TRAPD(err,newCon = Console::NewL(aName,TSize(aXSize,aYSize))); + if (!err) + { + (void)aXOrg; (void)aYOrg; //unable to use these without a dirty hack! + delete cons; + iTest.SetConsole(newCon); + } +#else //__WINS__ + (void)aName; (void)aXOrg; (void)aYOrg; (void)aXSize; (void)aYSize; +#endif //__WINS__ + } + +TBool CUnitTestBase::DoSingleTestL(TInt aMethodNum, TInt aTestNum, TTestMode aTestMode) + { + //LOGTEXT3(">>DoSingleTestL [aMethodNum=%d, aTestNum=%d]",aMethodNum,aTestNum); + + TInt numMethods; + TInt numTests; + TInt errorCode; + TInt leaveCode; + + // Check if the specified test is in a valid range - if we can + if (HasTestRangesDefined()) + { + RunTestsL(EFalse, EBatch, numMethods, leaveCode, 0, 0); + + // Check that the method number is correct + if (aMethodNum == 0 || aMethodNum > numMethods) + { + iTest.Printf(_L("Bad method number: %d - Needs to be in range 1 to %d\n"), + aMethodNum, numMethods); + iTest.Printf(_L("Press a key when ready\n")); + iTest.Console()->Getch(); + //LOGTEXT("< 100) testRange = 100; + + // Get the number of tests for this method and test if aTestNum is in range + RunTestsL(EFalse, EBatch, numTests, leaveCode, aMethodNum, testRange); + numTests += testRange; + + if (aTestNum <= testRange || aTestNum > numTests) + { + iTest.Printf(_L("Bad test number (%d) for method %d - Needs to be in range %d to %d\n"), + aTestNum, aMethodNum, testRange+1, numTests); + iTest.Printf(_L("Press a key when ready\n")); + iTest.Console()->Getch(); + //LOGTEXT("<>DoAutoMethodTestsL [aMethodNum=%d]",aMethodNum); + + TInt numMethods; + TInt numTests; + TInt errorCode; + TInt leaveCode; + + if (! HasTestRangesDefined()) + { + iTest.Printf(_L("Cannot auto run tests as test ranges not implemented\n")); + iTest.Printf(_L("Press a key when ready\n")); + iTest.Console()->Getch(); + return ETrue; + } + + // Check that the method number is correct + RunTestsL(EFalse, EBatch, numMethods, leaveCode, 0, 0); + + if (aMethodNum == 0 || aMethodNum > numMethods) + { + iTest.Printf(_L("Bad method number: %d - Needs to be in range 1 to %d\n"), + aMethodNum, numMethods); + iTest.Printf(_L("Press a key when ready\n")); + iTest.Console()->Getch(); + return ETrue; + } + + + // Get the number of automated tests for this method + RunTestsL(EFalse, EBatch, numTests, leaveCode, aMethodNum, 0); + + for (TInt testIndex = 1; testIndex <= numTests; testIndex++) + { + errorCode = KErrNone; + leaveCode = KErrNone; + + RunTestsL(EFalse, EBatch, errorCode, leaveCode, aMethodNum, testIndex); + LogTestResult(errorCode, leaveCode, EFalse, aMethodNum, testIndex, EBatch); + + if (errorCode || leaveCode) + { + TTestFailure theFailedTest(aMethodNum, testIndex); + (void) iFailedTests.Append(theFailedTest); + } + } + + //LOGTEXT("<>DoTestsInSpecifiedRangeL [aStartMethodNum=%d, aEndMethodNum=%d]", + // aStartMethodNum,aEndMethodNum); + + TInt numMethods; + TInt numTests; + TInt errorCode; + TInt leaveCode; + + if (! HasTestRangesDefined()) + { + iTest.Printf(_L("Cannot auto run tests as test ranges not implemented\n")); + iTest.Printf(_L("Press a key when ready\n")); + iTest.Console()->Getch(); + return ETrue; + } + + // Check that the method number is correct + RunTestsL(EFalse, EBatch, numMethods, leaveCode, 0, 0); + + if (aStartMethodNum == 0 || aStartMethodNum > numMethods) + { + iTest.Printf(_L("Bad method number: %d - Needs to be in range 1 to %d\n"), + aStartMethodNum, numMethods); + iTest.Printf(_L("Press a key when ready\n")); + iTest.Console()->Getch(); + return ETrue; + } + if (aEndMethodNum == 0 || aEndMethodNum > numMethods) + { + iTest.Printf(_L("Bad method number: %d - Needs to be in range 1 to %d\n"), + aEndMethodNum, numMethods); + iTest.Printf(_L("Press a key when ready\n")); + iTest.Console()->Getch(); + return ETrue; + } + if (aEndMethodNum == -1) + aEndMethodNum = numMethods; + + for (TInt methodIndex = aStartMethodNum; methodIndex <= aEndMethodNum; methodIndex++) + { + TInt testIndex; + + if ((methodIndex < aEndMethodNum) || (aEndTestNum == -1)) + { + // Get the number of automated tests for the current method + RunTestsL(EFalse, EBatch, numTests, leaveCode, methodIndex, 0); + } + else + { + // Finish on a specified test. + numTests = aEndTestNum; + } + + if (methodIndex == aStartMethodNum) + testIndex = aStartTestNum; + else + testIndex = 1; + + iTest.Printf(_L("Running tests %d to %d in method %d\n"), + testIndex, numTests, methodIndex); + for (; testIndex <= numTests; testIndex++) + { + errorCode = KErrNone; + leaveCode = KErrNone; + + RunTestsL(EFalse, EBatch, errorCode, leaveCode, methodIndex, testIndex); + + LogTestResult(errorCode, leaveCode, EFalse, methodIndex, testIndex, EBatch); + } + } + + //LOGTEXT("<>DoAutoMethodsL"); + + TInt numMethods; + TInt leaveCode; + + if (! HasTestRangesDefined()) + { + iTest.Printf(_L("Cannot auto run tests as test ranges not implemented\n")); + iTest.Printf(_L("Press a key when ready\n")); + iTest.Console()->Getch(); + return ETrue; + } + + // Get the number of automated tests for this method + RunTestsL(EFalse, EBatch, numMethods, leaveCode, 0, 0); + + iFailedTests.Reset(); + for (TInt methodIndex = 1; methodIndex <= numMethods; methodIndex++) + { + DoAutoMethodTestsL(methodIndex); + } + + TInt failedCount = iFailedTests.Count(); + if ( iRepeatFailedTests + && failedCount > 0) + { + iTest.Printf(_L("%d tests failed. Will retry them now.\n"), failedCount); + iLogFile.Write(_L8("#--- Retrying the tests that failed ---\r\n")); + for (TInt i = 0; i < failedCount; i++) + { + TTestFailure theFailedTest = iFailedTests[i]; + DoSingleTestL(theFailedTest.iMethodNum, theFailedTest.iTestIndex, EBatch); + } + } + iFailedTests.Reset(); + + //LOGTEXT("<Getch(); + return ETrue; + } + + if (exitTests) + { + return EFalse; + } + + // Is this a manual test? + if ((testNum != -1) && ((endTestNum == -1) || (testMode == EInteractive))) + { + iTest.Printf(_L("Running single test %d-%d\n"), methodNum, testNum); + DoSingleTestL(methodNum, testNum, testMode); + return ETrue; + } + + // Do we want to auto run all the tests for a specified method + if ((methodNum != -1) && (testNum == -1)) + { + iTest.Printf(_L("Running all tests in method %d\n"), methodNum); + DoAutoMethodTestsL(methodNum); + return ETrue; + } + + // Do we want to run tests from one index to another? + if (methodNum != -1) + { + iTest.Printf(_L("Running tests %d-%d to %d-%d\n"), methodNum, testNum, endMethodNum, endTestNum); + DoTestsInSpecifiedRangeL(methodNum, testNum, endMethodNum, endTestNum); + return ETrue; + } + + // methodNum == -1 && testNum == -1 => + // We want to all the tests for every method automatically + iTest.Printf(_L("Running all tests\n")); + return DoAutoMethodsL(); + } + +TInt CUnitTestBase::PostTestDelayTime() +/** + * This virtual function can be overridden by derived tests to + * configure the length of delay between running tests in + * automated mode. This used to be hard coded to KTsyTestCompleteTime, + * which was 3 seconds. + * + * With 100 tests, that adds up to 5 minutes of wasted time per run! + */ + { + return KTsyTestCompleteTime; + } + +void CUnitTestBase::ActionNoMatch(TBool aEndInd,TTestMode aTestMode, + TInt aApiNumber,TInt aTestNumber) +/** + * This function provides the default action for the case + * when the test identified by the API and test number is + * not implemented. It is to be called within RunTestsL() + * in the default case of its switch statement + */ + { + if(!aEndInd) + { + iTest.Printf(_L("** Not implemented CSY%S-%d-%d yet **\n"), + &iUnitTestName,aApiNumber,aTestNumber); + if(aTestMode==EInteractive) + { + iTest.Printf(_L("press any key to continue\n")); + iTest.Console()->Getch(); + } + } + } + +TInt CUnitTestBase::CompareTestResult +(TInt aExpectedResult,TRequestStatus aStatus) +/** + * This function compare the test result with the expected one + * + * @param aStatus stores the result of a client API request + * + */ + { + TInt ret=KErrNone; + if (aStatus.Int() != aExpectedResult) + { + if(aStatus==KErrNone) + ret=__LINE__; + else + ret=aStatus.Int(); + } + return ret; + } + +void CUnitTestBase::LogTestResult(TInt aErrCode, TInt aLeaveCode, + TBool aEndInd,TInt aApiNumber, + TInt aTestNumber,TTestMode aTestMode) +/** + * This function logs the test result + */ + { + TInt err=KErrNone; + if ((aErrCode)||(aLeaveCode)) + { + if (aLeaveCode) + { + iTest.Printf(_L("Test failed with a LEAVE: CSY%S-%d-%d\n"), + &iUnitTestName,aApiNumber,aTestNumber); + err=aLeaveCode; + } + else + { + iTest.Printf(_L("FAILURE: CSY%S-%d-%d failed with %d\n"), + &iUnitTestName,aApiNumber,aTestNumber,aErrCode); + err=aErrCode; + } + + //Print out test results in Symbian's requested format + TUint count=iFunIndices.Count(); + for(TUint i = 0; i < count; i++) + WriteLog(EFalse,iFunIndices[i],aApiNumber,aTestNumber,err); + iFunIndices.Reset(); + + if (aTestMode==EInteractive) + { + iTest.Printf(_L("press any key to continue\n")); + iTest.Console()->Getch(); + } + } + else + { + //these code will not be run if a user type E or e + //to end running the tests in interactive mode + if (!aEndInd) + { + iTest.Printf(_L("CSY%S-%d-%d finished successfully\n"), + &iUnitTestName,aApiNumber,aTestNumber); + +#ifndef LOG_FAILED_TESTS_ONLY + //Print out test results in Symbian's requested format + TUint count=iFunIndices.Count(); + for(TUint i = 0; i < count; i++) + WriteLog(ETrue,iFunIndices[i],aApiNumber,aTestNumber,err); + iFunIndices.Reset(); +#endif + iTest.Printf(_L("Waiting briefly for system to close\n")); + + // give some time for test to complete +// User::After(this->PostTestDelayTime()); + } + } + } + + +TBool CUnitTestBase::UserSelectionL(TChar aMainNumber, + TInt aNumMethods, + TBool aRangeSpecified, + TInt& aApiNum, TInt& aTestNum, + TTestMode& aTestMode) + { + TInt leaveCode = 0; + aApiNum = UserChoice(aMainNumber); + + if (aApiNum == -1) return EFalse; + + if (aNumMethods != -1 && (aApiNum < 1 || aApiNum > aNumMethods)) + { + aApiNum = -1; + aTestNum = -1; + return EFalse; + } + + PrintTestDetails(aApiNum); + + TInt numAutoTests = -1; + TInt numManualTests = -1; + + if (! HasTestRangesDefined()) + iTest.Printf(_L("Test number:")); + else + { + RunTestsL(EFalse, EBatch, numAutoTests, leaveCode, aApiNum, 0); + RunTestsL(EFalse, EBatch, numManualTests, leaveCode, aApiNum, 100); + + iTest.Printf(_L("There are %d auto and %d manual tests\n"), + numAutoTests, numManualTests); + if (aRangeSpecified) + iTest.Printf(_L("Range test number:")); + else + iTest.Printf(_L("Test number or 'A' for all tests:")); + } + + TChar numberKey = iTest.Console()->Getch(); + iTest.Printf(_L("\n")); + + if ((!aRangeSpecified) && HasTestRangesDefined() && ((numberKey == 'A')||(numberKey == 'a'))) + { + aTestMode = EBatch; + aTestNum = -1; + return ETrue; + } + + aTestNum = UserChoice(numberKey); + + if (aTestNum == -1) return EFalse; + + TBool ret = EFalse; + + if (! HasTestRangesDefined()) + ret = ETrue; + + if (aTestNum > 0 && aTestNum <= numAutoTests) + ret = ETrue; + + if (aTestNum > 100 && aTestNum <= (100+numManualTests)) + ret = ETrue; + + return ret; + } + +TBool CUnitTestBase::SelectTestL(TInt& aApiNum, TInt& aTestNum, + TInt& aEndApiNum, TInt& aEndTestNum, + TTestMode& aTestMode, TBool& aExit) +/** + * This function selects a unit test which is identified by its API & + * test numbers to be run either in batch or interactive mode + * + * @return return a TBool to indicate whether or not to end the test in + * interactive mode + */ + { + aTestMode = EBatch; + aExit = EFalse; + + iTest.Console()->ClearScreen(); + + if (CommandLineL(aApiNum, aTestNum, aEndApiNum, aEndTestNum)) + { + aTestMode = EBatch; + iExitAfterTestsComplete = ETrue; + + // we have got the numbers from the command line + iTest.Printf(_L("Running %S automated API tests\n"),&iUnitTestName); + + // give tester time to get up and running + User::After(KTsyTesterSetupTime); + return ETrue; + } + + // need to get numbers from the user + iTest.Printf(_L("Running %S API Tests - interactively\n"), &iUnitTestName); + + aTestMode = EInteractive; + + // helper to aid user - which identifier relates to which number + PrintTestSpecIdentifiers(); + + TInt numMethods = -1; + TInt leaveCode = 0; + TBool rangeSpecified = EFalse; + + // Get the numbers + if (! HasTestRangesDefined()) + iTest.Printf(_L("\nNumber or 'S' for specific test or 'E' to end:")); + else + { + RunTestsL(EFalse, EBatch, numMethods, leaveCode, 0, 0); + iTest.Printf(_L("\nNumber or 'S' for specific test, 'R' for range, 'A' for all or 'E' to end:"), numMethods); + } + + TChar numberKey = iTest.Console()->Getch(); + iTest.Printf(_L("\n")); + + if (!numberKey.IsDigit()) + { + switch (numberKey) + { + case 'E': + case 'e': + aExit = ETrue; + return ETrue; + case 'A': + case 'a': + { + if (HasTestRangesDefined()) + { + aTestMode = EBatch; + aApiNum = -1; + aTestNum = -1; + return ETrue; + } + } + return EFalse; + case 'R': + case 'r': + { + if (HasTestRangesDefined()) + { + aTestMode = EBatch; + iTest.Printf(_L("Enter Start Method of range (1 -> %d):"), numMethods); + numberKey = iTest.Console()->Getch(); + rangeSpecified = ETrue; + } + else + return EFalse; + } + break; + case 'S': + case 's': + { + iTest.Printf(_L("Method to test (1 -> %d):"), numMethods); + numberKey = iTest.Console()->Getch(); + } + break; + default: + iTest.Printf(_L("Incorrect value\n")); + return EFalse; + } + } + + // User to select test case or start of range + TBool ret = UserSelectionL(numberKey, numMethods, rangeSpecified, + aApiNum, aTestNum, aTestMode); + + if (ret && rangeSpecified) + { + PrintTestSpecIdentifiers(); + + iTest.Printf(_L("Enter end method of range (1 -> %d) or 'L' last"), numMethods); + numberKey = iTest.Console()->Getch(); + iTest.Printf(_L("\n")); + + if ((numberKey == 'L')||(numberKey == 'l')) + { + aTestMode = EBatch; + aEndApiNum = -1; + aEndTestNum = -1; + return ETrue; + } + + // User to select end of range + ret = UserSelectionL(numberKey, numMethods, ETrue, + aEndApiNum, aEndTestNum, aTestMode); + } + + return ret; + } + +TInt CUnitTestBase::UserChoice(TChar aNumberKey) +/** + * This function gets the number equivalent to the user's keyboard input + * and will return once the enter key is pressed + * + * @param aNumberKey is a key pressed by the user + * @return return the number equivalent to the user's keyboard input + */ + { + TInt choice=0; + TInt mult=1; + + while ( STATIC_CAST(TInt,aNumberKey) != EKeyEnter ) + { + // If the user pressed Backspace, delete the previous number. + if (aNumberKey == 0x8) + { + if (choice > 0) + { + iTest.Printf(_L("%c %c"), aNumberKey, aNumberKey); + choice /= 10; + if (choice == 0) + mult = 1; + } + } + + if (!aNumberKey.IsDigit()) + { + aNumberKey = iTest.Console()->Getch(); + continue; + } + + TInt val = aNumberKey.GetNumericValue(); + iTest.Printf(_L("%d"),val) ; + choice = (choice * mult) + val; + if(mult==1) + mult *= 10; + aNumberKey = iTest.Console()->Getch() ; + } + + iTest.Printf(_L("\n")) ; + return choice; + } + +TBool CUnitTestBase::CommandLineL(TInt& aApiNum, TInt& aTestNum, + TInt& aEndApiNum, TInt& aEndTestNum) +/** + * This function takes inputs from command lines in the batch file run_me.bat + */ + { + aApiNum = 0; + aTestNum = 0; + + TInt commandLineLength; +#ifndef BUILD_FOR_JETSTREAM + commandLineLength = User::CommandLineLength(); +#else + RProcess eteltest; + commandLineLength = eteltest.CommandLineLength(); +#endif // BUILD_FOR_JETSTREAM + + if (commandLineLength > 0) + { + HBufC* argv = HBufC::NewLC(commandLineLength); + TPtr cmd(argv->Des()); + +#ifndef BUILD_FOR_JETSTREAM + User::CommandLine(cmd); +#else + eteltest.CommandLine(cmd); +#endif // BUILD_FOR_JETSTREAM + + TLex argParser(*argv); + + TInt argc = 0; + while (argParser.NextToken().Length()) argc++; + if ((argc < 2) || (argc > 4)) + { + iTest.Console()->Printf(_L("Usage: [ ]\n")); + return EFalse; + } + + argParser.UnGetToMark(); //Returns to the beginning of argv. + argParser.SkipSpace(); + + argParser.Val(aApiNum); + argParser.SkipSpace(); + argParser.Val(aTestNum); + + if (argc == 4) + { + argParser.SkipSpace(); + argParser.Val(aEndApiNum); + argParser.SkipSpace(); + argParser.Val(aEndTestNum); + } + else + { + aEndApiNum = aApiNum; + aEndTestNum = aTestNum; + } + + delete argv; + CleanupStack::Pop();//argv + + // we did find some command line params + return ETrue; + } + return EFalse; + } + +TInt CUnitTestBase::WriteLog(TBool aIsPassed,TUint aFunIndex,TUint aApiNum, + TUint aTstNum, TInt aErrorCode) +/** + * This function write test result to log in the folowing formats: + * AUTO;;