diff -r 000000000000 -r af10295192d8 networkingtestandutils/networkingintegrationtest/scheduleTest/parseline.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkingtestandutils/networkingintegrationtest/scheduleTest/parseline.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,1562 @@ +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "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: +// This module contains CParseLine and CSuiteDll classes +// CParseLine contains the functions required to execute +// a line of test script file. +// CSuiteDll objects contains information about test suite +// dlls that have been loaded. +// +// + +/** + @file parseLine.cpp +*/ + +// system includes +#include +#include +#include "f32file.h" + +// test system includes +#include "../inc/Log.h" +#include "../inc/TestUtils.h" +#include "../inc/TestStep.h" +#include "../inc/TestSuite.h" +#include "script.h" +#include "parseline.h" + +/** +DLL fullpath +@internalComponent +*/ +_LIT(KTxtDLLpath,"c:\\;c:\\system\\libs\\;d:\\;d:\\system\\libs\\"); + +#ifdef __WINS__ +/** +Holds ced_exe DLL string constant +@internalComponent +*/ +_LIT(KTxtcedDLL,"ced_exe.dll"); +#endif + +/** +Thread name format +@internalComponent +*/ +_LIT(KThreadNameFmt, "DoTestThread_%d"); + +/** +Maximum test thread heap size +@internalComponent +*/ +const TInt KMaxTestThreadHeapSize = 0x10000; + +/** +extern global data - pointer to test utils +@internalComponent +*/ +GLDEF_D CTestUtils * pTestUtils; + +/** +extern global data - pointer to Log system +@internalComponent +*/ +GLDEF_D CLog * pLogSystem; + +/** +extern global data - running in automated, non-interactive, stop-for-nothing mode +@internalComponent +*/ +GLDEF_D TBool automatedMode = EFalse; + +/** +extern global data - pointer to console +@internalComponent +*/ +GLDEF_D CConsoleBase * console; + + +CParseLine::CParseLine():iTestVerdict(EPass) +/** +constructor +*/ + {} +void CParseLine::ConstructL(CScript * ptr) +/** +create a new Array to store the test steps in +*/ + { + // create a new Array to store the test steps in + iArrayLoadedSuiteDll = new(ELeave) CArrayPtrFlat(1); + + iScript = ptr; + iSeverity = ESevrAll; + iBreakOnError = EFalse; + iThreadNameSuffix = User::TickCount(); + } + +CParseLine* CParseLine::NewL( CScript * ptr) +/** +NewL static constructor +*/ + { + CParseLine * self = new(ELeave) CParseLine; + CleanupStack::PushL(self); + self->ConstructL(ptr); + CleanupStack::Pop(); + return self; + } + +CParseLine::~CParseLine() +/** +Delete all objects in iArrayLoadedSuiteDll. +This will unload any loaded test suite DLLS. +*/ + { + + // unload DLLs and their records + if (iArrayLoadedSuiteDll) + { + // delete all objects in iArrayLoadedSuiteDll + // the destructors will unload any loaded DLLS + iArrayLoadedSuiteDll->ResetAndDestroy(); + delete iArrayLoadedSuiteDll; + } + + } + +void CParseLine::ProcessLineL(const TPtrC8 &aNrrowline, TInt8 lineNo) +/** +Process a line from the script file + +@param aNrrowline The line to be parsed +@param lineNo The current line number +*/ + { + // make a local unicode buffer + TBuf LineBuf; + //If the lenght of the command line is more than MAX_SCRIPT_LINE_LENGTH=200 + //Igore the line with Warning and the test result would be Inconclusive + if (aNrrowline.Length() > LineBuf.MaxLength()) + { + TLex8 lex(aNrrowline); + // start at the begining + TPtrC8 token=lex.NextToken(); + TInt firstChar = aNrrowline[0]; + if(firstChar == '\r' || firstChar == '\n' || firstChar == '#' || firstChar == '/' || token.CompareF((TPtrC8((const TText8 *)("PRINT")))) == 0 || token.CompareF((TPtrC8((const TText8 *)("PAUSE_AT_END")))) == 0 || token.CompareF((TPtrC8((const TText8 *)("PAUSE")))) == 0) + { + // ignore command line with comments + } + else + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("WARNING : Command line too Long (Exceeds length of 200) Line:%d"), lineNo); + iTestVerdict = EInconclusive; + } + + return; + } + + LineBuf.Fill( '\0',MAX_SCRIPT_LINE_LENGTH); + + // convert the narrow script file to Unicode + TFileName testnameU; + testnameU.Copy(aNrrowline); + + // find the end of the line + TInt end= testnameU.Locate('\n'); + + // copy the line into LineBuf + if ((end != -1) && (end < MAX_SCRIPT_LINE_LENGTH)) + LineBuf = testnameU.Left(end-1); + else + LineBuf = testnameU; + + // the parser relies on spaces between tokens. Commas are + // allowed but are just replaced with spaces + while ( LineBuf.Locate(TChar(',')) != KErrNotFound ) + { + // found a comma so replave with space + LineBuf.Replace(LineBuf.Locate(TChar(',')),1,_L(" ")); + } + + // for debugging display the line with a line no +#ifdef SCRIPT_DEBUG + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Line:%d %s "), lineNo, LineBuf.Ptr() ); +#endif + + // if there has been a failure and the user has selected + // x then the next commands in the script are skipped until + // a test complete statement is found + if ( iBreakOnError ) + { + if (LineBuf.Find(_L("TEST_COMPLETE"))==0) + { + TestComplete( LineBuf ); + + // reset flag now test complete found + iBreakOnError = EFalse; + } + + // do not process the rest of the line + return; + } + + // check the line for command keywords + if ((LineBuf.Find(_L("//"))==0) || (LineBuf.Find(_L("#"))==0)) + { + // ignore comments + } + else + { + // use Tlex to decode the cmd + TLex lex(LineBuf); + // start at the begining + TPtrC token=lex.NextToken(); + + if (token.CompareF(_L("LOAD_SUITE"))==0) + { + LoadSuiteL( LineBuf ); + } + else if (token.CompareF(_L("RUN_SCRIPT"))==0) + { + RunScriptL( LineBuf ); + } + else if (token.CompareF(_L("RUN_TEST_STEP"))==0) + { + RunTestStep( LineBuf ); + } + else if (token.CompareF(_L("RUN_PANIC_STEP"))==0) + { + RunPanicTestStep( LineBuf ); + } + else if (token.CompareF(_L("RUN_UTILS"))==0) + { + RunUtil( LineBuf ); + } + else if (token.CompareF(_L("CED"))==0) + { + RunCed( LineBuf ); + } + else if (token.CompareF(_L("RUN_PROGRAM"))==0) + { + RunProgram( LineBuf ); + } + else if (token.CompareF(_L("UNLOAD"))==0) + { + Unload(LineBuf); + } + else if (token.CompareF(_L("HEAP_MARK"))==0) + { + HeapMark(); + } + else if (token.CompareF(_L("HEAP_MARKEND"))==0) + { + HeapCheck(); + } + else if (token.CompareF(_L("REQUEST_MARK"))==0) + { + RequestMark(); + } + else if (token.CompareF(_L("REQUEST_CHECK"))==0) + { + RequestCheck(); + } + else if (token.CompareF(_L("HANDLES_MARK"))==0) + { + HandlesMark(); + } + else if (token.CompareF(_L("HANDLES_CHECK"))==0) + { + HandlesCheck(); + } + else if (token.CompareF(_L("PRINT"))==0) + { + scriptPrint( LineBuf ); + } + else if (token.CompareF(_L("DELAY"))==0) + { + Delay( LineBuf ); + } + else if (token.CompareF(_L("SEVERITY"))==0) + { + SetSeverity( LineBuf ); + } + else if (token.CompareF(_L("PAUSE_AT_END"))==0) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Pause at end enabled ")); + iScript->iPauseAtEnd = ETrue; + } + else if (token.CompareF(_L("MULTITHREAD"))==0) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Multithread operation enabled ")); + iScript->iMultThread = ETrue; + } + else if (token.CompareF(_L("SINGLETHREAD"))==0) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Single thread operation enabled ")); + iScript->iMultThread = EFalse; + } + else if (token.CompareF(_L("PAUSE"))==0) + { + iScript->Pause(); + } + else if (token.CompareF(_L("BREAK_ON_ERROR"))==0) + { // if the current test verdict is not PASS + // give the user the chance to quit + if ( iTestVerdict != EPass ) + iBreakOnError = iScript->BreakOnError(); + } + else if (token.CompareF(_L("TEST_COMPLETE"))==0) + { + // use Tlex to decode the cmd line + TestComplete( LineBuf ); + } + else if (token.CompareF(_L("LOG_SETTINGS"))==0) + { + // use Tlex to decode the cmd line + LogSettings( LineBuf ); + } + else if (LineBuf.Length()==0) + { + // ignore blank lines + } + else + { + // failed to decode line + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Error in script line:%d - %s "), lineNo, LineBuf.Ptr() ); + } + } + +} + +void CParseLine::TestComplete( const TDesC& Text ) +/** +This function implements the script test complete keyword + +@param The contents of Text are added to the log file with the result +*/ + { + // use Tlex to decode the cmd line + TLex lex(Text); + + // start at the begining + TPtrC token=lex.NextToken(); + + // step over the keyword + token.Set(lex.NextToken()); + + if (token.Length() !=0 ) + iCurrentStepName = token; + + // Test cases must be careful to clean up after themselves - any stray signals generated in a test case + // lead here to automatic failure of the step. They are caught here to allow further cases to run + // without crashing. + while (RThread().RequestCount()!=0) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Warning! Test case generated stray signal! (cleaning up)") ); + User::WaitForAnyRequest(); + iTestVerdict = EFail; + } + + // add the current result to the script + iScript->AddResult( iTestVerdict ); + + // reset for next test + iTestVerdict = EPass; + } + +void CParseLine::scriptPrint( const TDesC& Text ) +/** +This function implements the script PRINT Keyword + +@param Text The text to be added to the log file +*/ + { + // display the text after the PRINT and 1 space = 6 + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("%s "), (Text.Ptr()+6) ); + } + +void CParseLine::Delay( const TDesC& Text ) +/** +This function implements the script Delay Keyword + +@param Text contains the time to delay in milliseconds +*/ + { + // if the test has already failed skip the delay + if ( iTestVerdict != EPass ) + { + pLogSystem->Log(_L("skipped delay as test has already failed") ); + return; + } + + // get the required time for the delay + // first get the value as a string + TLex TimeOut(Text); + TimeOut.NextToken(); + TPtrC token=TimeOut.NextToken(); + + // convert the value into a int + TLex timeoutLex(token); + TInt GuardTimerValue =2500; + if (timeoutLex.Val(GuardTimerValue) != KErrNone ) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, + _L("error in guard timer value could not decode >%S< as value"), + &token, + GuardTimerValue ); + return; + } + + // display the text after the PRINT and 1 space = 6 + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, + _L("Delay for %d mS"), GuardTimerValue ); + + // wait for the required delay + RTimer GuardTimer; + GuardTimer.CreateLocal(); // create for this thread + TRequestStatus TimerStatus; + GuardTimer.After(TimerStatus,GuardTimerValue * 1000); + User::WaitForRequest(TimerStatus); + GuardTimer.Cancel(); + + } + +void CParseLine::SetSeverity( const TDesC& Text ) +/** +This function implements the script SetSeverity Keyword + +@param Text contains the severity level +*/ + { + // get the required time for the delay + // first get the value as a string + TLex SeverityOut(Text); + SeverityOut.NextToken(); + TPtrC token=SeverityOut.NextToken(); + + // convert the value into a int + TLex Severity(token); + TInt SeverityValue = 7; + if (Severity.Val(SeverityValue) != KErrNone ) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, + _L("Error in severity level value could not decode >%S< as value"), + &token, + SeverityValue ); + return; + } + + if(SeverityValue & ~7) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, + ESevrErr, _L("Error in severity value.")); + SeverityValue = 7; + return; + } + else + { + iSeverity = SeverityValue; + + TInt NoOfDlls = iArrayLoadedSuiteDll->Count(); + for ( TInt i=0; i < NoOfDlls; i++ ) + { + CSuiteDll * ptrSuite = iArrayLoadedSuiteDll->At(i); + ptrSuite->iTestSuite->SetSeverity(iSeverity); + } + } + + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Severity is set to %d"), SeverityValue ); + } + +void CParseLine::RunScriptL( const TDesC& Text ) +/** +This function implements the script RUN_SCRIPT Keyword + +@param Text contains the script file name +*/ + { + // use Tlex to decode the cmd line + TLex lex(Text); + + // start at the begining + TPtrC token=lex.NextToken(); + + // step over the keyword + token.Set(lex.NextToken()); + + // format for printing + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("RUN_SCRIPT %S"),&token ); + + // create a new Script object (but use the current parse + // as it has the dll loaded record + CScript* newScript=CScript::NewL(this); + CleanupStack::PushL(newScript); + + // read in the script file + TFileName scriptFileName=token; + if ( newScript->OpenScriptFile( scriptFileName )) + { + // process it + iTestVerdict = newScript->ExecuteScriptL(); + + /* verdicts for scripts are not really useful so forget! */ + /* pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("The final result for test script %S was %s"), + &token, + pLogSystem->TestResultText( iTestVerdict ) ); */ + + // add results from the new script to the owner script + iScript->AddResult( newScript ); + } + else + { + // failed to find script so verdict incloncusive + iTestVerdict = EInconclusive; + } + + CleanupStack::PopAndDestroy(newScript); + + } + +void CParseLine::RunTestStep( const TDesC& Text ) +/** +RunTestStep + +@param Text contains the test step name +@return KErrNone or an error code +*/ + { + TPtrC suite, step, config; + + // use Tlex to decode the cmd line + TLex lex(Text); + + // start at the begining + TPtrC timeout=lex.NextToken(); + + // step over the keyword + timeout.Set(lex.NextToken()); + + // get the other parameters + suite.Set(lex.NextToken()); + step.Set(lex.NextToken()); + config.Set(lex.NextToken()); + + // save the name of the current test step + iCurrentStepName = step; + + // conert the guard timer value to a TInt + TLex lexTimeOut(timeout); + TInt GuardTimerValue; + if (lexTimeOut.Val(GuardTimerValue) != KErrNone ) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("error in guard timer value:%S using default 100mS"), &timeout); + GuardTimerValue = 100; + } + + // log the start of a test step + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("RUN_TEST_STEP:%S suite:%S timeout:%dmS config:%S"), + &step, + &suite, + GuardTimerValue, + &config ); + + // run the test step + enum TVerdict CurrentTestVerdict; + + // check which thread mode selected! + if ( iScript->iMultThread ) + CurrentTestVerdict = DoTestNewThread( suite, step, GuardTimerValue, config ); + else + CurrentTestVerdict = DoTestCurrentThread( suite, step, config ); + + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("TEST_STEP:%S returned:%s "), &step, pLogSystem->TestResultText(CurrentTestVerdict)); + + // this result is only significant if every thing else has passed + if ( iTestVerdict == EPass ) + iTestVerdict = CurrentTestVerdict; + + } + +void CParseLine::RunPanicTestStep( const TDesC& Text ) +/** +This function implements the script RUN_PANIC_STEP Keyword. +This step is expected to panic and gives a pass result if it panics +and a fail if it does not. + +@param Text contains the test step name +*/ + { + TPtrC suite, step, config; + + // use Tlex to decode the cmd line + TLex lex(Text); + + // start at the begining + TPtrC timeout=lex.NextToken(); + + // step over the keyword + timeout.Set(lex.NextToken()); + + // get the other parameters + suite.Set(lex.NextToken()); + step.Set(lex.NextToken()); + config.Set(lex.NextToken()); + + // save the name of the current test step + iCurrentStepName = step; + + // conert the guard timer value to a TInt + TLex lexTimeOut(timeout); + TInt GuardTimerValue; + if (lexTimeOut.Val(GuardTimerValue) != KErrNone ) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("error in guard timer value:%S using default 10000"), &timeout); + GuardTimerValue = 1000000; + } + + // log the start of a test step + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("RUN_PANIC_STEP:%S suite:%S timeout:%dmS config:%S"), + &step, + &suite, + GuardTimerValue, + &config ); + + // run the test step + enum TVerdict CurrentTestVerdict; + + // check which thread mode selected! + CurrentTestVerdict = DoPanicTest( suite, step, GuardTimerValue, config ); + + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("TEST_STEP:%S returned:%s "), &step, pLogSystem->TestResultText(CurrentTestVerdict)); + + // this result is only significant if every thing else has passed + if ( iTestVerdict == EPass ) + iTestVerdict = CurrentTestVerdict; + + } + + +void CParseLine::RunUtil( const TDesC& Text ) +/** +This function implements the script RUN_UTILS Keyword + +@param Text contains the util name +*/ + { + // Call the utils + pTestUtils->RunUtils( Text ); + } + +void CParseLine::Reboot(void) +/** +This function implements the script REBOOT Keyword +*/ + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("REBOOT ") ); + } + +TInt CParseLine::threadfn ( TAny * ptr ) +/** +Static function to call DoTestStep() which is run +in a separate thread + +@param ptr Contains the test step name, and configuration parameters passed to the new thread. +@return The test result as a TVerdict. +*/ + { + // get clean-up stack + CTrapCleanup* Cleanup=CTrapCleanup::New(); + + // get the data for the test + CStepData * data = (CStepData *)ptr; + + // do the test step + TVerdict result = data->iSuite->iTestSuite->DoTestStep( data->step, data->config); + + // done with the clean up stack + delete Cleanup; + + // return the test result + return result; + } + +enum TVerdict CParseLine::DoTestNewThread(TPtrC suite, TPtrC step, TInt GuardTimerValue, const TPtrC &config) +/** +Call the test step in the correct suite + +@param suite The test suite to use. +@param step The test step name +@param the guard timer in milliseconds +@param reference to the configuration file +@return The test result as a TVerdict +*/ + { + // get the number of suites loaded + TInt NoOfDlls = iArrayLoadedSuiteDll->Count(); + + TVerdict result = ETestSuiteError; + + // search the list of loaded test suite DLLs for the required one + for ( TInt i=0; i < NoOfDlls; i++ ) + { + CSuiteDll * ptrSuite = iArrayLoadedSuiteDll->At(i); + + if(ptrSuite->SuiteNameMatch(suite)) + { + + // do a test in a new thread + RThread NewThread; + + CStepData data; + data.step = step; + data.config = config; + data.iSuite = ptrSuite; + + // run in a new thread, with a new heap + TBuf<32> threadName; + threadName.Format(KThreadNameFmt, iThreadNameSuffix++); + TInt res=NewThread.Create(threadName, + threadfn, + KDefaultStackSize, + KMinHeapSize, + KMaxTestThreadHeapSize, + &data); + + if (res != KErrNone) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("unable to create test thread ") ); + return EFail; + } + + // start the thread and request the status + TRequestStatus ThreadStatus; + NewThread.Logon(ThreadStatus); + + // if the guard timer value is -1 don't time at all + if ( GuardTimerValue == -1 ) + { + // no guard timer + NewThread.Resume(); + User::WaitForRequest( ThreadStatus ); + } + else + { + // wait for either test thread or timer to end + RTimer GuardTimer; + GuardTimer.CreateLocal(); // create for this thread + TRequestStatus TimerStatus; + NewThread.Resume(); + GuardTimer.After(TimerStatus,GuardTimerValue * 1000); + User::WaitForRequest(ThreadStatus, TimerStatus); + if (TimerStatus==KRequestPending) + { + GuardTimer.Cancel(); + User::WaitForRequest(TimerStatus); + } + GuardTimer.Close(); + } + + // get the test result + result = (TVerdict)ThreadStatus.Int(); + + // check terminated ok + switch(NewThread.ExitType() ) + { + case EExitTerminate: + case EExitKill: + break; + case EExitPanic: + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("thread had a panic") ); + result = EFail; + break; + case EExitPending: + // if the thread is still pending then the guard timer must have expired + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("thread timed out") ); + // kill the test step thread + NewThread.Kill(1); + User::WaitForRequest(ThreadStatus); + result = EFail; + break; + default: + break; + } + + // done with the test thread + NewThread.Close(); + + // send the log data a line at a time + // find the end of the first line + TInt nl= ptrSuite->iTestSuite->iLogData.Locate(TChar('\n')); + + // get each line in turn + while ( nl != KErrNotFound ) + { + // display line + TPtrC16 line = ptrSuite->iTestSuite->iLogData.Left(nl); + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("%S"), &line ); + + // remove the line displayed + ptrSuite->iTestSuite->iLogData.Replace(0,nl+1,_L("")); + + // find the next newline + nl= ptrSuite->iTestSuite->iLogData.Locate(TChar('\n')); + } + + // return the test verdict + return result; + } + } + + // the required suite has not been found + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Error in test step:%S cannot find suite:%S" ), + &step, + &suite ); + + return ETestSuiteError; +} + +// DoTest +enum TVerdict CParseLine::DoPanicTest(TPtrC suite, TPtrC step, TInt GuardTimerValue, const TPtrC &config) +/** +Call the test step which is expected to Panic + +@param suite The test suite to use. +@param step The test step name +@param the guard timer in milliseconds +@param reference to the configuration file +@return The test result as a TVerdict +*/ + { + // get the number of suites loaded + TInt NoOfDlls = iArrayLoadedSuiteDll->Count(); + + TVerdict result; + + // search the list of loaded test suite DLLs for the required one + for ( TInt i=0; i < NoOfDlls; i++ ) + { + CSuiteDll * ptrSuite = iArrayLoadedSuiteDll->At(i); + + if(ptrSuite->SuiteNameMatch(suite)) + { + + // do a test in a new thread + RThread t; + + CStepData data; + data.step = step; + data.config = config; + data.iSuite = ptrSuite; + + // run in a new thread, with a new heap + TBuf<32> threadName; + threadName.Format(KThreadNameFmt, iThreadNameSuffix++); + TInt res=t.Create(threadName, + threadfn, + KDefaultStackSize, + KMinHeapSize, + KMaxTestThreadHeapSize, + &data); + + if (res != KErrNone) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("unable tp create test thread ") ); + return EFail; + } + + // start the thread and request the status + TRequestStatus ThreadStatus; + t.Logon(ThreadStatus); + + // if the guard timer value is -1 don't time at all + if ( GuardTimerValue == -1 ) + { + // no guard timer + t.Resume(); + User::WaitForRequest( ThreadStatus ); + } + else + { + // wait for either test thread or timer to end + RTimer GuardTimer; + GuardTimer.CreateLocal(); // create for this thread + TRequestStatus TimerStatus; + t.Resume(); + GuardTimer.After(TimerStatus,GuardTimerValue * 1000); + User::WaitForRequest(ThreadStatus, TimerStatus); + GuardTimer.Cancel(); + User::WaitForAnyRequest(); + } + + // get the test result + result = (TVerdict)ThreadStatus.Int(); + + TExitCategoryName category(t.ExitCategory()); + // check terminated ok + switch(t.ExitType() ) + { + case EExitPanic: + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Panic occurred of category %S and reason %d"), &category, t.ExitReason()); + result = + category.Left(4)==_L("KERN") || category.Left(3)==_L("E32") ? EFail : EPass; + break; + case EExitPending: + // if the thread is still pending then the guard timer must have expired + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("thread timed out") ); + // kill the test step thread + t.Kill(1); + result = EFail; + break; + case EExitTerminate: + case EExitKill: + default: + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Test did not panic so fail") ); + result = EFail; + break; + } + + // done with the test thread + t.Close(); + + // send the log data a line at a time + // find the end of the first line + TInt nl= ptrSuite->iTestSuite->iLogData.Locate(TChar('\n')); + + // get each line in turn + while ( nl != KErrNotFound ) + { + // display line + TPtrC16 line = ptrSuite->iTestSuite->iLogData.Left(nl); + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("%S"), &line ); + + // remove the line displayed + ptrSuite->iTestSuite->iLogData.Replace(0,nl+1,_L("")); + + // find the next newline + nl= ptrSuite->iTestSuite->iLogData.Locate(TChar('\n')); + } + + // return the test verdict + return result; + } + } + + // the required suite has not been found + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Error in test step:%S cannot find suite:%S" ), + &step, + &suite ); + + return ETestSuiteError; +} + +// DoTestCurrentThread +enum TVerdict CParseLine::DoTestCurrentThread(TPtrC suite, TPtrC step, TPtrC config) +/** +Call the test step in the current Thread + +@param suite The test suite to use. +@param step The test step name +@param reference to the configuration file +@return The test result as a TVerdict +*/ + { + // get the number of suites loaded + TInt NoOfDlls = iArrayLoadedSuiteDll->Count(); + + TVerdict result; + + // search the list of loaded test suite DLLs for the required one + for ( TInt i=0; i < NoOfDlls; i++ ) + { + + CSuiteDll * ptrSuite = iArrayLoadedSuiteDll->At(i); + + if(ptrSuite->SuiteNameMatch(suite)) + { + // execute in the current thread + result = ptrSuite->iTestSuite->DoTestStep(step, config); + + // send the log data a line at a time + // find the end of the first line + TInt nl= ptrSuite->iTestSuite->iLogData.Locate(TChar('\n')); + + // get each line in turn + while ( nl != KErrNotFound ) + { + // display line + TPtrC16 line = ptrSuite->iTestSuite->iLogData.Left(nl); + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("%S"), &line ); + + // remove the line displayed + ptrSuite->iTestSuite->iLogData.Replace(0,nl+1,_L("")); + + // find the next newline + nl= ptrSuite->iTestSuite->iLogData.Locate(TChar('\n')); + } + + // return the test verdict + return result; + } + } + + // the required suite has not been found + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Error in test step:%S cannot find suite:%S" ), + &step, + &suite ); + + return ETestSuiteError; + } + + + +// RunCed +void CParseLine::RunCed( const TDesC& Text ) +/** +This function runs CED the commdb tool.... + +@param text The name of tge ced.cfg file to use +*/ + { + // use Tlex to decode the cmd line + TLex lex(Text); + + // start at the begining + TPtrC token=lex.NextToken(); + + // step over the keyword "ced" and get the rest + token.Set(lex.Remainder()); + + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Run Ced parameters %S"), &token); + + // In the ARM and EKA2 emulator builds run ced as a new process + RProcess ced; + TBuf<100> CmdLine; + CmdLine.Format(_L("-i %S"),&token); + TInt ret = ced.Create( _L("z:\\system\\libs\\ced.exe"), CmdLine ); + + if ( ret != KErrNone ) + { + TPtrC Errortxt = CLog::EpocErrorToText(ret); + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Failed to start ced process %S"),&Errortxt ); + return; + } + else + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("ced.exe started %S"), &CmdLine); + + // create and start a guard timer + RTimer GuardTimer; + TRequestStatus TimerStatus(KRequestPending); + GuardTimer.CreateLocal(); // create for this thread + GuardTimer.After(TimerStatus,120 * 1000 *1000); + + // start ced + TRequestStatus ThreadStatus; + ced.Logon(ThreadStatus); + ced.Resume(); + + // wait for guard timer or ced + User::WaitForRequest(ThreadStatus, TimerStatus); + + // cancel the guard timer now a request has happened + GuardTimer.Cancel(); + + if(ThreadStatus==KRequestPending) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("CED TIMED OUT\n") ); + } + + User::WaitForAnyRequest(); //Need this to balance up the requests/completions + //as User::WaitForRequest(ThreadStatus, TimerStatus) only makes one request + + // check return type + TVerdict cedVerdict = EInconclusive; + TExitType cedExitType = ced.ExitType(); + if ( cedExitType == EExitTerminate || cedExitType == EExitKill ) + { + TInt exitReason = ced.ExitReason(); + if(exitReason == 0) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("ced exited with success") ); + cedVerdict = EPass; + } + else + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("ced exited with failure %d"), exitReason ); + } + else + { + // Describe what specifically happened + if ( cedExitType == EExitPanic) + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("ced exited with EExitPanic") ); + else if ( cedExitType == EExitPending) + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("ced still running (!)") ); + else + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("ced exited with unknown type %d"), cedExitType ); + } + // this result is only significant if every thing else has passed + if( iTestVerdict == EPass ) + { + iTestVerdict = cedVerdict; + } + } + + + +} + +void CParseLine::RunProgram( const TDesC& Text ) +/** +This function implements the script RunProgram command + +@param Text The name of the program to run +*/ + { + TPtrC Param; + + // use Tlex to decode the cmd line + TLex lex(Text); + + // start at the begining + TPtrC token=lex.NextToken(); + + // step over the keyword + token.Set(lex.NextToken()); + + // get the parameters + Param.Set(lex.NextToken()); + + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Run Program ")); + +#ifdef __WINS__ + // this is not supportted in WINS builds + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Warning RUN_PROGRAM is not supported on WINS") ); +#endif + + // In the ARM build run program as a new process + // use the rest of the text as parameters + RProcess program; + TInt ret = program.Create( token, lex.Remainder() ); + + if ( ret != KErrNone ) + { + TPtrC Errortxt = CLog::EpocErrorToText(ret); + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Failed to start process %S"),&Errortxt ); + return; + } + else + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Program started") ); + + // start program + TRequestStatus ThreadStatus; + program.Logon(ThreadStatus); + program.Resume(); + + // wait for guard timer or ced + User::WaitForRequest(ThreadStatus); + + // check return type + if ( program.ExitType() == EExitPanic) + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("program returned EExitPanic") ); + else if ( program.ExitType() == EExitPending) + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("program returned EExitPending") ); + else + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("program returned EExitTerminate") ); + } + } + +void CParseLine::LogSettings( const TDesC& Text ) +/** +This function parses "LOG_SETTNGS" command +Command format is LOG_SETTINGS "put src." (1/0), +"HTML format" (1/0) + +@param string to parse +*/ + { + // use Tlex to decode the cmd line + TLex lex(Text); + + // start at the begining + TPtrC token=lex.NextToken(); + + // step over the keyword + //Get information about source + token.Set(lex.NextToken()); + + TLex oSrcLex(token); + TInt isSrc = ETrue; //Shall we put src information? + if (oSrcLex.Val(isSrc) != KErrNone ) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, + _L("Error in LOG_SETTINGS value could not decode >%S< as value(0/1)"), + &token); + } + else + { + pLogSystem->SetPutSrcInfo(isSrc) ; + } + //Get information about format + //TInt isHtml = ETrue; //Shall we use HTML log format? + token.Set(lex.NextToken()); + TLex oHtmlLex(token); + + if (oHtmlLex.Val(isSrc) != KErrNone ) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, + _L("Error in LOG_SETTINGS value could not decode >%S< as value(0/1)"), + &token); + } + else + { + pLogSystem->SetHtmlLogMode(isSrc) ; + } + } + + +void CParseLine::LoadSuiteL( const TDesC& Text ) +/** +LoadSuite +This function loads a required test suite DLL +It also creates a CtestSuite object as a record +of the loaded dll + +@param suite dll name +*/ + { + // use Tlex to decode the cmd line + TLex lex(Text); + + // start at the begining + TPtrC token=lex.NextToken(); + + // step over the keyword + token.Set(lex.NextToken()); + + + RLibrary lib; + TInt err = lib.Load(token, KTxtDLLpath); + if (err == KErrNone) + { + lib.Close(); + } + + if ( err==KErrNotFound ) + { + // this is not going to load ! + // pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Test suite %S could not be found"),&token ); + //return; + } + + // check not already loaded + // by searching the list of loaded test suite DLLs for the required one + // start with the number of suites loaded + TInt NoOfDlls = iArrayLoadedSuiteDll->Count(); + for ( TInt i=0; i < NoOfDlls; i++ ) + { + CSuiteDll * ptrSuite = iArrayLoadedSuiteDll->At(i); + + // check the names + if ( ptrSuite->iName.CompareF( token ) == 0 ) + { + // this suite DDL is already loaded + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("warning Test suite %S already loaded not re-loaded"),&token ); + return; + } + } + + // create a new suitedll object to store info on loaded DLL + CSuiteDll * newRef = CSuiteDll::NewL( token ); + CleanupStack::PushL(newRef); + + // set default severity and logging system + newRef->iTestSuite->SetSeverity(iSeverity); + newRef->iTestSuite->SetLogSystem(pLogSystem); + + // add to data + iArrayLoadedSuiteDll->AppendL( newRef ); + CleanupStack::Pop(newRef); + } + +// unload all the loaded DLLS +void CParseLine::Unload(const TDesC& Text) +/** +This function implements the script Unload command +*/ + { + // use Tlex to decode the cmd line + TLex lex(Text); + + // start at the begining + TPtrC token=lex.NextToken(); + + + if (!lex.Eos()) + { + // step over the keyword + token.Set(lex.NextToken()); + TInt NoOfDlls = iArrayLoadedSuiteDll->Count(); + for ( TInt i=0; i < NoOfDlls; i++ ) + { + CSuiteDll * ptrSuite = iArrayLoadedSuiteDll->At(i); + + // check the names + if ( ptrSuite->iName.CompareF( token )==0 ) + { + if (NoOfDlls==1) + { + iArrayLoadedSuiteDll->ResetAndDestroy(); + } + else + { + // this suite DDL is to be unloaded. + iArrayLoadedSuiteDll->Delete(i); + iArrayLoadedSuiteDll->Compress(); + delete ptrSuite; + } + return; + } + } + } + else + { + if (iArrayLoadedSuiteDll) + { + // unload all the loaded DLLS and their records + iArrayLoadedSuiteDll->ResetAndDestroy(); + } + } + } + +void CParseLine::HeapMark(void) +/** +This function implements the script HeapMark command +*/ + { + __UHEAP_MARK; + } + + +void CParseLine::HeapCheck(void) +/** +This function implements the script HeapCheck command +*/ + { + __UHEAP_MARKEND; + } + +void CParseLine::RequestMark(void) +/** +This function implements the script RequestMark command +*/ + { + // get number of outstanding requetsts on thread before we run the test + iReqsAtStart = RThread().RequestCount(); + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Requests at the start %d "),iReqsAtStart); + } + + +void CParseLine::RequestCheck(void) +/** +This function implements the script RequestCheck command +*/ + { + // check the number of outstanding requests against recorded value + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Requests at the start %d now %d"), + iReqsAtStart, + RThread().RequestCount() ); + + if ( iReqsAtStart != RThread().RequestCount()) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Test failed on requests count")); + + // this result is only significant if every thing else has passed + if ( iTestVerdict == EPass ) + iTestVerdict = EFail; + + } + } + + +void CParseLine::HandlesMark(void) +/** +This function implements the script HandlesMark command +*/ + { + // get number of Handles *before* we start the program + RThread().HandleCount(iProcessHandleCountBefore, iThreadHandleCountBefore); + + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Process handles count %d thread handle count %d"), + iProcessHandleCountBefore, + iThreadHandleCountBefore ); + } + +void CParseLine::HandlesCheck(void) +/** +This function implements the script HandlesCheck command +*/ + { + TInt processHandleCountAfter; + TInt threadHandleCountAfter; + RThread().HandleCount(processHandleCountAfter, threadHandleCountAfter); + + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Process handles count %d thread handle count %d"), + processHandleCountAfter, + threadHandleCountAfter ); + + // check that we are closing all the threads + if(iThreadHandleCountBefore != threadHandleCountAfter) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Test failed on thread handle count")); + + // this result is only significant if every thing else has passed + if ( iTestVerdict == EPass ) + iTestVerdict = EFail; + } + + // check that we are closing all the handles + if(iProcessHandleCountBefore != processHandleCountAfter) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Test failed on Process handle count")); + + // this result is only significant if every thing else has passed + if ( iTestVerdict == EPass ) + iTestVerdict = EFail; + } + } + +CSuiteDll* CSuiteDll::NewL( const TDesC& aName ) + { + CSuiteDll* self = new(ELeave) CSuiteDll(aName); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +CSuiteDll::CSuiteDll( const TDesC& aName ) +/** +Constructor. +@param aName The name of the test suite DLL to be loaded (can contain file path) +*/ + { + // save the name + iName.Copy( aName ); + } + + +/** +Load a test suite dll and save the name and test +test suite pointers +*/ +void CSuiteDll::ConstructL() + { + // load DLL by name + TInt ret = iLibrary.Load(iName, KTxtDLLpath); + if ( ret != KErrNone ) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Test suite %S found but would not load"),&iName ); + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("check any other Dlls required by %S "),&iName ); + User::Leave(ret); + } + + // save the suite name dll without file path + TParse parse; + parse.Set(iName, NULL, NULL); + iName.Copy(parse.NameAndExt()); + + // get the interface pointer at ordinal 1 + TLibraryFunction entry=iLibrary.Lookup(1); + + // Call this interface pointer to create new CTestSuite + // If this call goes to the wrong function then the test + // suite does not have the correct function at ordinal 1 + // This is usually caused by an error in the def file + iTestSuite = (CTestSuite*) entry(); + + // Second-phase constructor for CTestSuite + TRAPD(error,iTestSuite->ConstructL() ); + + //-- set the suite name (internal variable) the same as suite name dll file name (without extention) + iTestSuite->OverrideSuiteName(parse.NameAndExt()); + + if (error) + { + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("Failed to contruct test suite")); + User::Leave(error); + } + + // set suite severity level + iTestSuite->SetSeverity(pLogSystem->Severity()); + + // get the version information + TPtrC Versiontxt = iTestSuite->GetVersion(); + + // add to log + pLogSystem->LogExtra(((TText8*)__FILE__), __LINE__, ESevrErr, _L("LOAD_SUITE %S version %S loaded ok"),&iName, &Versiontxt ); + } + + +CSuiteDll::~CSuiteDll() +/** +destructor Delete the TestSuiteObject in the loaded DLL and close +and unload the library +*/ + { + // delete the TestSuiteObject in the loaded DLL + if (iTestSuite) + { + delete iTestSuite; + } + + // close and unload the library + iLibrary.Close(); + } + +/** +* Find out if the suite name matches the suite dll name. +* +* @param aSuiteName suite name (without file extention) +* @return ETrue if the given suite name matches suite name dll file name. +*/ +TBool CSuiteDll::SuiteNameMatch(const TDesC& aSuiteName) const +{ + TParse parse; + + //-- iName contains suite dll name with file extention, strip the extention + parse.Set(iName, NULL, NULL); + + //-- using CompareF instead of FindF to avoid situation when "AAA" suite name can match "AAA123" + TBool bFound = (aSuiteName.CompareF(parse.Name()) ==0 ) ? ETrue : EFalse; + + return bFound; +} + + + + + + + + + + + + + + + + +