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_act.cpp
16 // Test CTimer based timers and error handling in active objects and
19 // CTimer, CActiveScheduler
21 // - Create and install the active scheduler
22 // - Create a timer, add it to the active scheduler and start the timer
23 // - Verify RunL is run when the timer fires off and test dequeuing itself from
24 // the active scheduler
25 // - Test that when a leave in RunL occurs, the active object gets the chance to
26 // handle it before the active scheduler
27 // - Test that leaves in RunL can be handled successfully in the active object
28 // - Test the active object can propagate the leave to the active scheduler
29 // - Test that leaves in RunL can be handled successfully in the active scheduler
30 // Platforms/Drives/Compatibility:
32 // Assumptions/Requirement/Pre-requisites:
33 // Failures and causes:
34 // Base Port information:
41 class CMyRequestManager : public CActiveScheduler
51 virtual void Error(TInt anError) const;
52 void SetMode(TMode aExpect);
58 class CMyTimer : public CTimer
61 static CMyTimer* New();
64 void StartLeave(TBool aHandleLocally, TBool aLeaveInOOM, CMyRequestManager::TMode aMode);
65 virtual TInt RunError(TInt aError);
67 void StartImbalance();
70 CMyTimer(TInt aPriority);
72 enum {EMaxCount=10,ETimeReq=100000};
83 LOCAL_D RTest test(_L("T_ACT"));
85 void CMyRequestManager::Error(TInt anError) const
87 // Called if any Run() method leaves.
94 _LIT(KExpectError,"CMyRequestManager::Error handling error %d\n");
95 test.Printf(KExpectError,anError);
99 case EGenerateException:
102 _LIT(KExpectError,"CMyRequestManager::Error about to generate exception...\n");
103 test.Printf(KExpectError,anError);
106 TRAPD(ret,User::Leave(KErrArgument));
108 if (ret != KErrArgument)
110 _LIT(KDoNotExpectError,"CMyRequestManager::Error unexpected");
111 test.Panic(anError,KDoNotExpectError);
119 _LIT(KDoNotExpectError,"CMyRequestManager::Error unexpected");
120 test.Panic(anError,KDoNotExpectError);
126 void CMyRequestManager::SetMode(TMode aMode)
131 CMyTimer* CMyTimer::New()
133 // Create a new CMyTimer.
137 return(new CMyTimer(0));
140 CMyTimer::CMyTimer(TInt aPriority)
144 : CTimer(aPriority),iCount(0), iImbalance(EFalse), iStopping(EFalse)
147 CMyTimer::~CMyTimer()
152 void CMyTimer::Start()
159 TRAPD(r, ConstructL());
161 iConstructed = ETrue;
162 iDummy = new(ELeave)CBase();
164 CActiveScheduler::Add(this); // Previously caused panic in UREL after Deque()
169 void CMyTimer::StartLeave(TBool aHandleLocally, TBool aLeaveInOOM, CMyRequestManager::TMode aMode)
174 CActiveScheduler::Add(this);
178 iHandleLocally = aHandleLocally;
179 iLeaveInOOM = aLeaveInOOM;
180 // STATIC_CAST(CMyRequestManager*,CActiveScheduler::Current())->ExpectError(!aHandleLocally);
181 STATIC_CAST(CMyRequestManager*,CActiveScheduler::Current())->SetMode(aMode);
184 void CMyTimer::StopLeave()
189 void CMyTimer::StartImbalance()
194 void CMyTimer::RunL()
196 // The timer has completed.
201 Deque(); // Test removal from scheduler
206 User::Leave(KErrGeneral);
209 // This switch is used when testing for imbalance in the cleanupstack
216 //CleanupStack::PopAndDestroy(iDummy);
217 CActiveScheduler::Stop();
222 // Push something onto the stack, but dont take it off
223 //- deal in CActiveScheduler::DoRunL
224 CleanupStack::PushL(iDummy);
225 iStopping=ETrue; //Stop the scheduler the next time
227 // CActiveScheduler::Stop();
235 test.Printf(_L("\r%03d"),iCount);
237 if (iCount<EMaxCount)
241 test.Printf(_L("\n"));
242 CActiveScheduler::Stop();
243 Deque(); // Test removal from scheduler
248 TInt CMyTimer::RunError(TInt aError)
250 // Handle leave from RunL
255 _LIT(KExpectError,"CMyTimer::RunError handling error %d\n");
256 test.Printf(KExpectError,aError);
257 CActiveScheduler::Stop();
261 return aError; // Let the scheduler handle this error
265 TInt DoImbalanceTest(TAny* /*aAny*/)
266 // This function is the first executing fuction of the cleanupstack imbalace
267 // testing thread - RunLCleanupImbalance
268 // see ImbalanceTest()
270 // Set up cleanup stack & scheduler
271 RTest test(_L("Thread:RunLCleanupImbalance - DoImbalanceTest()"));
272 test.Start(_L("DoImbalanceTest()"));
274 //Create a cleanup stack and scheduler
276 CActiveScheduler* cas = new(ELeave) CActiveScheduler();
277 CActiveScheduler::Install(cas);
280 CMyTimer* myTimer = CMyTimer::New();
281 myTimer->StopLeave();
282 myTimer->StartImbalance();
284 test.Next(_L("Start Imblance Test"));
287 test.Next(_L("Start Scheduler"));
288 // The following is expected to panic (with EUSER-CBase 90 EClnCheckFailed)
298 LOCAL_C void ImbalanceTest()
299 // this test will test whether the cleanup stack is imbalanced after
300 // a runL of an Active object.
302 TBool imbalanced = ETrue;
303 User::SetJustInTime(EFalse);
306 test.Next(_L("Create a thread (RunLCleanupImbalance)"));
307 TInt r=t.Create(_L("RunLCleanupImbalance"),DoImbalanceTest,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,&imbalanced);
310 test.Next(_L("Resume and wait for panic (E32USER-CBase 90 EClnCheckFailed) due to imbalance"));
312 User::WaitForRequest(s);
314 test.Printf(_L("Exit Type %d\r\n"),(TInt)t.ExitType());
315 test.Printf(_L("Exit Reason %d\r\n"),(TInt)t.ExitReason());
317 test(t.ExitReason()==EClnCheckFailed);
324 GLDEF_C TInt E32Main()
330 test.Start(_L("Creating CActiveScheduler"));
331 CMyRequestManager* pR=new CMyRequestManager;
333 CActiveScheduler::Install(pR);
335 test.Next(_L("Testing relative timers"));
336 CMyTimer* pT=CMyTimer::New();
339 test.Next(_L("Start timer"));
342 test.Next(_L("Start CMyRequestManager"));
343 CActiveScheduler::Start();
345 test.Next(_L("Start timer again"));
348 test.Next(_L("Start CMyRequestManager"));
349 CActiveScheduler::Start();
351 test.Next(_L("Start timer, leave in RunL, handle in scheduler"));
352 pT->StartLeave(EFalse, EFalse, CMyRequestManager::EExpectError );
354 test.Next(_L("Start CMyRequestManager"));
355 CActiveScheduler::Start();
358 test.Next(_L("Start timer, leave in RunL, generate nested exception under OOM condition"));
359 pT->StartLeave(EFalse, ETrue, CMyRequestManager::EGenerateException);
361 test.Next(_L("Start CMyRequestManager"));
362 CActiveScheduler::Start();
366 test.Next(_L("Start timer, leave in RunL, handle in object"));
367 pT->StartLeave(ETrue, EFalse, CMyRequestManager::EPanic);
369 test.Next(_L("Start CMyRequestManager"));
370 CActiveScheduler::Start();
373 // Test the cleanupstack imbalances
374 test.Next(_L("Test : Check Cleanupstack imbalance in RunL, handle(panic) in scheduler"));