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: // f32\runtests\runtests.cpp sl@0: // sl@0: // sl@0: sl@0: #include <e32std.h> sl@0: #include <e32std_private.h> sl@0: #include <e32def_private.h> sl@0: #include <e32svr.h> sl@0: #include <e32ldr.h> sl@0: #include <hal.h> sl@0: #include "f32file.h" sl@0: #include "f32dbg.h" sl@0: #include "runtests.h" sl@0: #include <u32hal.h> sl@0: sl@0: #define __PANIC(r) Panic(__LINE__,r) sl@0: sl@0: //#define _RUN_FOREVER_ sl@0: //#define _PANIC_ON_FAILURE_ sl@0: sl@0: const TInt KDefaultTimeout=1200; // 20 minutes sl@0: const TInt KBackgroundTimeout=3000000; // 3 seconds sl@0: const TInt KDestroyTimeout=1000000; // 1 second sl@0: sl@0: _LIT(KLitBackslash,"\\"); sl@0: _LIT(KDebugMessage, "Testing finished, and the system will be panicked"); sl@0: #ifdef __EPOC32__ sl@0: _LIT(KLitDefaultTestPath,"Z:\\TEST"); sl@0: #else sl@0: _LIT(KLitDefaultTestPath,""); sl@0: #endif sl@0: sl@0: #ifdef _DEBUG sl@0: _LIT(KBuildType, "UDEB"); sl@0: #else sl@0: _LIT(KBuildType, "UREL"); sl@0: #endif sl@0: sl@0: typedef RArray<TUint> RProcIdList; sl@0: sl@0: GLDEF_D TPath TheTestPath = KLitDefaultTestPath(); sl@0: GLDEF_D RFs TheFs; sl@0: GLDEF_D RLoader TheLoaderSession; sl@0: GLDEF_D TDesC8* TheTestList; sl@0: GLDEF_D RTimer TheTimer; sl@0: GLDEF_D TBuf<256> TheProcessCommand=KNullDesC(); sl@0: GLDEF_D TInt TheTimeOut = KDefaultTimeout; sl@0: GLDEF_D TInt TheCurrentProcessList; sl@0: GLDEF_D RProcIdList ProcLists[2]; sl@0: GLDEF_D RTimer IdleWaitTimer; sl@0: GLDEF_D RTimer DestructionTimer; sl@0: GLDEF_D RProperty CurrTest; sl@0: TBool ShowTimings = 0; sl@0: TInt TickPeriod = 15625; sl@0: TBool CleanUpProcesses = EFalse; sl@0: sl@0: #ifdef _ENABLE_BTRACE_ANALYSIS_ sl@0: sl@0: // BTrace analysis forward declarations sl@0: const TInt KDefaultBTraceLevel = 0; sl@0: TBool BtraceAnalysis = EFalse; sl@0: TInt BTraceAnalysisLevel; sl@0: TInt BTraceAnalyseSetup(); sl@0: void BTraceAnalyseEnd(); sl@0: void BTraceAnalyse(TInt aAnalysisLevel); sl@0: sl@0: #endif //_ENABLE_BTRACE_ANALYSIS_ sl@0: sl@0: _LIT(KLitPanicCategory,"RUNTESTS-"); sl@0: _LIT(KLitLogPreamble,"RUNTESTS: "); sl@0: sl@0: void LogMsg(TRefByValue<const TDesC> aFmt,...); sl@0: sl@0: void DisableSimulatedFailure() sl@0: { sl@0: // Turn off simulated failure mechanisms for all base servers sl@0: TheFs.SetAllocFailure(KAllocFailureOff); // F32 heap failure sl@0: TheFs.SetErrorCondition(KErrNone, 0); // F32 other failure sl@0: TheLoaderSession.DebugFunction(ELoaderDebug_SetHeapFail, 0, 0, 0); // Loader heap failure sl@0: TheLoaderSession.DebugFunction(ELoaderDebug_SetRFsFail, KErrNone, 0, 0); // Loader RFs failure sl@0: sl@0: // make sure kernel heap debug is off sl@0: __KHEAP_TOTAL_RESET; sl@0: } sl@0: sl@0: GLDEF_C void Panic(TInt aLine, TInt aReason) sl@0: { sl@0: TBuf<16> cat=KLitPanicCategory(); sl@0: cat.AppendNum(aLine); sl@0: User::Panic(cat,aReason); sl@0: } sl@0: sl@0: TInt CloseAndWait(RHandleBase aH, TRequestStatus *aN = NULL) sl@0: { sl@0: TRequestStatus tempS; sl@0: if(!aN) sl@0: { sl@0: // Create a destruction notifier if none was supplied. sl@0: aH.NotifyDestruction(tempS); sl@0: aN = &tempS; sl@0: } sl@0: if (*aN!=KRequestPending) sl@0: { sl@0: User::WaitForRequest(*aN); sl@0: aH.Close(); sl@0: return KErrNoMemory; sl@0: } sl@0: TRequestStatus t; sl@0: DestructionTimer.After(t, KDestroyTimeout); sl@0: aH.Close(); sl@0: User::WaitForRequest(*aN, t); sl@0: if (*aN != KRequestPending) sl@0: { sl@0: DestructionTimer.Cancel(); sl@0: User::WaitForRequest(t); sl@0: return KErrNone; sl@0: } sl@0: User::CancelMiscNotifier(*aN); sl@0: User::WaitForRequest(*aN); sl@0: return KErrTimedOut; sl@0: } sl@0: sl@0: void CloseWaitAndWarn(RHandleBase aH, TRequestStatus *aN = NULL) sl@0: { sl@0: TFullName fn(aH.FullName()); sl@0: TInt r = CloseAndWait(aH, aN); sl@0: if (r == KErrNoMemory) sl@0: LogMsg(_L("WARNING OOM checking destruction of %S"), &fn); sl@0: else if (r == KErrTimedOut) sl@0: LogMsg(_L("ERROR Destruction of %S timed out"), &fn); sl@0: } sl@0: sl@0: TInt InitIdleWait() sl@0: { sl@0: TInt r = IdleWaitTimer.CreateLocal(); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: return KErrNone; sl@0: } sl@0: sl@0: void WaitForIdle() sl@0: { sl@0: TRequestStatus idle_req; sl@0: TRequestStatus timer_req; sl@0: IdleWaitTimer.After(timer_req, KBackgroundTimeout); sl@0: User::NotifyOnIdle(idle_req); sl@0: User::WaitForRequest(idle_req, timer_req); sl@0: if (idle_req != KRequestPending) sl@0: { sl@0: IdleWaitTimer.Cancel(); sl@0: User::WaitForRequest(timer_req); sl@0: } sl@0: else sl@0: { sl@0: User::CancelMiscNotifier(idle_req); sl@0: User::WaitForRequest(idle_req); sl@0: LogMsg(_L("WARNING Excessive Background Activity Detected")); sl@0: } sl@0: } sl@0: sl@0: TBool IntentionallyPersistent(RProcess aProcess) sl@0: { sl@0: TInt v; sl@0: TInt r = RProperty::Get(aProcess.SecureId(), KRuntestsIntentionalPersistenceKey, v); sl@0: if (r==KErrNone && TUint(v)==KRuntestsIntentionalPersistenceValue) sl@0: return ETrue; sl@0: return EFalse; sl@0: } sl@0: sl@0: TInt GetProcessListThread(TAny* a) sl@0: { sl@0: RProcIdList& pl = *(RProcIdList*)a; sl@0: TFindProcess fp(_L("*")); sl@0: TFullName fn; sl@0: TInt r = KErrNone; sl@0: while (r==KErrNone && fp.Next(fn)==KErrNone) sl@0: { sl@0: RProcess p; sl@0: r = p.Open(fp, EOwnerThread); sl@0: if (r==KErrNone) sl@0: { sl@0: TUint id = (TUint)p.Id(); sl@0: r = pl.Append(id); sl@0: p.Close(); sl@0: } sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt GetProcessList(RProcIdList& aList) sl@0: { sl@0: aList.Reset(); sl@0: RThread t; sl@0: TRequestStatus s; sl@0: TInt r = t.Create(KNullDesC, &GetProcessListThread, 0x1000, NULL, &aList); sl@0: if (r==KErrNone) sl@0: { sl@0: t.Logon(s); sl@0: t.SetPriority(EPriorityAbsoluteHigh); sl@0: if (s==KRequestPending) sl@0: t.Resume(); sl@0: User::WaitForRequest(s); sl@0: r=s.Int(); sl@0: if (t.ExitType()==EExitPending) sl@0: { sl@0: t.Kill(0); sl@0: WaitForIdle(); sl@0: } sl@0: else if (t.ExitType()!=EExitKill) sl@0: { sl@0: r = -99; sl@0: } sl@0: CloseWaitAndWarn(t); sl@0: } sl@0: aList.Sort(); sl@0: return r; sl@0: } sl@0: sl@0: TBool ParseNumber(TLex& aLex, TUint& aNumber, TBool isTime) sl@0: { sl@0: TPtrC numberDes = aLex.NextToken(); sl@0: TInt len = numberDes.Length(); sl@0: if (len == 0) sl@0: { sl@0: return EFalse; sl@0: } sl@0: sl@0: aNumber = 0; sl@0: TInt magnitude = 1; sl@0: TChar c = numberDes[len-1]; sl@0: if (isTime) sl@0: { sl@0: switch (c) sl@0: { sl@0: case 'h': sl@0: case 'H': sl@0: len -= 1; sl@0: magnitude = 3600; sl@0: break; sl@0: sl@0: case 'm': sl@0: case 'M': sl@0: len -= 1; sl@0: /*FALLTHRU*/ sl@0: default: sl@0: magnitude = 60; sl@0: break; sl@0: sl@0: case 's': sl@0: case 'S': sl@0: len -= 1; sl@0: magnitude = 1; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: for (TInt i = len-1; i >= 0; --i) sl@0: { sl@0: c = numberDes[i]; sl@0: if (c < '0' || c > '9') sl@0: __PANIC(KErrArgument); sl@0: aNumber += ((TInt)c-'0')*magnitude; sl@0: magnitude *= 10; sl@0: } sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: void GetTimeOut(TLex& aLex) sl@0: // sl@0: // sl@0: // sl@0: { sl@0: TheTimeOut = KDefaultTimeout; sl@0: TUint timeOut = 0; sl@0: if (ParseNumber(aLex, timeOut, ETrue)) sl@0: { sl@0: TheTimeOut = timeOut; sl@0: } sl@0: } sl@0: sl@0: #ifdef _ENABLE_BTRACE_ANALYSIS_ sl@0: sl@0: void GetAnalysisLevel(TLex& aLex) sl@0: { sl@0: BTraceAnalysisLevel = KDefaultBTraceLevel; sl@0: TUint level; sl@0: if (ParseNumber(aLex, level, EFalse)) sl@0: { sl@0: BTraceAnalysisLevel = level; sl@0: } sl@0: } sl@0: #endif //_ENABLE_BTRACE_ANALYSIS_ sl@0: sl@0: void LogMsg(TRefByValue<const TDesC> aFmt,...) sl@0: { sl@0: VA_LIST list; sl@0: VA_START(list,aFmt); sl@0: TBuf<0x100> buf=KLitLogPreamble(); sl@0: buf.AppendFormatList(aFmt,list); sl@0: RDebug::Print(_L("%S"),&buf); sl@0: } sl@0: sl@0: _LIT(KLitError, "Error "); sl@0: TBool LogProcess(TUint aId, TBool aInit) sl@0: { sl@0: TFullName pn; sl@0: TFileName fn; sl@0: RProcess p; sl@0: TBool killed = EFalse; sl@0: TInt r = p.Open(TProcessId(aId)); sl@0: if (r==KErrNone) sl@0: { sl@0: if (IntentionallyPersistent(p)) sl@0: { sl@0: p.Close(); sl@0: return killed; sl@0: } sl@0: pn = p.FullName(); sl@0: fn = p.FileName(); sl@0: if (!aInit && CleanUpProcesses && p.ExitType()==EExitPending) sl@0: {// p is a left over process so terminate it. sl@0: killed = ETrue; sl@0: TRequestStatus status; sl@0: p.Logon(status); sl@0: p.Kill(KErrNone); // Kill with KErrNone to suppress extra debug output from kernel. sl@0: User::WaitForRequest(status); sl@0: CloseAndWait(p); sl@0: } sl@0: else sl@0: { sl@0: p.Close(); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: pn = KLitError; sl@0: pn.AppendNum(r); sl@0: } sl@0: if (aInit) sl@0: LogMsg(_L("Running process id=%d: %S (%S)"),aId,&pn,&fn); sl@0: else sl@0: { sl@0: if(killed) sl@0: LogMsg(_L("ERROR Leftover process was killed id=%d: %S (%S)"),aId,&pn,&fn); sl@0: else sl@0: LogMsg(_L("ERROR Leftover process id=%d: %S (%S)"),aId,&pn,&fn); sl@0: } sl@0: return killed; sl@0: } sl@0: sl@0: void ListProcesses() sl@0: { sl@0: RProcIdList& cur_list = ProcLists[TheCurrentProcessList]; sl@0: TInt cc = cur_list.Count(); sl@0: TInt ci; sl@0: for (ci=0; ci<cc; ++ci) sl@0: { sl@0: LogProcess(cur_list[ci], ETrue); sl@0: } sl@0: } sl@0: sl@0: void CheckProcesses() sl@0: { sl@0: RProcIdList& cur_list = ProcLists[TheCurrentProcessList]; sl@0: RProcIdList& new_list = ProcLists[1-TheCurrentProcessList]; sl@0: TInt r = GetProcessList(new_list); sl@0: if (r!=KErrNone) sl@0: { sl@0: LogMsg(_L("WARNING Problem getting process list, error %d"),r); sl@0: return; sl@0: } sl@0: sl@0: TInt cc = cur_list.Count(); sl@0: TInt nc = new_list.Count(); sl@0: TInt ci = 0; sl@0: TInt ni = 0; sl@0: while (ci<cc || ni<nc) sl@0: { sl@0: TUint id1=0; sl@0: TUint id2=0; sl@0: if (ci<cc) sl@0: id1 = cur_list[ci]; sl@0: if (ni<nc) sl@0: id2 = new_list[ni]; sl@0: if (ci==cc) sl@0: { sl@0: // extra process has appeared so kill it and output an error message. sl@0: if (LogProcess(id2, EFalse)) sl@0: {// Remove from list as we don't want it to be considered as vanished when the next test completes. sl@0: new_list.Remove(ni); sl@0: nc--; sl@0: } sl@0: else sl@0: {// Extra process was left running so just move onto the next one. sl@0: ni++; sl@0: } sl@0: } sl@0: else if (ni<nc && id1==id2) sl@0: { sl@0: // process remains sl@0: ++ci, ++ni; sl@0: } sl@0: else sl@0: { sl@0: // process has disappeared sl@0: LogMsg(_L("WARNING Vanished process, id=%d"),id1); sl@0: ++ci; sl@0: } sl@0: } sl@0: sl@0: // current list = new list sl@0: TheCurrentProcessList = 1 - TheCurrentProcessList; sl@0: sl@0: // throw away the old list sl@0: cur_list.Reset(); sl@0: } sl@0: sl@0: _LIT8 (KLitRemark,"REM"); sl@0: _LIT8 (KLitAtRemark,"@REM"); sl@0: sl@0: void ProcessLine(const TDesC8& aLine) sl@0: { sl@0: TLex8 lex(aLine); sl@0: TPtrC8 testname=lex.NextToken(); sl@0: if (testname.Length()>=2 && testname[0]=='/' && testname[1]=='/') sl@0: return; sl@0: // ignore this line if it begins with rem or @rem sl@0: if (testname.CompareF(KLitRemark) == 0 || testname.CompareF(KLitAtRemark) == 0) sl@0: return; sl@0: TFileName testnameU; sl@0: testnameU.Copy(testname); sl@0: TFileName fullpathname; sl@0: if (testnameU.Locate(TChar('\\'))==KErrNotFound) sl@0: fullpathname=TheTestPath; sl@0: fullpathname+=testnameU; sl@0: if (testname.Locate(TChar('.'))==KErrNotFound) sl@0: fullpathname+=_L(".EXE"); sl@0: TInt r; sl@0: sl@0: RFile file; sl@0: r=file.Open(TheFs,fullpathname,EFileRead); sl@0: if (r!=KErrNone) sl@0: { sl@0: // Remove path to let loader locate exe sl@0: fullpathname = fullpathname.Mid(fullpathname.LocateReverse('\\')+1); sl@0: } sl@0: else sl@0: file.Close(); sl@0: sl@0: RProcess p; sl@0: if(TheProcessCommand==KNullDesC) sl@0: { sl@0: TheProcessCommand.Copy(lex.Remainder()); sl@0: r=p.Create(fullpathname, TheProcessCommand); sl@0: TheProcessCommand=KNullDesC(); sl@0: } sl@0: else sl@0: r=p.Create(fullpathname, TheProcessCommand); sl@0: if (r!=KErrNone) sl@0: { sl@0: LogMsg(_L("Test %S ERROR Could not load file, error %d"),&fullpathname,r); sl@0: return; sl@0: } sl@0: else sl@0: { sl@0: LogMsg(_L("Started test %S"),&fullpathname); sl@0: } sl@0: TRequestStatus ds; sl@0: p.NotifyDestruction(ds); // allocate the destruction notifier early so that it doesn't get flagged as a leak by kernel heap checking in e.g., efile (DEF133800) sl@0: CurrTest.Set(p.FileName()); sl@0: User::After(100000); // allow latency measurements to be output sl@0: p.SetJustInTime(EFalse); // we don't want the automatic test run to be halted by the debugger sl@0: TRequestStatus ps; sl@0: p.Rendezvous(ps); sl@0: TInt time_remain = TheTimeOut; sl@0: TRequestStatus ts; sl@0: TUint start = User::TickCount(); sl@0: p.Resume(); sl@0: TBool persist = EFalse; sl@0: TBool timer_running = EFalse; sl@0: FOREVER sl@0: { sl@0: TInt nsec = Min(time_remain, 1800); sl@0: if (!timer_running) sl@0: TheTimer.After(ts, nsec*1000000); sl@0: timer_running = ETrue; sl@0: User::WaitForRequest(ps,ts); sl@0: if (ps!=KRequestPending) sl@0: { sl@0: if (p.ExitType()==EExitPending) sl@0: { sl@0: // rendezvous completed but process not terminated sl@0: if (!IntentionallyPersistent(p)) sl@0: { sl@0: // not persistent - wait for process to terminate sl@0: p.Logon(ps); sl@0: continue; sl@0: } sl@0: persist = ETrue; sl@0: } sl@0: break; sl@0: } sl@0: timer_running = EFalse; sl@0: time_remain -= nsec; sl@0: if (time_remain==0) sl@0: { sl@0: LogMsg(_L("Going to kill test %S: it's taken %u seconds, which is too long"),&fullpathname,TheTimeOut); sl@0: p.Kill(0); sl@0: User::WaitForRequest(ps); sl@0: p.Logon(ps); sl@0: User::WaitForRequest(ps); sl@0: sl@0: CloseWaitAndWarn(p, &ds); sl@0: RDebug::Print(_L("\n")); sl@0: LogMsg(_L("Test %S TIMEOUT"),&fullpathname); sl@0: return; sl@0: } sl@0: else sl@0: { sl@0: LogMsg(_L("Taken %u seconds so far"),TheTimeOut-time_remain); sl@0: } sl@0: } sl@0: TUint end = User::TickCount(); sl@0: if(timer_running) sl@0: { sl@0: TheTimer.Cancel(); sl@0: User::WaitForRequest(ts); sl@0: } sl@0: sl@0: #ifdef _ENABLE_BTRACE_ANALYSIS_ sl@0: // sl@0: // sl@0: // sl@0: if (BtraceAnalysis) sl@0: {// Analyse BTrace buffer sl@0: BTraceAnalyse(BTraceAnalysisLevel); sl@0: } sl@0: #endif //_ENABLE_BTRACE_ANALYSIS_ sl@0: sl@0: TBuf<32> exitCat=p.ExitCategory(); sl@0: TExitType exitType=p.ExitType(); sl@0: TInt exitReason=p.ExitReason(); sl@0: if (persist || (exitType==EExitKill && exitReason==KErrNone)) sl@0: { sl@0: TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000); sl@0: if(ShowTimings) sl@0: { sl@0: LogMsg(_L("Test %S OK - Seconds Taken: %u"),&fullpathname, time); sl@0: } sl@0: else sl@0: { sl@0: LogMsg(_L("Test %S OK"),&fullpathname); sl@0: } sl@0: if (persist) sl@0: { sl@0: // We do not need this destruction notifier so cancel it. sl@0: User::CancelMiscNotifier(ds); sl@0: User::WaitForRequest(ds); sl@0: sl@0: p.Close(); sl@0: } sl@0: else sl@0: { sl@0: CloseWaitAndWarn(p, &ds); sl@0: } sl@0: return; sl@0: } sl@0: LogMsg(_L("Test %S FAIL - Exit code %d,%d,%S"),&fullpathname,exitType,exitReason,&exitCat); sl@0: CloseWaitAndWarn(p, &ds); sl@0: #if defined(_PANIC_ON_FAILURE_) sl@0: __PANIC(KErrGeneral); sl@0: #endif sl@0: } sl@0: sl@0: void ProcessTestList() sl@0: { sl@0: TUint start = User::TickCount(); sl@0: sl@0: TLex8 llex(*TheTestList); sl@0: while(!llex.Eos()) sl@0: { sl@0: llex.SkipSpace(); sl@0: llex.Mark(); sl@0: while(!llex.Eos() && llex.Peek()!='\n' && llex.Peek()!='\r') sl@0: llex.Inc(); sl@0: TPtrC8 line=llex.MarkedToken(); sl@0: if (line.Length()!=0) sl@0: ProcessLine(line); sl@0: sl@0: // allow cleanup to complete before starting the next test sl@0: WaitForIdle(); sl@0: sl@0: // make sure simulated failure is off sl@0: DisableSimulatedFailure(); sl@0: sl@0: // check for leftover processes sl@0: CheckProcesses(); sl@0: sl@0: // Reset the demand paging cache to its default size. sl@0: UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize, 0, 0); sl@0: } sl@0: sl@0: TUint end = User::TickCount(); sl@0: TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000); sl@0: LogMsg(_L("Elapsed Seconds: %u"), time); sl@0: } sl@0: sl@0: void Help() sl@0: { sl@0: RDebug::Print(_L("Runtests test list [-x where tests are] [-d drive letter to test] [-t timeout] [-p] [-st] [-c]")); sl@0: RDebug::Print(_L("where -p sets runtests to be system permanent, -st enables timing information,")); sl@0: RDebug::Print(_L("-c enables left over processes to be cleaned up")); sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: HAL::Get(HAL::ESystemTickPeriod, TickPeriod); sl@0: RThread().SetPriority(EPriorityAbsoluteHigh); sl@0: TBuf<0x100> cmd; sl@0: User::CommandLine(cmd); sl@0: TFileName thisfile=RProcess().FileName(); sl@0: TLex lex(cmd); sl@0: TPtrC token=lex.NextToken(); sl@0: if (token.MatchF(thisfile)==0) sl@0: { sl@0: token.Set(lex.NextToken()); sl@0: } sl@0: if (token.Length()==0) sl@0: {// __PANIC(0); sl@0: Help(); sl@0: return 0; sl@0: } sl@0: TFileName listfilename=token; sl@0: while (!lex.Eos()) sl@0: { sl@0: token.Set(lex.NextToken()); sl@0: if (token.Length()==0) sl@0: break; // ignore trailing whitespace sl@0: else if (token==_L("-x")) sl@0: { sl@0: token.Set(lex.NextToken()); sl@0: TheTestPath = token; sl@0: } sl@0: else if (token==_L("-d")) sl@0: { sl@0: token.Set(lex.NextToken()); sl@0: TheProcessCommand = token; sl@0: } sl@0: else if (token==_L("-t")) sl@0: { sl@0: GetTimeOut(lex); sl@0: } sl@0: else if (token==_L("-p")) sl@0: { sl@0: User::SetCritical(User::ESystemPermanent); sl@0: } sl@0: else if (token==_L("-st")) sl@0: ShowTimings = 1; sl@0: sl@0: #ifdef _ENABLE_BTRACE_ANALYSIS_ sl@0: else if (token == _L("-a")) sl@0: { sl@0: BtraceAnalysis = ETrue; sl@0: GetAnalysisLevel(lex); sl@0: TInt r = BTraceAnalyseSetup(); sl@0: if (r != KErrNone) sl@0: { sl@0: RDebug::Print(_L("ERROR - Couldn't open BTrace driver (Code %d)"), r); sl@0: return 0; sl@0: } sl@0: } sl@0: #endif //_ENABLE_BTRACE_ANALYSIS_ sl@0: sl@0: else if (token == _L("-c")) sl@0: CleanUpProcesses = ETrue; sl@0: else sl@0: { sl@0: RDebug::Print(_L("Unknown option %S"), &token); sl@0: Help(); sl@0: return 0; sl@0: } sl@0: } sl@0: sl@0: RDebug::Print(_L("TPTT= %S \n"), &TheProcessCommand); sl@0: RDebug::Print(_L("TTL= %S \n"), &listfilename); sl@0: RDebug::Print(_L("TTP= %S \n"), &TheTestPath); sl@0: RDebug::Print(_L("TO= %d seconds\n"), TheTimeOut); sl@0: sl@0: TInt l=TheTestPath.Length(); sl@0: if (l > 0 && TheTestPath[l-1]!='\\') sl@0: TheTestPath+=KLitBackslash; sl@0: if (listfilename.Locate(TChar('\\'))==KErrNotFound) sl@0: listfilename.Insert(0,TheTestPath); sl@0: TInt r=TheFs.Connect(); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: r = TheLoaderSession.Connect(); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: DisableSimulatedFailure(); sl@0: r=TheFs.SetSessionPath(_L("Z:\\test\\")); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: r=TheTimer.CreateLocal(); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: RFile listfile; sl@0: r=listfile.Open(TheFs,listfilename,EFileRead|EFileShareAny); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: TInt listfilesize; sl@0: r=listfile.Size(listfilesize); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: HBufC8* pL=HBufC8::New(listfilesize); sl@0: if (!pL) sl@0: __PANIC(KErrNoMemory); sl@0: TPtr8 ptr=pL->Des(); sl@0: TheTestList=pL; sl@0: r=listfile.Read(ptr); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: listfile.Close(); sl@0: LogMsg(_L("Running test script %S"),&listfilename); sl@0: LogMsg(_L("Build %S"),&KBuildType); sl@0: LogMsg(_L("Path to test %S"),&TheProcessCommand); sl@0: sl@0: r = RProperty::Define( KRuntestsCurrentTestKey, sl@0: RProperty::EText, sl@0: TSecurityPolicy(TSecurityPolicy::EAlwaysPass), sl@0: TSecurityPolicy(RProcess().SecureId()), sl@0: 512 sl@0: ); sl@0: if (r!=KErrNone && r!=KErrAlreadyExists) sl@0: __PANIC(r); sl@0: r = CurrTest.Attach(RProcess().SecureId(), KRuntestsCurrentTestKey); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: r = CurrTest.Set(KNullDesC); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: sl@0: r = DestructionTimer.CreateLocal(); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: TheCurrentProcessList = 0; sl@0: r = GetProcessList(ProcLists[0]); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: ListProcesses(); sl@0: r = InitIdleWait(); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: #if defined(_RUN_FOREVER_) sl@0: FOREVER sl@0: #endif sl@0: ProcessTestList(); sl@0: r = CurrTest.Set(KNullDesC); sl@0: if (r!=KErrNone) sl@0: __PANIC(r); sl@0: CurrTest.Close(); sl@0: User::After(1000000); // allow latency measurements to be output before exiting sl@0: LogMsg(_L("Completed test script %S"),&listfilename); sl@0: TheLoaderSession.Close(); sl@0: TheFs.Close(); sl@0: TheTimer.Close(); sl@0: IdleWaitTimer.Close(); sl@0: DestructionTimer.Close(); sl@0: sl@0: #ifdef _ENABLE_BTRACE_ANALYSIS_ sl@0: BTraceAnalyseEnd(); sl@0: #endif //_ENABLE_BTRACE_ANALYSIS_ sl@0: if(User::Critical()==User::ESystemPermanent) sl@0: RDebug::Print(KDebugMessage); sl@0: return KErrNone; sl@0: }