|
1 // Copyright (c) 2008-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 "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 // |
|
15 |
|
16 /** |
|
17 @file |
|
18 @test |
|
19 @internalComponent - Internal Symbian test code |
|
20 */ |
|
21 |
|
22 #include "tmultiptreventhandlingperf.h" |
|
23 #include <hal.h> |
|
24 |
|
25 _LIT(KPerformanceTimingChunk, "PerformanceTimingChunk"); |
|
26 |
|
27 // Number of iterations for eventset |
|
28 const TInt KNumOfIterations = 100; |
|
29 |
|
30 // Maximum descriptor length for results |
|
31 const TInt KMaxDescLength = 528; |
|
32 |
|
33 // Static variables used for synchronisation between threads |
|
34 GLDEF_D TInt NumOfEventsAdded = 0; |
|
35 GLDEF_D RMutex Mutex; |
|
36 GLDEF_D RCondVar ConVar; |
|
37 |
|
38 void MultiPtrPerfPanic(TInt aPanic) |
|
39 { |
|
40 User::Panic(_L("MultiPterEventHanldingPerformancePanic"), aPanic); |
|
41 } |
|
42 |
|
43 // This function opens the chunk and adds the failure description followed by '*' |
|
44 TInt CMultiPtrPerfTestControl::Failed(TPoint3D aExp3DPoint, TPoint3D aActual3DPoint, TInt aErrorCode, TInt aExpPtrNum, TInt aActPtrNum) |
|
45 { |
|
46 TInt ret = iChunk.OpenGlobal(KPerformanceTimingChunk, ETrue); |
|
47 if (ret != KErrNone) |
|
48 { |
|
49 return ret; |
|
50 } |
|
51 TUint8* desPtr = iChunk.Base() + iChunkOffset; |
|
52 TPtr8 ptrDes(desPtr, 0, KMaxDescLength); |
|
53 |
|
54 TBuf<80> buf; |
|
55 if (aExpPtrNum != aActPtrNum) |
|
56 { |
|
57 _LIT(KFailedPointerNum, "Failed Expected Pointer Num = %d Actual Pointer Num = %d*"); |
|
58 buf.AppendFormat(KFailedPointerNum, aExpPtrNum, aActPtrNum); |
|
59 ptrDes.Append(buf); |
|
60 } |
|
61 else if (aErrorCode != KErrNone) |
|
62 { |
|
63 _LIT(KFailedErrorCode, "Failed Errorcode = %d*"); |
|
64 buf.AppendFormat(KFailedErrorCode, aErrorCode); |
|
65 ptrDes.Append(buf); |
|
66 } |
|
67 else |
|
68 { |
|
69 _LIT(KFailedWrongCoord, "Failed Coordinates Expected = [%d, %d, %d] Actual = [%d, %d, %d]*"); |
|
70 buf.AppendFormat(KFailedWrongCoord, aExp3DPoint.iX, aExp3DPoint.iY, aExp3DPoint.iZ, aActual3DPoint.iX, aActual3DPoint.iY, aActual3DPoint.iZ); |
|
71 ptrDes.Append(buf); |
|
72 } |
|
73 |
|
74 iChunk.Close(); |
|
75 return ret; |
|
76 } |
|
77 |
|
78 // This function opens the chunk and adds a pointer event not supported message followed by '#' |
|
79 TInt CMultiPtrPerfTestControl::PointerEventsNotSupported() |
|
80 { |
|
81 iPointerEventNotSupported = ETrue; |
|
82 TInt ret = iChunk.OpenGlobal(KPerformanceTimingChunk, ETrue); |
|
83 if (ret != KErrNone) |
|
84 { |
|
85 return ret; |
|
86 } |
|
87 TUint8* desPtr = iChunk.Base() + iChunkOffset; |
|
88 TPtr8 ptrDes(desPtr, 0, KMaxDescLength); |
|
89 TBuf<80> buf; |
|
90 _LIT(KPointerEventsNotSupported, "Test Skipped As Pointer Events Are Not Supported By This Configuration#"); |
|
91 buf.AppendFormat(KPointerEventsNotSupported); |
|
92 ptrDes.Append(buf); |
|
93 iChunk.Close(); |
|
94 return ret; |
|
95 } |
|
96 |
|
97 // This function calulates the average latency, opens the chunk and appends |
|
98 // the same in descriptor form. Then close the child thread and calls function |
|
99 // for creating new thread for events. |
|
100 // If all the events have been tested then stops the tests |
|
101 // by calling active CActiveScheduler::Stop. |
|
102 TInt CMultiPtrPerfTestControl::CalculateLatencyAndStartThread() |
|
103 { |
|
104 TInt ret = KErrNone; |
|
105 switch (iPtrAppUi->TestCaseNum()) |
|
106 { |
|
107 case 1: |
|
108 case 5: |
|
109 case 9: |
|
110 case 13: |
|
111 iAverageLatency = iLatency/(4*KNumOfIterations); |
|
112 break; |
|
113 case 2: |
|
114 case 6: |
|
115 case 10: |
|
116 case 14: |
|
117 iAverageLatency = iLatency/(8*KNumOfIterations); |
|
118 break; |
|
119 case 3: |
|
120 case 7: |
|
121 case 11: |
|
122 case 15: |
|
123 iAverageLatency = iLatency/(16*KNumOfIterations); |
|
124 break; |
|
125 case 4: |
|
126 case 8: |
|
127 case 12: |
|
128 case 16: |
|
129 iAverageLatency = iLatency/(32*KNumOfIterations); |
|
130 break; |
|
131 default: |
|
132 MultiPtrPerfPanic(EMultiPtrPerfPanicWrongTest); |
|
133 } |
|
134 |
|
135 ret = iChunk.OpenGlobal(KPerformanceTimingChunk, ETrue); |
|
136 if (ret != KErrNone) |
|
137 { |
|
138 return ret; |
|
139 } |
|
140 TUint8* desPtr = iChunk.Base() + iChunkOffset; |
|
141 TPtr8 ptrDes(desPtr, iLatLenInLetters, KMaxDescLength); |
|
142 |
|
143 TBuf<66> buf; |
|
144 buf.Num(iAverageLatency); |
|
145 buf.Append(','); |
|
146 ptrDes.Append(buf); |
|
147 |
|
148 // reset the iLatency for next set of test |
|
149 iLatency = 0; |
|
150 |
|
151 // For writing the next latency in chunk memory |
|
152 iLatLenInLetters = ptrDes.Length(); |
|
153 |
|
154 iChunk.Close(); |
|
155 |
|
156 // Before calling the thread Function close the current thread and then call the function |
|
157 // here when we kill the child thread it releases both mutex and condvar that it holds |
|
158 iPtrAppUi->ChildThread().Kill(KErrNone); |
|
159 iPtrAppUi->ChildThread().Close(); |
|
160 |
|
161 if (iPtrAppUi->TestCaseNum() == 16) |
|
162 { |
|
163 // It it is the last test case then stop the active scheduler |
|
164 CActiveScheduler::Stop(); |
|
165 return ret; |
|
166 } |
|
167 else |
|
168 { |
|
169 return iPtrAppUi->CreateEventSimulatingThreads(); |
|
170 } |
|
171 } |
|
172 |
|
173 // This function is called by Cone whenever a event is outstanding |
|
174 // Here we check if the sent event is same as the expected event in array. |
|
175 // Then resumes the thread for next set of events. When all the events are completed |
|
176 // calls CalculateLatencyAndStartThread |
|
177 void CMultiPtrPerfTestControl::HandlePointerEventL(const TPointerEvent& aPointerEvent) |
|
178 { |
|
179 ASSERT(!iPointerEventNotSupported); |
|
180 // The event that is received is (0,0,0) then it is the first event that the test code is sending |
|
181 const TAdvancedPointerEvent* advancedPointerEvent = aPointerEvent.AdvancedPointerEvent(); |
|
182 |
|
183 if (iPtrAppUi->TestCaseNum() == 0) |
|
184 { |
|
185 if (advancedPointerEvent->PointerNumber() == 0 && advancedPointerEvent->Position3D() == TPoint3D()) |
|
186 { |
|
187 iPtrAppUi->CreateEventSimulatingThreads(); |
|
188 return; |
|
189 } |
|
190 else |
|
191 { |
|
192 return; // ignore other events before starting the tests |
|
193 } |
|
194 } |
|
195 |
|
196 // Get the current time. |
|
197 // Subtract from the test start time. |
|
198 TTime currentTime; |
|
199 currentTime.UniversalTime(); |
|
200 TInt64 curTime64 = currentTime.Int64(); |
|
201 TInt timeSinceTestStart = curTime64 - iPtrAppUi->TestStartTime(); |
|
202 |
|
203 // Get the event, get the time stored in Z corodinate |
|
204 // Then subtract the calculated time from Z coordinate |
|
205 iLatency += timeSinceTestStart - advancedPointerEvent->ProximityAndPressure(); |
|
206 |
|
207 // Get the current event from buffer and compare it with got event |
|
208 TAdvancedPointerEvent expectedPtrEvent; |
|
209 if(0 == iEventBuffer.Remove(&expectedPtrEvent)) |
|
210 { |
|
211 iPtrAppUi->Failed(TPoint3D(), TPoint3D(), KErrNotFound); |
|
212 return; |
|
213 } |
|
214 |
|
215 // Here Z corodinate is not checked. |
|
216 if (expectedPtrEvent.iPosition != advancedPointerEvent->iPosition) |
|
217 { |
|
218 iPtrAppUi->Failed(expectedPtrEvent.Position3D(), advancedPointerEvent->Position3D(), KErrNone); |
|
219 return; |
|
220 } |
|
221 |
|
222 if (expectedPtrEvent.PointerNumber() != advancedPointerEvent->PointerNumber()) |
|
223 { |
|
224 iPtrAppUi->Failed(TPoint3D(), TPoint3D(), KErrNone, expectedPtrEvent.PointerNumber(), advancedPointerEvent->PointerNumber()); |
|
225 return; |
|
226 } |
|
227 |
|
228 iPtrAppUi->DecrementEventCount(); |
|
229 NumOfEventsAdded--; |
|
230 |
|
231 // Event count is zero when all the events have been tested |
|
232 if (iPtrAppUi->EventCount() == 0) |
|
233 { |
|
234 TInt ret = CalculateLatencyAndStartThread(); |
|
235 if (ret != KErrNone) |
|
236 { |
|
237 iPtrAppUi->Failed(TPoint3D(), TPoint3D(), ret); |
|
238 return; |
|
239 } |
|
240 } |
|
241 else if (NumOfEventsAdded == 0) |
|
242 { |
|
243 ConVar.Signal(); |
|
244 } |
|
245 } |
|
246 |
|
247 void CMultiPtrPerfTestControl::AddExpectedEvent(TAdvancedPointerEvent& aExpEvent) |
|
248 { |
|
249 iEventBuffer.Add(&aExpEvent); |
|
250 } |
|
251 |
|
252 CMultiPtrPerfTestControl::~CMultiPtrPerfTestControl() |
|
253 { |
|
254 iChunk.Close(); |
|
255 } |
|
256 |
|
257 void CMultiPtrPerfTestControl::ConstructL() |
|
258 { |
|
259 iPointerEventNotSupported = EFalse; |
|
260 ConstructL(TPoint(), ControlEnv()->ScreenDevice()->SizeInPixels()); |
|
261 } |
|
262 |
|
263 void CMultiPtrPerfTestControl::ConstructL(TPoint aOrigin, TSize aSize) |
|
264 { |
|
265 iEventBuffer.SetLengthL(EEventBufferSize); |
|
266 |
|
267 iPtrAppUi = static_cast<CMultiPtrPerfTestAppUi*>(ControlEnv()->AppUi()); |
|
268 |
|
269 CreateWindowL(); |
|
270 Window().EnableAdvancedPointers(); |
|
271 EnableDragEvents(); |
|
272 SetExtent(aOrigin, aSize); |
|
273 ActivateL(); |
|
274 |
|
275 // Get the cmdline argument of this process in descriptor |
|
276 // convert the descriptor to number and store it in iChunkOffset |
|
277 TBuf<128> buf; |
|
278 User::CommandLine(buf); |
|
279 TLex lex(buf); |
|
280 User::LeaveIfError(lex.Val(iChunkOffset)); |
|
281 } |
|
282 |
|
283 // This function gets the current time and subtracts it from the time when the whole test was started. |
|
284 // Simulates the event and suspends the thread if aWaitAfterEachEvent is ETrue |
|
285 // If aWaitAfterEachEvent is EFalse then it suspends the thread after each set of event i,e after 4, 8, 16 and 32 events |
|
286 void SimulatePointerEvents(TInt aCount, CMultiPtrPerfTestAppUi* appUi, TBool aMultiPtrEvent = EFalse, TBool aWaitAfterEachEvent = ETrue) |
|
287 { |
|
288 TRawEvent rawEvent; |
|
289 TPoint ptrPos; |
|
290 TTime currentTime; |
|
291 TInt64 testStartTime = appUi->TestStartTime(); |
|
292 TInt ptrNum = 0; |
|
293 TInt ptrMax = 0; |
|
294 // HAL as already been tested at the start of these tests. So no need to test once again |
|
295 HAL::Get(HALData::EPointerNumberOfPointers, ptrMax); |
|
296 |
|
297 appUi->SetNumberOfEvents((KNumOfIterations*aCount)-1); |
|
298 |
|
299 // For testing time taken for each event and for each set of events we make use of RMutex and RConvar. |
|
300 // RMutex is used not to preempt this thread until events has been added |
|
301 // RConVar is used to hold this thread until the events have been tested |
|
302 for (TInt loop = 0; loop < KNumOfIterations; loop++) |
|
303 { |
|
304 ptrNum = 0; |
|
305 ptrPos.iX = ptrPos.iY = 0; |
|
306 Mutex.Wait(); |
|
307 for (TInt count = 0; count < aCount/2; count++, ptrNum++) |
|
308 { |
|
309 if (ptrNum >= ptrMax) |
|
310 { |
|
311 ptrNum = 0; |
|
312 } |
|
313 ptrPos.iX += 2; |
|
314 ptrPos.iY += 1; |
|
315 |
|
316 TWsEvent event; |
|
317 event.InitAdvancedPointerEvent(TPointerEvent::EButton1Down, 0, TPoint3D(ptrPos.iX, ptrPos.iY, 0), (aMultiPtrEvent ? ptrNum : 0)); |
|
318 appUi->AddExpectedEvent(*event.Pointer()); |
|
319 currentTime.UniversalTime(); |
|
320 TInt64 curTime64 = currentTime.Int64(); |
|
321 TInt timeSinceTestStart = curTime64 - testStartTime; |
|
322 rawEvent.Set(TRawEvent::EButton1Down, ptrPos.iX, ptrPos.iY, timeSinceTestStart, (aMultiPtrEvent ? ptrNum : 0)); |
|
323 UserSvr::AddEvent(rawEvent); |
|
324 NumOfEventsAdded++; |
|
325 if (aWaitAfterEachEvent) |
|
326 { |
|
327 while(NumOfEventsAdded) |
|
328 ConVar.Wait(Mutex); |
|
329 } |
|
330 |
|
331 event.InitAdvancedPointerEvent(TPointerEvent::EButton1Up, 0, TPoint3D(ptrPos.iX, ptrPos.iY, 0), (aMultiPtrEvent ? ptrNum : 0)); |
|
332 appUi->AddExpectedEvent(*event.Pointer()); |
|
333 currentTime.UniversalTime(); |
|
334 curTime64 = currentTime.Int64(); |
|
335 timeSinceTestStart = curTime64 - testStartTime; |
|
336 rawEvent.Set(TRawEvent::EButton1Up, ptrPos.iX, ptrPos.iY, timeSinceTestStart, (aMultiPtrEvent ? ptrNum : 0)); |
|
337 UserSvr::AddEvent(rawEvent); |
|
338 NumOfEventsAdded++; |
|
339 if (aWaitAfterEachEvent) |
|
340 { |
|
341 while(NumOfEventsAdded) |
|
342 ConVar.Wait(Mutex); |
|
343 } |
|
344 } |
|
345 if (!aWaitAfterEachEvent) |
|
346 { |
|
347 while(NumOfEventsAdded) |
|
348 ConVar.Wait(Mutex); |
|
349 } |
|
350 Mutex.Signal(); |
|
351 } |
|
352 } |
|
353 |
|
354 TInt EventSimulatingThreadStartFunc(TAny* aAny) |
|
355 { |
|
356 CMultiPtrPerfTestAppUi* appUi = static_cast<CMultiPtrPerfTestAppUi*>(aAny); |
|
357 |
|
358 switch(appUi->TestCaseNum()++) |
|
359 { |
|
360 case 0: |
|
361 SimulatePointerEvents(4, appUi); |
|
362 break; |
|
363 case 1: |
|
364 SimulatePointerEvents(8, appUi); |
|
365 break; |
|
366 case 2: |
|
367 SimulatePointerEvents(16, appUi); |
|
368 break; |
|
369 case 3: |
|
370 SimulatePointerEvents(32, appUi); |
|
371 break; |
|
372 case 4: |
|
373 SimulatePointerEvents(4, appUi, ETrue); |
|
374 break; |
|
375 case 5: |
|
376 SimulatePointerEvents(8, appUi, ETrue); |
|
377 break; |
|
378 case 6: |
|
379 SimulatePointerEvents(16, appUi, ETrue); |
|
380 break; |
|
381 case 7: |
|
382 SimulatePointerEvents(32, appUi, ETrue); |
|
383 break; |
|
384 case 8: |
|
385 SimulatePointerEvents(4, appUi, EFalse, EFalse); |
|
386 break; |
|
387 case 9: |
|
388 SimulatePointerEvents(8, appUi, EFalse, EFalse); |
|
389 break; |
|
390 case 10: |
|
391 SimulatePointerEvents(16, appUi, EFalse, EFalse); |
|
392 break; |
|
393 case 11: |
|
394 SimulatePointerEvents(32, appUi, EFalse, EFalse); |
|
395 break; |
|
396 case 12: |
|
397 SimulatePointerEvents(4, appUi, ETrue, EFalse); |
|
398 break; |
|
399 case 13: |
|
400 SimulatePointerEvents(8, appUi, ETrue, EFalse); |
|
401 break; |
|
402 case 14: |
|
403 SimulatePointerEvents(16, appUi, ETrue, EFalse); |
|
404 break; |
|
405 case 15: |
|
406 SimulatePointerEvents(32, appUi, ETrue, EFalse); |
|
407 break; |
|
408 default: |
|
409 break; |
|
410 } |
|
411 return KErrNone; |
|
412 } |
|
413 |
|
414 TInt CMultiPtrPerfTestAppUi::CreateEventSimulatingThreads() |
|
415 { |
|
416 // Depending upon the iTestCase number create thread and simulate events in that thread function |
|
417 TInt ret = KErrNone; |
|
418 _LIT(KSimulateEventsThread, "Events simulating thread"); |
|
419 ret = iThread.Create(KSimulateEventsThread, EventSimulatingThreadStartFunc, KDefaultStackSize, 0x4000, 0x4000, this, EOwnerThread); |
|
420 if (ret == KErrNone) |
|
421 { |
|
422 iThread.Resume(); |
|
423 } |
|
424 return ret; |
|
425 } |
|
426 |
|
427 void CMultiPtrPerfTestAppUi::AddExpectedEvent(TAdvancedPointerEvent& aExpEvent) |
|
428 { |
|
429 iControl->AddExpectedEvent(aExpEvent); |
|
430 } |
|
431 |
|
432 void CMultiPtrPerfTestAppUi::Failed(TPoint3D aExp3DPoint, TPoint3D aActual3DPoint, TInt aErrorCode, TInt aExpPtrNum, TInt aActPtrNum) |
|
433 { |
|
434 // Write error description in the memory of shared chunk |
|
435 // so that the main performance test just stops by saying that it failed |
|
436 // and then stop the active scheduler. |
|
437 iControl->Failed(aExp3DPoint, aActual3DPoint, aErrorCode, aExpPtrNum, aActPtrNum); |
|
438 CActiveScheduler::Stop(); |
|
439 } |
|
440 |
|
441 void CMultiPtrPerfTestAppUi::PointerEventsNotSupported() |
|
442 { |
|
443 // Write a pointer events not supported message in the memory of shared chunk |
|
444 // so that the main performance test just skips the pointer test |
|
445 iControl->PointerEventsNotSupported(); |
|
446 } |
|
447 |
|
448 CMultiPtrPerfTestAppUi::CMultiPtrPerfTestAppUi() |
|
449 { |
|
450 } |
|
451 |
|
452 CMultiPtrPerfTestAppUi::~CMultiPtrPerfTestAppUi() |
|
453 { |
|
454 RemoveFromStack(iControl); |
|
455 delete iControl; |
|
456 } |
|
457 |
|
458 void CMultiPtrPerfTestAppUi::ConstructL() |
|
459 { |
|
460 CCoeAppUi::ConstructL(); |
|
461 |
|
462 TTime testStartTime; |
|
463 testStartTime.UniversalTime(); |
|
464 iTestStartTime = testStartTime.Int64(); |
|
465 |
|
466 iControl = new (ELeave) CMultiPtrPerfTestControl(); |
|
467 iControl->ConstructL(); |
|
468 AddToStackL(iControl); |
|
469 } |
|
470 |
|
471 void ConstructControlEnvironmentL(CCoeEnv* aCoe) |
|
472 { |
|
473 aCoe->ConstructL(); |
|
474 CMultiPtrPerfTestAppUi* appUi=new(ELeave) CMultiPtrPerfTestAppUi(); |
|
475 CleanupStack::PushL(appUi); // If it leaves after this then there is no way of deleting the appui |
|
476 aCoe->SetAppUi(appUi); // So pushed it on to cleanup stack |
|
477 aCoe->WsSession().SetAutoFlush(ETrue); |
|
478 appUi->ConstructL(); |
|
479 User::LeaveIfError(Mutex.CreateLocal(EOwnerProcess)); |
|
480 User::LeaveIfError(ConVar.CreateLocal(EOwnerProcess)); |
|
481 CleanupStack::Pop(appUi); |
|
482 } |
|
483 |
|
484 GLDEF_C TInt E32Main() |
|
485 { |
|
486 __UHEAP_MARK; |
|
487 CCoeEnv* coe = new CCoeEnv; |
|
488 if (!coe) |
|
489 { |
|
490 return KErrNoMemory; |
|
491 } |
|
492 TRAPD(err, ConstructControlEnvironmentL(coe)); |
|
493 if (err != KErrNone) |
|
494 { |
|
495 delete coe; |
|
496 } |
|
497 else // If KErrNone then no need to delte coe as it is taken care by ConEnv |
|
498 { |
|
499 // Check whether the configuration supports pointer events. |
|
500 // If it dosn't support pointer events then the pointer cursor area will be empty, |
|
501 // in this case skip the test and inform the test framework that the test has been skipped |
|
502 TRect pointerCursorArea = coe->WsSession().PointerCursorArea(); |
|
503 if(pointerCursorArea.IsEmpty()) |
|
504 { |
|
505 RDebug::Printf("PointerCursorArea is Empty"); |
|
506 CMultiPtrPerfTestAppUi* appUi = static_cast<CMultiPtrPerfTestAppUi*>(coe->AppUi()); |
|
507 appUi->PointerEventsNotSupported(); |
|
508 } |
|
509 else |
|
510 { |
|
511 // First event which starts the test from HandlePointerEventL |
|
512 TRawEvent rawEvent; |
|
513 rawEvent.Set(TRawEvent::EButton1Down, 0, 0, 0, 0); |
|
514 UserSvr::AddEvent(rawEvent); |
|
515 coe->ExecuteD(); |
|
516 } |
|
517 Mutex.Close(); |
|
518 ConVar.Close(); |
|
519 } |
|
520 |
|
521 __UHEAP_MARKEND; |
|
522 return err; |
|
523 } |