Update contrib.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\active\t_cact.cpp
16 // Test the CActiveScheduler class, including scheduling priority, thread
17 // panics and cancelling objects attached to the scheduler.
21 // - Verify the thread is panicked when one of the following programming errors occurs:
22 // - start an uninstalled scheduler
23 // - install a scheduler twice
24 // - stop the scheduler twice
25 // - stop an uninstalled scheduler
26 // - set active an active object twice
27 // - add an active object to an uninstalled scheduler
28 // - add a NULL pointer to the scheduler
29 // - add an active object twice
30 // - thread gets a stray signal
31 // - make request on an un-added active object
32 // - Create timers with different priorities
33 // - Check the timers are scheduled according to expiration time
34 // - Check the timers are scheduled in order of their priority when they expire at the
36 // - Check the timers are scheduled in order of the addition to the scheduler when
37 // they expire at the same time and they have the same priority
38 // - Verify that a leave in RunL method not handled by the active object calls the active
39 // scheduler's Error method
40 // - Test a cancelled timer will not be scheduled
41 // - Create a thread with its own heap and test that timers are scheduled in the order of
42 // their expiration time, priority and order of addition to the scheduler
43 // - Check the heap is not corrupted by all the tests
44 // Platforms/Drives/Compatibility:
46 // Assumptions/Requirement/Pre-requisites:
47 // Failures and causes:
48 // Base Port information:
55 const TInt KmyErrorNum=999;
56 const TInt KLeaveCode=1234;
57 const TInt KgTimerID=4321;
58 const TInt KCancelCode=1111;
59 const TInt KTestArraySize=10;
60 const TInt KPanicThreadRet=2222;
61 const TInt KHeapSize=0x2000;
63 enum TActivePriority {eLowest=-100,eLow=-1,eNone=0,eHigh=1,eHighest=100};
64 enum TDirective {EStartUninstalled,EInstallTwice,EStopTwice,EStopUninstalled,ESetActiveTwice,
65 EAddToUninstalled,EAddNull,EAddTwice,ECreateStray,ERequestUnadded,EStraySignalNoKRequestPending,EStraySignalNoSetActive,ENormal};
76 class MyManager : public CActiveScheduler
79 virtual void Error(TInt anError) const {CActiveScheduler::Halt(anError);}
82 class myTimer : public CTimer
85 myTimer(const TInt aPriority, const TInt anIdentifier):CTimer(aPriority){iIdentifier=anIdentifier;}
88 void Setactive() {SetActive();}
89 static void SetNum(const TInt aNum) {iNum=aNum; iCount=0;}
96 class myThreadTimer : public CTimer
99 myThreadTimer(const TInt aPriority, const TInt anIdentifier):CTimer(aPriority){iIdentifier=anIdentifier;}
101 static void SetNum(const TInt aNum) {iNum=aNum; iCount=0;}
109 class CreateStray : public CActive
112 CreateStray(TInt aPriority);
119 class myStray : public CActive
122 myStray(TInt aPriority) : CActive(aPriority) {};
124 void RunL() { CActiveScheduler::Stop(); }
129 void myStray::Start1()
131 TRequestStatus* s=&iStatus;
133 RThread().RequestComplete(s,KErrNone);
136 void myStray::Start2()
138 TRequestStatus* s=&iStatus;
139 iStatus=KRequestPending;
140 User::RequestComplete(s,KErrNone);
143 TInt myTimer::iCount;
145 TInt myThreadTimer::iCount;
146 TInt myThreadTimer::iNum;
148 LOCAL_D RTest test(_L("T_CACT"));
149 LOCAL_D myTimer* gTimer; // This is cancelled from within the run method
150 LOCAL_D RSemaphore threadSemaphore;
151 LOCAL_D myTimer* pLowest=NULL;
152 LOCAL_D myTimer* pLow=NULL;
153 LOCAL_D myTimer* pNone=NULL;
154 LOCAL_D myTimer* pHigh=NULL;
155 LOCAL_D myTimer* pHigh2=NULL;
156 LOCAL_D myTimer* pHigh3=NULL;
157 LOCAL_D myTimer* pHighest=NULL;
158 LOCAL_D TInt order[KTestArraySize]; // When a timer expires its identifier is placed in here
159 LOCAL_D TInt threadArray[KTestArraySize];
161 LOCAL_C TInt myThreadEntryPoint(TAny*)
168 RTest test(_L("Separate thread tests"));
170 test.Start(_L("Create semaphore"));
172 TInt ret=t.CreateLocal();
175 test.Next(_L("Install scheduler"));
176 MyManager* pManager=new MyManager;
177 CActiveScheduler::Install(pManager);
179 test.Next(_L("Create active objects"));
180 myThreadTimer* pLowest=new myThreadTimer(eLowest, eLowest);
182 myThreadTimer* pLow=new myThreadTimer(eLow, eLow);
184 myThreadTimer* pNone=new myThreadTimer(eNone, eNone);
186 myThreadTimer* pHigh=new myThreadTimer(eHigh, eHigh);
188 myThreadTimer* pHigh2=new myThreadTimer(eHigh, eHigh+2);
190 myThreadTimer* pHigh3=new myThreadTimer(eHigh, eHigh+3);
192 myThreadTimer* pHighest=new myThreadTimer(eHighest, eHighest);
193 test(pHighest!=NULL);
195 test.Next(_L("Test low is scheduled before lowest"));
196 myThreadTimer::SetNum(2);
203 test(s==KRequestPending);
204 User::WaitForRequest(s);
205 CActiveScheduler::Start();
206 test(threadArray[0]==eLow && threadArray[1]==eLowest);
208 test.Next(_L("Test none is scheduled before low"));
209 myThreadTimer::SetNum(2);
214 test(s==KRequestPending);
215 User::WaitForRequest(s);
216 CActiveScheduler::Start();
217 test(threadArray[0]==eNone && threadArray[1]==eLow);
219 test.Next(_L("Test high is scheduled before none"));
220 myThreadTimer::SetNum(2);
225 test(s==KRequestPending);
226 User::WaitForRequest(s);
227 CActiveScheduler::Start();
228 test(threadArray[0]==eHigh && threadArray[1]==eNone);
230 test.Next(_L("Test highest is scheduled before high"));
231 myThreadTimer::SetNum(2);
236 test(s==KRequestPending);
237 User::WaitForRequest(s);
238 CActiveScheduler::Start();
239 test(threadArray[0]==eHighest && threadArray[1]==eHigh);
241 test.Next(_L("Test objects are scheduled according to priority"));
242 myThreadTimer::SetNum(5);
249 test(s==KRequestPending);
250 User::WaitForRequest(s);
251 CActiveScheduler::Start();
252 test(threadArray[0]==eHighest && threadArray[1]==eHigh && threadArray[2]==eNone &&
253 threadArray[3]==eLow && threadArray[4]==eLowest);
255 test.Next(_L("Test objects are scheduled according to timer expiry"));
256 myThreadTimer::SetNum(5);
259 pNone->After(1000000);
260 pHigh->After(1500000);
261 pHighest->After(2000000);
262 CActiveScheduler::Start();
263 test(threadArray[4]==eHighest && threadArray[3]==eHigh && threadArray[2]==eNone &&
264 threadArray[1]==eLow && threadArray[0]==eLowest);
266 test.Next(_L("Test with some objects having the same priority"));
267 myThreadTimer::SetNum(7);
278 test(s==KRequestPending);
279 User::WaitForRequest(s);
280 CActiveScheduler::Start();
281 test(threadArray[0]==eHighest && threadArray[1]==eHigh && threadArray[2]==eHigh+2 &&
282 threadArray[3]==eHigh+3 && threadArray[4]==eNone && threadArray[5]==eLow && threadArray[6]==eLowest);
284 test.Next(_L("Tidying up"));
295 threadSemaphore.Signal();
299 LOCAL_D TInt panicThread(TAny* aDirective)
301 // Test thread which panics
304 // cause panics in various ways depending upon aDirective
305 MyManager* pManager=new MyManager;
307 switch((TInt)aDirective)
309 case EStartUninstalled:
310 CActiveScheduler::Start(); // Start an uninstalled active schedler
313 CActiveScheduler::Install(pManager); // Install the scheduler twice
314 CActiveScheduler::Install(pManager);
317 CActiveScheduler::Install(pManager); // Stop a scheduler twice
318 CActiveScheduler::Stop();
319 CActiveScheduler::Stop();
321 case EStopUninstalled:
322 CActiveScheduler::Stop(); // Stop an uninstalled active scheduler
324 case ESetActiveTwice:
327 // Set an active object to active twice
329 myTimer* pTimer=new myTimer(eNone,eNone);
330 CActiveScheduler::Install(pManager);
331 CActiveScheduler::Add(pTimer);
336 case EAddToUninstalled:
339 // Add an active object to an uninstalled scheduler
341 myTimer* pTimer=new myTimer(eNone,eNone);
342 CActiveScheduler::Add(pTimer);
347 // Add Null to the scheduling queue
349 CActiveScheduler::Install(pManager);
350 CActiveScheduler::Add(NULL);
355 // Add the same object twice to the scheduling queue
357 myTimer* pTimer=new myTimer(eNone,eNone);
358 CActiveScheduler::Install(pManager);
359 CActiveScheduler::Add(pTimer);
360 CActiveScheduler::Add(pTimer);
366 // Create a stray signal
368 CActiveScheduler::Install(pManager);
370 CActiveScheduler::Start();
373 case ERequestUnadded:
376 // Make a request of an active object not added to the scheduling queue
378 CActiveScheduler::Install(pManager);
379 myTimer* pTimer=new myTimer(eNone,eNone);
383 case EStraySignalNoKRequestPending:
385 CActiveScheduler::Install(pManager);
386 myStray* pStray = new myStray(eNone);
387 CActiveScheduler::Add(pStray);
389 CActiveScheduler::Start();
392 case EStraySignalNoSetActive:
394 CActiveScheduler::Install(pManager);
395 myStray* pStray = new myStray(eNone);
396 CActiveScheduler::Add(pStray);
398 CActiveScheduler::Start();
406 return(KPanicThreadRet);
411 // Handle the timer completion
415 if (iIdentifier==KLeaveCode) // Used to test that the request manager error() method is called
416 User::Leave(KmyErrorNum);
417 if (iIdentifier==KCancelCode) // Used to test cancelling an object
419 order[iCount++]=iIdentifier;
421 CActiveScheduler::Stop();
424 void myTimer::Start()
431 CActiveScheduler::Add(this);
434 void myThreadTimer::RunL()
436 // Handle timer completion
440 threadArray[iCount++]=iIdentifier;
442 CActiveScheduler::Stop();
445 void myThreadTimer::Start()
452 CActiveScheduler::Add(this);
455 CreateStray::CreateStray(TInt aPriority)
462 iTimer.CreateLocal();
463 CActiveScheduler::Add(this);
464 iTimer.After(iStatus, 1000000);
467 void TSecdulerTester::Test1()
480 test.Start(_L("First test normal thread termination"));
481 TInt r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ENormal);
485 User::WaitForRequest(stat);
486 test(thread.ExitCategory().Compare(_L("Kill"))==0);
487 test(thread.ExitReason()==KPanicThreadRet);
488 test(thread.ExitType()==EExitKill);
489 CLOSE_AND_WAIT(thread);
491 test.Next(_L("Starting an uninstalled scheduler panics"));
492 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStartUninstalled);
496 User::WaitForRequest(stat);
497 test(thread.ExitReason()==EReqManagerDoesNotExist);
498 test(thread.ExitType()==EExitPanic);
499 CLOSE_AND_WAIT(thread);
501 test.Next(_L("Installing the scheduler twice panics"));
502 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EInstallTwice);
506 User::WaitForRequest(stat);
507 test(thread.ExitReason()==EReqManagerAlreadyExists);
508 test(thread.ExitType()==EExitPanic);
509 CLOSE_AND_WAIT(thread);
511 test.Next(_L("Stopping the scheduler twice panics"));
512 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStopTwice);
516 User::WaitForRequest(stat);
517 test(thread.ExitReason()==EReqTooManyStops);
518 test(thread.ExitType()==EExitPanic);
519 CLOSE_AND_WAIT(thread);
521 test.Next(_L("Stopping an uninstalled scheduler panics"));
522 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStopUninstalled);
526 User::WaitForRequest(stat);
527 test(thread.ExitReason()==EReqManagerDoesNotExist);
528 test(thread.ExitType()==EExitPanic);
529 CLOSE_AND_WAIT(thread);
531 test.Next(_L("Setting an active object to active twice panics"));
532 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ESetActiveTwice);
536 User::WaitForRequest(stat);
537 test(thread.ExitReason()==EReqAlreadyActive);
538 test(thread.ExitType()==EExitPanic);
539 CLOSE_AND_WAIT(thread);
541 test.Next(_L("Adding an active object to an uninstalled scheduler panics"));
542 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EAddToUninstalled);
546 User::WaitForRequest(stat);
547 test(thread.ExitReason()==EReqManagerDoesNotExist);
548 test(thread.ExitType()==EExitPanic);
549 CLOSE_AND_WAIT(thread);
551 test.Next(_L("Adding NULL panics"));
552 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EAddNull);
556 User::WaitForRequest(stat);
557 test(thread.ExitReason()==EReqNull);
558 test(thread.ExitType()==EExitPanic);
559 CLOSE_AND_WAIT(thread);
561 test.Next(_L("Adding an active object twice panics"));
562 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EAddTwice);
566 User::WaitForRequest(stat);
567 test(thread.ExitReason()==EReqAlreadyAdded);
568 test(thread.ExitType()==EExitPanic);
569 CLOSE_AND_WAIT(thread);
571 test.Next(_L("A stray signal causes a panic"));
572 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ECreateStray);
576 User::WaitForRequest(stat);
577 test(thread.ExitReason()==EReqStrayEvent);
578 test(thread.ExitType()==EExitPanic);
579 CLOSE_AND_WAIT(thread);
581 test.Next(_L("Making a request on an unadded active object panics"));
582 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)ERequestUnadded);
586 User::WaitForRequest(stat);
587 test(thread.ExitReason()==EActiveNotAdded);
588 test(thread.ExitType()==EExitPanic);
589 CLOSE_AND_WAIT(thread);
591 test.Next(_L("The service provider does not set the status to KRequestPending"));
592 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStraySignalNoKRequestPending);
596 User::WaitForRequest(stat);
598 //this might fail if we're using a UREL euser
599 test(thread.ExitReason()==EReqStrayEvent);
600 test(thread.ExitType()==EExitPanic);
602 test(thread.ExitCategory().Compare(_L("Kill"))==0);
603 test(thread.ExitReason()==KPanicThreadRet);
604 test(thread.ExitType()==EExitKill);
606 CLOSE_AND_WAIT(thread);
609 //this might fail if we're using a UREL euser
610 test.Next(_L("The active object does not call SetActive"));
611 r=thread.Create(_L("myThread"),panicThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)EStraySignalNoSetActive);
615 User::WaitForRequest(stat);
616 test(thread.ExitReason()==EReqStrayEvent);
617 test(thread.ExitType()==EExitPanic);
618 CLOSE_AND_WAIT(thread);
624 void TSecdulerTester::Test2()
630 test.Start(_L("Create timer"));
632 TInt ret=t.CreateLocal();
636 test.Next(_L("Test low is scheduled before lowest when timing equal"));
641 test(s==KRequestPending);
642 User::WaitForRequest(s);
643 CActiveScheduler::Start();
644 test(order[0]==eLow && order[1]==eLowest);
646 test.Next(_L("Test low is not before lowest when it expires later"));
649 pLow->After(1000000);
650 CActiveScheduler::Start();
651 test(order[0]==eLowest && order[1]==eLow);
653 test.Next(_L("Test none is scheduled before low"));
658 test(s==KRequestPending);
659 User::WaitForRequest(s);
660 CActiveScheduler::Start();
661 test(order[0]==eNone && order[1]==eLow);
663 test.Next(_L("Test none is not before low when it expires later"));
666 pNone->After(1000000);
667 CActiveScheduler::Start();
668 test(order[0]==eLow && order[1]==eNone);
670 test.Next(_L("Test high is scheduled before none"));
675 test(s==KRequestPending);
676 User::WaitForRequest(s);
677 CActiveScheduler::Start();
678 test(order[0]==eHigh && order[1]==eNone);
680 test.Next(_L("Test high is not before none when it expires later"));
682 pHigh->After(1000000);
684 CActiveScheduler::Start();
685 test(order[0]==eNone && order[1]==eHigh);
687 test.Next(_L("Test highest is scheduled before high"));
692 test(s==KRequestPending);
693 User::WaitForRequest(s);
694 CActiveScheduler::Start();
695 test(order[0]==eHighest && order[1]==eHigh);
697 test.Next(_L("Test highest is not before high when it expires later"));
699 pHighest->After(1000000);
701 CActiveScheduler::Start();
702 test(order[0]==eHigh && order[1]==eHighest);
704 test.Next(_L("Test all objects are scheduled in priority order"));
712 test(s==KRequestPending);
713 User::WaitForRequest(s);
714 CActiveScheduler::Start();
715 test(order[0]==eHighest && order[1]==eHigh && order[2]==eNone && order[3]==eLow && order[4]==eLowest);
717 test.Next(_L("Test objects are scheduled according to expiry of timers"));
721 pNone->After(1000000);
722 pHigh->After(1500000);
723 pHighest->After(2000000);
724 CActiveScheduler::Start();
725 test(order[4]==eHighest && order[3]==eHigh && order[2]==eNone && order[1]==eLow && order[0]==eLowest);
727 test.Next(_L("Test with some objects having the same priority"));
737 test(s==KRequestPending);
738 User::WaitForRequest(s);
739 CActiveScheduler::Start();
740 test(order[0]==eHighest && order[1]==eHigh && order[2]==eHigh+2 && order[3]==eHigh+3 && order[4]==eNone && order[5]==eLow && order[6]==eLowest);
745 void TSecdulerTester::Test3()
752 // Test that a leave in a Run method calls the requestmanager error() method
754 myTimer* pTimer=new myTimer(0, KLeaveCode);
756 pTimer->After(100000);
757 TRAPD(ret,CActiveScheduler::Start());
758 test(ret==KmyErrorNum);
760 // Test cancelling an object
761 // Without the cancel the schedule order should be: pTimer1, gTimer, pTimer3
762 // gTimer is cancelled so should not be scheduled
765 myTimer* pTimer2=new myTimer(eHighest,KCancelCode);
766 myTimer* pTimer3=new myTimer(eLowest,eLowest);
768 pTimer2->After(100000);
770 gTimer->After(1000000);
772 pTimer3->After(2000000);
773 CActiveScheduler::Start();
774 test(order[0]==KCancelCode && order[1]==eLowest);
780 void TSecdulerTester::Test4()
782 // Create a thread with its own scheduler
786 threadSemaphore.CreateLocal(0);
788 test(myThread.Create(_L("myThread"),myThreadEntryPoint,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
792 threadSemaphore.Wait();
796 GLDEF_C TInt E32Main()
799 // don't want just in time debugging as we trap panics
800 TBool justInTime=User::JustInTime();
801 User::SetJustInTime(EFalse);
806 test.Start(_L("Test1"));
807 TSecdulerTester sched;
809 MyManager* pManager=new MyManager;
810 test(pManager!=NULL);
811 CActiveScheduler::Install(pManager);
812 test(CActiveScheduler::Current()==pManager);
813 MyManager* pManager2=new MyManager;
814 test(pManager2!=NULL);
816 test(CActiveScheduler::Current()==pManager);
817 pLowest=new myTimer(eLowest,eLowest);
819 pLow=new myTimer(eLow,eLow);
821 pNone=new myTimer(eNone,eNone);
823 pHigh=new myTimer(eHigh,eHigh);
825 pHigh2=new myTimer(eHigh,eHigh+2);
827 pHigh3=new myTimer(eHigh,eHigh+3);
829 pHighest=new myTimer(eHighest,eHighest);
830 test(pHighest!=NULL);
839 test.Next(_L("Test2"));
843 test.Next(_L("Test3"));
844 gTimer=new myTimer(eNone, KgTimerID);
847 test.Next(_L("Test4"));
863 User::SetJustInTime(justInTime);