os/kernelhwsrv/userlibandfileserver/fileserver/runtests/runtests.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/runtests/runtests.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,790 @@
     1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// f32\runtests\runtests.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include <e32std.h>
    1.22 +#include <e32std_private.h>
    1.23 +#include <e32def_private.h>
    1.24 +#include <e32svr.h>
    1.25 +#include <e32ldr.h>
    1.26 +#include <hal.h>
    1.27 +#include "f32file.h"
    1.28 +#include "f32dbg.h"
    1.29 +#include "runtests.h"
    1.30 +#include <u32hal.h>
    1.31 +
    1.32 +#define __PANIC(r) Panic(__LINE__,r)
    1.33 +
    1.34 +//#define _RUN_FOREVER_
    1.35 +//#define _PANIC_ON_FAILURE_
    1.36 +
    1.37 +const TInt KDefaultTimeout=1200;		// 20 minutes
    1.38 +const TInt KBackgroundTimeout=3000000;	// 3 seconds
    1.39 +const TInt KDestroyTimeout=1000000;		// 1 second
    1.40 +
    1.41 +_LIT(KLitBackslash,"\\");
    1.42 +_LIT(KDebugMessage, "Testing finished, and the system will be panicked");
    1.43 +#ifdef __EPOC32__
    1.44 +_LIT(KLitDefaultTestPath,"Z:\\TEST");
    1.45 +#else
    1.46 +_LIT(KLitDefaultTestPath,"");
    1.47 +#endif
    1.48 +
    1.49 +#ifdef _DEBUG
    1.50 +_LIT(KBuildType, "UDEB");
    1.51 +#else
    1.52 +_LIT(KBuildType, "UREL");
    1.53 +#endif
    1.54 +
    1.55 +typedef RArray<TUint> RProcIdList;
    1.56 +
    1.57 +GLDEF_D TPath TheTestPath = KLitDefaultTestPath();
    1.58 +GLDEF_D RFs TheFs;
    1.59 +GLDEF_D RLoader TheLoaderSession;
    1.60 +GLDEF_D TDesC8* TheTestList;
    1.61 +GLDEF_D RTimer TheTimer;
    1.62 +GLDEF_D TBuf<256> TheProcessCommand=KNullDesC();
    1.63 +GLDEF_D TInt TheTimeOut = KDefaultTimeout;
    1.64 +GLDEF_D TInt TheCurrentProcessList;
    1.65 +GLDEF_D RProcIdList ProcLists[2];
    1.66 +GLDEF_D RTimer IdleWaitTimer;
    1.67 +GLDEF_D RTimer DestructionTimer;
    1.68 +GLDEF_D RProperty CurrTest;
    1.69 +TBool ShowTimings = 0;
    1.70 +TInt TickPeriod = 15625;
    1.71 +TBool CleanUpProcesses = EFalse;
    1.72 +
    1.73 +#ifdef _ENABLE_BTRACE_ANALYSIS_
    1.74 +
    1.75 +// BTrace analysis forward declarations
    1.76 +const TInt KDefaultBTraceLevel = 0;
    1.77 +TBool BtraceAnalysis = EFalse;
    1.78 +TInt BTraceAnalysisLevel;
    1.79 +TInt BTraceAnalyseSetup();
    1.80 +void BTraceAnalyseEnd();
    1.81 +void BTraceAnalyse(TInt aAnalysisLevel);
    1.82 +
    1.83 +#endif //_ENABLE_BTRACE_ANALYSIS_
    1.84 +
    1.85 +_LIT(KLitPanicCategory,"RUNTESTS-");
    1.86 +_LIT(KLitLogPreamble,"RUNTESTS: ");
    1.87 +
    1.88 +void LogMsg(TRefByValue<const TDesC> aFmt,...);
    1.89 +
    1.90 +void DisableSimulatedFailure()
    1.91 +	{
    1.92 +	// Turn off simulated failure mechanisms for all base servers
    1.93 +	TheFs.SetAllocFailure(KAllocFailureOff);	// F32 heap failure
    1.94 +	TheFs.SetErrorCondition(KErrNone, 0);		// F32 other failure
    1.95 +	TheLoaderSession.DebugFunction(ELoaderDebug_SetHeapFail, 0, 0, 0);	// Loader heap failure
    1.96 +	TheLoaderSession.DebugFunction(ELoaderDebug_SetRFsFail, KErrNone, 0, 0);	// Loader RFs failure
    1.97 +
    1.98 +	// make sure kernel heap debug is off
    1.99 +	__KHEAP_TOTAL_RESET;
   1.100 +	}
   1.101 +
   1.102 +GLDEF_C void Panic(TInt aLine, TInt aReason)
   1.103 +	{
   1.104 +	TBuf<16> cat=KLitPanicCategory();
   1.105 +	cat.AppendNum(aLine);
   1.106 +	User::Panic(cat,aReason);
   1.107 +	}
   1.108 +
   1.109 +TInt CloseAndWait(RHandleBase aH, TRequestStatus *aN = NULL)
   1.110 +	{
   1.111 +	TRequestStatus tempS;
   1.112 +	if(!aN)
   1.113 +		{
   1.114 +		// Create a destruction notifier if none was supplied.
   1.115 +		aH.NotifyDestruction(tempS);
   1.116 +		aN = &tempS;
   1.117 +		}
   1.118 +	if (*aN!=KRequestPending)
   1.119 +		{
   1.120 +		User::WaitForRequest(*aN);
   1.121 +		aH.Close();
   1.122 +		return KErrNoMemory;
   1.123 +		}
   1.124 +	TRequestStatus t;
   1.125 +	DestructionTimer.After(t, KDestroyTimeout);
   1.126 +	aH.Close();
   1.127 +	User::WaitForRequest(*aN, t);
   1.128 +	if (*aN != KRequestPending)
   1.129 +		{
   1.130 +		DestructionTimer.Cancel();
   1.131 +		User::WaitForRequest(t);
   1.132 +		return KErrNone;
   1.133 +		}
   1.134 +	User::CancelMiscNotifier(*aN);
   1.135 +	User::WaitForRequest(*aN);
   1.136 +	return KErrTimedOut;
   1.137 +	}
   1.138 +
   1.139 +void CloseWaitAndWarn(RHandleBase aH, TRequestStatus *aN = NULL)
   1.140 +	{
   1.141 +	TFullName fn(aH.FullName());
   1.142 +	TInt r = CloseAndWait(aH, aN);
   1.143 +	if (r == KErrNoMemory)
   1.144 +		LogMsg(_L("WARNING OOM checking destruction of %S"), &fn);
   1.145 +	else if (r == KErrTimedOut)
   1.146 +		LogMsg(_L("ERROR Destruction of %S timed out"), &fn);
   1.147 +	}
   1.148 +
   1.149 +TInt InitIdleWait()
   1.150 +	{
   1.151 +	TInt r = IdleWaitTimer.CreateLocal();
   1.152 +	if (r!=KErrNone)
   1.153 +		return r;
   1.154 +	return KErrNone;
   1.155 +	}
   1.156 +
   1.157 +void WaitForIdle()
   1.158 +	{
   1.159 +	TRequestStatus idle_req;
   1.160 +	TRequestStatus timer_req;
   1.161 +	IdleWaitTimer.After(timer_req, KBackgroundTimeout);
   1.162 +	User::NotifyOnIdle(idle_req);
   1.163 +	User::WaitForRequest(idle_req, timer_req);
   1.164 +	if (idle_req != KRequestPending)
   1.165 +		{
   1.166 +		IdleWaitTimer.Cancel();
   1.167 +		User::WaitForRequest(timer_req);
   1.168 +		}
   1.169 +	else
   1.170 +		{
   1.171 +		User::CancelMiscNotifier(idle_req);
   1.172 +		User::WaitForRequest(idle_req);
   1.173 +		LogMsg(_L("WARNING Excessive Background Activity Detected"));
   1.174 +		}
   1.175 +	}
   1.176 +
   1.177 +TBool IntentionallyPersistent(RProcess aProcess)
   1.178 +	{
   1.179 +	TInt v;
   1.180 +	TInt r = RProperty::Get(aProcess.SecureId(), KRuntestsIntentionalPersistenceKey, v);
   1.181 +	if (r==KErrNone && TUint(v)==KRuntestsIntentionalPersistenceValue)
   1.182 +		return ETrue;
   1.183 +	return EFalse;
   1.184 +	}
   1.185 +
   1.186 +TInt GetProcessListThread(TAny* a)
   1.187 +	{
   1.188 +	RProcIdList& pl = *(RProcIdList*)a;
   1.189 +	TFindProcess fp(_L("*"));
   1.190 +	TFullName fn;
   1.191 +	TInt r = KErrNone;
   1.192 +	while (r==KErrNone && fp.Next(fn)==KErrNone)
   1.193 +		{
   1.194 +		RProcess p;
   1.195 +		r = p.Open(fp, EOwnerThread);
   1.196 +		if (r==KErrNone)
   1.197 +			{
   1.198 +			TUint id = (TUint)p.Id();
   1.199 +			r = pl.Append(id);
   1.200 +			p.Close();
   1.201 +			}
   1.202 +		}
   1.203 +	return r;
   1.204 +	}
   1.205 +
   1.206 +TInt GetProcessList(RProcIdList& aList)
   1.207 +	{
   1.208 +	aList.Reset();
   1.209 +	RThread t;
   1.210 +	TRequestStatus s;
   1.211 +	TInt r = t.Create(KNullDesC, &GetProcessListThread, 0x1000, NULL, &aList);
   1.212 +	if (r==KErrNone)
   1.213 +		{
   1.214 +		t.Logon(s);
   1.215 +		t.SetPriority(EPriorityAbsoluteHigh);
   1.216 +		if (s==KRequestPending)
   1.217 +			t.Resume();
   1.218 +		User::WaitForRequest(s);
   1.219 +		r=s.Int();
   1.220 +		if (t.ExitType()==EExitPending)
   1.221 +			{
   1.222 +			t.Kill(0);
   1.223 +			WaitForIdle();
   1.224 +			}
   1.225 +		else if (t.ExitType()!=EExitKill)
   1.226 +			{
   1.227 +			r = -99;
   1.228 +			}
   1.229 +		CloseWaitAndWarn(t);
   1.230 +		}
   1.231 +	aList.Sort();
   1.232 +	return r;
   1.233 +	}
   1.234 +
   1.235 +TBool ParseNumber(TLex& aLex, TUint& aNumber, TBool isTime)
   1.236 +	{
   1.237 +	TPtrC numberDes = aLex.NextToken();
   1.238 +	TInt len = numberDes.Length();
   1.239 +	if (len == 0)
   1.240 +		{
   1.241 +		return EFalse;
   1.242 +		}
   1.243 +
   1.244 +	aNumber = 0;
   1.245 +	TInt magnitude = 1;
   1.246 +	TChar c = numberDes[len-1];
   1.247 +	if (isTime)
   1.248 +		{
   1.249 +		switch (c)
   1.250 +			{
   1.251 +			case 'h':
   1.252 +			case 'H':
   1.253 +				len -= 1;
   1.254 +				magnitude = 3600;
   1.255 +				break;
   1.256 +
   1.257 +			case 'm':
   1.258 +			case 'M':
   1.259 +				len -= 1;
   1.260 +				/*FALLTHRU*/
   1.261 +			default:
   1.262 +				magnitude = 60;
   1.263 +				break;
   1.264 +
   1.265 +			case 's':
   1.266 +			case 'S':
   1.267 +				len -= 1;
   1.268 +				magnitude = 1;
   1.269 +				break;
   1.270 +			}
   1.271 +		}
   1.272 +
   1.273 +	for (TInt i = len-1; i >= 0; --i)
   1.274 +		{
   1.275 +		c = numberDes[i];
   1.276 +		if (c < '0' || c > '9')
   1.277 +			__PANIC(KErrArgument);
   1.278 +		aNumber += ((TInt)c-'0')*magnitude;
   1.279 +		magnitude *= 10;
   1.280 +		}
   1.281 +
   1.282 +	return ETrue;
   1.283 +	}
   1.284 +
   1.285 +void GetTimeOut(TLex& aLex)
   1.286 +//
   1.287 +//
   1.288 +//
   1.289 +	{
   1.290 +	TheTimeOut = KDefaultTimeout;
   1.291 +	TUint timeOut = 0;
   1.292 +	if (ParseNumber(aLex, timeOut, ETrue))
   1.293 +		{
   1.294 +		TheTimeOut = timeOut;
   1.295 +		}
   1.296 +	}
   1.297 +
   1.298 +#ifdef _ENABLE_BTRACE_ANALYSIS_
   1.299 +
   1.300 +void GetAnalysisLevel(TLex& aLex)
   1.301 +	{
   1.302 +	BTraceAnalysisLevel = KDefaultBTraceLevel;
   1.303 +	TUint level;
   1.304 +	if (ParseNumber(aLex, level, EFalse))
   1.305 +		{
   1.306 +		BTraceAnalysisLevel = level;
   1.307 +		}
   1.308 +	}
   1.309 +#endif //_ENABLE_BTRACE_ANALYSIS_
   1.310 +
   1.311 +void LogMsg(TRefByValue<const TDesC> aFmt,...)
   1.312 +	{
   1.313 +	VA_LIST list;
   1.314 +	VA_START(list,aFmt);
   1.315 +	TBuf<0x100> buf=KLitLogPreamble();
   1.316 +	buf.AppendFormatList(aFmt,list);
   1.317 +	RDebug::Print(_L("%S"),&buf);
   1.318 +	}
   1.319 +
   1.320 +_LIT(KLitError, "Error ");
   1.321 +TBool LogProcess(TUint aId, TBool aInit)
   1.322 +	{
   1.323 +	TFullName pn;
   1.324 +	TFileName fn;
   1.325 +	RProcess p;
   1.326 +	TBool killed = EFalse;
   1.327 +	TInt r = p.Open(TProcessId(aId));
   1.328 +	if (r==KErrNone)
   1.329 +		{
   1.330 +		if (IntentionallyPersistent(p))
   1.331 +			{
   1.332 +			p.Close();
   1.333 +			return killed;
   1.334 +			}
   1.335 +		pn = p.FullName();
   1.336 +		fn = p.FileName();
   1.337 +		if (!aInit && CleanUpProcesses && p.ExitType()==EExitPending)
   1.338 +			{// p is a left over process so terminate it.
   1.339 +			killed = ETrue;
   1.340 +			TRequestStatus status;
   1.341 +			p.Logon(status);
   1.342 +			p.Kill(KErrNone);	// Kill with KErrNone to suppress extra debug output from kernel.
   1.343 +			User::WaitForRequest(status);
   1.344 +			CloseAndWait(p);
   1.345 +			}
   1.346 +		else
   1.347 +			{
   1.348 +			p.Close();
   1.349 +			}
   1.350 +		}
   1.351 +	else
   1.352 +		{
   1.353 +		pn = KLitError;
   1.354 +		pn.AppendNum(r);
   1.355 +		}
   1.356 +	if (aInit)
   1.357 +		LogMsg(_L("Running process id=%d: %S (%S)"),aId,&pn,&fn);
   1.358 +	else
   1.359 +		{
   1.360 +		if(killed)
   1.361 +			LogMsg(_L("ERROR Leftover process was killed id=%d: %S (%S)"),aId,&pn,&fn);
   1.362 +		else
   1.363 +			LogMsg(_L("ERROR Leftover process id=%d: %S (%S)"),aId,&pn,&fn);
   1.364 +		}
   1.365 +	return killed;
   1.366 +	}
   1.367 +
   1.368 +void ListProcesses()
   1.369 +	{
   1.370 +	RProcIdList& cur_list = ProcLists[TheCurrentProcessList];
   1.371 +	TInt cc = cur_list.Count();
   1.372 +	TInt ci;
   1.373 +	for (ci=0; ci<cc; ++ci)
   1.374 +		{
   1.375 +		LogProcess(cur_list[ci], ETrue);
   1.376 +		}
   1.377 +	}
   1.378 +
   1.379 +void CheckProcesses()
   1.380 +	{
   1.381 +	RProcIdList& cur_list = ProcLists[TheCurrentProcessList];
   1.382 +	RProcIdList& new_list = ProcLists[1-TheCurrentProcessList];
   1.383 +	TInt r = GetProcessList(new_list);
   1.384 +	if (r!=KErrNone)
   1.385 +		{
   1.386 +		LogMsg(_L("WARNING Problem getting process list, error %d"),r);
   1.387 +		return;
   1.388 +		}
   1.389 +
   1.390 +	TInt cc = cur_list.Count();
   1.391 +	TInt nc = new_list.Count();
   1.392 +	TInt ci = 0;
   1.393 +	TInt ni = 0;
   1.394 +	while (ci<cc || ni<nc)
   1.395 +		{
   1.396 +		TUint id1=0;
   1.397 +		TUint id2=0;
   1.398 +		if (ci<cc)
   1.399 +			id1 = cur_list[ci];
   1.400 +		if (ni<nc)
   1.401 +			id2 = new_list[ni];
   1.402 +		if (ci==cc)
   1.403 +			{
   1.404 +			// extra process has appeared so kill it and output an error message.
   1.405 +			if (LogProcess(id2, EFalse))
   1.406 +				{// Remove from list as we don't want it to be considered as vanished when the next test completes.
   1.407 +				new_list.Remove(ni);
   1.408 +				nc--;
   1.409 +				}
   1.410 +			else
   1.411 +				{// Extra process was left running so just move onto the next one.
   1.412 +				ni++;
   1.413 +				}
   1.414 +			}
   1.415 +		else if (ni<nc && id1==id2)
   1.416 +			{
   1.417 +			// process remains
   1.418 +			++ci, ++ni;
   1.419 +			}
   1.420 +		else
   1.421 +			{
   1.422 +			// process has disappeared
   1.423 +			LogMsg(_L("WARNING Vanished process, id=%d"),id1);
   1.424 +			++ci;
   1.425 +			}
   1.426 +		}
   1.427 +
   1.428 +	// current list = new list
   1.429 +	TheCurrentProcessList = 1 - TheCurrentProcessList;
   1.430 +
   1.431 +	// throw away the old list
   1.432 +	cur_list.Reset();
   1.433 +	}
   1.434 +
   1.435 +_LIT8 (KLitRemark,"REM");
   1.436 +_LIT8 (KLitAtRemark,"@REM");
   1.437 +
   1.438 +void ProcessLine(const TDesC8& aLine)
   1.439 +	{
   1.440 +	TLex8 lex(aLine);
   1.441 +	TPtrC8 testname=lex.NextToken();
   1.442 +	if (testname.Length()>=2 && testname[0]=='/' && testname[1]=='/')
   1.443 +		return;
   1.444 +	// ignore this line if it begins with rem or @rem 
   1.445 +	if (testname.CompareF(KLitRemark) == 0 || testname.CompareF(KLitAtRemark) == 0)
   1.446 +		return;
   1.447 +	TFileName testnameU;
   1.448 +	testnameU.Copy(testname);
   1.449 +	TFileName fullpathname;
   1.450 +	if (testnameU.Locate(TChar('\\'))==KErrNotFound)
   1.451 +		fullpathname=TheTestPath;
   1.452 +	fullpathname+=testnameU;
   1.453 +	if (testname.Locate(TChar('.'))==KErrNotFound)
   1.454 +		fullpathname+=_L(".EXE");
   1.455 +	TInt r;
   1.456 +
   1.457 +	RFile file;
   1.458 +	r=file.Open(TheFs,fullpathname,EFileRead);
   1.459 +	if (r!=KErrNone)
   1.460 +		{
   1.461 +		// Remove path to let loader locate exe
   1.462 +		fullpathname = fullpathname.Mid(fullpathname.LocateReverse('\\')+1);
   1.463 +		}
   1.464 +	else
   1.465 +		file.Close();
   1.466 +
   1.467 +	RProcess p;
   1.468 +	if(TheProcessCommand==KNullDesC)
   1.469 +		{
   1.470 +		TheProcessCommand.Copy(lex.Remainder());
   1.471 +		r=p.Create(fullpathname, TheProcessCommand);
   1.472 +		TheProcessCommand=KNullDesC();
   1.473 +		}
   1.474 +	else
   1.475 +		r=p.Create(fullpathname, TheProcessCommand);
   1.476 +	if (r!=KErrNone)
   1.477 +		{
   1.478 +		LogMsg(_L("Test %S ERROR Could not load file, error %d"),&fullpathname,r);
   1.479 +		return;
   1.480 +		}
   1.481 +	else
   1.482 +		{
   1.483 +		LogMsg(_L("Started test %S"),&fullpathname);
   1.484 +		}
   1.485 +	TRequestStatus ds;
   1.486 +	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)
   1.487 +	CurrTest.Set(p.FileName());
   1.488 +	User::After(100000);		// allow latency measurements to be output
   1.489 +	p.SetJustInTime(EFalse);	// we don't want the automatic test run to be halted by the debugger
   1.490 +	TRequestStatus ps;
   1.491 +	p.Rendezvous(ps);
   1.492 +	TInt time_remain = TheTimeOut;
   1.493 +	TRequestStatus ts;
   1.494 +	TUint start = User::TickCount();
   1.495 +	p.Resume();
   1.496 +	TBool persist = EFalse;
   1.497 +	TBool timer_running = EFalse;
   1.498 +	FOREVER
   1.499 +		{
   1.500 +		TInt nsec = Min(time_remain, 1800);
   1.501 +		if (!timer_running)
   1.502 +			TheTimer.After(ts, nsec*1000000);
   1.503 +		timer_running = ETrue;
   1.504 +		User::WaitForRequest(ps,ts);
   1.505 +		if (ps!=KRequestPending)
   1.506 +			{
   1.507 +			if (p.ExitType()==EExitPending)
   1.508 +				{
   1.509 +				// rendezvous completed but process not terminated
   1.510 +				if (!IntentionallyPersistent(p))
   1.511 +					{
   1.512 +					// not persistent - wait for process to terminate
   1.513 +					p.Logon(ps);
   1.514 +					continue;
   1.515 +					}
   1.516 +				persist = ETrue;
   1.517 +				}
   1.518 +			break;
   1.519 +			}
   1.520 +		timer_running = EFalse;
   1.521 +		time_remain -= nsec;
   1.522 +		if (time_remain==0)
   1.523 +			{
   1.524 +			LogMsg(_L("Going to kill test %S: it's taken %u seconds, which is too long"),&fullpathname,TheTimeOut);
   1.525 +			p.Kill(0);
   1.526 +			User::WaitForRequest(ps);
   1.527 +			p.Logon(ps);
   1.528 +			User::WaitForRequest(ps);
   1.529 +
   1.530 +			CloseWaitAndWarn(p, &ds);
   1.531 +			RDebug::Print(_L("\n"));
   1.532 +			LogMsg(_L("Test %S TIMEOUT"),&fullpathname);
   1.533 +			return;
   1.534 +			}
   1.535 +		else
   1.536 +			{
   1.537 +			LogMsg(_L("Taken %u seconds so far"),TheTimeOut-time_remain);
   1.538 +			}
   1.539 +		}
   1.540 +	TUint end = User::TickCount();
   1.541 +	if(timer_running)
   1.542 +		{
   1.543 +		TheTimer.Cancel();
   1.544 +		User::WaitForRequest(ts);
   1.545 +		}
   1.546 +
   1.547 +#ifdef _ENABLE_BTRACE_ANALYSIS_
   1.548 +	//
   1.549 +	//
   1.550 +	//
   1.551 +	if (BtraceAnalysis)
   1.552 +		{// Analyse BTrace buffer
   1.553 +		BTraceAnalyse(BTraceAnalysisLevel);
   1.554 +		}
   1.555 +#endif //_ENABLE_BTRACE_ANALYSIS_
   1.556 +
   1.557 +	TBuf<32> exitCat=p.ExitCategory();
   1.558 +	TExitType exitType=p.ExitType();
   1.559 +	TInt exitReason=p.ExitReason();
   1.560 +	if (persist || (exitType==EExitKill && exitReason==KErrNone))
   1.561 +		{
   1.562 +		TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
   1.563 +		if(ShowTimings)
   1.564 +			{
   1.565 +			LogMsg(_L("Test %S OK - Seconds Taken: %u"),&fullpathname, time);
   1.566 +			}
   1.567 +		else
   1.568 +			{
   1.569 +			LogMsg(_L("Test %S OK"),&fullpathname);
   1.570 +			}
   1.571 +		if (persist)
   1.572 +			{
   1.573 +			// We do not need this destruction notifier so cancel it.
   1.574 +			User::CancelMiscNotifier(ds);
   1.575 +			User::WaitForRequest(ds);
   1.576 +			
   1.577 +			p.Close();
   1.578 +			}
   1.579 +		else
   1.580 +			{
   1.581 +			CloseWaitAndWarn(p, &ds);
   1.582 +			}
   1.583 +		return;
   1.584 +		}
   1.585 +	LogMsg(_L("Test %S FAIL - Exit code %d,%d,%S"),&fullpathname,exitType,exitReason,&exitCat);
   1.586 +	CloseWaitAndWarn(p, &ds);
   1.587 +#if defined(_PANIC_ON_FAILURE_)
   1.588 +	__PANIC(KErrGeneral);
   1.589 +#endif
   1.590 +	}
   1.591 +
   1.592 +void ProcessTestList()
   1.593 +	{
   1.594 +	TUint start = User::TickCount();
   1.595 +
   1.596 +	TLex8 llex(*TheTestList);
   1.597 +	while(!llex.Eos())
   1.598 +		{
   1.599 +		llex.SkipSpace();
   1.600 +		llex.Mark();
   1.601 +		while(!llex.Eos() && llex.Peek()!='\n' && llex.Peek()!='\r')
   1.602 +			llex.Inc();
   1.603 +		TPtrC8 line=llex.MarkedToken();
   1.604 +		if (line.Length()!=0)
   1.605 +			ProcessLine(line);
   1.606 +
   1.607 +		// allow cleanup to complete before starting the next test
   1.608 +		WaitForIdle();
   1.609 +
   1.610 +		// make sure simulated failure is off
   1.611 +		DisableSimulatedFailure();
   1.612 +
   1.613 +		// check for leftover processes
   1.614 +		CheckProcesses();
   1.615 +		
   1.616 +		// Reset the demand paging cache to its default size.
   1.617 +		UserSvr::HalFunction(EHalGroupVM,EVMHalSetCacheSize, 0, 0);
   1.618 +		}
   1.619 +
   1.620 +	TUint end = User::TickCount();
   1.621 +	TUint time = TUint((TUint64)(end-start)*(TUint64)TickPeriod/(TUint64)1000000);
   1.622 +	LogMsg(_L("Elapsed Seconds: %u"), time);
   1.623 +	}
   1.624 +
   1.625 +void Help()
   1.626 +	{
   1.627 +	RDebug::Print(_L("Runtests test list [-x where tests are] [-d drive letter to test] [-t timeout] [-p] [-st] [-c]"));
   1.628 +	RDebug::Print(_L("where -p sets runtests to be system permanent, -st enables timing information,"));
   1.629 +	RDebug::Print(_L("-c enables left over processes to be cleaned up"));
   1.630 +	}
   1.631 +
   1.632 +GLDEF_C TInt E32Main()
   1.633 +	{
   1.634 +	HAL::Get(HAL::ESystemTickPeriod, TickPeriod);
   1.635 +	RThread().SetPriority(EPriorityAbsoluteHigh);
   1.636 +	TBuf<0x100> cmd;
   1.637 +	User::CommandLine(cmd);
   1.638 +	TFileName thisfile=RProcess().FileName();
   1.639 +	TLex lex(cmd);
   1.640 +	TPtrC token=lex.NextToken();
   1.641 +	if (token.MatchF(thisfile)==0)
   1.642 +		{
   1.643 +		token.Set(lex.NextToken());
   1.644 +		}
   1.645 +	if (token.Length()==0)
   1.646 +		{//	__PANIC(0);
   1.647 +		Help();
   1.648 +		return 0;
   1.649 +		}
   1.650 +	TFileName listfilename=token;
   1.651 +	while (!lex.Eos())
   1.652 +		{
   1.653 +		token.Set(lex.NextToken());
   1.654 +		if (token.Length()==0)
   1.655 +			break;	// ignore trailing whitespace
   1.656 +		else if (token==_L("-x"))
   1.657 +			{
   1.658 +			token.Set(lex.NextToken());
   1.659 +			TheTestPath = token;
   1.660 +			}
   1.661 +		else if (token==_L("-d"))
   1.662 +			{
   1.663 +			token.Set(lex.NextToken());
   1.664 +			TheProcessCommand = token;
   1.665 +			}
   1.666 +		else if (token==_L("-t"))
   1.667 +			{
   1.668 +			GetTimeOut(lex);
   1.669 +			}
   1.670 +		else if (token==_L("-p"))
   1.671 +			{
   1.672 +			User::SetCritical(User::ESystemPermanent);
   1.673 +			}
   1.674 +		else if (token==_L("-st"))
   1.675 +			ShowTimings = 1;
   1.676 +		
   1.677 +#ifdef _ENABLE_BTRACE_ANALYSIS_		
   1.678 +		else if (token == _L("-a"))
   1.679 +			{
   1.680 +			BtraceAnalysis = ETrue;
   1.681 +			GetAnalysisLevel(lex);
   1.682 +			TInt r = BTraceAnalyseSetup();
   1.683 +			if (r != KErrNone)
   1.684 +				{
   1.685 +				RDebug::Print(_L("ERROR - Couldn't open BTrace driver (Code %d)"), r);
   1.686 +				return 0;
   1.687 +				}
   1.688 +			}
   1.689 +#endif //_ENABLE_BTRACE_ANALYSIS_
   1.690 +
   1.691 +		else if (token == _L("-c"))
   1.692 +			CleanUpProcesses = ETrue;
   1.693 +		else
   1.694 +			{
   1.695 +			RDebug::Print(_L("Unknown option %S"), &token);
   1.696 +			Help();
   1.697 +			return 0;
   1.698 +			}
   1.699 +		}
   1.700 +		
   1.701 +	RDebug::Print(_L("TPTT= %S \n"), &TheProcessCommand);											
   1.702 +	RDebug::Print(_L("TTL= %S \n"), &listfilename);
   1.703 +	RDebug::Print(_L("TTP= %S \n"), &TheTestPath);
   1.704 +	RDebug::Print(_L("TO= %d seconds\n"), TheTimeOut);
   1.705 +
   1.706 +	TInt l=TheTestPath.Length();
   1.707 +	if (l > 0 && TheTestPath[l-1]!='\\')
   1.708 +		TheTestPath+=KLitBackslash;
   1.709 +	if (listfilename.Locate(TChar('\\'))==KErrNotFound)
   1.710 +		listfilename.Insert(0,TheTestPath);
   1.711 +	TInt r=TheFs.Connect();
   1.712 +	if (r!=KErrNone)
   1.713 +		__PANIC(r);
   1.714 +	r = TheLoaderSession.Connect();
   1.715 +	if (r!=KErrNone)
   1.716 +		__PANIC(r);
   1.717 +	DisableSimulatedFailure();
   1.718 +	r=TheFs.SetSessionPath(_L("Z:\\test\\"));
   1.719 +	if (r!=KErrNone)
   1.720 +		__PANIC(r);
   1.721 +	r=TheTimer.CreateLocal();
   1.722 +	if (r!=KErrNone)
   1.723 +		__PANIC(r);
   1.724 +	RFile listfile;
   1.725 +	r=listfile.Open(TheFs,listfilename,EFileRead|EFileShareAny);
   1.726 +	if (r!=KErrNone)
   1.727 +		__PANIC(r);
   1.728 +	TInt listfilesize;
   1.729 +	r=listfile.Size(listfilesize);
   1.730 +	if (r!=KErrNone)
   1.731 +		__PANIC(r);
   1.732 +	HBufC8* pL=HBufC8::New(listfilesize);
   1.733 +	if (!pL)
   1.734 +		__PANIC(KErrNoMemory);
   1.735 +	TPtr8 ptr=pL->Des();
   1.736 +	TheTestList=pL;
   1.737 +	r=listfile.Read(ptr);
   1.738 +	if (r!=KErrNone)
   1.739 +		__PANIC(r);
   1.740 +	listfile.Close();
   1.741 +	LogMsg(_L("Running test script %S"),&listfilename);
   1.742 +	LogMsg(_L("Build %S"),&KBuildType);
   1.743 +	LogMsg(_L("Path to test %S"),&TheProcessCommand);
   1.744 +
   1.745 +	r = RProperty::Define(	KRuntestsCurrentTestKey,
   1.746 +							RProperty::EText,
   1.747 +							TSecurityPolicy(TSecurityPolicy::EAlwaysPass),
   1.748 +							TSecurityPolicy(RProcess().SecureId()),
   1.749 +							512
   1.750 +						);
   1.751 +	if (r!=KErrNone && r!=KErrAlreadyExists)
   1.752 +		__PANIC(r);
   1.753 +	r = CurrTest.Attach(RProcess().SecureId(), KRuntestsCurrentTestKey);
   1.754 +	if (r!=KErrNone)
   1.755 +		__PANIC(r);
   1.756 +	r = CurrTest.Set(KNullDesC);
   1.757 +	if (r!=KErrNone)
   1.758 +		__PANIC(r);
   1.759 +
   1.760 +	r = DestructionTimer.CreateLocal();
   1.761 +	if (r!=KErrNone)
   1.762 +		__PANIC(r);
   1.763 +	TheCurrentProcessList = 0;
   1.764 +	r = GetProcessList(ProcLists[0]);
   1.765 +	if (r!=KErrNone)
   1.766 +		__PANIC(r);
   1.767 +	ListProcesses();
   1.768 +	r = InitIdleWait();
   1.769 +	if (r!=KErrNone)
   1.770 +		__PANIC(r);
   1.771 +#if defined(_RUN_FOREVER_)
   1.772 +	FOREVER
   1.773 +#endif
   1.774 +	ProcessTestList();
   1.775 +	r = CurrTest.Set(KNullDesC);
   1.776 +	if (r!=KErrNone)
   1.777 +		__PANIC(r);
   1.778 +	CurrTest.Close();
   1.779 +	User::After(1000000);	// allow latency measurements to be output before exiting
   1.780 +	LogMsg(_L("Completed test script %S"),&listfilename);
   1.781 +	TheLoaderSession.Close();
   1.782 +	TheFs.Close();
   1.783 +	TheTimer.Close();
   1.784 +	IdleWaitTimer.Close();
   1.785 +	DestructionTimer.Close();
   1.786 +
   1.787 +#ifdef _ENABLE_BTRACE_ANALYSIS_
   1.788 +	BTraceAnalyseEnd();
   1.789 +#endif //_ENABLE_BTRACE_ANALYSIS_
   1.790 +	if(User::Critical()==User::ESystemPermanent)
   1.791 +		RDebug::Print(KDebugMessage);
   1.792 +	return KErrNone;
   1.793 +	}