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