|
1 // Copyright (c) 2001-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 |
|
18 // INCLUDES |
|
19 #include "ctlbsclientpostp208.h" |
|
20 #include <lbs/epos_cposmodules.h> |
|
21 #include <lbs/epos_cposmoduleupdate.h> |
|
22 #include <lbs/epos_cposmoduleidlist.h> |
|
23 |
|
24 // CONSTANTS |
|
25 static const TInt KNrOfClients = 5; |
|
26 static const TInt KNrOfRuns = 20; |
|
27 |
|
28 static const TInt KServerMinHeapSize = 4096; |
|
29 static const TInt KServerMaxHeapSize = 128000; |
|
30 |
|
31 |
|
32 _LIT(KThread2Name, "req_location1"); |
|
33 _LIT(KThread3Name, "req_location2"); |
|
34 _LIT(KErrMsgThreadCreation, "failed to create thread"); |
|
35 |
|
36 // ================= MEMBER FUNCTIONS ======================= |
|
37 |
|
38 // Constructor. |
|
39 CT_LbsClientPosTp208::CT_LbsClientPosTp208(CT_LbsServer& aParent): CT_LbsPortedStepBase(aParent) |
|
40 { |
|
41 _LIT(KTestName, "TP208-Multi Thread Connection"); |
|
42 SetTestStepName(KTestName); |
|
43 } |
|
44 |
|
45 // --------------------------------------------------------- |
|
46 // Destructor. |
|
47 // --------------------------------------------------------- |
|
48 CT_LbsClientPosTp208::~CT_LbsClientPosTp208() |
|
49 { |
|
50 } |
|
51 |
|
52 // --------------------------------------------------------- |
|
53 // CPosTp208::CloseTest |
|
54 // Always called after the test, even if the test leaves |
|
55 // (other items were commented in a header). |
|
56 // --------------------------------------------------------- |
|
57 // |
|
58 void CT_LbsClientPosTp208::CloseTest() |
|
59 { |
|
60 ClosePositioner(); |
|
61 Disconnect(); |
|
62 } |
|
63 |
|
64 // Struct passed to the thread in a TAny* |
|
65 struct MyAnyData |
|
66 { |
|
67 TBool iFullTest; // If fulltest defined |
|
68 TInt iNrOfRuns; // number if requests to make for each thread |
|
69 }; |
|
70 |
|
71 // |
|
72 // Performes the test by connecting to MLFW |
|
73 // (and makes a number of Location requests if aFullTest is true |
|
74 // |
|
75 void DoTestL(TBool aFullTest, TInt aNumberOfRuns, TInt *aResult) |
|
76 { |
|
77 RPositionServer posServer; |
|
78 TInt errorCode = errorCode = posServer.Connect(); |
|
79 |
|
80 if (errorCode != KErrNone) |
|
81 { |
|
82 *aResult = KErrCouldNotConnect; |
|
83 return; |
|
84 } |
|
85 CleanupClosePushL(posServer); |
|
86 |
|
87 RPositioner positioner; |
|
88 |
|
89 |
|
90 // Full test means requesting position updates |
|
91 if (aFullTest) |
|
92 { |
|
93 TPositionInfo positionInfo = TPositionInfo(); |
|
94 const TInt32 KUidMultiPsy = 0x01010176; |
|
95 TUid uidMultiPsy; |
|
96 uidMultiPsy.iUid = KUidMultiPsy; |
|
97 errorCode = positioner.Open(posServer, uidMultiPsy); |
|
98 |
|
99 if (errorCode != KErrNone) |
|
100 { |
|
101 *aResult = errorCode; |
|
102 return; |
|
103 } |
|
104 CleanupClosePushL(positioner); |
|
105 |
|
106 _LIT(KService ,"Service"); |
|
107 errorCode = positioner.SetRequestor(CRequestor::ERequestorService, |
|
108 CRequestor::EFormatApplication, KService); |
|
109 |
|
110 if (errorCode != KErrNone) |
|
111 { |
|
112 *aResult = 1001; |
|
113 return; |
|
114 } |
|
115 |
|
116 TRequestStatus status; |
|
117 TLocality loca(TCoordinate(0,0,0),0); |
|
118 TPosition pos(loca, TTime(0)); |
|
119 |
|
120 for (TInt i = 0; i < aNumberOfRuns; i++) |
|
121 { |
|
122 positionInfo.SetPosition(pos); |
|
123 positioner.NotifyPositionUpdate(positionInfo, status); |
|
124 User::WaitForRequest(status); |
|
125 TInt err = status.Int(); |
|
126 if (err != KErrNone) |
|
127 { |
|
128 *aResult = err; |
|
129 } |
|
130 TPosition result; |
|
131 positionInfo.GetPosition(result); |
|
132 |
|
133 //sanity check |
|
134 if (result.Latitude() == pos.Latitude() || |
|
135 result.Longitude() == pos.Longitude() || |
|
136 result.Altitude() == pos.Altitude()) |
|
137 { |
|
138 //_LIT(KErrorPositon, "ERROR:: The postion was not updated"); |
|
139 errorCode = 1005; |
|
140 } |
|
141 } |
|
142 positioner.Close(); |
|
143 CleanupStack::PopAndDestroy(&positioner); |
|
144 } |
|
145 |
|
146 posServer.Close(); |
|
147 CleanupStack::PopAndDestroy(&posServer); |
|
148 } |
|
149 |
|
150 // --------------------------------------------------------- |
|
151 // LOCAL_C TInt MyThreadFunctionL(TAny* aData) |
|
152 // Runs the DoTestL in a TRAP nest |
|
153 // Panics this thread if any errors occurred |
|
154 // --------------------------------------------------------- |
|
155 // |
|
156 LOCAL_C TInt MyThreadFunctionL(TAny* aData) |
|
157 { |
|
158 __UHEAP_MARK; |
|
159 CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack |
|
160 |
|
161 // Read parameters from TAny* |
|
162 MyAnyData* info = (MyAnyData*) aData; |
|
163 |
|
164 TInt result = KErrNone; |
|
165 TInt err = KErrNone; |
|
166 // Why must this function be TRAPPED? |
|
167 TRAP(err, DoTestL(info->iFullTest, info->iNrOfRuns, &result)); |
|
168 |
|
169 _LIT(KErrorConnect, "Error when connecting to RPositionServer"); |
|
170 __ASSERT_ALWAYS(!err, User::Panic(KErrorConnect, err)); |
|
171 __ASSERT_ALWAYS(result == KErrNone, User::Panic(KErrorConnect, result)); |
|
172 |
|
173 delete cleanup; // destroy clean-up stack |
|
174 __UHEAP_MARKEND; |
|
175 return 0; |
|
176 } |
|
177 |
|
178 // --------------------------------------------------------- |
|
179 // CPosTp208::StartThreads |
|
180 // |
|
181 // (other items were commented in a header). |
|
182 // --------------------------------------------------------- |
|
183 // |
|
184 TInt CT_LbsClientPosTp208::StartThreads(TBool aFullTest) |
|
185 { |
|
186 TFixedArray<TRequestStatus, KNrOfClients> statusArray; |
|
187 TFixedArray<RThread, KNrOfClients> threadArray; |
|
188 TFixedArray<TInt, KNrOfClients> retArray; |
|
189 |
|
190 TBuf<150> buf; |
|
191 TInt errorsFound = KErrNone; |
|
192 _LIT(KInfoCreate, "Creating threads"); |
|
193 INFO_PRINTF1(KInfoCreate); |
|
194 _LIT(KThreadName, "Thread %d"); |
|
195 |
|
196 // Introduce parameters for each thread. |
|
197 MyAnyData info; |
|
198 |
|
199 info.iNrOfRuns = KNrOfRuns; |
|
200 info.iFullTest = aFullTest; |
|
201 // Make sure that if one of the threads panic, whole emulator is not |
|
202 // paniced (this has effect only in Wins). |
|
203 TBool jit = User::JustInTime(); |
|
204 User::SetJustInTime(EFalse); |
|
205 |
|
206 TInt i=0; |
|
207 for (i=0; i<KNrOfClients; i++) |
|
208 { |
|
209 iThreadCount++; |
|
210 buf.Zero(); |
|
211 buf.Format(KThreadName, iThreadCount); |
|
212 retArray[i] = threadArray[i].Create(buf, MyThreadFunctionL, KDefaultStackSize, KServerMinHeapSize, KServerMaxHeapSize, &info); |
|
213 if (retArray[i] != KErrNone) |
|
214 { |
|
215 _LIT(KErr, "Error when creating thread%d, errorcode %d"); |
|
216 buf.Format(KErr, i, retArray[i]); |
|
217 INFO_PRINTF1(buf); |
|
218 errorsFound++; |
|
219 } |
|
220 else |
|
221 { |
|
222 _LIT(KErr, "Created thread %d"); |
|
223 buf.Format(KErr, i); |
|
224 INFO_PRINTF1(buf); |
|
225 threadArray[i].Logon(statusArray[i]); |
|
226 } |
|
227 } |
|
228 |
|
229 for (TInt j=0; j<KNrOfClients; j++) |
|
230 { |
|
231 if (retArray[j] == KErrNone) |
|
232 { |
|
233 buf.Zero(); |
|
234 _LIT(KInfoResume, "Resuming thread %d"); |
|
235 buf.Format(KInfoResume, j); |
|
236 //if (bDEBUG) |
|
237 INFO_PRINTF1(buf); |
|
238 User::After(6000000); |
|
239 threadArray[j].Resume(); |
|
240 } |
|
241 } |
|
242 for (i = KNrOfClients-1; i>=0; i--) |
|
243 { |
|
244 |
|
245 if (retArray[i] == KErrNone) User::WaitForRequest(statusArray[i]); |
|
246 |
|
247 buf.Zero(); |
|
248 buf.Format(KThreadName, i); |
|
249 |
|
250 _LIT(KWaitForRequest, " User::WaitForRequest "); |
|
251 buf.Append(KWaitForRequest); |
|
252 INFO_PRINTF1(buf); |
|
253 |
|
254 buf.Zero(); |
|
255 buf.Format(KThreadName, i); |
|
256 |
|
257 if (threadArray[i].ExitType() == EExitPanic) |
|
258 { |
|
259 _LIT(KPanicExit, " EExitPanic "); |
|
260 buf.Append(KPanicExit); |
|
261 INFO_PRINTF1(buf); |
|
262 errorsFound++; |
|
263 } |
|
264 else if (threadArray[i].ExitType() == EExitKill) |
|
265 { |
|
266 _LIT(KKillExit, " EExitKill"); |
|
267 buf.Append(KKillExit); |
|
268 INFO_PRINTF1(buf); |
|
269 } |
|
270 else if (threadArray[i].ExitType() == EExitPending) |
|
271 { |
|
272 _LIT(KPendingExit, " EExitPending"); |
|
273 buf.Append(KPendingExit); |
|
274 INFO_PRINTF1(buf); |
|
275 errorsFound++; |
|
276 } |
|
277 else |
|
278 { |
|
279 _LIT(KOtherExit, " other "); |
|
280 buf.Append(KOtherExit); |
|
281 INFO_PRINTF1(buf); |
|
282 errorsFound++; |
|
283 } |
|
284 } |
|
285 |
|
286 for (i=0; i<KNrOfClients; i++) |
|
287 { |
|
288 buf.Zero(); |
|
289 _LIT(KDEBUG, "Wrong reasoncode from Thread %d reasoncode %d"); |
|
290 buf.Format(KDEBUG, i, threadArray[i].ExitReason()); |
|
291 if (threadArray[i].ExitReason() != KErrNone) INFO_PRINTF1(buf); |
|
292 threadArray[i].Close(); |
|
293 } |
|
294 |
|
295 // Only affected on WINS emulator |
|
296 User::SetJustInTime(jit); |
|
297 |
|
298 return errorsFound; |
|
299 } |
|
300 |
|
301 |
|
302 /** |
|
303 * Connection is opened to location server,and closed |
|
304 * |
|
305 * If anything fails during the execution of this test, then function |
|
306 * leaves with proper error code. |
|
307 * |
|
308 * Parameters: |
|
309 **/ |
|
310 void LocationRequestThreadMainPartL(TDes& aErrorBuf) |
|
311 { |
|
312 // Open connection to Location server |
|
313 RPositionServer server; |
|
314 |
|
315 TInt err = server.Connect(); |
|
316 |
|
317 if (err != KErrNone) |
|
318 { |
|
319 _LIT(KErrOpen, "Server open failed with code %d\r\n"); |
|
320 aErrorBuf.Format(KErrOpen, err); |
|
321 } |
|
322 else |
|
323 { |
|
324 _LIT(KOkOpen, "Server open ok\r\n"); |
|
325 aErrorBuf.Copy(KOkOpen); |
|
326 } |
|
327 |
|
328 User::LeaveIfError(err); |
|
329 |
|
330 CleanupClosePushL(server); |
|
331 |
|
332 |
|
333 CleanupStack::PopAndDestroy(1); // server, positioner |
|
334 |
|
335 _LIT(KInfTestComplet, "Test completed ok for this thread\r\n"); |
|
336 aErrorBuf.Append(KInfTestComplet); |
|
337 } |
|
338 |
|
339 /** |
|
340 * This is the main function for threads that connects and |
|
341 * disconnect from MLFW |
|
342 * |
|
343 * Function returns 0 if running of the test did not leave. |
|
344 *Otherwise the leave code is returned. |
|
345 **/ |
|
346 LOCAL_C TInt LocationRequestThread(TAny* aData) |
|
347 { |
|
348 // Create cleanupstack for this thread |
|
349 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
350 |
|
351 // No parameters to read, just start main function. |
|
352 |
|
353 HBufC* buf = HBufC::NewL(1024); |
|
354 |
|
355 TPtr ptr = buf->Des(); |
|
356 |
|
357 // Run the actual test, and trap possible leave |
|
358 TRAPD(leave, LocationRequestThreadMainPartL(ptr)); |
|
359 |
|
360 // Open connection to file server |
|
361 RFs fs; |
|
362 User::LeaveIfError(fs.Connect()); |
|
363 |
|
364 TInt index = *((TInt*) aData); |
|
365 |
|
366 TBuf<30> errorFile; |
|
367 _LIT(KInfThread, "c:\\logs\\thread%derrinfo.txt"); |
|
368 errorFile.Format(KInfThread, index); |
|
369 |
|
370 // Open log file |
|
371 RFile file; |
|
372 |
|
373 TInt err = file.Replace(fs,errorFile,EFileStreamText|EFileWrite); |
|
374 |
|
375 if (err != KErrNone) |
|
376 { |
|
377 User::Leave(err); |
|
378 } |
|
379 |
|
380 _LIT(KErrLeave, "*** This thread (thread %d) leave code: %d\r\n"); |
|
381 ptr.AppendFormat(KErrLeave, index, leave); |
|
382 |
|
383 TFileText fileText; |
|
384 fileText.Set(file); |
|
385 |
|
386 fileText.Write(ptr); |
|
387 |
|
388 // Close log file |
|
389 file.Close(); |
|
390 fs.Close(); |
|
391 |
|
392 // Delete cleanup stack |
|
393 delete cleanup; |
|
394 |
|
395 // Exit this thread with leave code (KErrNone in successful case) |
|
396 User::Exit(leave); |
|
397 |
|
398 return 0; |
|
399 } |
|
400 |
|
401 // --------------------------------------------------------- |
|
402 // CPosTp208::DoFastConnectionL |
|
403 // |
|
404 // (other items were commented in a header). |
|
405 // --------------------------------------------------------- |
|
406 // |
|
407 TInt CT_LbsClientPosTp208::DoFastConnectionL() |
|
408 { |
|
409 TInt err; |
|
410 |
|
411 // Create two different threads. Each thread connects |
|
412 // and disconnect from MLFW very fast. |
|
413 const TInt KMinHeapSize = 4096; |
|
414 const TInt KMaxHeapSize = 128000; |
|
415 |
|
416 RThread thread2; |
|
417 RThread thread3; |
|
418 |
|
419 TInt thread2Id = 2; |
|
420 TInt thread3Id = 3; |
|
421 |
|
422 // Make sure that if one of the threads panic, whole emulator is not |
|
423 // paniced (this has effect only in Wins). |
|
424 User::SetJustInTime(EFalse); |
|
425 |
|
426 _LIT(KInfo, "Create two threads"); |
|
427 INFO_PRINTF1(KInfo); |
|
428 |
|
429 err = thread2.Create(KThread2Name, LocationRequestThread, KDefaultStackSize, |
|
430 KMinHeapSize, KMaxHeapSize, &thread2Id); |
|
431 |
|
432 AssertTrueL(err == KErrNone, KErrMsgThreadCreation, err); |
|
433 |
|
434 err = thread3.Create(KThread3Name, LocationRequestThread, KDefaultStackSize, |
|
435 KMinHeapSize, KMaxHeapSize, &thread3Id); |
|
436 |
|
437 AssertTrueL(err == KErrNone, KErrMsgThreadCreation, err); |
|
438 |
|
439 // Logon to each thread, so we can get a notification when they kill |
|
440 // themselves. |
|
441 TRequestStatus status2, status3; |
|
442 thread2.Logon(status2); |
|
443 thread3.Logon(status3); |
|
444 |
|
445 _LIT(KStart, "Start the threads will connect to and disconnect to MLFW,"); |
|
446 INFO_PRINTF1(KStart); |
|
447 |
|
448 // Start all treads. |
|
449 thread2.Resume(); |
|
450 User::After(2000000); |
|
451 thread3.Resume(); |
|
452 |
|
453 |
|
454 // Wait for all threads to exit |
|
455 User::WaitForRequest(status2); |
|
456 User::WaitForRequest(status3); |
|
457 |
|
458 // Actual test is now run. |
|
459 _LIT(KInfoExit, "All threads have exited, exit reasons:"); |
|
460 INFO_PRINTF1(KInfoExit); |
|
461 |
|
462 // Check that all threads had correct exit reason. Also log |
|
463 // all the exit reasons into log file. |
|
464 TInt exitReasonsCorrect = 0; |
|
465 |
|
466 exitReasonsCorrect |= thread2.ExitReason(); |
|
467 exitReasonsCorrect |= thread3.ExitReason(); |
|
468 |
|
469 // Close all handles to threads. |
|
470 thread2.Close(); |
|
471 thread3.Close(); |
|
472 |
|
473 // Return back to normal mode |
|
474 User::SetJustInTime(ETrue); |
|
475 return exitReasonsCorrect; |
|
476 } |
|
477 |
|
478 // --------------------------------------------------------- |
|
479 // CPosTp208::StartL |
|
480 // |
|
481 // (other items were commented in a header). |
|
482 // --------------------------------------------------------- |
|
483 // |
|
484 void CT_LbsClientPosTp208::StartL() |
|
485 { |
|
486 //first do a simple connection test |
|
487 TInt fasterr = DoFastConnectionL(); |
|
488 _LIT(KFailConnect, "Fast connection failed"); |
|
489 AssertTrueL(fasterr == KErrNone, KFailConnect, fasterr); |
|
490 |
|
491 SetupPsyL(iUidMultiPsy); |
|
492 |
|
493 TInt nrOfRounds = 1; |
|
494 TBuf<100> buf; |
|
495 |
|
496 _LIT(KPsitionUpdate, |
|
497 ">>>>>>>>>>Running StartThreads(ETrue) requesting position updates<<<<<<<<"); |
|
498 INFO_PRINTF1(KPsitionUpdate); |
|
499 |
|
500 _LIT(KEmptySpace, ""); |
|
501 _LIT(KRound, ">>>>>>Round nr %d :"); |
|
502 _LIT(KErrorsFound, "Errors found!!!"); |
|
503 |
|
504 for (TInt i=0; i<nrOfRounds; i++) |
|
505 { |
|
506 INFO_PRINTF1(KEmptySpace); |
|
507 buf.Format(KRound, i); |
|
508 INFO_PRINTF1(buf); |
|
509 TTime now, startTime; |
|
510 TTimeIntervalMicroSeconds requestTime; |
|
511 |
|
512 startTime.UniversalTime(); |
|
513 TInt res = StartThreads(ETrue); |
|
514 if (res != KErrNone) |
|
515 LogErrorAndLeaveL(KErrorsFound, res); |
|
516 now.UniversalTime(); |
|
517 |
|
518 requestTime = now.MicroSecondsFrom(startTime); |
|
519 _LIT(KDebug, "%d requests from %d threads took: %d microsecs."); |
|
520 buf.Zero(); |
|
521 TInt64 reqTime = requestTime.Int64(); |
|
522 buf.Format(KDebug, KNrOfClients * KNrOfRuns, KNrOfClients, reqTime); |
|
523 INFO_PRINTF1(buf); |
|
524 |
|
525 } |
|
526 |
|
527 _LIT(KConnectDisconnect, |
|
528 ">>>>>>>>>>Running StartThreads(EFalse) connect/disconnect Epos<<<<<<<<"); |
|
529 INFO_PRINTF1(KConnectDisconnect); |
|
530 nrOfRounds = 5; |
|
531 for (TInt j=0; j<nrOfRounds; j++) |
|
532 { |
|
533 INFO_PRINTF1(KEmptySpace); |
|
534 buf.Format(KRound, j); |
|
535 INFO_PRINTF1(buf); |
|
536 TTime now, startTime; |
|
537 TTimeIntervalMicroSeconds requestTime; |
|
538 |
|
539 startTime.UniversalTime(); |
|
540 |
|
541 // Threads only connects to Epos server and then disconnect |
|
542 TInt res = StartThreads(EFalse); |
|
543 if (res != KErrNone) |
|
544 LogErrorAndLeaveL(KErrorsFound, res); |
|
545 now.UniversalTime(); |
|
546 |
|
547 requestTime = now.MicroSecondsFrom(startTime); |
|
548 _LIT(KDebug, "%d threads connecting and disconnecting to Epos server took: %d microsecs."); |
|
549 buf.Zero(); |
|
550 TInt64 reqTime = requestTime.Int64(); |
|
551 buf.Format(KDebug, KNrOfClients, reqTime); |
|
552 INFO_PRINTF1(buf); |
|
553 } |
|
554 } |
|
555 |
|
556 // End of File |