os/kernelhwsrv/kerneltest/e32test/active/t_cact.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/active/t_cact.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,865 @@
     1.4 +// Copyright (c) 1995-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 +// e32test\active\t_cact.cpp
    1.18 +// Overview:
    1.19 +// Test the CActiveScheduler class, including scheduling priority, thread 
    1.20 +// panics and cancelling objects attached to the scheduler. 
    1.21 +// API Information:
    1.22 +// CActiveScheduler 
    1.23 +// Details:
    1.24 +// - Verify the thread is panicked when one of the following programming errors occurs:
    1.25 +// - start an uninstalled scheduler
    1.26 +// - install a scheduler twice
    1.27 +// - stop the scheduler twice 
    1.28 +// - stop an uninstalled scheduler
    1.29 +// - set active an active object twice
    1.30 +// - add an active object to an uninstalled scheduler
    1.31 +// - add a NULL pointer to the scheduler
    1.32 +// - add an active object twice
    1.33 +// - thread gets a stray signal
    1.34 +// - make request on an un-added active object
    1.35 +// - Create timers with different priorities
    1.36 +// - Check the timers are scheduled according to expiration time
    1.37 +// - Check the timers are scheduled in order of their priority when they expire at the
    1.38 +// same time
    1.39 +// - Check the timers are scheduled in order of the addition to the scheduler when
    1.40 +// they expire at the same time and they have the same priority
    1.41 +// - Verify that a leave in RunL method not handled by the active object calls the active 
    1.42 +// scheduler's Error method
    1.43 +// - Test a cancelled timer will not be scheduled 
    1.44 +// - Create a thread with its own heap and test that timers are scheduled in the order of
    1.45 +// their expiration time, priority and order of addition to the scheduler
    1.46 +// - Check the heap is not corrupted by all the tests
    1.47 +// Platforms/Drives/Compatibility:
    1.48 +// All
    1.49 +// Assumptions/Requirement/Pre-requisites:
    1.50 +// Failures and causes:
    1.51 +// Base Port information:
    1.52 +// 
    1.53 +//
    1.54 +
    1.55 +#include <e32test.h>
    1.56 +#include <e32panic.h>
    1.57 +
    1.58 +const TInt KmyErrorNum=999;
    1.59 +const TInt KLeaveCode=1234;  
    1.60 +const TInt KgTimerID=4321;
    1.61 +const TInt KCancelCode=1111;
    1.62 +const TInt KTestArraySize=10;
    1.63 +const TInt KPanicThreadRet=2222;
    1.64 +const TInt KHeapSize=0x2000;
    1.65 +
    1.66 +enum TActivePriority {eLowest=-100,eLow=-1,eNone=0,eHigh=1,eHighest=100};
    1.67 +enum TDirective {EStartUninstalled,EInstallTwice,EStopTwice,EStopUninstalled,ESetActiveTwice,
    1.68 +				 EAddToUninstalled,EAddNull,EAddTwice,ECreateStray,ERequestUnadded,EStraySignalNoKRequestPending,EStraySignalNoSetActive,ENormal};
    1.69 +
    1.70 +class TSecdulerTester
    1.71 +	{
    1.72 +public:
    1.73 +	void Test1();
    1.74 +	void Test2();
    1.75 +	void Test3();
    1.76 +	void Test4();
    1.77 +	};
    1.78 +
    1.79 +class MyManager : public CActiveScheduler
    1.80 +	{
    1.81 +public:
    1.82 +	virtual void Error(TInt anError) const {CActiveScheduler::Halt(anError);}
    1.83 +	};
    1.84 +
    1.85 +class myTimer : public CTimer
    1.86 +	{
    1.87 +public:
    1.88 +	myTimer(const TInt aPriority, const TInt anIdentifier):CTimer(aPriority){iIdentifier=anIdentifier;}
    1.89 +	virtual void RunL();
    1.90 +	void Start();		  
    1.91 +	void Setactive() {SetActive();}
    1.92 +	static void SetNum(const TInt aNum) {iNum=aNum; iCount=0;}
    1.93 +private:   
    1.94 +	TInt iIdentifier;
    1.95 +	static TInt iCount;
    1.96 +	static TInt iNum;
    1.97 +	};
    1.98 +
    1.99 +class myThreadTimer : public CTimer
   1.100 +	{
   1.101 +public:
   1.102 +	myThreadTimer(const TInt aPriority, const TInt anIdentifier):CTimer(aPriority){iIdentifier=anIdentifier;}
   1.103 +	virtual void RunL();
   1.104 +	static void SetNum(const TInt aNum) {iNum=aNum; iCount=0;}
   1.105 +	void Start();
   1.106 +private:
   1.107 +	TInt iIdentifier;
   1.108 +	static TInt iCount;
   1.109 +	static TInt iNum;
   1.110 +	};
   1.111 +
   1.112 +class CreateStray : public CActive
   1.113 +	{
   1.114 +public:
   1.115 +	CreateStray(TInt aPriority);
   1.116 +	void DoCancel() {}
   1.117 +	void RunL() {}
   1.118 +private:
   1.119 +	RTimer iTimer;
   1.120 +	};
   1.121 +
   1.122 +class myStray : public CActive
   1.123 +	{
   1.124 +public:
   1.125 +	myStray(TInt aPriority) : CActive(aPriority) {};
   1.126 +	void DoCancel() {}
   1.127 +	void RunL() { CActiveScheduler::Stop(); }
   1.128 +	void Start1();
   1.129 +	void Start2();
   1.130 +	};
   1.131 +
   1.132 +void myStray::Start1()
   1.133 +	{
   1.134 +	TRequestStatus* s=&iStatus;
   1.135 +	SetActive();
   1.136 +	RThread().RequestComplete(s,KErrNone);
   1.137 +	}
   1.138 +
   1.139 +void myStray::Start2()
   1.140 +	{
   1.141 +	TRequestStatus* s=&iStatus;
   1.142 +	iStatus=KRequestPending;
   1.143 +	User::RequestComplete(s,KErrNone);
   1.144 +	}
   1.145 +
   1.146 +TInt myTimer::iCount;
   1.147 +TInt myTimer::iNum;
   1.148 +TInt myThreadTimer::iCount;
   1.149 +TInt myThreadTimer::iNum;
   1.150 +
   1.151 +LOCAL_D RTest test(_L("T_CACT"));
   1.152 +LOCAL_D myTimer* gTimer; // This is cancelled from within the run method 
   1.153 +LOCAL_D RSemaphore threadSemaphore;
   1.154 +LOCAL_D myTimer* pLowest=NULL;
   1.155 +LOCAL_D myTimer* pLow=NULL;
   1.156 +LOCAL_D myTimer* pNone=NULL;
   1.157 +LOCAL_D myTimer* pHigh=NULL;
   1.158 +LOCAL_D myTimer* pHigh2=NULL;
   1.159 +LOCAL_D myTimer* pHigh3=NULL;
   1.160 +LOCAL_D myTimer* pHighest=NULL;
   1.161 +LOCAL_D TInt order[KTestArraySize]; // When a timer expires its identifier is placed in here
   1.162 +LOCAL_D TInt threadArray[KTestArraySize];
   1.163 +
   1.164 +LOCAL_C TInt myThreadEntryPoint(TAny*)
   1.165 +//
   1.166 +// myThread tests 
   1.167 +//
   1.168 +	{
   1.169 +
   1.170 +	__UHEAP_MARK;
   1.171 +	RTest test(_L("Separate thread tests"));
   1.172 +	test.Title();
   1.173 +	test.Start(_L("Create semaphore"));
   1.174 +	RTimer t;
   1.175 +	TInt ret=t.CreateLocal();
   1.176 +	test(ret==KErrNone);
   1.177 +//
   1.178 +	test.Next(_L("Install scheduler"));
   1.179 +	MyManager* pManager=new MyManager;
   1.180 +	CActiveScheduler::Install(pManager);
   1.181 +//
   1.182 +	test.Next(_L("Create active objects"));
   1.183 +	myThreadTimer* pLowest=new myThreadTimer(eLowest, eLowest);
   1.184 +	test(pLowest!=NULL);
   1.185 +	myThreadTimer* pLow=new myThreadTimer(eLow, eLow);
   1.186 +	test(pLow!=NULL);
   1.187 +	myThreadTimer* pNone=new myThreadTimer(eNone, eNone);
   1.188 +	test(pNone!=NULL);
   1.189 +	myThreadTimer* pHigh=new myThreadTimer(eHigh, eHigh);
   1.190 +	test(pHigh!=NULL);
   1.191 +	myThreadTimer* pHigh2=new myThreadTimer(eHigh, eHigh+2);
   1.192 +	test(pHigh2!=NULL);
   1.193 +	myThreadTimer* pHigh3=new myThreadTimer(eHigh, eHigh+3);
   1.194 +	test(pHigh3!=NULL);
   1.195 +	myThreadTimer* pHighest=new myThreadTimer(eHighest, eHighest);
   1.196 +	test(pHighest!=NULL);
   1.197 +//
   1.198 +	test.Next(_L("Test low is scheduled before lowest"));
   1.199 +	myThreadTimer::SetNum(2);
   1.200 +	pLowest->Start();
   1.201 +	pLowest->After(0);
   1.202 +	pLow->Start();
   1.203 +	pLow->After(0);
   1.204 +	TRequestStatus s;
   1.205 +	t.After(s,100000);
   1.206 +	test(s==KRequestPending);
   1.207 +	User::WaitForRequest(s);
   1.208 +	CActiveScheduler::Start();
   1.209 +	test(threadArray[0]==eLow && threadArray[1]==eLowest);
   1.210 +//
   1.211 +	test.Next(_L("Test none is scheduled before low"));
   1.212 +	myThreadTimer::SetNum(2);
   1.213 +	pLow->After(0);
   1.214 +	pNone->Start();
   1.215 +	pNone->After(0);
   1.216 +	t.After(s,100000);
   1.217 +	test(s==KRequestPending);
   1.218 +	User::WaitForRequest(s);
   1.219 +	CActiveScheduler::Start();
   1.220 +	test(threadArray[0]==eNone && threadArray[1]==eLow);
   1.221 +//
   1.222 +	test.Next(_L("Test high is scheduled before none"));
   1.223 +	myThreadTimer::SetNum(2);
   1.224 +	pHigh->Start();
   1.225 +	pHigh->After(0);
   1.226 +	pNone->After(0);
   1.227 +	t.After(s, 100000);
   1.228 +	test(s==KRequestPending);
   1.229 +	User::WaitForRequest(s);
   1.230 +	CActiveScheduler::Start();
   1.231 +	test(threadArray[0]==eHigh && threadArray[1]==eNone);
   1.232 +//
   1.233 +	test.Next(_L("Test highest is scheduled before high"));
   1.234 +	myThreadTimer::SetNum(2);
   1.235 +	pHighest->Start();
   1.236 +	pHighest->After(0);
   1.237 +	pHigh->After(0);
   1.238 +	t.After(s, 100000);
   1.239 +	test(s==KRequestPending);
   1.240 +	User::WaitForRequest(s);
   1.241 +	CActiveScheduler::Start();
   1.242 +	test(threadArray[0]==eHighest && threadArray[1]==eHigh);
   1.243 +//
   1.244 +	test.Next(_L("Test objects are scheduled according to priority"));
   1.245 +	myThreadTimer::SetNum(5);
   1.246 +	pLowest->After(0);
   1.247 +	pLow->After(0);
   1.248 +	pNone->After(0);
   1.249 +	pHigh->After(0);
   1.250 +	pHighest->After(0);
   1.251 +	t.After(s, 100000);
   1.252 +	test(s==KRequestPending);
   1.253 +	User::WaitForRequest(s);
   1.254 +	CActiveScheduler::Start();
   1.255 +	test(threadArray[0]==eHighest && threadArray[1]==eHigh && threadArray[2]==eNone && 
   1.256 +		 threadArray[3]==eLow && threadArray[4]==eLowest);
   1.257 +//
   1.258 +	test.Next(_L("Test objects are scheduled according to timer expiry"));
   1.259 +	myThreadTimer::SetNum(5);
   1.260 +	pLowest->After(0);
   1.261 +	pLow->After(500000);
   1.262 +	pNone->After(1000000);
   1.263 +	pHigh->After(1500000);
   1.264 +	pHighest->After(2000000);
   1.265 +	CActiveScheduler::Start();
   1.266 +	test(threadArray[4]==eHighest && threadArray[3]==eHigh && threadArray[2]==eNone && 
   1.267 +		 threadArray[1]==eLow && threadArray[0]==eLowest);
   1.268 +//
   1.269 +	test.Next(_L("Test with some objects having the same priority"));
   1.270 +	myThreadTimer::SetNum(7);
   1.271 +	pLowest->After(0);
   1.272 +	pLow->After(0);
   1.273 +	pNone->After(0);
   1.274 +	pHigh->After(0);
   1.275 +	pHigh2->Start();
   1.276 +	pHigh2->After(0);
   1.277 +	pHigh3->Start();
   1.278 +	pHigh3->After(0);
   1.279 +	pHighest->After(0);
   1.280 +	t.After(s, 100000);
   1.281 +	test(s==KRequestPending);
   1.282 +	User::WaitForRequest(s);
   1.283 +	CActiveScheduler::Start();
   1.284 +	test(threadArray[0]==eHighest && threadArray[1]==eHigh && threadArray[2]==eHigh+2 && 
   1.285 +		 threadArray[3]==eHigh+3 && threadArray[4]==eNone && threadArray[5]==eLow && threadArray[6]==eLowest);
   1.286 +//
   1.287 +	test.Next(_L("Tidying up"));
   1.288 +	delete pManager;
   1.289 +	delete pLowest;
   1.290 +	delete pLow;
   1.291 +	delete pNone;
   1.292 +	delete pHigh;
   1.293 +	delete pHigh2;
   1.294 +	delete pHigh3;
   1.295 +	delete pHighest;
   1.296 +	test.Close();
   1.297 +	__UHEAP_MARKEND;
   1.298 +	threadSemaphore.Signal();
   1.299 +	return(KErrNone);
   1.300 +	}
   1.301 +
   1.302 +LOCAL_D TInt panicThread(TAny* aDirective)
   1.303 +//
   1.304 +// Test thread which panics
   1.305 +//
   1.306 +	{
   1.307 +	// cause panics in various ways depending upon aDirective
   1.308 +	MyManager* pManager=new MyManager;
   1.309 +	
   1.310 +	switch((TInt)aDirective)
   1.311 +		{
   1.312 +	case EStartUninstalled:
   1.313 +		CActiveScheduler::Start(); // Start an uninstalled active schedler
   1.314 +		break;
   1.315 +	case EInstallTwice:
   1.316 +		CActiveScheduler::Install(pManager); // Install the scheduler twice
   1.317 +		CActiveScheduler::Install(pManager);
   1.318 +		break;
   1.319 +	case EStopTwice:
   1.320 +		CActiveScheduler::Install(pManager); // Stop a scheduler twice
   1.321 +		CActiveScheduler::Stop();
   1.322 +		CActiveScheduler::Stop();
   1.323 +		break;
   1.324 +	case EStopUninstalled:
   1.325 +		CActiveScheduler::Stop(); // Stop an uninstalled active scheduler
   1.326 +		break;
   1.327 +	case ESetActiveTwice:
   1.328 +		{
   1.329 +//
   1.330 +// Set an active object to active twice
   1.331 +//
   1.332 +		myTimer* pTimer=new myTimer(eNone,eNone);
   1.333 +		CActiveScheduler::Install(pManager);
   1.334 +		CActiveScheduler::Add(pTimer);
   1.335 +		pTimer->Setactive();
   1.336 +		pTimer->Setactive();
   1.337 +		}
   1.338 +		break;
   1.339 +	case EAddToUninstalled:
   1.340 +		{
   1.341 +//
   1.342 +// Add an active object to an uninstalled scheduler
   1.343 +//
   1.344 +		myTimer* pTimer=new myTimer(eNone,eNone);
   1.345 +		CActiveScheduler::Add(pTimer); 
   1.346 +		}
   1.347 +		break;
   1.348 +	case EAddNull:
   1.349 +//
   1.350 +// Add Null to the scheduling queue
   1.351 +//
   1.352 +		CActiveScheduler::Install(pManager);  
   1.353 +		CActiveScheduler::Add(NULL);
   1.354 +		break;
   1.355 +	case EAddTwice:
   1.356 +		{
   1.357 +//
   1.358 +// Add the same object twice to the scheduling queue
   1.359 +//
   1.360 +		myTimer* pTimer=new myTimer(eNone,eNone);
   1.361 +		CActiveScheduler::Install(pManager);  
   1.362 +		CActiveScheduler::Add(pTimer);
   1.363 +		CActiveScheduler::Add(pTimer);
   1.364 +		}
   1.365 +		break;
   1.366 +	case ECreateStray:
   1.367 +		{
   1.368 +//
   1.369 +// Create a stray signal
   1.370 +//
   1.371 +		CActiveScheduler::Install(pManager); 
   1.372 +		new CreateStray(1);
   1.373 +		CActiveScheduler::Start();
   1.374 +		}
   1.375 +		break;
   1.376 +	case ERequestUnadded:
   1.377 +		{
   1.378 +//
   1.379 +// Make a request of an active object not added to the scheduling queue
   1.380 +//
   1.381 +		CActiveScheduler::Install(pManager);
   1.382 +		myTimer* pTimer=new myTimer(eNone,eNone);
   1.383 +		pTimer->Setactive();
   1.384 +		}
   1.385 +		break;
   1.386 +	case EStraySignalNoKRequestPending:
   1.387 +		{
   1.388 +		CActiveScheduler::Install(pManager);
   1.389 +		myStray* pStray = new myStray(eNone);
   1.390 +		CActiveScheduler::Add(pStray);
   1.391 +		pStray->Start1();
   1.392 +		CActiveScheduler::Start();
   1.393 +		}
   1.394 +		break;
   1.395 +	case EStraySignalNoSetActive:
   1.396 +		{
   1.397 +		CActiveScheduler::Install(pManager);
   1.398 +		myStray* pStray = new myStray(eNone);
   1.399 +		CActiveScheduler::Add(pStray);
   1.400 +		pStray->Start2();
   1.401 +		CActiveScheduler::Start();
   1.402 +		}
   1.403 +		break;
   1.404 +	case ENormal:
   1.405 +	default:
   1.406 +		break;
   1.407 +		}
   1.408 +	delete pManager;
   1.409 +	return(KPanicThreadRet);
   1.410 +	}
   1.411 +
   1.412 +void myTimer::RunL()
   1.413 +//
   1.414 +// Handle the timer completion
   1.415 +//
   1.416 +	{
   1.417 +
   1.418 +	if (iIdentifier==KLeaveCode)	// Used to test that the request manager error() method is called
   1.419 +		User::Leave(KmyErrorNum);
   1.420 +	if (iIdentifier==KCancelCode) // Used to test cancelling an object
   1.421 +		gTimer->Cancel();
   1.422 +	order[iCount++]=iIdentifier;
   1.423 +	if (iCount>=iNum)
   1.424 +		CActiveScheduler::Stop();
   1.425 +	}
   1.426 +
   1.427 +void myTimer::Start()
   1.428 +//
   1.429 +// Start a timer
   1.430 +//
   1.431 +	{
   1.432 +
   1.433 +	ConstructL();
   1.434 +	CActiveScheduler::Add(this);
   1.435 +	}
   1.436 +
   1.437 +void myThreadTimer::RunL()
   1.438 +//
   1.439 +// Handle timer completion
   1.440 +//
   1.441 +	{
   1.442 +	
   1.443 +	threadArray[iCount++]=iIdentifier;
   1.444 +	if(iCount>=iNum)
   1.445 +		CActiveScheduler::Stop();
   1.446 +	}
   1.447 +
   1.448 +void myThreadTimer::Start()
   1.449 +//
   1.450 +// Start a timer
   1.451 +//
   1.452 +	{
   1.453 +
   1.454 +	ConstructL();
   1.455 +	CActiveScheduler::Add(this);
   1.456 +	}
   1.457 +
   1.458 +CreateStray::CreateStray(TInt aPriority)
   1.459 +//
   1.460 +// Constructor
   1.461 +//
   1.462 +	: CActive(aPriority)
   1.463 +	{
   1.464 +
   1.465 +	iTimer.CreateLocal();
   1.466 +	CActiveScheduler::Add(this);
   1.467 +	iTimer.After(iStatus, 1000000);
   1.468 +	}
   1.469 +
   1.470 +void TSecdulerTester::Test1()
   1.471 +//
   1.472 +// Test 1
   1.473 +//
   1.474 +	{
   1.475 +
   1.476 +//
   1.477 +// Test the panics
   1.478 +//
   1.479 +
   1.480 +	RThread thread;
   1.481 +	TRequestStatus stat;
   1.482 +//
   1.483 +	test.Start(_L("First test normal thread termination"));
   1.484 +	TInt r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ENormal);
   1.485 +	test(r==KErrNone);
   1.486 +	thread.Logon(stat);
   1.487 +	thread.Resume();
   1.488 +	User::WaitForRequest(stat);
   1.489 +	test(thread.ExitCategory().Compare(_L("Kill"))==0);
   1.490 +	test(thread.ExitReason()==KPanicThreadRet);	  
   1.491 +	test(thread.ExitType()==EExitKill);
   1.492 +	CLOSE_AND_WAIT(thread);
   1.493 +//
   1.494 +	test.Next(_L("Starting an uninstalled scheduler panics"));
   1.495 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStartUninstalled);
   1.496 +	test(r==KErrNone);
   1.497 +	thread.Logon(stat);
   1.498 +	thread.Resume();
   1.499 +	User::WaitForRequest(stat);
   1.500 +	test(thread.ExitReason()==EReqManagerDoesNotExist);
   1.501 +	test(thread.ExitType()==EExitPanic);
   1.502 +	CLOSE_AND_WAIT(thread);
   1.503 +//
   1.504 +	test.Next(_L("Installing the scheduler twice panics"));
   1.505 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EInstallTwice);
   1.506 +	test(r==KErrNone);
   1.507 +	thread.Logon(stat);
   1.508 +	thread.Resume();
   1.509 +	User::WaitForRequest(stat);
   1.510 +	test(thread.ExitReason()==EReqManagerAlreadyExists);
   1.511 +	test(thread.ExitType()==EExitPanic);
   1.512 +	CLOSE_AND_WAIT(thread);
   1.513 +//
   1.514 +	test.Next(_L("Stopping the scheduler twice panics"));
   1.515 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStopTwice);
   1.516 +	test(r==KErrNone);
   1.517 +	thread.Logon(stat);
   1.518 +	thread.Resume();
   1.519 +	User::WaitForRequest(stat);
   1.520 +	test(thread.ExitReason()==EReqTooManyStops);
   1.521 +	test(thread.ExitType()==EExitPanic);
   1.522 +	CLOSE_AND_WAIT(thread);
   1.523 +//
   1.524 +	test.Next(_L("Stopping an uninstalled scheduler panics"));
   1.525 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStopUninstalled);
   1.526 +	test(r==KErrNone);
   1.527 +	thread.Logon(stat);
   1.528 +	thread.Resume();
   1.529 +	User::WaitForRequest(stat);
   1.530 +	test(thread.ExitReason()==EReqManagerDoesNotExist);
   1.531 +	test(thread.ExitType()==EExitPanic);
   1.532 +	CLOSE_AND_WAIT(thread);
   1.533 +//
   1.534 +	test.Next(_L("Setting an active object to active twice panics"));
   1.535 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ESetActiveTwice);
   1.536 +	test(r==KErrNone);
   1.537 +	thread.Logon(stat);
   1.538 +	thread.Resume();
   1.539 +	User::WaitForRequest(stat);
   1.540 +	test(thread.ExitReason()==EReqAlreadyActive);
   1.541 +	test(thread.ExitType()==EExitPanic);
   1.542 +	CLOSE_AND_WAIT(thread);
   1.543 +//
   1.544 +	test.Next(_L("Adding an active object to an uninstalled scheduler panics"));
   1.545 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EAddToUninstalled);
   1.546 +	test(r==KErrNone);
   1.547 +	thread.Logon(stat);
   1.548 +	thread.Resume();
   1.549 +	User::WaitForRequest(stat);
   1.550 +	test(thread.ExitReason()==EReqManagerDoesNotExist);
   1.551 +	test(thread.ExitType()==EExitPanic);
   1.552 +	CLOSE_AND_WAIT(thread);
   1.553 +//
   1.554 +	test.Next(_L("Adding NULL panics"));
   1.555 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EAddNull);
   1.556 +	test(r==KErrNone);
   1.557 +	thread.Logon(stat);
   1.558 +	thread.Resume();
   1.559 +	User::WaitForRequest(stat);
   1.560 +	test(thread.ExitReason()==EReqNull);
   1.561 +	test(thread.ExitType()==EExitPanic);
   1.562 +	CLOSE_AND_WAIT(thread);
   1.563 +//
   1.564 +	test.Next(_L("Adding an active object twice panics"));
   1.565 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EAddTwice);
   1.566 +	test(r==KErrNone);
   1.567 +	thread.Logon(stat);
   1.568 +	thread.Resume();
   1.569 +	User::WaitForRequest(stat);
   1.570 +	test(thread.ExitReason()==EReqAlreadyAdded);
   1.571 +	test(thread.ExitType()==EExitPanic);
   1.572 +	CLOSE_AND_WAIT(thread);
   1.573 +//
   1.574 +	test.Next(_L("A stray signal causes a panic"));
   1.575 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ECreateStray);
   1.576 +	test(r==KErrNone);
   1.577 +	thread.Logon(stat);
   1.578 +	thread.Resume();
   1.579 +	User::WaitForRequest(stat);
   1.580 +	test(thread.ExitReason()==EReqStrayEvent);
   1.581 +	test(thread.ExitType()==EExitPanic);
   1.582 +	CLOSE_AND_WAIT(thread);
   1.583 +//
   1.584 +	test.Next(_L("Making a request on an unadded active object panics"));
   1.585 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ERequestUnadded);
   1.586 +	test(r==KErrNone);
   1.587 +	thread.Logon(stat);
   1.588 +	thread.Resume();
   1.589 +	User::WaitForRequest(stat);
   1.590 +	test(thread.ExitReason()==EActiveNotAdded);
   1.591 +	test(thread.ExitType()==EExitPanic);
   1.592 +	CLOSE_AND_WAIT(thread);
   1.593 +//
   1.594 +	test.Next(_L("The service provider does not set the status to KRequestPending"));
   1.595 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStraySignalNoKRequestPending);
   1.596 +	test(r==KErrNone);
   1.597 +	thread.Logon(stat);
   1.598 +	thread.Resume();
   1.599 +	User::WaitForRequest(stat);
   1.600 +#ifdef _DEBUG
   1.601 +	//this might fail if we're using a UREL euser
   1.602 +	test(thread.ExitReason()==EReqStrayEvent);
   1.603 +	test(thread.ExitType()==EExitPanic);
   1.604 +#else
   1.605 +	test(thread.ExitCategory().Compare(_L("Kill"))==0);
   1.606 +	test(thread.ExitReason()==KPanicThreadRet);	  
   1.607 +	test(thread.ExitType()==EExitKill);
   1.608 +#endif 
   1.609 +	CLOSE_AND_WAIT(thread);
   1.610 +//
   1.611 +#ifdef _DEBUG
   1.612 +	//this might fail if we're using a UREL euser
   1.613 +	test.Next(_L("The active object does not call SetActive"));
   1.614 +	r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStraySignalNoSetActive);
   1.615 +	test(r==KErrNone);
   1.616 +	thread.Logon(stat);
   1.617 +	thread.Resume();
   1.618 +	User::WaitForRequest(stat);
   1.619 +	test(thread.ExitReason()==EReqStrayEvent);
   1.620 +	test(thread.ExitType()==EExitPanic);
   1.621 +	CLOSE_AND_WAIT(thread);
   1.622 +#endif
   1.623 +//
   1.624 +	test.End();
   1.625 +	}
   1.626 +
   1.627 +void TSecdulerTester::Test2()
   1.628 +//
   1.629 +// Test 2
   1.630 +//
   1.631 +	{
   1.632 +
   1.633 +	test.Start(_L("Create timer"));
   1.634 +	RTimer t;
   1.635 +	TInt ret=t.CreateLocal();
   1.636 +	test(ret==KErrNone);
   1.637 +	TRequestStatus s;
   1.638 +//
   1.639 +	test.Next(_L("Test low is scheduled before lowest when timing equal"));
   1.640 +	myTimer::SetNum(2);
   1.641 +	pLowest->After(0);
   1.642 +	pLow->After(0);
   1.643 +	t.After(s, 100000);
   1.644 +	test(s==KRequestPending);
   1.645 +	User::WaitForRequest(s);
   1.646 +	CActiveScheduler::Start();
   1.647 +	test(order[0]==eLow && order[1]==eLowest);
   1.648 +//
   1.649 +	test.Next(_L("Test low is not before lowest when it expires later"));
   1.650 +	myTimer::SetNum(2);
   1.651 +	pLowest->After(0);
   1.652 +	pLow->After(1000000);
   1.653 +	CActiveScheduler::Start();
   1.654 +	test(order[0]==eLowest && order[1]==eLow);
   1.655 +//
   1.656 +	test.Next(_L("Test none is scheduled before low"));
   1.657 +	myTimer::SetNum(2);
   1.658 +	pLow->After(0);
   1.659 +	pNone->After(0);
   1.660 +	t.After(s, 100000);
   1.661 +	test(s==KRequestPending);
   1.662 +	User::WaitForRequest(s);
   1.663 +	CActiveScheduler::Start();
   1.664 +	test(order[0]==eNone && order[1]==eLow);
   1.665 +//
   1.666 +	test.Next(_L("Test none is not before low when it expires later"));
   1.667 +	myTimer::SetNum(2);
   1.668 +	pLow->After(0);
   1.669 +	pNone->After(1000000);
   1.670 +	CActiveScheduler::Start();
   1.671 +	test(order[0]==eLow && order[1]==eNone);
   1.672 +//
   1.673 +	test.Next(_L("Test high is scheduled before none"));
   1.674 +	myTimer::SetNum(2);
   1.675 +	pHigh->After(0);
   1.676 +	pNone->After(0);
   1.677 +	t.After(s, 100000);
   1.678 +	test(s==KRequestPending);
   1.679 +	User::WaitForRequest(s);
   1.680 +	CActiveScheduler::Start();
   1.681 +	test(order[0]==eHigh && order[1]==eNone);
   1.682 +//
   1.683 +	test.Next(_L("Test high is not before none when it expires later"));
   1.684 +	myTimer::SetNum(2);
   1.685 +	pHigh->After(1000000);
   1.686 +	pNone->After(0);
   1.687 +	CActiveScheduler::Start();
   1.688 +	test(order[0]==eNone && order[1]==eHigh);
   1.689 +//
   1.690 +	test.Next(_L("Test highest is scheduled before high"));
   1.691 +	myTimer::SetNum(2);
   1.692 +	pHighest->After(0);
   1.693 +	pHigh->After(0);
   1.694 +	t.After(s, 100000);
   1.695 +	test(s==KRequestPending);
   1.696 +	User::WaitForRequest(s);
   1.697 +	CActiveScheduler::Start();
   1.698 +	test(order[0]==eHighest && order[1]==eHigh);
   1.699 +//
   1.700 +	test.Next(_L("Test highest is not before high when it expires later"));
   1.701 +	myTimer::SetNum(2);
   1.702 +	pHighest->After(1000000);
   1.703 +	pHigh->After(0);
   1.704 +	CActiveScheduler::Start();
   1.705 +	test(order[0]==eHigh && order[1]==eHighest);
   1.706 +//			  
   1.707 +	test.Next(_L("Test all objects are scheduled in priority order"));
   1.708 +	myTimer::SetNum(5);
   1.709 +	pLowest->After(0);
   1.710 +	pLow->After(0);
   1.711 +	pNone->After(0);
   1.712 +	pHigh->After(0);
   1.713 +	pHighest->After(0);
   1.714 +	t.After(s, 100000);
   1.715 +	test(s==KRequestPending);
   1.716 +	User::WaitForRequest(s);
   1.717 +	CActiveScheduler::Start();
   1.718 +	test(order[0]==eHighest && order[1]==eHigh && order[2]==eNone && order[3]==eLow && order[4]==eLowest);
   1.719 +//
   1.720 +	test.Next(_L("Test objects are scheduled according to expiry of timers"));
   1.721 +	myTimer::SetNum(5);
   1.722 +	pLowest->After(0);
   1.723 +	pLow->After(500000);
   1.724 +	pNone->After(1000000);
   1.725 +	pHigh->After(1500000);
   1.726 +	pHighest->After(2000000);
   1.727 +	CActiveScheduler::Start();
   1.728 +	test(order[4]==eHighest && order[3]==eHigh && order[2]==eNone && order[1]==eLow && order[0]==eLowest);
   1.729 +//
   1.730 +	test.Next(_L("Test with some objects having the same priority"));
   1.731 +	myTimer::SetNum(7);
   1.732 +	pLowest->After(0);
   1.733 +	pLow->After(0);
   1.734 +	pNone->After(0);
   1.735 +	pHigh->After(0);
   1.736 +	pHigh2->After(0);
   1.737 +	pHigh3->After(0);
   1.738 +	pHighest->After(0);	  
   1.739 +	t.After(s, 100000);
   1.740 +	test(s==KRequestPending);
   1.741 +	User::WaitForRequest(s);
   1.742 +	CActiveScheduler::Start();
   1.743 +	test(order[0]==eHighest && order[1]==eHigh && order[2]==eHigh+2 && order[3]==eHigh+3 && order[4]==eNone && order[5]==eLow && order[6]==eLowest);
   1.744 +//
   1.745 +	test.End();
   1.746 +	}
   1.747 +
   1.748 +void TSecdulerTester::Test3()
   1.749 +//
   1.750 +// Test 3
   1.751 +//
   1.752 +	{
   1.753 +
   1.754 +//
   1.755 +// Test that a leave in a Run method calls the requestmanager error() method
   1.756 +//
   1.757 +	myTimer* pTimer=new myTimer(0, KLeaveCode);
   1.758 +	pTimer->Start();
   1.759 +	pTimer->After(100000);
   1.760 +	TRAPD(ret,CActiveScheduler::Start());
   1.761 +	test(ret==KmyErrorNum);		
   1.762 +//
   1.763 +// Test cancelling an object
   1.764 +// Without the cancel the schedule order should be: pTimer1, gTimer, pTimer3
   1.765 +// gTimer is cancelled so should not be scheduled 
   1.766 +//
   1.767 +	myTimer::SetNum(2);
   1.768 +	myTimer* pTimer2=new myTimer(eHighest,KCancelCode);
   1.769 +	myTimer* pTimer3=new myTimer(eLowest,eLowest);
   1.770 +	pTimer2->Start();
   1.771 +	pTimer2->After(100000);
   1.772 +	gTimer->Start();
   1.773 +	gTimer->After(1000000);
   1.774 +	pTimer3->Start();
   1.775 +	pTimer3->After(2000000);
   1.776 +	CActiveScheduler::Start();
   1.777 +	test(order[0]==KCancelCode && order[1]==eLowest);
   1.778 +	delete pTimer;
   1.779 +	delete pTimer2;
   1.780 +	delete pTimer3;
   1.781 +	}
   1.782 +
   1.783 +void TSecdulerTester::Test4()
   1.784 +//
   1.785 +// Create a thread with its own scheduler
   1.786 +//
   1.787 +	{	  
   1.788 +
   1.789 +	threadSemaphore.CreateLocal(0);
   1.790 +	RThread myThread;
   1.791 +	test(myThread.Create(_L("myThread"),myThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
   1.792 +	myThread.Resume();
   1.793 +	myThread.Close();
   1.794 +	Test2();
   1.795 +	threadSemaphore.Wait();
   1.796 +	User::After(100000);
   1.797 +	}
   1.798 +
   1.799 +GLDEF_C TInt E32Main()
   1.800 +    {
   1.801 +
   1.802 +	// don't want just in time debugging as we trap panics
   1.803 +	TBool justInTime=User::JustInTime(); 
   1.804 +	User::SetJustInTime(EFalse); 
   1.805 +
   1.806 +	test.Title();
   1.807 +	__UHEAP_MARK;
   1.808 +//
   1.809 +	test.Start(_L("Test1"));
   1.810 +	TSecdulerTester sched;
   1.811 +	sched.Test1();
   1.812 +	MyManager* pManager=new MyManager;
   1.813 +	test(pManager!=NULL);
   1.814 +	CActiveScheduler::Install(pManager);
   1.815 +	test(CActiveScheduler::Current()==pManager);
   1.816 +	MyManager* pManager2=new MyManager;
   1.817 +	test(pManager2!=NULL);
   1.818 +	delete pManager2;
   1.819 +	test(CActiveScheduler::Current()==pManager);
   1.820 +	pLowest=new myTimer(eLowest,eLowest);
   1.821 +	test(pLowest!=NULL);
   1.822 +	pLow=new myTimer(eLow,eLow);
   1.823 +	test(pLow!=NULL);
   1.824 +	pNone=new myTimer(eNone,eNone);
   1.825 +	test(pNone!=NULL);
   1.826 +	pHigh=new myTimer(eHigh,eHigh);
   1.827 +	test(pHigh!=NULL);
   1.828 +	pHigh2=new myTimer(eHigh,eHigh+2);
   1.829 +	test(pHigh2!=NULL);
   1.830 +	pHigh3=new myTimer(eHigh,eHigh+3);
   1.831 +	test(pHigh3!=NULL);
   1.832 +	pHighest=new myTimer(eHighest,eHighest);
   1.833 +	test(pHighest!=NULL);
   1.834 +	pLowest->Start();
   1.835 +	pLow->Start();
   1.836 +	pNone->Start();
   1.837 +	pHigh->Start();
   1.838 +	pHigh2->Start();
   1.839 +	pHigh3->Start();
   1.840 +	pHighest->Start();
   1.841 +//
   1.842 +	test.Next(_L("Test2"));
   1.843 +	sched.Test2();	
   1.844 +	User::Check();
   1.845 +//
   1.846 +	test.Next(_L("Test3"));
   1.847 +	gTimer=new myTimer(eNone, KgTimerID);
   1.848 +	sched.Test3();
   1.849 +//
   1.850 +	test.Next(_L("Test4"));
   1.851 +	sched.Test4();
   1.852 +	delete gTimer;
   1.853 +	User::Check();
   1.854 +	delete pManager;
   1.855 +	delete pLowest;
   1.856 +	delete pLow;
   1.857 +	delete pNone;
   1.858 +	delete pHigh;
   1.859 +	delete pHigh2;
   1.860 +	delete pHigh3;
   1.861 +	delete pHighest;
   1.862 +//
   1.863 +	test.End();
   1.864 +	__UHEAP_MARKEND;
   1.865 +
   1.866 +	User::SetJustInTime(justInTime);
   1.867 +	return(KErrNone);
   1.868 +    }