--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/active/t_cact.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,865 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\active\t_cact.cpp
+// Overview:
+// Test the CActiveScheduler class, including scheduling priority, thread
+// panics and cancelling objects attached to the scheduler.
+// API Information:
+// CActiveScheduler
+// Details:
+// - Verify the thread is panicked when one of the following programming errors occurs:
+// - start an uninstalled scheduler
+// - install a scheduler twice
+// - stop the scheduler twice
+// - stop an uninstalled scheduler
+// - set active an active object twice
+// - add an active object to an uninstalled scheduler
+// - add a NULL pointer to the scheduler
+// - add an active object twice
+// - thread gets a stray signal
+// - make request on an un-added active object
+// - Create timers with different priorities
+// - Check the timers are scheduled according to expiration time
+// - Check the timers are scheduled in order of their priority when they expire at the
+// same time
+// - Check the timers are scheduled in order of the addition to the scheduler when
+// they expire at the same time and they have the same priority
+// - Verify that a leave in RunL method not handled by the active object calls the active
+// scheduler's Error method
+// - Test a cancelled timer will not be scheduled
+// - Create a thread with its own heap and test that timers are scheduled in the order of
+// their expiration time, priority and order of addition to the scheduler
+// - Check the heap is not corrupted by all the tests
+// Platforms/Drives/Compatibility:
+// All
+// Assumptions/Requirement/Pre-requisites:
+// Failures and causes:
+// Base Port information:
+//
+//
+
+#include <e32test.h>
+#include <e32panic.h>
+
+const TInt KmyErrorNum=999;
+const TInt KLeaveCode=1234;
+const TInt KgTimerID=4321;
+const TInt KCancelCode=1111;
+const TInt KTestArraySize=10;
+const TInt KPanicThreadRet=2222;
+const TInt KHeapSize=0x2000;
+
+enum TActivePriority {eLowest=-100,eLow=-1,eNone=0,eHigh=1,eHighest=100};
+enum TDirective {EStartUninstalled,EInstallTwice,EStopTwice,EStopUninstalled,ESetActiveTwice,
+ EAddToUninstalled,EAddNull,EAddTwice,ECreateStray,ERequestUnadded,EStraySignalNoKRequestPending,EStraySignalNoSetActive,ENormal};
+
+class TSecdulerTester
+ {
+public:
+ void Test1();
+ void Test2();
+ void Test3();
+ void Test4();
+ };
+
+class MyManager : public CActiveScheduler
+ {
+public:
+ virtual void Error(TInt anError) const {CActiveScheduler::Halt(anError);}
+ };
+
+class myTimer : public CTimer
+ {
+public:
+ myTimer(const TInt aPriority, const TInt anIdentifier):CTimer(aPriority){iIdentifier=anIdentifier;}
+ virtual void RunL();
+ void Start();
+ void Setactive() {SetActive();}
+ static void SetNum(const TInt aNum) {iNum=aNum; iCount=0;}
+private:
+ TInt iIdentifier;
+ static TInt iCount;
+ static TInt iNum;
+ };
+
+class myThreadTimer : public CTimer
+ {
+public:
+ myThreadTimer(const TInt aPriority, const TInt anIdentifier):CTimer(aPriority){iIdentifier=anIdentifier;}
+ virtual void RunL();
+ static void SetNum(const TInt aNum) {iNum=aNum; iCount=0;}
+ void Start();
+private:
+ TInt iIdentifier;
+ static TInt iCount;
+ static TInt iNum;
+ };
+
+class CreateStray : public CActive
+ {
+public:
+ CreateStray(TInt aPriority);
+ void DoCancel() {}
+ void RunL() {}
+private:
+ RTimer iTimer;
+ };
+
+class myStray : public CActive
+ {
+public:
+ myStray(TInt aPriority) : CActive(aPriority) {};
+ void DoCancel() {}
+ void RunL() { CActiveScheduler::Stop(); }
+ void Start1();
+ void Start2();
+ };
+
+void myStray::Start1()
+ {
+ TRequestStatus* s=&iStatus;
+ SetActive();
+ RThread().RequestComplete(s,KErrNone);
+ }
+
+void myStray::Start2()
+ {
+ TRequestStatus* s=&iStatus;
+ iStatus=KRequestPending;
+ User::RequestComplete(s,KErrNone);
+ }
+
+TInt myTimer::iCount;
+TInt myTimer::iNum;
+TInt myThreadTimer::iCount;
+TInt myThreadTimer::iNum;
+
+LOCAL_D RTest test(_L("T_CACT"));
+LOCAL_D myTimer* gTimer; // This is cancelled from within the run method
+LOCAL_D RSemaphore threadSemaphore;
+LOCAL_D myTimer* pLowest=NULL;
+LOCAL_D myTimer* pLow=NULL;
+LOCAL_D myTimer* pNone=NULL;
+LOCAL_D myTimer* pHigh=NULL;
+LOCAL_D myTimer* pHigh2=NULL;
+LOCAL_D myTimer* pHigh3=NULL;
+LOCAL_D myTimer* pHighest=NULL;
+LOCAL_D TInt order[KTestArraySize]; // When a timer expires its identifier is placed in here
+LOCAL_D TInt threadArray[KTestArraySize];
+
+LOCAL_C TInt myThreadEntryPoint(TAny*)
+//
+// myThread tests
+//
+ {
+
+ __UHEAP_MARK;
+ RTest test(_L("Separate thread tests"));
+ test.Title();
+ test.Start(_L("Create semaphore"));
+ RTimer t;
+ TInt ret=t.CreateLocal();
+ test(ret==KErrNone);
+//
+ test.Next(_L("Install scheduler"));
+ MyManager* pManager=new MyManager;
+ CActiveScheduler::Install(pManager);
+//
+ test.Next(_L("Create active objects"));
+ myThreadTimer* pLowest=new myThreadTimer(eLowest, eLowest);
+ test(pLowest!=NULL);
+ myThreadTimer* pLow=new myThreadTimer(eLow, eLow);
+ test(pLow!=NULL);
+ myThreadTimer* pNone=new myThreadTimer(eNone, eNone);
+ test(pNone!=NULL);
+ myThreadTimer* pHigh=new myThreadTimer(eHigh, eHigh);
+ test(pHigh!=NULL);
+ myThreadTimer* pHigh2=new myThreadTimer(eHigh, eHigh+2);
+ test(pHigh2!=NULL);
+ myThreadTimer* pHigh3=new myThreadTimer(eHigh, eHigh+3);
+ test(pHigh3!=NULL);
+ myThreadTimer* pHighest=new myThreadTimer(eHighest, eHighest);
+ test(pHighest!=NULL);
+//
+ test.Next(_L("Test low is scheduled before lowest"));
+ myThreadTimer::SetNum(2);
+ pLowest->Start();
+ pLowest->After(0);
+ pLow->Start();
+ pLow->After(0);
+ TRequestStatus s;
+ t.After(s,100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(threadArray[0]==eLow && threadArray[1]==eLowest);
+//
+ test.Next(_L("Test none is scheduled before low"));
+ myThreadTimer::SetNum(2);
+ pLow->After(0);
+ pNone->Start();
+ pNone->After(0);
+ t.After(s,100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(threadArray[0]==eNone && threadArray[1]==eLow);
+//
+ test.Next(_L("Test high is scheduled before none"));
+ myThreadTimer::SetNum(2);
+ pHigh->Start();
+ pHigh->After(0);
+ pNone->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(threadArray[0]==eHigh && threadArray[1]==eNone);
+//
+ test.Next(_L("Test highest is scheduled before high"));
+ myThreadTimer::SetNum(2);
+ pHighest->Start();
+ pHighest->After(0);
+ pHigh->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(threadArray[0]==eHighest && threadArray[1]==eHigh);
+//
+ test.Next(_L("Test objects are scheduled according to priority"));
+ myThreadTimer::SetNum(5);
+ pLowest->After(0);
+ pLow->After(0);
+ pNone->After(0);
+ pHigh->After(0);
+ pHighest->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(threadArray[0]==eHighest && threadArray[1]==eHigh && threadArray[2]==eNone &&
+ threadArray[3]==eLow && threadArray[4]==eLowest);
+//
+ test.Next(_L("Test objects are scheduled according to timer expiry"));
+ myThreadTimer::SetNum(5);
+ pLowest->After(0);
+ pLow->After(500000);
+ pNone->After(1000000);
+ pHigh->After(1500000);
+ pHighest->After(2000000);
+ CActiveScheduler::Start();
+ test(threadArray[4]==eHighest && threadArray[3]==eHigh && threadArray[2]==eNone &&
+ threadArray[1]==eLow && threadArray[0]==eLowest);
+//
+ test.Next(_L("Test with some objects having the same priority"));
+ myThreadTimer::SetNum(7);
+ pLowest->After(0);
+ pLow->After(0);
+ pNone->After(0);
+ pHigh->After(0);
+ pHigh2->Start();
+ pHigh2->After(0);
+ pHigh3->Start();
+ pHigh3->After(0);
+ pHighest->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(threadArray[0]==eHighest && threadArray[1]==eHigh && threadArray[2]==eHigh+2 &&
+ threadArray[3]==eHigh+3 && threadArray[4]==eNone && threadArray[5]==eLow && threadArray[6]==eLowest);
+//
+ test.Next(_L("Tidying up"));
+ delete pManager;
+ delete pLowest;
+ delete pLow;
+ delete pNone;
+ delete pHigh;
+ delete pHigh2;
+ delete pHigh3;
+ delete pHighest;
+ test.Close();
+ __UHEAP_MARKEND;
+ threadSemaphore.Signal();
+ return(KErrNone);
+ }
+
+LOCAL_D TInt panicThread(TAny* aDirective)
+//
+// Test thread which panics
+//
+ {
+ // cause panics in various ways depending upon aDirective
+ MyManager* pManager=new MyManager;
+
+ switch((TInt)aDirective)
+ {
+ case EStartUninstalled:
+ CActiveScheduler::Start(); // Start an uninstalled active schedler
+ break;
+ case EInstallTwice:
+ CActiveScheduler::Install(pManager); // Install the scheduler twice
+ CActiveScheduler::Install(pManager);
+ break;
+ case EStopTwice:
+ CActiveScheduler::Install(pManager); // Stop a scheduler twice
+ CActiveScheduler::Stop();
+ CActiveScheduler::Stop();
+ break;
+ case EStopUninstalled:
+ CActiveScheduler::Stop(); // Stop an uninstalled active scheduler
+ break;
+ case ESetActiveTwice:
+ {
+//
+// Set an active object to active twice
+//
+ myTimer* pTimer=new myTimer(eNone,eNone);
+ CActiveScheduler::Install(pManager);
+ CActiveScheduler::Add(pTimer);
+ pTimer->Setactive();
+ pTimer->Setactive();
+ }
+ break;
+ case EAddToUninstalled:
+ {
+//
+// Add an active object to an uninstalled scheduler
+//
+ myTimer* pTimer=new myTimer(eNone,eNone);
+ CActiveScheduler::Add(pTimer);
+ }
+ break;
+ case EAddNull:
+//
+// Add Null to the scheduling queue
+//
+ CActiveScheduler::Install(pManager);
+ CActiveScheduler::Add(NULL);
+ break;
+ case EAddTwice:
+ {
+//
+// Add the same object twice to the scheduling queue
+//
+ myTimer* pTimer=new myTimer(eNone,eNone);
+ CActiveScheduler::Install(pManager);
+ CActiveScheduler::Add(pTimer);
+ CActiveScheduler::Add(pTimer);
+ }
+ break;
+ case ECreateStray:
+ {
+//
+// Create a stray signal
+//
+ CActiveScheduler::Install(pManager);
+ new CreateStray(1);
+ CActiveScheduler::Start();
+ }
+ break;
+ case ERequestUnadded:
+ {
+//
+// Make a request of an active object not added to the scheduling queue
+//
+ CActiveScheduler::Install(pManager);
+ myTimer* pTimer=new myTimer(eNone,eNone);
+ pTimer->Setactive();
+ }
+ break;
+ case EStraySignalNoKRequestPending:
+ {
+ CActiveScheduler::Install(pManager);
+ myStray* pStray = new myStray(eNone);
+ CActiveScheduler::Add(pStray);
+ pStray->Start1();
+ CActiveScheduler::Start();
+ }
+ break;
+ case EStraySignalNoSetActive:
+ {
+ CActiveScheduler::Install(pManager);
+ myStray* pStray = new myStray(eNone);
+ CActiveScheduler::Add(pStray);
+ pStray->Start2();
+ CActiveScheduler::Start();
+ }
+ break;
+ case ENormal:
+ default:
+ break;
+ }
+ delete pManager;
+ return(KPanicThreadRet);
+ }
+
+void myTimer::RunL()
+//
+// Handle the timer completion
+//
+ {
+
+ if (iIdentifier==KLeaveCode) // Used to test that the request manager error() method is called
+ User::Leave(KmyErrorNum);
+ if (iIdentifier==KCancelCode) // Used to test cancelling an object
+ gTimer->Cancel();
+ order[iCount++]=iIdentifier;
+ if (iCount>=iNum)
+ CActiveScheduler::Stop();
+ }
+
+void myTimer::Start()
+//
+// Start a timer
+//
+ {
+
+ ConstructL();
+ CActiveScheduler::Add(this);
+ }
+
+void myThreadTimer::RunL()
+//
+// Handle timer completion
+//
+ {
+
+ threadArray[iCount++]=iIdentifier;
+ if(iCount>=iNum)
+ CActiveScheduler::Stop();
+ }
+
+void myThreadTimer::Start()
+//
+// Start a timer
+//
+ {
+
+ ConstructL();
+ CActiveScheduler::Add(this);
+ }
+
+CreateStray::CreateStray(TInt aPriority)
+//
+// Constructor
+//
+ : CActive(aPriority)
+ {
+
+ iTimer.CreateLocal();
+ CActiveScheduler::Add(this);
+ iTimer.After(iStatus, 1000000);
+ }
+
+void TSecdulerTester::Test1()
+//
+// Test 1
+//
+ {
+
+//
+// Test the panics
+//
+
+ RThread thread;
+ TRequestStatus stat;
+//
+ test.Start(_L("First test normal thread termination"));
+ TInt r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ENormal);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitCategory().Compare(_L("Kill"))==0);
+ test(thread.ExitReason()==KPanicThreadRet);
+ test(thread.ExitType()==EExitKill);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("Starting an uninstalled scheduler panics"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStartUninstalled);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqManagerDoesNotExist);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("Installing the scheduler twice panics"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EInstallTwice);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqManagerAlreadyExists);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("Stopping the scheduler twice panics"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStopTwice);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqTooManyStops);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("Stopping an uninstalled scheduler panics"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStopUninstalled);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqManagerDoesNotExist);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("Setting an active object to active twice panics"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ESetActiveTwice);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqAlreadyActive);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("Adding an active object to an uninstalled scheduler panics"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EAddToUninstalled);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqManagerDoesNotExist);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("Adding NULL panics"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EAddNull);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqNull);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("Adding an active object twice panics"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EAddTwice);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqAlreadyAdded);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("A stray signal causes a panic"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ECreateStray);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqStrayEvent);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("Making a request on an unadded active object panics"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ERequestUnadded);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EActiveNotAdded);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+//
+ test.Next(_L("The service provider does not set the status to KRequestPending"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStraySignalNoKRequestPending);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+#ifdef _DEBUG
+ //this might fail if we're using a UREL euser
+ test(thread.ExitReason()==EReqStrayEvent);
+ test(thread.ExitType()==EExitPanic);
+#else
+ test(thread.ExitCategory().Compare(_L("Kill"))==0);
+ test(thread.ExitReason()==KPanicThreadRet);
+ test(thread.ExitType()==EExitKill);
+#endif
+ CLOSE_AND_WAIT(thread);
+//
+#ifdef _DEBUG
+ //this might fail if we're using a UREL euser
+ test.Next(_L("The active object does not call SetActive"));
+ r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStraySignalNoSetActive);
+ test(r==KErrNone);
+ thread.Logon(stat);
+ thread.Resume();
+ User::WaitForRequest(stat);
+ test(thread.ExitReason()==EReqStrayEvent);
+ test(thread.ExitType()==EExitPanic);
+ CLOSE_AND_WAIT(thread);
+#endif
+//
+ test.End();
+ }
+
+void TSecdulerTester::Test2()
+//
+// Test 2
+//
+ {
+
+ test.Start(_L("Create timer"));
+ RTimer t;
+ TInt ret=t.CreateLocal();
+ test(ret==KErrNone);
+ TRequestStatus s;
+//
+ test.Next(_L("Test low is scheduled before lowest when timing equal"));
+ myTimer::SetNum(2);
+ pLowest->After(0);
+ pLow->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(order[0]==eLow && order[1]==eLowest);
+//
+ test.Next(_L("Test low is not before lowest when it expires later"));
+ myTimer::SetNum(2);
+ pLowest->After(0);
+ pLow->After(1000000);
+ CActiveScheduler::Start();
+ test(order[0]==eLowest && order[1]==eLow);
+//
+ test.Next(_L("Test none is scheduled before low"));
+ myTimer::SetNum(2);
+ pLow->After(0);
+ pNone->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(order[0]==eNone && order[1]==eLow);
+//
+ test.Next(_L("Test none is not before low when it expires later"));
+ myTimer::SetNum(2);
+ pLow->After(0);
+ pNone->After(1000000);
+ CActiveScheduler::Start();
+ test(order[0]==eLow && order[1]==eNone);
+//
+ test.Next(_L("Test high is scheduled before none"));
+ myTimer::SetNum(2);
+ pHigh->After(0);
+ pNone->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(order[0]==eHigh && order[1]==eNone);
+//
+ test.Next(_L("Test high is not before none when it expires later"));
+ myTimer::SetNum(2);
+ pHigh->After(1000000);
+ pNone->After(0);
+ CActiveScheduler::Start();
+ test(order[0]==eNone && order[1]==eHigh);
+//
+ test.Next(_L("Test highest is scheduled before high"));
+ myTimer::SetNum(2);
+ pHighest->After(0);
+ pHigh->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(order[0]==eHighest && order[1]==eHigh);
+//
+ test.Next(_L("Test highest is not before high when it expires later"));
+ myTimer::SetNum(2);
+ pHighest->After(1000000);
+ pHigh->After(0);
+ CActiveScheduler::Start();
+ test(order[0]==eHigh && order[1]==eHighest);
+//
+ test.Next(_L("Test all objects are scheduled in priority order"));
+ myTimer::SetNum(5);
+ pLowest->After(0);
+ pLow->After(0);
+ pNone->After(0);
+ pHigh->After(0);
+ pHighest->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(order[0]==eHighest && order[1]==eHigh && order[2]==eNone && order[3]==eLow && order[4]==eLowest);
+//
+ test.Next(_L("Test objects are scheduled according to expiry of timers"));
+ myTimer::SetNum(5);
+ pLowest->After(0);
+ pLow->After(500000);
+ pNone->After(1000000);
+ pHigh->After(1500000);
+ pHighest->After(2000000);
+ CActiveScheduler::Start();
+ test(order[4]==eHighest && order[3]==eHigh && order[2]==eNone && order[1]==eLow && order[0]==eLowest);
+//
+ test.Next(_L("Test with some objects having the same priority"));
+ myTimer::SetNum(7);
+ pLowest->After(0);
+ pLow->After(0);
+ pNone->After(0);
+ pHigh->After(0);
+ pHigh2->After(0);
+ pHigh3->After(0);
+ pHighest->After(0);
+ t.After(s, 100000);
+ test(s==KRequestPending);
+ User::WaitForRequest(s);
+ CActiveScheduler::Start();
+ test(order[0]==eHighest && order[1]==eHigh && order[2]==eHigh+2 && order[3]==eHigh+3 && order[4]==eNone && order[5]==eLow && order[6]==eLowest);
+//
+ test.End();
+ }
+
+void TSecdulerTester::Test3()
+//
+// Test 3
+//
+ {
+
+//
+// Test that a leave in a Run method calls the requestmanager error() method
+//
+ myTimer* pTimer=new myTimer(0, KLeaveCode);
+ pTimer->Start();
+ pTimer->After(100000);
+ TRAPD(ret,CActiveScheduler::Start());
+ test(ret==KmyErrorNum);
+//
+// Test cancelling an object
+// Without the cancel the schedule order should be: pTimer1, gTimer, pTimer3
+// gTimer is cancelled so should not be scheduled
+//
+ myTimer::SetNum(2);
+ myTimer* pTimer2=new myTimer(eHighest,KCancelCode);
+ myTimer* pTimer3=new myTimer(eLowest,eLowest);
+ pTimer2->Start();
+ pTimer2->After(100000);
+ gTimer->Start();
+ gTimer->After(1000000);
+ pTimer3->Start();
+ pTimer3->After(2000000);
+ CActiveScheduler::Start();
+ test(order[0]==KCancelCode && order[1]==eLowest);
+ delete pTimer;
+ delete pTimer2;
+ delete pTimer3;
+ }
+
+void TSecdulerTester::Test4()
+//
+// Create a thread with its own scheduler
+//
+ {
+
+ threadSemaphore.CreateLocal(0);
+ RThread myThread;
+ test(myThread.Create(_L("myThread"),myThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
+ myThread.Resume();
+ myThread.Close();
+ Test2();
+ threadSemaphore.Wait();
+ User::After(100000);
+ }
+
+GLDEF_C TInt E32Main()
+ {
+
+ // don't want just in time debugging as we trap panics
+ TBool justInTime=User::JustInTime();
+ User::SetJustInTime(EFalse);
+
+ test.Title();
+ __UHEAP_MARK;
+//
+ test.Start(_L("Test1"));
+ TSecdulerTester sched;
+ sched.Test1();
+ MyManager* pManager=new MyManager;
+ test(pManager!=NULL);
+ CActiveScheduler::Install(pManager);
+ test(CActiveScheduler::Current()==pManager);
+ MyManager* pManager2=new MyManager;
+ test(pManager2!=NULL);
+ delete pManager2;
+ test(CActiveScheduler::Current()==pManager);
+ pLowest=new myTimer(eLowest,eLowest);
+ test(pLowest!=NULL);
+ pLow=new myTimer(eLow,eLow);
+ test(pLow!=NULL);
+ pNone=new myTimer(eNone,eNone);
+ test(pNone!=NULL);
+ pHigh=new myTimer(eHigh,eHigh);
+ test(pHigh!=NULL);
+ pHigh2=new myTimer(eHigh,eHigh+2);
+ test(pHigh2!=NULL);
+ pHigh3=new myTimer(eHigh,eHigh+3);
+ test(pHigh3!=NULL);
+ pHighest=new myTimer(eHighest,eHighest);
+ test(pHighest!=NULL);
+ pLowest->Start();
+ pLow->Start();
+ pNone->Start();
+ pHigh->Start();
+ pHigh2->Start();
+ pHigh3->Start();
+ pHighest->Start();
+//
+ test.Next(_L("Test2"));
+ sched.Test2();
+ User::Check();
+//
+ test.Next(_L("Test3"));
+ gTimer=new myTimer(eNone, KgTimerID);
+ sched.Test3();
+//
+ test.Next(_L("Test4"));
+ sched.Test4();
+ delete gTimer;
+ User::Check();
+ delete pManager;
+ delete pLowest;
+ delete pLow;
+ delete pNone;
+ delete pHigh;
+ delete pHigh2;
+ delete pHigh3;
+ delete pHighest;
+//
+ test.End();
+ __UHEAP_MARKEND;
+
+ User::SetJustInTime(justInTime);
+ return(KErrNone);
+ }