|
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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32test\active\t_cper.cpp |
|
15 // Overview: |
|
16 // Test periodic timers. |
|
17 // API Information: |
|
18 // CPeriodic, CHeartbeat |
|
19 // Details: |
|
20 // - Create some CPeriodic timer active objects with different priorities. |
|
21 // - Start the periodic timers with varying delay time to start generation |
|
22 // of first event and different intervals between events |
|
23 // - Verify the callback functions associated with each periodic are called |
|
24 // in order of the time when the event occurred and considering the priority |
|
25 // of the periodics. |
|
26 // - Create heartbeat timer with different priorities |
|
27 // - Start one heartbeat synchronized at ETwelveOClock |
|
28 // - Start two heartbeats synchronized at ETwelveOClock, ESixOClock |
|
29 // - Start three heartbeats synchronized at ETwelveOClock, ESixOClock, ETwelveOClock |
|
30 // - Display start time and beat time for each heartbeat timer |
|
31 // - Check if the heap has been corrupted by all the tests. |
|
32 // Platforms/Drives/Compatibility: |
|
33 // All. |
|
34 // Assumptions/Requirement/Pre-requisites: |
|
35 // Failures and causes: |
|
36 // - The first part of the test (for CPeriodic) will fail if the timers are not completed in order. |
|
37 // The test on emulator is very sensitive on the background activities on PC. |
|
38 // Base Port information: |
|
39 // |
|
40 // |
|
41 |
|
42 #include <e32base.h> |
|
43 #include <e32base_private.h> |
|
44 #include <e32hal.h> |
|
45 #include <e32test.h> |
|
46 #include <hal.h> |
|
47 #include <u32hal.h> |
|
48 #include <e32svr.h> |
|
49 |
|
50 LOCAL_D RTest test(_L("T_CPER")); |
|
51 |
|
52 class myScheduler: public CActiveScheduler |
|
53 { |
|
54 public: |
|
55 virtual void Error(TInt anError) const; |
|
56 }; |
|
57 |
|
58 void myScheduler::Error(TInt anError) const |
|
59 // |
|
60 // virtual error handler |
|
61 // |
|
62 { |
|
63 test.Panic(anError,_L("myScheduler::Error")); |
|
64 } |
|
65 |
|
66 TInt Array[11]; |
|
67 TTime Times[11]; |
|
68 TInt counter = 0; |
|
69 |
|
70 CPeriodic* pPer1; |
|
71 CPeriodic* pPer2; |
|
72 CPeriodic* pPer3; |
|
73 CPeriodic* pPer4; |
|
74 CPeriodic* pPer5; |
|
75 CPeriodic* pPer6; |
|
76 CPeriodic* pPer7; |
|
77 |
|
78 TInt CallBackFn(TAny* Ptr) |
|
79 // |
|
80 // Callback function used for all periodics |
|
81 // On calling Ptr is actually a TInt - the periodic Id |
|
82 // |
|
83 { |
|
84 if (counter < 11) |
|
85 { |
|
86 Array[counter] = (TInt)Ptr; |
|
87 Times[counter].HomeTime(); |
|
88 counter++; |
|
89 } |
|
90 return(0); |
|
91 } |
|
92 |
|
93 TInt CallBackPanic(TAny* Ptr) |
|
94 // |
|
95 // Periodic should never get called |
|
96 // |
|
97 { |
|
98 test.Printf(_L(" PERIODIC %d HAS GONE OFF!\n"),(TInt)Ptr); |
|
99 test(EFalse); |
|
100 return(KErrGeneral); |
|
101 } |
|
102 |
|
103 class myTimer: public CTimer |
|
104 { |
|
105 public: |
|
106 myTimer(TInt aPriority); |
|
107 virtual void RunL(); |
|
108 }; |
|
109 |
|
110 myTimer::myTimer(TInt aPriority) : CTimer(aPriority) |
|
111 // |
|
112 // Constructor - Creates AND ADDS TO MYSCHEDULER |
|
113 // |
|
114 { |
|
115 ConstructL(); |
|
116 myScheduler::Add(this); |
|
117 } |
|
118 |
|
119 void myTimer::RunL() |
|
120 // |
|
121 // The timer stops the scheduler |
|
122 // |
|
123 { |
|
124 myScheduler::Stop(); |
|
125 test.Printf(_L(" Timer has stopped ActiveScheduler\n")); |
|
126 } |
|
127 |
|
128 |
|
129 // |
|
130 // CHeartbeat test code |
|
131 // |
|
132 class CTick : public CBase, public MBeating |
|
133 { |
|
134 public: |
|
135 virtual void Beat(); |
|
136 virtual void Synchronize(); |
|
137 void Display(); |
|
138 TInt iTicks; |
|
139 TTime iStartTime; |
|
140 TTime iTimes[4]; |
|
141 }; |
|
142 void CTick::Beat() |
|
143 { |
|
144 |
|
145 test.Printf(_L("Tick\n")); |
|
146 iTimes[iTicks].HomeTime(); |
|
147 if (++iTicks>=4) |
|
148 CActiveScheduler::Stop(); |
|
149 } |
|
150 void CTick::Synchronize() |
|
151 { |
|
152 |
|
153 test.Printf(_L("Sync tick to system clock\n")); |
|
154 iStartTime.HomeTime(); |
|
155 iTicks=0; |
|
156 } |
|
157 |
|
158 void PrintTime(const TDesC& aName, const TTime& aTime) |
|
159 { |
|
160 TDateTime dt(aTime.DateTime()); |
|
161 test.Printf(_L("%S = %02d:%02d:%02d:%06d\n"),&aName,dt.Hour(),dt.Minute(),dt.Second(),dt.MicroSecond()); |
|
162 } |
|
163 |
|
164 void CTick::Display() |
|
165 { |
|
166 PrintTime(_L("Start time"),iStartTime); |
|
167 TInt i; |
|
168 for (i=0; i<4; i++) |
|
169 { |
|
170 TBuf<16> name; |
|
171 name.Format(_L("Beat %d"),i); |
|
172 PrintTime(name,iTimes[i]); |
|
173 } |
|
174 } |
|
175 |
|
176 class CTock : public CTick |
|
177 { |
|
178 public: |
|
179 virtual void Beat(); |
|
180 virtual void Synchronize(); |
|
181 }; |
|
182 |
|
183 void CTock::Beat() |
|
184 { |
|
185 |
|
186 iTimes[iTicks++].HomeTime(); |
|
187 test.Printf(_L("Tock\n")); |
|
188 } |
|
189 |
|
190 void CTock::Synchronize() |
|
191 { |
|
192 |
|
193 test.Printf(_L("Sync tock to system clock\n")); |
|
194 iStartTime.HomeTime(); |
|
195 iTicks=0; |
|
196 } |
|
197 |
|
198 class CBigTock : public CTick |
|
199 { |
|
200 public: |
|
201 virtual void Beat(); |
|
202 virtual void Synchronize(); |
|
203 }; |
|
204 |
|
205 void CBigTock::Beat() |
|
206 { |
|
207 |
|
208 iTimes[iTicks++].HomeTime(); |
|
209 test.Printf(_L("TOCK!\n")); |
|
210 } |
|
211 |
|
212 void CBigTock::Synchronize() |
|
213 { |
|
214 |
|
215 test.Printf(_L("Sync TOCK to system clock\n")); |
|
216 iStartTime.HomeTime(); |
|
217 iTicks=0; |
|
218 } |
|
219 |
|
220 void testHeartbeat() |
|
221 // |
|
222 // Test CHeartBeat |
|
223 // |
|
224 { |
|
225 |
|
226 test.Start(_L("Test CHeartbeat timer")); |
|
227 CActiveScheduler *scheduler = new CActiveScheduler; |
|
228 CActiveScheduler::Install(scheduler); |
|
229 |
|
230 test.Next(_L("Create a beating object synchronised at ETwelveOClock")); |
|
231 CTick *tick=new CTick; |
|
232 CHeartbeat *pH=NULL; |
|
233 TRAPD(r, pH=CHeartbeat::NewL(EPriorityNormal)); |
|
234 test(r==KErrNone); |
|
235 test.Next(_L("Run for 4 beats on the second")); |
|
236 pH->Start(ETwelveOClock, tick); |
|
237 CActiveScheduler::Start(); |
|
238 pH->Cancel(); |
|
239 tick->Display(); |
|
240 |
|
241 User::After(1000000); |
|
242 test.Next(_L("Create another heartbeat synchronised at ESixOClock")); |
|
243 CHeartbeat *pH6=CHeartbeat::New(EPriorityNormal); |
|
244 CTock *tock=new CTock; |
|
245 test.Next(_L("Start both")); |
|
246 pH->Start(ETwelveOClock, tick); |
|
247 pH6->Start(ESixOClock, tock); |
|
248 CActiveScheduler::Start(); |
|
249 tick->Display(); |
|
250 tock->Display(); |
|
251 |
|
252 pH->Cancel(); |
|
253 pH6->Cancel(); |
|
254 User::After(1000000); |
|
255 test.Next(_L("Create another beating object synchronised at ESixOClock with a higher priority")); |
|
256 CHeartbeat *pH2=CHeartbeat::New(EPriorityHigh); |
|
257 CBigTock *bigtock=new CBigTock; |
|
258 test.Next(_L("Start all")); |
|
259 pH->Start(ETwelveOClock, tick); |
|
260 pH6->Start(ESixOClock, tock); |
|
261 pH2->Start(ESixOClock, bigtock); |
|
262 CActiveScheduler::Start(); |
|
263 pH->Cancel(); |
|
264 pH2->Cancel(); |
|
265 pH6->Cancel(); |
|
266 tick->Display(); |
|
267 tock->Display(); |
|
268 bigtock->Display(); |
|
269 |
|
270 delete pH; |
|
271 delete pH2; |
|
272 delete pH6; |
|
273 delete tock; |
|
274 delete tick; |
|
275 delete bigtock; |
|
276 delete scheduler; |
|
277 test.End(); |
|
278 } |
|
279 |
|
280 void testLockSpec() |
|
281 // |
|
282 // test the operators defined for TTimerLockSpec |
|
283 // |
|
284 { |
|
285 /* |
|
286 test.Start(_L("Test pre fix operator ++")); |
|
287 TTimerLockSpec i=ETwelveOClock,k=EOneOClock,l; |
|
288 TInt j; |
|
289 for (j=0; j<30; j++) |
|
290 { |
|
291 ++k=EOneOClock; |
|
292 test(k==EOneOClock); |
|
293 k=i; |
|
294 l=++i; |
|
295 switch (k) |
|
296 { |
|
297 case EOneOClock: |
|
298 test(i==ETwoOClock); |
|
299 test(l==ETwoOClock); |
|
300 break; |
|
301 case ETwoOClock: |
|
302 test(i==EThreeOClock); |
|
303 test(l==EThreeOClock); |
|
304 break; |
|
305 case EThreeOClock: |
|
306 test(i==EFourOClock); |
|
307 test(l==EFourOClock); |
|
308 break; |
|
309 case EFourOClock: |
|
310 test(i==EFiveOClock); |
|
311 test(l==EFiveOClock); |
|
312 break; |
|
313 case EFiveOClock: |
|
314 test(i==ESixOClock); |
|
315 test(l==ESixOClock); |
|
316 break; |
|
317 case ESixOClock: |
|
318 test(i==ESevenOClock); |
|
319 test(l==ESevenOClock); |
|
320 break; |
|
321 case ESevenOClock: |
|
322 test(i==EEightOClock); |
|
323 test(l==EEightOClock); |
|
324 break; |
|
325 case EEightOClock: |
|
326 test(i==ENineOClock); |
|
327 test(l==ENineOClock); |
|
328 break; |
|
329 case ENineOClock: |
|
330 test(i==ETenOClock); |
|
331 test(l==ETenOClock); |
|
332 break; |
|
333 case ETenOClock: |
|
334 test(i==EElevenOClock); |
|
335 test(l==EElevenOClock); |
|
336 break; |
|
337 case EElevenOClock: |
|
338 test(i==ETwelveOClock); |
|
339 test(l==ETwelveOClock); |
|
340 break; |
|
341 case ETwelveOClock: |
|
342 test(i==EOneOClock); |
|
343 test(l==EOneOClock); |
|
344 break; |
|
345 } |
|
346 } |
|
347 |
|
348 test.Next(_L("Test post fix operator ++")); |
|
349 for (j=0; j<30; j++) |
|
350 { |
|
351 ++k=EOneOClock; |
|
352 test(k==EOneOClock); |
|
353 k=i; |
|
354 l=i++; |
|
355 switch (k) |
|
356 { |
|
357 case EOneOClock: |
|
358 test(i==ETwoOClock); |
|
359 test(l==k); |
|
360 break; |
|
361 case ETwoOClock: |
|
362 test(i==EThreeOClock); |
|
363 test(l==k); |
|
364 break; |
|
365 case EThreeOClock: |
|
366 test(i==EFourOClock); |
|
367 test(l==k); |
|
368 break; |
|
369 case EFourOClock: |
|
370 test(i==EFiveOClock); |
|
371 test(l==k); |
|
372 break; |
|
373 case EFiveOClock: |
|
374 test(i==ESixOClock); |
|
375 test(l==k); |
|
376 break; |
|
377 case ESixOClock: |
|
378 test(i==ESevenOClock); |
|
379 test(l==k); |
|
380 break; |
|
381 case ESevenOClock: |
|
382 test(i==EEightOClock); |
|
383 test(l==k); |
|
384 break; |
|
385 case EEightOClock: |
|
386 test(i==ENineOClock); |
|
387 test(l==k); |
|
388 break; |
|
389 case ENineOClock: |
|
390 test(i==ETenOClock); |
|
391 test(l==k); |
|
392 break; |
|
393 case ETenOClock: |
|
394 test(i==EElevenOClock); |
|
395 test(l==k); |
|
396 break; |
|
397 case EElevenOClock: |
|
398 test(i==ETwelveOClock); |
|
399 test(l==k); |
|
400 break; |
|
401 case ETwelveOClock: |
|
402 test(i==EOneOClock); |
|
403 test(l==k); |
|
404 break; |
|
405 } |
|
406 } |
|
407 test.End(); |
|
408 */ |
|
409 } |
|
410 |
|
411 |
|
412 GLDEF_C TInt E32Main() |
|
413 { |
|
414 |
|
415 test.Title(); |
|
416 __UHEAP_MARK; |
|
417 test.Start(_L("Create some CPeriodics")); |
|
418 |
|
419 myScheduler* pScheduler = new myScheduler; |
|
420 myScheduler::Install(pScheduler); |
|
421 |
|
422 pPer1 = CPeriodic::New(0); |
|
423 pPer2 = CPeriodic::NewL(0); |
|
424 pPer3 = CPeriodic::NewL(10); |
|
425 pPer4 = CPeriodic::NewL(100); |
|
426 pPer5 = CPeriodic::NewL(100); |
|
427 pPer6 = CPeriodic::NewL(100); |
|
428 pPer7 = CPeriodic::NewL(100); |
|
429 myTimer* pTimer = new myTimer(50); |
|
430 |
|
431 test.Next(_L("Start them")); |
|
432 |
|
433 TCallBack callBack1(CallBackFn,(TAny*)1); |
|
434 TCallBack callBack2(CallBackFn,(TAny*)2); |
|
435 TCallBack callBack3(CallBackFn,(TAny*)3); |
|
436 TCallBack callBack4(CallBackPanic,(TAny*)4); |
|
437 TCallBack callBack5(CallBackPanic,(TAny*)5); |
|
438 TCallBack callBack6(CallBackPanic,(TAny*)6); |
|
439 TCallBack callBack7(CallBackPanic,(TAny*)7); |
|
440 |
|
441 TInt p=0; |
|
442 HAL::Get(HAL::ESystemTickPeriod, p); |
|
443 |
|
444 User::After(p); // ensure tick does not occur while starting all these timers |
|
445 |
|
446 pPer1->Start(2*p+1,7*p+1,callBack1); //After 3 ticks, complete every 8th tick |
|
447 pPer2->Start(1, 2*p+1,callBack2); //After 1 tick , complete every 3rd tick |
|
448 pPer3->Start(7*p+1, p+1,callBack3); //After 8 ticks, complete every 2nd tick |
|
449 |
|
450 pPer4->Start(KMaxTInt,KMaxTInt,callBack4); |
|
451 pPer5->Start(60000000,60000000,callBack5); |
|
452 pPer6->Start(KMaxTInt/91,KMaxTInt/91,callBack6); |
|
453 pPer7->Start(KMaxTInt/91+1,KMaxTInt/91+1,callBack7); |
|
454 pTimer->After(20*p-1); // ensure there's enough time for them to fill up the array. |
|
455 /* |
|
456 Time per1 per2 per3 |
|
457 1 - |
|
458 2 |
|
459 3 - |
|
460 4 - |
|
461 5 |
|
462 6 |
|
463 7 - |
|
464 8 - |
|
465 9 |
|
466 10 - - |
|
467 11 - |
|
468 12 - |
|
469 13 - |
|
470 14 - |
|
471 */ |
|
472 |
|
473 myScheduler::Start(); |
|
474 |
|
475 TInt i; |
|
476 for (i=0; i<counter; ++i) |
|
477 { |
|
478 test.Printf(_L(" Time: %7d Periodic: %d\n"),static_cast<TUint32>(Times[i].Int64()-Times[0].Int64()),Array[i]); |
|
479 } |
|
480 |
|
481 test(Array[0]==2); |
|
482 test(Array[1]==1); |
|
483 test(Array[2]==2); |
|
484 test(Array[3]==2); |
|
485 test(Array[4]==3); |
|
486 TBool normal56 = (Array[5]==3 && Array[6]==2); |
|
487 TBool reverse56 = (Array[5]==2 && Array[6]==3); |
|
488 if (UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0) > 1) |
|
489 { |
|
490 // If there are multiple processors the order of 'simultaneous' timers is undefined since |
|
491 // the test may get to run as soon as the first timer is completed, instead of only after |
|
492 // the timer thread blocks, which would be after both timers completed. |
|
493 test(normal56 || reverse56); |
|
494 } |
|
495 else |
|
496 test(normal56); |
|
497 test(Array[7]==1); |
|
498 test(Array[8]==3); |
|
499 test(Array[9]==2); |
|
500 test(Array[10]==3); |
|
501 |
|
502 test.Next(_L("Destroy them")); |
|
503 |
|
504 delete pPer1; |
|
505 delete pPer2; |
|
506 delete pPer3; |
|
507 delete pPer4; |
|
508 delete pPer5; |
|
509 delete pPer6; |
|
510 delete pPer7; |
|
511 delete pTimer; |
|
512 delete pScheduler; |
|
513 |
|
514 test.Next(_L("Test CHeartbeat")); |
|
515 testHeartbeat(); |
|
516 test.Next(_L("Test TTimerLockSpec")); |
|
517 testLockSpec(); |
|
518 __UHEAP_MARKEND; |
|
519 test.End(); |
|
520 return(KErrNone); |
|
521 } |