/** Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).* All rights reserved.* This component and the accompanying materials are made available* under the terms of the License "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 "t_testsetup.h"#include "t_testactionspec.h"#include "t_input.h"#include "t_certstoreactionmemfail.h"#include "tcancel.h"#include "t_message.h"#include "tScriptSetup.h"#include "Thardcodedsetup.h"#include "t_testhandler.h"#include "t_output.h"#include "tTestSpec.h"#include "ttesthandlersettings.h"#include "testexecuteinterface.h"#include "t_logger.h"#include "t_testrunner.h"#include "t_dummyconsole.h"EXPORT_C HBufC* CTestSetup::GetArgument(TInt nPos) { // Get command line HBufC *argv = HBufC::NewLC(User::CommandLineLength()); TPtr cmd(argv->Des()); User::CommandLine(cmd); TLex arguments(cmd); TPtrC token; token.Set(KNullDesC); // finds nth parameter that doesnt have a - while(nPos >= 0 && !arguments.Eos()) { token.Set(arguments.NextToken()); if(token.Length() > 0 && token[0] != '-') nPos--; } HBufC* result = token.AllocL(); CleanupStack::PopAndDestroy(argv); return result; }void CTestSetup::InitFileserverSessionLC(RFs& aFs) { User::LeaveIfError(aFs.Connect()); CleanupClosePushL(aFs); // enable tests to pass file handles between processes aFs.ShareProtected(); // Create the private directory, to fix failures in tests that write to // relative paths that were broken when the default path was changed to the // private path in build 03429 TFileName privatePath; User::LeaveIfError(aFs.PrivatePath(privatePath)); TInt err = aFs.MkDir(privatePath); if (err != KErrNone && err != KErrAlreadyExists) { User::Leave(err); } }EXPORT_C void CTestSetup::CreateAndRunTestsL(TScriptTests theTestTypes[], const TDesC& aScript, const TDesC& aLogFile, TBool aUseCommandLine, CConsoleBase* aConsole, TBool* aResult){ LOG(_L("-- Test handler starting")); RFs fs; InitFileserverSessionLC(fs); CScriptSetup* testSetup = CScriptSetup::NewLC(aConsole); CTestHandlerSettings* commandLineArgs = CTestHandlerSettings::NewLC(); CTestSpec* testSpec = CTestSpec::NewL(); CleanupStack::PushL(testSpec); TTestSummary summary; if(testSetup->InitialiseL(fs, aScript, aLogFile, aUseCommandLine)) { // Store the state of the heap and RFs resource count before the tests TInt initAllocCount = User::CountAllocCells(); TInt initRFsCount = fs.ResourceCount(); // Store the initial count of process and thread handles TInt initThreadHandleCount; TInt initProcessHandleCount; RThread().HandleCount(initProcessHandleCount, initThreadHandleCount); testSetup->LogFile().write(_L("<html><body><pre>\r\n")); testSetup->LogFile().write(_L("State of the system before the tests:\n")); testSetup->LogFile().write(_L("\tRFs resource count: %d\n"), initRFsCount); testSetup->LogFile().write(_L("\tProcess handle count: %d\n"), initProcessHandleCount); testSetup->LogFile().write(_L("\tThread handle count: %d\n"), initThreadHandleCount); TRAPD(error, testSetup->SetupTestsL(fs, *testSpec, theTestTypes, *commandLineArgs)) if(error==KErrNone) { CTestHandler* handler = CTestHandler::NewLC(fs, *testSpec, *commandLineArgs, &testSetup->Console(), &testSetup->LogFile()); handler->RunTestsL(); summary = handler->Summary(); testSpec->FreeAllTests(); CleanupStack::PopAndDestroy(handler); // Do heap, RFs resource, process and thread handle balance checks TInt finalRFsCount = fs.ResourceCount(); testSetup->LogFile().write(_L("State of the system after the tests:\n")); testSetup->LogFile().write(_L("\tRFs resource count: %d\n"), finalRFsCount); if (initRFsCount == finalRFsCount) { testSetup->LogFile().write(_L("\nRFs resource count ok: %d final\n\n"), finalRFsCount); } else { testSetup->LogFile().write(_L("\nRFs resource count inbalance: %d final\n\n"), finalRFsCount); ++summary.iTestsFailed; } TInt finalAllocCount = User::CountAllocCells(); if (initAllocCount == finalAllocCount) { testSetup->LogFile().write(_L("\nHeap alloc count ok: %d final vs %d initial\n\n"), finalAllocCount, initAllocCount); } else { testSetup->LogFile().write(_L("\nHeap alloc count inbalance: %d final vs %d initial\n\n"), finalAllocCount, initAllocCount); ++summary.iTestsFailed; } TInt finalThreadHandleCount; TInt finalProcessHandleCount; RThread().HandleCount(finalProcessHandleCount, finalThreadHandleCount); if (initProcessHandleCount == finalProcessHandleCount) { testSetup->LogFile().write(_L("\nProcess handle count ok: %d final vs %d initial\n\n"), finalProcessHandleCount, initProcessHandleCount); } else { testSetup->LogFile().write(_L("\nProcess handle count imbalance: %d final vs %d initial\n\n"), finalProcessHandleCount, initProcessHandleCount); ++summary.iTestsFailed; } if (initThreadHandleCount == finalThreadHandleCount) { testSetup->LogFile().write(_L("\nThread handle count ok: %d final vs %d initial\n\n"), finalThreadHandleCount, initThreadHandleCount); } else { testSetup->LogFile().write(_L("\nThread handle count imbalance: %d final vs %d initial\n\n"), finalThreadHandleCount, initThreadHandleCount); ++summary.iTestsFailed; } ++summary.iTestsRun; } // Set the result if required by caller if (aResult) { *aResult = summary.AllTestsPassed(); } summary.PrintL(testSetup->LogFile()); // pauses runtime if command line requests it i.e. -w if(commandLineArgs->iWaitForKeyPressAtEnd) { testSetup->Console().Printf(_L("\nPress a key to quit")); testSetup->Console().Getch(); } } CleanupStack::PopAndDestroy(4, &fs); // fs, testsetup, commandLineArgs and testspec // this MUST be the last thing to do incase objects being destructed on cleanup // have debug info //if (bTestSuccess) // RDebug::RawPrint(_L("RTEST: SUCCESS : testhandler\n"));}EXPORT_C void CTestSetup::CreateAndRunTestsL(THardcodedTests theTestTypes[], const TDesC& aDefaultLog){ LOG(_L("-- Test handler starting")); RFs fs; InitFileserverSessionLC(fs); InitFileserverSessionLC(fs); CHardcodedSetup* testSetup = CHardcodedSetup::NewLC(); CTestHandlerSettings* commandLineArgs = CTestHandlerSettings::NewLC(); CTestSpec* testSpec = CTestSpec::NewL(); CleanupStack::PushL(testSpec); TTestSummary summary; if(testSetup->InitialiseL(fs, aDefaultLog)) { // Store the state of the heap and RFs resource count before the tests TInt initAllocCount = User::CountAllocCells(); TInt initRFsCount = fs.ResourceCount(); TRAPD(error, testSetup->SetupTestsL(fs, *testSpec, theTestTypes, *commandLineArgs)); if(error==KErrNone) { CTestHandler* handler = CTestHandler::NewLC(fs, *testSpec, *commandLineArgs, &testSetup->Console(), &testSetup->LogFile()); handler->RunTestsL(); summary = handler->Summary(); testSpec->FreeAllTests(); CleanupStack::PopAndDestroy(handler); // Do heap and RFs resource balance checks TInt finalRFsCount = fs.ResourceCount(); testSetup->LogFile().write(_L("State of the system after the tests:\n")); testSetup->LogFile().write(_L("\tRFs resource count: %d\n"), finalRFsCount); if (initRFsCount == finalRFsCount) { testSetup->LogFile().write(_L("\nRFs resource count ok: %d final\n\n"), finalRFsCount); } else { testSetup->LogFile().write(_L("\nRFs resource count inbalance: %d final\n\n"), finalRFsCount); ++summary.iTestsFailed; } TInt finalAllocCount = User::CountAllocCells(); if (initAllocCount == finalAllocCount) { testSetup->LogFile().write(_L("\nHeap alloc count ok: %d final vs %d initial\n\n"), finalAllocCount, initAllocCount); } else { testSetup->LogFile().write(_L("\nHeap alloc count inbalance: %d final vs %d initial\n\n"), finalAllocCount, initAllocCount); ++summary.iTestsFailed; } ++summary.iTestsRun; } summary.PrintL(testSetup->LogFile()); // pauses runtime if command line requests it i.e. -w if(commandLineArgs->iWaitForKeyPressAtEnd) { testSetup->Console().Printf(_L("\nPress a key to quit")); testSetup->Console().Getch(); } } CleanupStack::PopAndDestroy(4, &fs); // fs, testsetup, commandLineArgs and testspec //if (bTestSuccess) // RDebug::RawPrint(_L("RTEST: SUCCESS : testhandler\n"));}//Check all flags is provided for understanability - Each grouping function called calls the next function// if it has succeededTBool CTestSetup::CheckAllFlags(const CTestHandlerSettings& aCommandLineSettings, TInt& aScriptGroupings) { return CheckExhaustiveandSmoke(aCommandLineSettings,aScriptGroupings); }TBool CTestSetup::CheckExhaustiveandSmoke(const CTestHandlerSettings& aCommandLineSettings, TInt& aScriptGroupings) { if (aCommandLineSettings.iExhaust || (aScriptGroupings & SMOKE)) { //Do other flags return CheckSkipped(aCommandLineSettings, aScriptGroupings); } else return EFalse; }TBool CTestSetup::CheckSkipped(const CTestHandlerSettings& aCommandLineSettings, TInt& aScriptGroupings) { if (aCommandLineSettings.iSkip || !(aScriptGroupings & SKIP)) { //Do other flags return CheckInteractive(aCommandLineSettings, aScriptGroupings); } else return EFalse; }TBool CTestSetup::CheckInteractive(const CTestHandlerSettings& aCommandLineSettings, TInt& aScriptGroupings) { if (aCommandLineSettings.iInt || !(aScriptGroupings & INTER)) { //Do other flags return CheckOOMandCancel(aCommandLineSettings, aScriptGroupings); } else return EFalse; }TBool CTestSetup::CheckOOMandCancel(const CTestHandlerSettings& aCommandLineSettings, TInt& aScriptGroupings) { if ((aScriptGroupings & (EXOOM | INOOM)) == (EXOOM | INOOM)) User::Panic(_L("Test is both Included and Excluded from OOM"), 1); if ((aScriptGroupings & (EXCANCEL | INCANCEL)) == (EXCANCEL | INCANCEL)) User::Panic(_L("Test is both Included and Excluded from Cancel"), 1); if ((aScriptGroupings & (INOOM | INCANCEL)) == (INOOM | INCANCEL)) User::Panic(_L("Test is in both OOM and Cancel groups"), 1); // Check to see whether -o set if (aCommandLineSettings.iOOM) { //Is the test in OOM group? if (aScriptGroupings & INOOM) return ETrue; else //Is the test excluded from OOM? if (aScriptGroupings & EXOOM) return EFalse; } else if (aScriptGroupings & INOOM) return EFalse; // Check to see whether -c set if (aCommandLineSettings.iCancel) { //Is the test in CANCEL group? if (aScriptGroupings & INCANCEL) return ETrue; else //Is the test excluded from CANCEL? if (aScriptGroupings & EXCANCEL) return EFalse; } else if (aScriptGroupings & INCANCEL) return EFalse; return ETrue; }EXPORT_C CTestSetup::~CTestSetup() { delete iLogFile; delete iTestConsole; if (iConsoleOwned) { // Note that the heap count when this is deleted must be the same as // when the console was allocated, otherwise a panic will occur. This // is due to the techview implementation of the console doing a heap // mark in its destructor. delete iConsole; } }CTestSetup::CTestSetup(CConsoleBase* aConsole) : iConsole(aConsole), iConsoleOwned(aConsole == NULL) { }void CTestSetup::ConstructL() { if (iConsoleOwned) { iConsole = Console::NewL(_L("Test code"), TSize(KDefaultConsWidth, KDefaultConsHeight)); } // Currently the console passed to the test actions discards all output - // this is an attempt to make hardware tests run faster. All information // should be written to the log file anyway, and I'd like to remove use of a // console as well as the log file. -- jc iTestConsole = new (ELeave) CDummyConsole(); }void CTestSetup::OpenLogFileL(RFs &aFs, TInt nPos, const TDesC &aLogFile, TBool aUseCommandline) { HBufC* logFileName = NULL; if (aUseCommandline) { logFileName = GetArgument(nPos); CleanupStack::PushL(logFileName); // check if logfile was specified on command line if(logFileName->Length()==0) { // empty so remove it CleanupStack::PopAndDestroy(logFileName); logFileName = NULL; } } if(logFileName == NULL) { if(aLogFile.Length()==0) { PRINTANDLOG(_L("No log file specified on command line and no default given")); User::Leave(KErrArgument); } else { // there is a default copy that logFileName = aLogFile.AllocL(); CleanupStack::PushL(logFileName); } } PRINTANDLOG1(_L("Log file: %S"), logFileName); RFile logFile; // attempts to create directories incase they dont exist aFs.MkDirAll(*logFileName); // ignore errors // write over any existing log User::LeaveIfError(logFile.Replace(aFs, *logFileName, EFileWrite)); // output goes only to the log file iLogFile = new(ELeave) FileOutput(logFile); CleanupStack::PopAndDestroy(logFileName); };