diff -r 000000000000 -r bde4ae8d615e os/kernelhwsrv/kerneltest/e32test/active/t_cact.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/kernelhwsrv/kerneltest/e32test/active/t_cact.cpp Fri Jun 15 03:10:57 2012 +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 +#include + +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); + }