|
1 // Copyright (c) 2005-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\emi\t_emi.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include <e32test.h> |
|
19 #include <e32math.h> |
|
20 #include <e32def.h> |
|
21 #include <e32def_private.h> |
|
22 #include "d_emitest.h" |
|
23 |
|
24 //#define VERBOSE |
|
25 |
|
26 LOCAL_D RTest test(_L("T_EMI")); |
|
27 |
|
28 _LIT(KEMITestLddFileName,"D_EMITEST"); |
|
29 const TInt KHeapSize=0x200; |
|
30 |
|
31 REMITest Ldd; |
|
32 |
|
33 |
|
34 /* |
|
35 TestEventLogging |
|
36 |
|
37 Tests initialisation of the logging system, ensuring no memory leaks, and then that user events can |
|
38 be added and read correctly. |
|
39 |
|
40 The test tries filling and emptying the buffer from each possible start position. |
|
41 Each time it over fills it (Causing offset to rotate) and each time try and take too many. |
|
42 The last record should show the event lost flag. Each field is checked for consistency. |
|
43 |
|
44 */ |
|
45 |
|
46 void TestEventLogging() |
|
47 { |
|
48 TInt no; |
|
49 TInt i; |
|
50 TInt ii; |
|
51 TInt iii; |
|
52 TUint time; |
|
53 TInt wrapcount = 0; |
|
54 TInt changecount = 0; |
|
55 |
|
56 TUserTaskEventRecord outrec; |
|
57 TUserTaskEventRecord rec[5]; |
|
58 TUserTaskEventRecord blank; |
|
59 |
|
60 |
|
61 //! @SYMTestCaseID t_emi_0 |
|
62 //! @SYMTestType CT |
|
63 //! @SYMTestCaseDesc Set/Get State |
|
64 //! @SYMPREQ PREQ898 |
|
65 //! @SYMTestActions Sets the EMI user state randomly 100 times, and reads back the state. |
|
66 //! @SYMTestExpectedResults The read back state should always be the same as set. |
|
67 //! @SYMTestPriority High |
|
68 //! @SYMTestStatus Defined |
|
69 |
|
70 test.Next(_L("(Set/Get)State")); |
|
71 for (i=0; i<100; i++) |
|
72 { |
|
73 no = Math::Random(); |
|
74 Ldd.SetState(no); |
|
75 test(Ldd.GetState()==no); |
|
76 } |
|
77 |
|
78 //! @SYMTestCaseID t_emi_1 |
|
79 //! @SYMTestType CT |
|
80 //! @SYMTestCaseDesc Log Alloc/Free |
|
81 //! @SYMPREQ PREQ898 |
|
82 //! @SYMTestActions Allocates different sizes of event log. |
|
83 //! @SYMTestExpectedResults No memory leak. |
|
84 //! @SYMTestPriority High |
|
85 //! @SYMTestStatus Defined |
|
86 |
|
87 test.Next(_L("TaskEventLogging - Log Alloc/Free")); |
|
88 |
|
89 __KHEAP_MARK; |
|
90 test(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNone); |
|
91 test(Ldd.TaskEventLogging(EFalse,2,ENone)==KErrNone); |
|
92 test(Ldd.TaskEventLogging(EFalse,200,ENone)==KErrNone); |
|
93 test(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNone); |
|
94 __KHEAP_MARKEND; |
|
95 |
|
96 #ifdef _DEBUG |
|
97 __KHEAP_MARK; |
|
98 __KHEAP_FAILNEXT(1); |
|
99 test(Ldd.TaskEventLogging(EFalse,200,ENone)==KErrNoMemory); |
|
100 __KHEAP_MARKEND; |
|
101 #endif |
|
102 |
|
103 |
|
104 //! @SYMTestCaseID t_emi_2 |
|
105 //! @SYMTestType CT |
|
106 //! @SYMTestCaseDesc AddTaskEvent/GetTaskEvent |
|
107 //! @SYMPREQ PREQ898 |
|
108 //! @SYMTestActions Tries filling and emptying the buffer from each possible start position. Each time it over fills it (Causing offset to rotate) and each time try and take too many. |
|
109 //! @SYMTestExpectedResults The last record of each group should show the event lost flag. Except for the lost record, the contents should be consistant with when the record was added. |
|
110 //! @SYMTestPriority High |
|
111 //! @SYMTestStatus Defined |
|
112 |
|
113 test.Next(_L("AddTaskEvent/GetTaskEvent")); |
|
114 |
|
115 test(!Ldd.GetTaskEvent(outrec)); |
|
116 |
|
117 test(Ldd.TaskEventLogging(EFalse,5,ENone)==KErrNone); |
|
118 |
|
119 test(Ldd.AddTaskEvent(blank)); |
|
120 test(Ldd.GetTaskEvent(outrec)); |
|
121 |
|
122 time=outrec.iTime; |
|
123 |
|
124 test(!Ldd.GetTaskEvent(outrec)); |
|
125 |
|
126 // This next test tries filling and emptying the buffer from each possible start position. |
|
127 // Each time it over fills it (Causeing offset to rotate) and each time try and take too many. |
|
128 // The last record should show the event lost flag. |
|
129 |
|
130 // To ensure the time field is samething like you'd expect, let it tick over by 50. |
|
131 iii=0; |
|
132 do |
|
133 { |
|
134 for (ii=0; ii<5; ii++) |
|
135 { |
|
136 test(Ldd.AddTaskEvent(blank)); //will be lost |
|
137 for (i=0; i<5; i++) |
|
138 { |
|
139 rec[i].iType=(TUint8) ((Math::Random() & 255) | 128); |
|
140 rec[i].iFlags=0; |
|
141 rec[i].iExtra=(TUint16) (Math::Random() & 65535); |
|
142 rec[i].iPrevious=&rec[i]; |
|
143 rec[i].iNext=&rec[ii]; |
|
144 no = Math::Random(); |
|
145 Ldd.SetState(no); |
|
146 test(Ldd.AddTaskEvent(rec[i])); |
|
147 rec[i].iUserState=no; |
|
148 } |
|
149 |
|
150 for (i=0; i<5; i++) |
|
151 { |
|
152 test(Ldd.GetTaskEvent(outrec)); |
|
153 #ifdef VERBOSE |
|
154 test.Printf(_L("%x : Type %x(%x), Time %x, flag %x, ThdA %x ThdB %x\n"),i,outrec.iType,rec[i].iType,outrec.iTime, outrec.iFlags, outrec.iPrevious,outrec.iNext); |
|
155 #endif |
|
156 if (i==0) |
|
157 test((outrec.iFlags & KEMI_EventLost)==KEMI_EventLost); |
|
158 else |
|
159 test((outrec.iFlags & KEMI_EventLost)!=KEMI_EventLost); |
|
160 |
|
161 test(outrec.iType==rec[i].iType); |
|
162 test(outrec.iExtra==rec[i].iExtra); |
|
163 test(outrec.iPrevious==rec[i].iPrevious); |
|
164 test(outrec.iNext==rec[i].iNext); |
|
165 test(outrec.iUserState==rec[i].iUserState); |
|
166 if (outrec.iTime!=time) |
|
167 { |
|
168 if (outrec.iTime<time) |
|
169 wrapcount++; |
|
170 time=outrec.iTime; |
|
171 changecount++; |
|
172 } |
|
173 } |
|
174 test(!Ldd.GetTaskEvent(outrec)); |
|
175 } |
|
176 #ifdef VERBOSE |
|
177 test.Printf(_L("Time = %i\n"),time); |
|
178 #endif |
|
179 iii++; |
|
180 if (changecount<50) |
|
181 User::After(1); |
|
182 } while ((changecount<50) && (iii<50)); |
|
183 test(changecount>=50); |
|
184 test(wrapcount<2); |
|
185 } |
|
186 |
|
187 |
|
188 |
|
189 /* Used by TestStartStopMonitors() and TestScheduleEventLogging() */ |
|
190 |
|
191 TBool ShortLivedThreadDone; |
|
192 |
|
193 LOCAL_C TInt ShortLivedThread(TAny*) |
|
194 { |
|
195 int i; |
|
196 for (i=0; i<50; i++) |
|
197 User::After(1); |
|
198 ShortLivedThreadDone=ETrue; |
|
199 return(KErrNone); |
|
200 } |
|
201 |
|
202 |
|
203 /* |
|
204 TestStartStopMonitors |
|
205 |
|
206 Checks Start monitor was iterated with current thread list on startup. |
|
207 It then creates and destroys a thread, and see if it triggered the |
|
208 monitor callbacks in the test driver. The test driver will add |
|
209 events to the event log, which are read and checked. |
|
210 |
|
211 */ |
|
212 |
|
213 void TestStartStopMonitors() |
|
214 { |
|
215 TInt i; |
|
216 TInt no; |
|
217 TUserTaskEventRecord outrec; |
|
218 RThread thread; |
|
219 TRequestStatus stat; |
|
220 TAny* myNThread; |
|
221 TInt seenIdle; |
|
222 TInt seenSigma; |
|
223 |
|
224 TAny* idleThread; |
|
225 TAny* sigmaThread; |
|
226 |
|
227 //! @SYMTestCaseID t_emi_5 |
|
228 //! @SYMTestType CT |
|
229 //! @SYMTestCaseDesc Null/Sigma |
|
230 //! @SYMPREQ PREQ898 |
|
231 //! @SYMTestActions Get the null and sigma thread pointers. |
|
232 //! @SYMTestExpectedResults Non-null pointers, which are usable in the following tests. |
|
233 //! @SYMTestPriority High |
|
234 //! @SYMTestStatus Defined |
|
235 |
|
236 |
|
237 test.Next(_L("Check Null/Sigma")); |
|
238 sigmaThread=Ldd.GetSigmaThread(); |
|
239 test(sigmaThread!=NULL); |
|
240 |
|
241 idleThread=Ldd.GetIdleThread(); |
|
242 test(idleThread!=NULL); |
|
243 |
|
244 sigmaThread=((TInt*) sigmaThread)+1; |
|
245 idleThread=((TInt*) idleThread)+1; |
|
246 |
|
247 //! @SYMTestCaseID t_emi_3 |
|
248 //! @SYMTestType CT |
|
249 //! @SYMTestCaseDesc Thread start/stop Monitors |
|
250 //! @SYMPREQ PREQ898 |
|
251 //! @SYMTestActions The start stop monitors are enabled. The start/stop monitors have been made to add event log entries, to allow there execution to be visible. After all existing threads have be iterated by the start monitor, the log is first filled with random entries for the thread, and then the log is watched as a thread is started and stopped. |
|
252 //! @SYMTestExpectedResults At least 15 threads should be iterated on activation, and then both monitors should be called for the new thread. The random entries should have changed to refer to the sigma thread. |
|
253 //! @SYMTestPriority High |
|
254 //! @SYMTestStatus Defined |
|
255 |
|
256 test.Next(_L("Thread start/stop Monitors")); |
|
257 for (i=0; i<3; i++) |
|
258 { |
|
259 test(Ldd.TaskEventLogging(EFalse,50,ENone)==KErrNone); |
|
260 test(Ldd.TaskEventLogging(EFalse,50,ENormal)==KErrNone); |
|
261 |
|
262 |
|
263 // Check Start monitor was iterated with current thread list. |
|
264 test.Printf(_L("Check start monitor called for theads. (try %d)\n"),i); |
|
265 |
|
266 seenIdle=0; |
|
267 seenSigma=0; |
|
268 |
|
269 no=0; |
|
270 while (Ldd.GetTaskEvent(outrec)) |
|
271 { |
|
272 test(outrec.iType==128); |
|
273 if (outrec.iPrevious==sigmaThread) |
|
274 { |
|
275 test.Printf(_L("Seen Sigma Thread\n")); |
|
276 seenSigma++; |
|
277 } |
|
278 if (outrec.iPrevious==idleThread) |
|
279 { |
|
280 test.Printf(_L("Seen Idle Thread\n")); |
|
281 seenIdle++; |
|
282 } |
|
283 |
|
284 no++; |
|
285 } |
|
286 test.Printf(_L("Records = %d\n"),no); |
|
287 test(no>=15); |
|
288 test(seenSigma==1); |
|
289 test(seenIdle==1); |
|
290 } |
|
291 |
|
292 |
|
293 |
|
294 test.Next(_L("Check monitor behaviour on thead creation/deletion")); |
|
295 |
|
296 // To test monitors, we need to create and destroy a thread, and see if it |
|
297 // triggered the callbacks in the test driver. The test driver will add |
|
298 // events to the event log. |
|
299 |
|
300 |
|
301 // First Check for background noise |
|
302 for (i=0; i<50; i++) |
|
303 { |
|
304 test(!Ldd.GetTaskEvent(outrec)); |
|
305 User::After(1); |
|
306 } |
|
307 |
|
308 test.Printf(_L("Create Thread..\n")); |
|
309 // Start thread, and let it die |
|
310 |
|
311 test(thread.Create(_L("ShortLivedThread"),ShortLivedThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone); |
|
312 thread.Logon(stat); |
|
313 test(stat==KRequestPending); |
|
314 |
|
315 myNThread = Ldd.GetNThread(thread); |
|
316 |
|
317 // Fill with records - should not survive cleanup |
|
318 for (i=0; i<50; i++) |
|
319 { |
|
320 outrec.iType=(TUint8) (((Math::Random() & 63) + 10) | 128); |
|
321 |
|
322 outrec.iPrevious= i<5?myNThread:(TAny*) Math::Random(); |
|
323 outrec.iNext= i>10?myNThread:(TAny*) Math::Random(); |
|
324 |
|
325 test(Ldd.AddTaskEvent(outrec)); |
|
326 } |
|
327 |
|
328 // Let thead run |
|
329 thread.Resume(); |
|
330 User::WaitForRequest(stat); |
|
331 thread.Close(); |
|
332 test(Ldd.TaskEventLogging(EFalse,50,ENone)==KErrNone); |
|
333 |
|
334 // Did it leave log as expected? |
|
335 test.Printf(_L("Check for logging/Clearing\n")); |
|
336 i = 0; |
|
337 no=0; |
|
338 while (Ldd.GetTaskEvent(outrec)) |
|
339 { |
|
340 i++; |
|
341 #ifdef VERBOSE |
|
342 test.Printf(_L("%x : Type %x, Time %x,ThdA %x ThdB %x\n"),i,outrec.iType,outrec.iTime, outrec.iPrevious,outrec.iNext); |
|
343 #endif |
|
344 if (outrec.iType==128) |
|
345 { |
|
346 test((TInt)outrec.iPrevious==((TInt) myNThread)+4); |
|
347 no++; |
|
348 } |
|
349 if (outrec.iType==129) |
|
350 { |
|
351 test(outrec.iPrevious==myNThread); |
|
352 no++; |
|
353 } |
|
354 else |
|
355 { |
|
356 test(outrec.iPrevious!=myNThread); |
|
357 test(outrec.iNext!=myNThread); |
|
358 } |
|
359 } |
|
360 test (no==2); |
|
361 } |
|
362 |
|
363 |
|
364 |
|
365 /* |
|
366 |
|
367 Thread Tracking functions, |
|
368 used in TestScheduleEventLogging() and TestTagMaskDFC() |
|
369 |
|
370 */ |
|
371 |
|
372 struct TThreadList |
|
373 { |
|
374 TAny* iThread; |
|
375 TUint iRan; |
|
376 }; |
|
377 |
|
378 TThreadList ThreadList[51]; |
|
379 TInt NoThreads=0; |
|
380 |
|
381 inline TUint LookupThread(TAny* aThread) |
|
382 { |
|
383 for (TInt i=0; i<NoThreads;i++) |
|
384 if (aThread==ThreadList[i].iThread) |
|
385 return i; |
|
386 if (NoThreads<49) |
|
387 { |
|
388 ThreadList[NoThreads].iThread=aThread; |
|
389 ThreadList[NoThreads].iRan=0; |
|
390 NoThreads++; |
|
391 |
|
392 } |
|
393 return NoThreads-1; |
|
394 } |
|
395 |
|
396 void AddThread(TAny* aThread) |
|
397 { |
|
398 test(NoThreads<49); |
|
399 ThreadList[NoThreads].iThread=aThread; |
|
400 ThreadList[NoThreads].iRan=0; |
|
401 NoThreads++; |
|
402 } |
|
403 |
|
404 |
|
405 /* |
|
406 TestScheduleEventLogging |
|
407 |
|
408 Checks AfterIdle, Null/Sigma thread lookup, Set/Get Loggable, as well as |
|
409 Schedule Event logging. Select threads are marked as loggable, and starts a |
|
410 new thread (that repeatadly sleeps for short times, to generate events). |
|
411 The events are then collected and all of the fields checked. The test |
|
412 |
|
413 */ |
|
414 |
|
415 void TestScheduleEventLogging() |
|
416 { |
|
417 RThread thread; |
|
418 TRequestStatus stat; |
|
419 TAny* myNThread; |
|
420 TInt i; |
|
421 TInt ii; |
|
422 TUint time=0; |
|
423 TInt wrapcount = 0; |
|
424 TInt changecount = 0; |
|
425 TUserTaskEventRecord outrec; |
|
426 |
|
427 |
|
428 //! @SYMTestCaseID t_emi_4 |
|
429 //! @SYMTestType CT |
|
430 //! @SYMTestCaseDesc AfterIdle |
|
431 //! @SYMPREQ PREQ898 |
|
432 //! @SYMTestActions Uses AfterIdle. |
|
433 //! @SYMTestExpectedResults No panic. |
|
434 //! @SYMTestPriority High |
|
435 //! @SYMTestStatus Defined |
|
436 |
|
437 |
|
438 test.Next(_L("Check AfterIdle")); |
|
439 Ldd.AfterIdle(100); |
|
440 |
|
441 |
|
442 //! @SYMTestCaseID t_emi_6 |
|
443 //! @SYMTestType CT |
|
444 //! @SYMTestCaseDesc Set/Get Loggable |
|
445 //! @SYMPREQ PREQ898 |
|
446 //! @SYMTestActions Get/Set ThreadLoggable are used on multiple threads. |
|
447 //! @SYMTestExpectedResults The Get function should confirm that the Set function changed the loggable state. |
|
448 //! @SYMTestPriority High |
|
449 //! @SYMTestStatus Defined |
|
450 |
|
451 test.Next(_L("Check Set/Get Loggable")); |
|
452 myNThread=Ldd.GetSigmaThread(); |
|
453 test(myNThread!=NULL); |
|
454 AddThread(myNThread); |
|
455 |
|
456 myNThread=Ldd.GetIdleThread(); |
|
457 test(myNThread!=NULL); |
|
458 AddThread(myNThread); |
|
459 |
|
460 |
|
461 Ldd.SetThreadLoggable(myNThread,ETrue); |
|
462 test(Ldd.GetThreadLoggable(myNThread)!=EFalse); |
|
463 |
|
464 Ldd.SetThreadLoggable(myNThread,EFalse); |
|
465 test(Ldd.GetThreadLoggable(myNThread)==EFalse); |
|
466 |
|
467 Ldd.SetThreadLoggable(myNThread,ETrue); |
|
468 test(Ldd.GetThreadLoggable(myNThread)!=EFalse); |
|
469 |
|
470 |
|
471 //! @SYMTestCaseID t_emi_7 |
|
472 //! @SYMTestType CT |
|
473 //! @SYMTestCaseDesc Set/Get VEMSData |
|
474 //! @SYMPREQ PREQ898 |
|
475 //! @SYMTestActions Get/Set VEMSData are used on a thread 100 times. |
|
476 //! @SYMTestExpectedResults The Get function should confirm that the Set function set the value correctly. |
|
477 //! @SYMTestPriority High |
|
478 //! @SYMTestStatus Defined |
|
479 |
|
480 |
|
481 test.Next(_L("(Set/Get) VEMSData")); |
|
482 |
|
483 test.Printf(_L("Spawn Thread\n")); |
|
484 ShortLivedThreadDone=EFalse; |
|
485 test(thread.Create(_L("ShortLivedThread"),ShortLivedThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone); |
|
486 thread.Logon(stat); |
|
487 test(stat==KRequestPending); |
|
488 myNThread = Ldd.GetNThread(thread); |
|
489 Ldd.SetThreadLoggable(myNThread,ETrue); |
|
490 AddThread(myNThread); |
|
491 test(Ldd.GetThreadLoggable(myNThread)!=EFalse); |
|
492 |
|
493 for (i=0; i<100; i++) |
|
494 { |
|
495 ii = Math::Random(); |
|
496 Ldd.SetVEMSData(myNThread,(TAny*)ii); |
|
497 test((TInt)Ldd.GetVEMSData(myNThread)==ii); |
|
498 } |
|
499 |
|
500 //! @SYMTestCaseID t_emi_8 |
|
501 //! @SYMTestType CT |
|
502 //! @SYMTestCaseDesc Task Event Logging |
|
503 //! @SYMPREQ PREQ898 |
|
504 //! @SYMTestActions Task event logging is turned on, with a thread running in the background. Some threads set as loggable. Each event record is inspected, and a count for the seen thread in incremented. User state is incremented on each iteration. |
|
505 //! @SYMTestExpectedResults Each thread ran at lest 10 times. Time changed over 45 times, but wrapped no more then once. User state changed over 15, some events where seen to be waiting, thread order is consistent, record type is correct, and at lest 100 records where read before the test finished. |
|
506 //! @SYMTestPriority High |
|
507 //! @SYMTestStatus Defined |
|
508 |
|
509 |
|
510 |
|
511 test.Next(_L("Task Event Logging")); |
|
512 |
|
513 Ldd.SetState(0); |
|
514 thread.Resume(); |
|
515 User::After(1); |
|
516 test(Ldd.TaskEventLogging(ETrue,50,ENone)==KErrNone); |
|
517 i=0; |
|
518 ii=0; |
|
519 TInt prevNextThread=-1; |
|
520 TInt lastThread; |
|
521 TInt nextThread; |
|
522 TBool seenWaiting=EFalse; |
|
523 wrapcount=0; |
|
524 changecount=0; |
|
525 TUint lastUserState=0; |
|
526 TInt userStateChange=0; |
|
527 FOREVER |
|
528 { |
|
529 |
|
530 if (!Ldd.GetTaskEvent(outrec)) |
|
531 { |
|
532 if ((i>100) && ShortLivedThreadDone) |
|
533 break; |
|
534 Ldd.AfterIdle(5); |
|
535 test((ii++)<500); //timeout! |
|
536 } |
|
537 else |
|
538 { |
|
539 lastThread=LookupThread(outrec.iPrevious); |
|
540 nextThread=LookupThread(outrec.iNext); |
|
541 #ifdef VERBOSE |
|
542 test.Printf(_L("%x: Ty %x Tm %x ThdA %x ThdB %x F %x U %x\n"), |
|
543 i,outrec.iType,outrec.iTime, lastThread,nextThread, outrec.iFlags, outrec.iUserState); |
|
544 #endif |
|
545 test(outrec.iType==0); |
|
546 |
|
547 |
|
548 if (outrec.iTime!=time) |
|
549 { |
|
550 if ((outrec.iTime<time) && (time!=0)) |
|
551 wrapcount++; |
|
552 time=outrec.iTime; |
|
553 changecount++; |
|
554 } |
|
555 |
|
556 if ((outrec.iFlags & KEMI_PrevWaiting)!=0) |
|
557 seenWaiting=ETrue; |
|
558 |
|
559 if (((outrec.iFlags & KEMI_EventLost)==0) && (prevNextThread!=-1)) |
|
560 test (prevNextThread==lastThread); |
|
561 prevNextThread=nextThread; |
|
562 ThreadList[nextThread].iRan++; |
|
563 |
|
564 test(outrec.iUserState>=lastUserState); |
|
565 if (outrec.iUserState!=lastUserState) |
|
566 { |
|
567 userStateChange++; |
|
568 lastUserState=outrec.iUserState; |
|
569 } |
|
570 |
|
571 i++; |
|
572 Ldd.SetState(i); |
|
573 } |
|
574 if ((i>100) && ShortLivedThreadDone) |
|
575 test(Ldd.TaskEventLogging(EFalse,50,ENone)==KErrNone); |
|
576 } |
|
577 |
|
578 test.Printf(_L("DTime %x DState %x Wrap %x\n"),changecount,userStateChange, wrapcount); |
|
579 |
|
580 test(changecount>=45); |
|
581 test(userStateChange>15); |
|
582 test(wrapcount<2); |
|
583 |
|
584 test(seenWaiting); |
|
585 |
|
586 User::WaitForRequest(stat); |
|
587 thread.Close(); |
|
588 |
|
589 for (i=0; i<NoThreads;i++) |
|
590 { |
|
591 test.Printf(_L("Thread %x ran %d times.\n"),i,ThreadList[i].iRan); |
|
592 test(ThreadList[i].iRan>10); |
|
593 } |
|
594 } |
|
595 |
|
596 |
|
597 |
|
598 |
|
599 /* TagMaskTestThread() - used by TestTagMaskDFC */ |
|
600 LOCAL_C TInt TagMaskTestThread(TAny*) |
|
601 { |
|
602 TInt i; |
|
603 TInt mask=1; |
|
604 for (i=0; i<31; i++) |
|
605 { |
|
606 User::After(1); |
|
607 mask = mask << 1; |
|
608 Ldd.SetMask(mask); |
|
609 } |
|
610 ShortLivedThreadDone=ETrue; |
|
611 return(KErrNone); |
|
612 } |
|
613 |
|
614 /* |
|
615 TestTagMaskDFC() |
|
616 |
|
617 Checks Mask and Tag setting. |
|
618 Checks a that a DFC (found in driver) is triggered my an apropriate tag and mask. |
|
619 */ |
|
620 |
|
621 void TestTagMaskDFC() |
|
622 { |
|
623 RThread thread; |
|
624 TRequestStatus stat; |
|
625 TAny* myNThread; |
|
626 TUserTaskEventRecord outrec; |
|
627 TInt i=0; |
|
628 TInt ii=0; |
|
629 TInt seen9=0; |
|
630 TInt seen18=0; |
|
631 TInt seen27=0; |
|
632 TUint no; |
|
633 |
|
634 #ifdef VERBOSE |
|
635 TInt lastThread; |
|
636 #endif |
|
637 TInt nextThread; |
|
638 |
|
639 |
|
640 //! @SYMTestCaseID t_emi_9 |
|
641 //! @SYMTestType CT |
|
642 //! @SYMTestCaseDesc Set/Get Mask |
|
643 //! @SYMPREQ PREQ898 |
|
644 //! @SYMTestActions Get/Set the mask 100 times. |
|
645 //! @SYMTestExpectedResults The Get function should confirm that the Set function changed the mask state. |
|
646 //! @SYMTestPriority High |
|
647 //! @SYMTestStatus Defined |
|
648 |
|
649 |
|
650 test.Next(_L("(Set/Get)Mask")); |
|
651 for (i=0; i<100; i++) |
|
652 { |
|
653 no = Math::Random(); |
|
654 Ldd.SetMask(no); |
|
655 test(Ldd.GetMask()==no); |
|
656 } |
|
657 |
|
658 //! @SYMTestCaseID t_emi_10 |
|
659 //! @SYMTestType CT |
|
660 //! @SYMTestCaseDesc Tag/Mask DFC |
|
661 //! @SYMPREQ PREQ898 |
|
662 //! @SYMTestActions A DFC is set than will change the user state to the results of GetDFCTriggerTag. The event log is monitored, with a background thread, which has had a tag set. This thread repeatedly changes the mask. |
|
663 //! @SYMTestExpectedResults The state should be seen to change once to the correct tag for the thread. Other factors also checked in t_emi_7 should show the test running correctly. |
|
664 //! @SYMTestPriority High |
|
665 //! @SYMTestStatus Defined |
|
666 |
|
667 |
|
668 test.Next(_L("Tag/Mask DFC.")); |
|
669 |
|
670 NoThreads=0; // Reset Thread Tracking |
|
671 |
|
672 myNThread=Ldd.GetSigmaThread(); |
|
673 test(myNThread!=NULL); |
|
674 AddThread(myNThread); |
|
675 |
|
676 myNThread=Ldd.GetIdleThread(); |
|
677 test(myNThread!=NULL); |
|
678 AddThread(myNThread); |
|
679 |
|
680 Ldd.SetThreadLoggable(myNThread,ETrue); |
|
681 test(Ldd.GetThreadLoggable(myNThread)!=EFalse); |
|
682 |
|
683 Ldd.SetDfc(); |
|
684 test(Ldd.GetMask()==0); |
|
685 |
|
686 test.Printf(_L("Spawn Thread\n")); |
|
687 ShortLivedThreadDone=EFalse; |
|
688 test(thread.Create(_L("TagMaskTestThread"),TagMaskTestThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone); |
|
689 thread.Logon(stat); |
|
690 test(stat==KRequestPending); |
|
691 myNThread = Ldd.GetNThread(thread); |
|
692 test(Ldd.GetThreadLoggable(myNThread)==EFalse); |
|
693 Ldd.SetThreadLoggable(myNThread,ETrue); |
|
694 test(Ldd.GetThreadLoggable(myNThread)!=EFalse); |
|
695 AddThread(myNThread); |
|
696 Ldd.SetThreadTag(myNThread,(1<<9)+(1<<18)+(1<<27)); |
|
697 test(Ldd.GetThreadTag(myNThread)==(1<<9)+(1<<18)+(1<<27)); |
|
698 |
|
699 Ldd.SetState(0); |
|
700 |
|
701 test.Printf(_L("Start Event Logging\n")); |
|
702 test(Ldd.TaskEventLogging(ETrue,50,ENone)==KErrNone); |
|
703 |
|
704 thread.Resume(); |
|
705 |
|
706 FOREVER |
|
707 { |
|
708 if (!Ldd.GetTaskEvent(outrec)) |
|
709 { |
|
710 if ((i>100) && ShortLivedThreadDone) |
|
711 break; |
|
712 Ldd.AfterIdle(5); |
|
713 test((ii++)<500); //timeout! |
|
714 } |
|
715 else |
|
716 { |
|
717 |
|
718 #ifdef VERBOSE |
|
719 lastThread=LookupThread(outrec.iPrevious); |
|
720 #else |
|
721 LookupThread(outrec.iPrevious); |
|
722 #endif |
|
723 nextThread=LookupThread(outrec.iNext); |
|
724 |
|
725 #ifdef VERBOSE |
|
726 test.Printf(_L("%x: Ty %x Tm %x ThdA %x ThdB %x F %x U %x\n"), |
|
727 i,outrec.iType,outrec.iTime, lastThread,nextThread, outrec.iFlags, outrec.iUserState); |
|
728 #endif |
|
729 |
|
730 ThreadList[nextThread].iRan++; |
|
731 |
|
732 switch(outrec.iUserState) |
|
733 { |
|
734 case 0 : break; |
|
735 case (1<<9) : ++seen9; break; |
|
736 case (1<<18): ++seen18; break; |
|
737 case (1<<27): ++seen27; break; |
|
738 default: test(0); // bad state |
|
739 } |
|
740 } |
|
741 i++; |
|
742 if ((i>100) && ShortLivedThreadDone) |
|
743 test(Ldd.TaskEventLogging(EFalse,50,ENone)==KErrNone); |
|
744 |
|
745 } |
|
746 Ldd.SetMask(0); |
|
747 |
|
748 test(seen9); |
|
749 test(seen18); |
|
750 test(seen27); |
|
751 User::WaitForRequest(stat); |
|
752 thread.Close(); |
|
753 |
|
754 for (i=0; i<NoThreads;i++) |
|
755 { |
|
756 test.Printf(_L("Thread %x ran %d times.\n"),i,ThreadList[i].iRan); |
|
757 test(ThreadList[i].iRan>10); |
|
758 } |
|
759 test(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNone); |
|
760 } |
|
761 |
|
762 |
|
763 /* |
|
764 void SoakTest() |
|
765 |
|
766 Repeatedly changes the start/exit monitors, while repeatedly starting and stopping threads. |
|
767 As threads exit, they are checked for consistency. |
|
768 |
|
769 */ |
|
770 |
|
771 TBool FinishedSoak=EFalse; |
|
772 TBool Going=EFalse; |
|
773 LOCAL_C TInt SoakTest_Thread(TAny*) |
|
774 { |
|
775 int i; |
|
776 Going=ETrue; |
|
777 for (i=(Math::Random() & 1); i<2; i++) |
|
778 User::AfterHighRes(1000+(Math::Random() & 31)); |
|
779 return(KErrNone); |
|
780 } |
|
781 |
|
782 TInt MainCount=0; |
|
783 TInt ThreadGenCount=0; |
|
784 TInt Maxloops=4100; |
|
785 TBool Forever=EFalse; |
|
786 TInt State=1; |
|
787 TInt GoodCount=0; |
|
788 |
|
789 LOCAL_C TInt SoakTest_ThreadGenerator(TAny*) |
|
790 { |
|
791 const TInt NOTHREADS=100; |
|
792 |
|
793 RThread threadlist[NOTHREADS]; |
|
794 TRequestStatus threadlist_stat[NOTHREADS]; |
|
795 TInt head=0; |
|
796 TInt tail=0; |
|
797 TBool done=EFalse; |
|
798 TInt newHead; |
|
799 RThread thisThread = RThread(); |
|
800 FOREVER |
|
801 { |
|
802 |
|
803 switch (Math::Random() & 63) |
|
804 { |
|
805 case 1: thisThread.SetPriority(EPriorityLess); |
|
806 break; |
|
807 case 2: thisThread.SetPriority(EPriorityNormal); |
|
808 break; |
|
809 case 3: thisThread.SetPriority(EPriorityMore); |
|
810 break; |
|
811 } |
|
812 |
|
813 newHead = head+1; |
|
814 if (newHead==NOTHREADS) |
|
815 newHead=0; |
|
816 if ((newHead!=tail) && !done) //not full & not finished |
|
817 { |
|
818 test(threadlist[head].Create(_L(""),SoakTest_Thread,KDefaultStackSize,NULL,NULL)==KErrNone); |
|
819 threadlist[head].Logon(threadlist_stat[head]); |
|
820 switch (Math::Random() & 3) |
|
821 { |
|
822 case 1: threadlist[head].SetPriority(EPriorityLess); |
|
823 break; |
|
824 case 2: threadlist[head].SetPriority(EPriorityNormal); |
|
825 break; |
|
826 case 3: threadlist[head].SetPriority(EPriorityMore); |
|
827 break; |
|
828 } |
|
829 |
|
830 threadlist[head].Resume(); |
|
831 head=newHead; |
|
832 } |
|
833 else |
|
834 { |
|
835 if (head==tail)//empty |
|
836 { |
|
837 |
|
838 if (done) |
|
839 break; |
|
840 } |
|
841 |
|
842 else |
|
843 { |
|
844 User::WaitForRequest(threadlist_stat[tail] ); |
|
845 |
|
846 if (State==1) |
|
847 { |
|
848 State=(TInt) Ldd.GetVEMSData(Ldd.GetNThread(threadlist[tail])); |
|
849 if (State!=1) |
|
850 done=ETrue; |
|
851 else |
|
852 GoodCount++; |
|
853 } |
|
854 threadlist[tail].Close(); |
|
855 tail++; |
|
856 if (tail==NOTHREADS) |
|
857 tail=0; |
|
858 } |
|
859 } |
|
860 if ((Math::Random() & 63)==1) |
|
861 User::AfterHighRes((Math::Random() & 32)); |
|
862 ThreadGenCount=MainCount; |
|
863 if ((ThreadGenCount>=Maxloops) && !Forever) |
|
864 done=ETrue; |
|
865 } |
|
866 FinishedSoak=ETrue; |
|
867 return(KErrNone); |
|
868 } |
|
869 |
|
870 |
|
871 void SoakTest() |
|
872 { |
|
873 RThread threadGenerator; |
|
874 TRequestStatus stat; |
|
875 TInt count=0; |
|
876 TInt oldcount=0; |
|
877 RThread thisThread = RThread(); |
|
878 TInt ret; |
|
879 TMonitors monitor=EStressSecond; |
|
880 |
|
881 test.Next(_L("Repeated monitor switching Test")); |
|
882 test(Ldd.TaskEventLogging(EFalse,0,EStressSecond)==KErrNone); |
|
883 |
|
884 for (count=1; count<100; count++) |
|
885 { |
|
886 |
|
887 Going=EFalse; |
|
888 test(threadGenerator.Create(_L(""),SoakTest_Thread,KDefaultStackSize,NULL,NULL)==KErrNone); |
|
889 threadGenerator.Logon(stat); |
|
890 test(stat==KRequestPending); |
|
891 threadGenerator.Resume(); |
|
892 while (!Going) User::AfterHighRes(Math::Random() & 15); |
|
893 |
|
894 monitor= (monitor==EStressFirst)?EStressSecond:EStressFirst; |
|
895 test(Ldd.TaskEventLogging(EFalse,0,monitor)==KErrNone); |
|
896 |
|
897 if (count & 1) |
|
898 { |
|
899 monitor= (monitor==EStressFirst)?EStressSecond:EStressFirst; |
|
900 test(Ldd.TaskEventLogging(EFalse,0,monitor)==KErrNone); |
|
901 } |
|
902 User::WaitForRequest(stat); |
|
903 ret=(TInt) Ldd.GetVEMSData(Ldd.GetNThread(threadGenerator)); |
|
904 if (ret!=1) |
|
905 test.Printf(_L("Thread %x had VEMs value was %x \n"),count,ret); |
|
906 threadGenerator.Close(); |
|
907 test(ret==1); |
|
908 } |
|
909 |
|
910 |
|
911 // Full soak test |
|
912 |
|
913 count=1; |
|
914 test.Next(_L("Soak test")); |
|
915 test(Ldd.TaskEventLogging(EFalse,0,EStressSecond)==KErrNone); |
|
916 |
|
917 // Start threadGenerator |
|
918 test(threadGenerator.Create(_L("threadGenerator"),SoakTest_ThreadGenerator,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone); |
|
919 threadGenerator.Logon(stat); |
|
920 test(stat==KRequestPending); |
|
921 threadGenerator.Resume(); |
|
922 |
|
923 for (;!FinishedSoak; MainCount=ThreadGenCount+1) |
|
924 { |
|
925 switch (Math::Random() & 63) |
|
926 { |
|
927 case 1: thisThread.SetPriority(EPriorityLess); |
|
928 break; |
|
929 case 2: thisThread.SetPriority(EPriorityNormal); |
|
930 break; |
|
931 case 3: thisThread.SetPriority(EPriorityMore); |
|
932 break; |
|
933 } |
|
934 |
|
935 // Now repeatadly start and stop the start/exit monitors. |
|
936 test(Ldd.TaskEventLogging(EFalse,0,EStressFirst)==KErrNone); |
|
937 if ((Math::Random() & 63)==1) |
|
938 User::AfterHighRes((Math::Random() & 31)); |
|
939 test(Ldd.TaskEventLogging(EFalse,0,EStressSecond)==KErrNone); |
|
940 if (MainCount>>7 != oldcount) |
|
941 { |
|
942 oldcount=MainCount>>7; |
|
943 if ((count & 15)==1) |
|
944 test.Printf(_L("\nCount: ")); |
|
945 test.Printf(_L("%x "),count); |
|
946 |
|
947 count++; |
|
948 } |
|
949 if ((Math::Random() & 63)==1) |
|
950 User::AfterHighRes((Math::Random() & 31)); |
|
951 } |
|
952 |
|
953 test.Printf(_L("\nDone.\n: ")); |
|
954 User::WaitForRequest(stat); |
|
955 threadGenerator.Close(); |
|
956 if (State!=1) |
|
957 { |
|
958 test.Printf(_L("Thread %x VEMs value was %x \n"),GoodCount,State); |
|
959 test(0); |
|
960 } |
|
961 |
|
962 test(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNone); |
|
963 } |
|
964 |
|
965 void ParseCommandLine() |
|
966 { |
|
967 TBuf<32> args; |
|
968 User::CommandLine(args); |
|
969 |
|
970 if (args == KNullDesC) |
|
971 { |
|
972 test.Printf(_L("No soaklength specified, using default.\n")); |
|
973 return; |
|
974 } |
|
975 else if (args == _L("-")) |
|
976 { |
|
977 test.Printf(_L("Infinate soaklength specified.\n")); |
|
978 |
|
979 Forever=ETrue; |
|
980 } |
|
981 else |
|
982 { |
|
983 TLex l(args); |
|
984 TInt r = l.Val(Maxloops); |
|
985 if (r != KErrNone) |
|
986 { |
|
987 test.Printf(_L("Bad parameter!\nUsage: t_emi <soaklength>\n '-' indicates infinity.\n\n")); |
|
988 User::After(4000000); |
|
989 test(0); |
|
990 } |
|
991 else |
|
992 { |
|
993 test.Printf(_L("Soaklength set to 0x%x\n"),Maxloops); |
|
994 Maxloops = Maxloops << 7; |
|
995 } |
|
996 |
|
997 } |
|
998 } |
|
999 |
|
1000 /* |
|
1001 E32Main - Where it all begins. |
|
1002 */ |
|
1003 |
|
1004 GLDEF_C TInt E32Main() |
|
1005 { |
|
1006 TInt r; |
|
1007 |
|
1008 test.Title(); |
|
1009 ParseCommandLine(); |
|
1010 |
|
1011 test.Start(_L("Loading Device")); |
|
1012 |
|
1013 r=User::LoadLogicalDevice(KEMITestLddFileName); |
|
1014 test(r==KErrNone || r==KErrAlreadyExists); |
|
1015 |
|
1016 test.Next(_L("Open Logical Channel")); |
|
1017 r=Ldd.Open(); |
|
1018 test(r==KErrNone); |
|
1019 |
|
1020 |
|
1021 test.Next(_L("Calling LDD")); |
|
1022 |
|
1023 if(Ldd.TaskEventLogging(EFalse,0,ENone)==KErrNotSupported) |
|
1024 { |
|
1025 test.Printf(_L("********************\n")); |
|
1026 test.Printf(_L("* NO EMI SUPPORT *\n")); |
|
1027 test.Printf(_L("********************\n")); |
|
1028 test.Printf(_L("* Testing SKIPPED *\n")); |
|
1029 test.Printf(_L("********************\n")); |
|
1030 User::After(2000000); //Time to read it! |
|
1031 test.Next(_L("Close Logical Channel")); |
|
1032 Ldd.Close(); |
|
1033 test.End(); |
|
1034 return(0); |
|
1035 } |
|
1036 |
|
1037 // Start Testing! |
|
1038 |
|
1039 TestEventLogging(); |
|
1040 TestStartStopMonitors(); |
|
1041 TestScheduleEventLogging(); |
|
1042 TestTagMaskDFC(); |
|
1043 SoakTest(); |
|
1044 |
|
1045 test.Next(_L("Close Logical Channel")); |
|
1046 Ldd.Close(); |
|
1047 test.End(); |
|
1048 |
|
1049 return(0); |
|
1050 } |