|
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 // This file contains test classes and their implementations |
|
15 // to test production class CCustomResolverCache. |
|
16 // |
|
17 // |
|
18 |
|
19 #include <e32test.h> |
|
20 #include <f32file.h> |
|
21 #include <hal.h> |
|
22 #include <bautils.h> |
|
23 #include <babitflags.h> |
|
24 #include <babackup.h> |
|
25 #include <startup.hrh> |
|
26 #include <ecom/resolver.h> |
|
27 #include "EComErrorCodes.h" |
|
28 #include "EComUidCodes.h" |
|
29 #include "ImplementationInformation.h" |
|
30 #include "RegistryData.h" |
|
31 #include "Registrar.h" |
|
32 #include "RegistrarObserver.h" |
|
33 #include "../EcomTestUtils/EcomTestUtils.h" |
|
34 #include <swi/swispubsubdefs.h> |
|
35 #include "../EcomTestUtils/TPropertyManager.h" |
|
36 #include "EComPatchDataConstantv2.h" |
|
37 #include "RegistryResolveTransaction.h" // ecom3 code |
|
38 #include "callback.h" |
|
39 #include "resolvercache.h" |
|
40 #include "EComServer.h" |
|
41 |
|
42 |
|
43 const TInt KOneSecond = 1000000; |
|
44 const TInt KHalfSecond = KOneSecond / 2; |
|
45 // Use this timeout to wait for events occuring within a few seconds. |
|
46 const TInt KIndefiniteWait = KOneSecond * 20; |
|
47 |
|
48 LOCAL_D RTest test(_L("t_resolvercache.exe")); |
|
49 |
|
50 LOCAL_D RFs TheFs; |
|
51 LOCAL_D CTrapCleanup* TheTrapCleanup = NULL; |
|
52 class CDerivedActiveScheduler; |
|
53 LOCAL_D CDerivedActiveScheduler* TheActiveScheduler = NULL; |
|
54 |
|
55 |
|
56 // custom resolvers available for testing. |
|
57 // 200126cd, A0001346 and A0001347 are allocated outside the |
|
58 // ECOM Uid Allocations.doc |
|
59 const TUid KDummyResolverUid2 = {0xA0001346}; |
|
60 const TUid KDummyResolverUid3 = {0xA0001347}; |
|
61 const TUid KExampleResolverUid = {0x10009DD0}; |
|
62 const TUid KMyResolverUid = {0x10009E12}; |
|
63 const TUid KDummyResolverUid1 = {0x200126CD}; |
|
64 |
|
65 // The custom resolver in RAMOnly dir |
|
66 _LIT(KDummyRscInC, "c:\\resource\\plugins\\dummycustomresolver1.rsc"); |
|
67 _LIT(KDummyDllInC, "c:\\sys\\bin\\dummycustomresolver1.dll"); |
|
68 |
|
69 _LIT(KDummyRscInZ, "z:\\ramonly\\dummycustomresolver1.rsc"); |
|
70 _LIT(KDummyDllInZ, "z:\\ramonly\\dummycustomresolver1.dll"); |
|
71 |
|
72 // This pair is to upgrade a resolver DLL. |
|
73 // NB: to supersede a Z: drive plugin, the C: DLL must have the |
|
74 // same name as the one in z: drive. Hence the '2' is dropped. |
|
75 _LIT(KDllUpgradeInZ, "z:\\ramonly\\cachedcustomresolver2.dll"); |
|
76 _LIT(KDllUpgradeInC, "c:\\sys\\bin\\cachedcustomresolver.dll"); |
|
77 |
|
78 _LIT(KRscUpgradeInZ, "z:\\ramonly\\cachedcustomresolver2.rsc"); |
|
79 _LIT(KRscUpgradeInC, "c:\\resource\\plugins\\cachedcustomresolver.rsc"); |
|
80 |
|
81 /** User::AfterHighRes is not a reliable mechanism to wait |
|
82 for async events. Especially when we have 4 different timers |
|
83 firing within a span of 4 s. Hence this harness intercepts |
|
84 and inserts callbacks in the notification sources and set |
|
85 the following flag to indicate what event has occured. */ |
|
86 LOCAL_D TBitFlags32 AsyncEvents = 0; |
|
87 |
|
88 /** enum to identify different async events */ |
|
89 enum TAsyncEventId |
|
90 { |
|
91 EAsyncEvent_Unknown = 0, |
|
92 EAsyncEvent_ImplUpgrade, |
|
93 EAsyncEvent_SwiStart, |
|
94 EAsyncEvent_SwiEnd, |
|
95 EAsyncEvent_BurStart, |
|
96 EAsyncEvent_BurEnd, |
|
97 EAsyncEvent_CacheTimer, |
|
98 EAsyncEvent_HaltTimer |
|
99 }; |
|
100 |
|
101 // |
|
102 // maps callback data to enum TAsyncEventId. |
|
103 LOCAL_C TAsyncEventId CallbackDataToEventId(TInt aEvent, TAny* aData) |
|
104 { |
|
105 TAsyncEventId ret = EAsyncEvent_Unknown; |
|
106 TCallBackState* state = static_cast<TCallBackState*>(aData); |
|
107 if (aEvent == ECallBackId_SwiEvent) |
|
108 { |
|
109 if (*state == ECallBackState_EventStart) |
|
110 { |
|
111 ret = EAsyncEvent_SwiStart; |
|
112 } |
|
113 else // treat all unexpected states as SWI end! |
|
114 { |
|
115 ret = EAsyncEvent_SwiEnd; |
|
116 } |
|
117 } |
|
118 else if (aEvent == ECallBackId_BurEvent) |
|
119 { |
|
120 if (*state == ECallBackState_EventStart) |
|
121 { |
|
122 ret = EAsyncEvent_BurStart; |
|
123 } |
|
124 else // treat all unexpected states as BUR finish! |
|
125 { |
|
126 ret = EAsyncEvent_BurEnd; |
|
127 } |
|
128 } |
|
129 else if (aEvent == ECallBackId_ImplUpgrade) |
|
130 { |
|
131 ret = EAsyncEvent_ImplUpgrade; |
|
132 } |
|
133 return ret; |
|
134 } |
|
135 |
|
136 // beginningOfTest is set when this harness is run. |
|
137 LOCAL_D TTime beginningOfTest; |
|
138 LOCAL_C void WaitForLazyUnloadingL() |
|
139 { |
|
140 TTime now; |
|
141 now.UniversalTime(); |
|
142 |
|
143 TTimeIntervalSeconds n; |
|
144 User::LeaveIfError(now.SecondsFrom(beginningOfTest, n)); |
|
145 const TInt KLazyDllUnloadPeriod = 150; // actual is 2 minutes |
|
146 TInt secondsToWait = KLazyDllUnloadPeriod - n.Int(); |
|
147 test.Printf(_L("Amount to wait for lazy unload is %d seconds.\n"), secondsToWait); |
|
148 if (secondsToWait > 0) |
|
149 { |
|
150 User::After(KOneSecond * secondsToWait); |
|
151 } |
|
152 } |
|
153 |
|
154 // Copies the Plugins to specific folder for testing purpose |
|
155 LOCAL_C void CopyPluginsL() |
|
156 { |
|
157 EComTestUtils::FileManCopyFileL(KDummyRscInZ, KDummyRscInC); |
|
158 EComTestUtils::FileManCopyFileL(KDummyDllInZ, KDummyDllInC); |
|
159 } |
|
160 |
|
161 // Deleting plugin from the RAM for cleanup purpose |
|
162 LOCAL_C void DeleteTestPlugin() |
|
163 { |
|
164 TRAP_IGNORE(EComTestUtils::FileManDeleteFileL(KDummyRscInC)); |
|
165 TRAP_IGNORE(EComTestUtils::FileManDeleteFileL(KDummyDllInC)); |
|
166 |
|
167 TRAP_IGNORE(EComTestUtils::FileManDeleteFileL(KRscUpgradeInC)); |
|
168 TRAP_IGNORE(EComTestUtils::FileManDeleteFileL(KDllUpgradeInC)); |
|
169 } |
|
170 |
|
171 // utility to help cast TTimeIntervalMicroSeconds to TInt |
|
172 LOCAL_C TInt CalcElapsedMicroseconds(const TTime& aStart) |
|
173 { |
|
174 TTime now; |
|
175 now.UniversalTime(); |
|
176 TTimeIntervalMicroSeconds timediff = now.MicroSecondsFrom(aStart); |
|
177 return I64LOW( timediff.Int64() ); |
|
178 } |
|
179 |
|
180 /** Need a CActive to wait for various change notifications. */ |
|
181 class CHaltTimer : public CTimer |
|
182 { |
|
183 public: |
|
184 CHaltTimer(TInt aPriority); |
|
185 ~CHaltTimer(); |
|
186 void ConstructL(); |
|
187 void StartTimer(TInt aTimeInterval); |
|
188 |
|
189 private: |
|
190 void RunL(); |
|
191 }; |
|
192 |
|
193 CHaltTimer::CHaltTimer(TInt aPriority) |
|
194 : CTimer(aPriority) |
|
195 { |
|
196 CActiveScheduler::Add(this); |
|
197 } |
|
198 |
|
199 CHaltTimer::~CHaltTimer() |
|
200 { |
|
201 Cancel(); |
|
202 } |
|
203 |
|
204 void CHaltTimer::ConstructL() |
|
205 { |
|
206 CTimer::ConstructL(); |
|
207 } |
|
208 |
|
209 void CHaltTimer::StartTimer(TInt aTimeInterval) |
|
210 { |
|
211 After(aTimeInterval); |
|
212 } |
|
213 |
|
214 void CHaltTimer::RunL() |
|
215 { |
|
216 AsyncEvents.Set(EAsyncEvent_HaltTimer); |
|
217 CActiveScheduler::Stop(); |
|
218 } |
|
219 |
|
220 /** Avoid E32User::Case 47 panic in OOM test */ |
|
221 class CDerivedActiveScheduler : public CActiveScheduler |
|
222 { |
|
223 public: |
|
224 virtual void Error(TInt aError) const; |
|
225 }; |
|
226 |
|
227 void CDerivedActiveScheduler::Error(TInt aError) const |
|
228 { |
|
229 Halt(aError); |
|
230 } |
|
231 |
|
232 /** friend class to access private members of CEComServer */ |
|
233 class TEComServer_StateAccessor |
|
234 { |
|
235 public: |
|
236 static void InterceptCallbacks(CEComServer& aEComServer, TCallBackWithArg aCb); |
|
237 static CCustomResolverCache* GetResolverCache(CEComServer& aEComServer); |
|
238 }; |
|
239 |
|
240 /** Test class for object CCustomResolverCache. |
|
241 */ |
|
242 class CCustomResolverCacheTest : public CBase |
|
243 { |
|
244 public: |
|
245 typedef void (CCustomResolverCacheTest::*ClassFuncPtrL) (void); |
|
246 |
|
247 virtual ~CCustomResolverCacheTest(); |
|
248 static CCustomResolverCacheTest* NewL(); |
|
249 static void RunAllTestsL(); |
|
250 static TInt InterceptCacheMgrCallback(TAny* aObj, TInt aEvent, TAny* aData); |
|
251 static TInt CacheTimeoutCallback(TAny* aObj, TInt aEvent, TAny* aData); |
|
252 |
|
253 private: |
|
254 CCustomResolverCacheTest(); |
|
255 void ConstructL(); |
|
256 |
|
257 static void DoBasicTestL(ClassFuncPtrL aTestFunc); |
|
258 static void DoOOMTestL(ClassFuncPtrL aTestFunc); |
|
259 |
|
260 // Test cases |
|
261 void TestUpgradingCachedResolverL(); |
|
262 void TestDeletingCachedResolverL(); |
|
263 |
|
264 void TestCacheQueueFullPattern1L(); |
|
265 void TestCacheQueueFullPattern2L(); |
|
266 void TestCacheQueueFullPattern3L(); |
|
267 void DoQueueFullTestL(const RArray<TUid>& aResolverList); |
|
268 |
|
269 void TestCounterWrapAroundL(); |
|
270 void TestCacheTimerAccuracyL(); |
|
271 void TestTimestampUpdateOnCacheHitL(); |
|
272 void TestSWIDisableRwResolverCachingL(); |
|
273 void TestBurDisableRwResolverCachingL(); |
|
274 void TestClockChangeHasNoEffectOnCacheTimeoutL(); |
|
275 void TestCacheSizeZeroL(); |
|
276 void TestCacheTimeoutZeroL(); |
|
277 void TestResolverWithBadProxyTable(); |
|
278 |
|
279 // utilities |
|
280 TBool UseResolverCheckVersionL(TUid aResolverUid, |
|
281 TInt aVersion = 0); |
|
282 void YieldToOtherCActive(TInt aMicroSeconds); |
|
283 void WaitAsyncL(TInt aNumSeconds); |
|
284 TBool WaitForEvict(TUid aResolverUid); |
|
285 |
|
286 // access private data of CCustomResolverCache |
|
287 TInt CacheSize(); |
|
288 TBool HasResolverUid(TUid aUid); |
|
289 TBool QueueIsSorted(); |
|
290 inline CCustomResolverCache* ResolverCache(); |
|
291 |
|
292 private: |
|
293 /** need a CActive to wait for other async events */ |
|
294 CHaltTimer* iHaltTimer; |
|
295 |
|
296 CEComServer* iEComServer; |
|
297 }; |
|
298 |
|
299 //============================================== |
|
300 // class TEComServer_StateAccessor |
|
301 //============================================== |
|
302 void TEComServer_StateAccessor::InterceptCallbacks(CEComServer& aEComServer, |
|
303 TCallBackWithArg aCb) |
|
304 { |
|
305 aEComServer.iRegistrar->InstallSwiEventCallBack(aCb); |
|
306 aEComServer.iRegistrar->InstallBurEventCallBack(aCb); |
|
307 aEComServer.iRegistryData->SetImplUpgradeCallBack(aCb); |
|
308 } |
|
309 |
|
310 CCustomResolverCache* |
|
311 TEComServer_StateAccessor::GetResolverCache(CEComServer& aEComServer) |
|
312 { |
|
313 return aEComServer.iResolverCache; |
|
314 } |
|
315 |
|
316 //============================================== |
|
317 // class CCustomResolverCacheTest |
|
318 //============================================== |
|
319 |
|
320 /** CCustomResolverCacheTest constructor */ |
|
321 CCustomResolverCacheTest::CCustomResolverCacheTest() |
|
322 { |
|
323 } |
|
324 |
|
325 /** CCustomResolverCacheTest destructor. */ |
|
326 CCustomResolverCacheTest::~CCustomResolverCacheTest() |
|
327 { |
|
328 delete iEComServer; |
|
329 delete iHaltTimer; |
|
330 } |
|
331 |
|
332 /** static factory method to instantiate CCustomResolverCacheTest object. |
|
333 */ |
|
334 CCustomResolverCacheTest* CCustomResolverCacheTest::NewL() |
|
335 { |
|
336 CCustomResolverCacheTest* self = new(ELeave) CCustomResolverCacheTest; |
|
337 CleanupStack::PushL(self); |
|
338 self->ConstructL(); |
|
339 CleanupStack::Pop(self); |
|
340 return self; |
|
341 } |
|
342 |
|
343 /** |
|
344 Standardized 2nd phase of two phase construction. |
|
345 */ |
|
346 void CCustomResolverCacheTest::ConstructL() |
|
347 { |
|
348 iHaltTimer = new(ELeave) CHaltTimer(CActive::EPriorityIdle); |
|
349 iHaltTimer->ConstructL(); |
|
350 |
|
351 iEComServer = CEComServer::NewLC(); |
|
352 CleanupStack::Pop(iEComServer); |
|
353 |
|
354 TCallBackWithArg interceptorCB(&InterceptCacheMgrCallback, this); |
|
355 TEComServer_StateAccessor::InterceptCallbacks(*iEComServer, interceptorCB); |
|
356 |
|
357 TCallBackWithArg cacheTimerCb(&CacheTimeoutCallback, this); |
|
358 ResolverCache()->iTimerExpireCB = cacheTimerCb; |
|
359 } |
|
360 |
|
361 /** util to fetch CEComServer::iResolverCache */ |
|
362 inline CCustomResolverCache* CCustomResolverCacheTest::ResolverCache() |
|
363 { |
|
364 return TEComServer_StateAccessor::GetResolverCache(*iEComServer); |
|
365 } |
|
366 |
|
367 /** the test harness install this callback with ECOM server objects |
|
368 to intercept async events. This callback will relay the original |
|
369 call to CEComServer, then raise a flag to indicate what |
|
370 event has occurred. |
|
371 @param aObj pointer to the CCustomResolverCacheTest object |
|
372 @param aEvent ID of event triggering the callback |
|
373 @param aData pointer to some data associated with the event. |
|
374 @return Always KErrNone. It is ignored. |
|
375 */ |
|
376 TInt CCustomResolverCacheTest::InterceptCacheMgrCallback(TAny* aObj, |
|
377 TInt aEvent, |
|
378 TAny* aData) |
|
379 { |
|
380 CCustomResolverCacheTest* self = static_cast<CCustomResolverCacheTest*>(aObj); |
|
381 // Pass the event along to let CEComServer does its thing. |
|
382 CEComServer::NotifyEvents(self->iEComServer, aEvent, aData); |
|
383 |
|
384 if (self->iHaltTimer->IsActive()) |
|
385 { |
|
386 TAsyncEventId event = CallbackDataToEventId(aEvent, aData); |
|
387 AsyncEvents.Set(event); |
|
388 |
|
389 self->iHaltTimer->Cancel(); |
|
390 CActiveScheduler::Stop(); |
|
391 } |
|
392 else |
|
393 { |
|
394 // BUR and SWI unit test cases just call the notifier |
|
395 // directly. So CHaltTimer is not running. |
|
396 test.Printf(_L("CacheTest: caught async event %d when timer not running\n"), aEvent); |
|
397 } |
|
398 return KErrNone; |
|
399 } |
|
400 |
|
401 /** A callback installed in cache mgr. Whenever the cache timer expires |
|
402 this callback is invoked by CCustomResolverCache |
|
403 @param aObj pointer to CCustomResolverCacheTest |
|
404 @return Always KErrNone. It is ignored. |
|
405 */ |
|
406 TInt CCustomResolverCacheTest::CacheTimeoutCallback(TAny* aObj, TInt, TAny*) |
|
407 { |
|
408 AsyncEvents.Set(EAsyncEvent_CacheTimer); |
|
409 |
|
410 CCustomResolverCacheTest* self = static_cast<CCustomResolverCacheTest*>(aObj); |
|
411 self->iHaltTimer->Cancel(); |
|
412 CActiveScheduler::Stop(); |
|
413 return KErrNone; |
|
414 } |
|
415 |
|
416 /** Wrapper function to run normal mode (non-OOM) test |
|
417 */ |
|
418 void CCustomResolverCacheTest::DoBasicTestL(ClassFuncPtrL aTestFunc) |
|
419 { |
|
420 __UHEAP_MARK; |
|
421 TInt startProcessHandleCount; |
|
422 TInt startThreadHandleCount; |
|
423 RThread().HandleCount(startProcessHandleCount, startThreadHandleCount); |
|
424 |
|
425 CCustomResolverCacheTest* p = CCustomResolverCacheTest::NewL(); |
|
426 (p->*aTestFunc)(); |
|
427 delete p; |
|
428 |
|
429 // check that no handles have leaked |
|
430 TInt endProcessHandleCount; |
|
431 TInt endThreadHandleCount; |
|
432 RThread().HandleCount(endProcessHandleCount, endThreadHandleCount); |
|
433 |
|
434 test(startProcessHandleCount == endProcessHandleCount); |
|
435 test(startThreadHandleCount == endThreadHandleCount); |
|
436 __UHEAP_MARKEND; |
|
437 } |
|
438 |
|
439 /** |
|
440 @SYMTestCaseID SYSLIB-ECOM-UT-4020 |
|
441 @SYMTestCaseDesc Verify no memory leak in CCustomResolverCache. |
|
442 @SYMTestPriority Critical |
|
443 @SYMTestActions Run UT-4015, UT-4016 and UT-4017 under OOM. |
|
444 @SYMTestExpectedResults No memory leak, no handle leak. |
|
445 @SYMCR CR1182 |
|
446 */ |
|
447 void CCustomResolverCacheTest::DoOOMTestL(ClassFuncPtrL aTestFunc) |
|
448 { |
|
449 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4020 ")); |
|
450 __UHEAP_MARK; |
|
451 TInt startProcessHandleCount; |
|
452 TInt startThreadHandleCount; |
|
453 RThread().HandleCount(startProcessHandleCount, startThreadHandleCount); |
|
454 TInt err(KErrNone); |
|
455 TInt oomStep = 0; |
|
456 |
|
457 do { |
|
458 // Instantiation of CCustomResolverCacheTest involves building |
|
459 // the registry. It will take couple hours under OOM. Hence do it |
|
460 // outside __UHEAP_SETFAIL. |
|
461 CCustomResolverCacheTest* p = CCustomResolverCacheTest::NewL(); |
|
462 |
|
463 __UHEAP_SETFAIL(RHeap::EDeterministic, ++oomStep); |
|
464 TRAP(err, (p->*aTestFunc)()); |
|
465 __UHEAP_SETFAIL(RHeap::ENone, 0); |
|
466 |
|
467 delete p; |
|
468 } while (err == KErrNoMemory); |
|
469 |
|
470 test(err == KErrNone); |
|
471 test.Printf(_L("OOM succeeded at heap failure rate %d\n"), oomStep); |
|
472 |
|
473 // check that no handles have leaked |
|
474 TInt endProcessHandleCount; |
|
475 TInt endThreadHandleCount; |
|
476 RThread().HandleCount(endProcessHandleCount, endThreadHandleCount); |
|
477 |
|
478 test(startProcessHandleCount == endProcessHandleCount); |
|
479 test(startThreadHandleCount == endThreadHandleCount); |
|
480 __UHEAP_MARKEND; |
|
481 } |
|
482 |
|
483 /** helper, ecom3 code |
|
484 Issue a list request to add resolver to cache and check if |
|
485 the registry has the expected version of the resolver. |
|
486 @param aResolverUid the custom resolver to create |
|
487 @param aVersion the expected version of the custom resolver. Check is skipped |
|
488 if aVersion is zero. |
|
489 */ |
|
490 TBool CCustomResolverCacheTest::UseResolverCheckVersionL(TUid aResolverUid, |
|
491 TInt aVersion) |
|
492 { |
|
493 TEComResolverParams resolverparams; |
|
494 _LIT8(KDummyData,"dummy"); |
|
495 resolverparams.SetDataType(KDummyData); |
|
496 |
|
497 TClientRequest clientReq; |
|
498 RArray<TUid> extendedInterfaces; |
|
499 RImplInfoArray* infoArray = iEComServer->ListImplementationsL( |
|
500 KCustomResolverInterfaceUid, resolverparams, aResolverUid, |
|
501 extendedInterfaces, clientReq); |
|
502 |
|
503 TBool ret = (aVersion == 0); |
|
504 |
|
505 // infoArray not pushed because there are no leave in this search. |
|
506 for (TInt i = 0; !ret && i < infoArray->Count(); i++) |
|
507 { |
|
508 const CImplementationInformation* impl = (*infoArray)[i]; |
|
509 if (impl->ImplementationUid() == aResolverUid && impl->Version() == aVersion) |
|
510 { |
|
511 ret = ETrue; |
|
512 } |
|
513 } |
|
514 |
|
515 infoArray->Reset(); |
|
516 delete infoArray; |
|
517 |
|
518 return ret; |
|
519 } |
|
520 |
|
521 /** utility to let other CActive s to run. */ |
|
522 void CCustomResolverCacheTest::YieldToOtherCActive(TInt aMicroSeconds) |
|
523 { |
|
524 iHaltTimer->StartTimer(aMicroSeconds); |
|
525 CActiveScheduler::Start(); |
|
526 } |
|
527 |
|
528 /** Call YieldToOtherCActive as many times as needed |
|
529 until aNumSeconds is reached. */ |
|
530 void CCustomResolverCacheTest::WaitAsyncL(TInt aNumSeconds) |
|
531 { |
|
532 TTime start, now; |
|
533 start.UniversalTime(); |
|
534 TTimeIntervalSeconds elapsed; |
|
535 |
|
536 for (elapsed = 0; elapsed.Int() < aNumSeconds; ) |
|
537 { |
|
538 AsyncEvents.ClearAll(); |
|
539 TInt seconds = (aNumSeconds - elapsed.Int()); |
|
540 YieldToOtherCActive(KOneSecond * seconds); |
|
541 now.UniversalTime(); |
|
542 User::LeaveIfError(now.SecondsFrom(start, elapsed)); |
|
543 } |
|
544 } |
|
545 |
|
546 /** |
|
547 This method is used in the situation that cache timer is already |
|
548 started when we load the given resolver. Then when cache timer |
|
549 expires, the resolver is not ripe to be evicted. Have to wait a |
|
550 second time. |
|
551 @param aResolverUid the Resolver to wait for evict. |
|
552 @return ETrue means the resolver is evicted correctly. |
|
553 EFalse means error, i.e. test fail. |
|
554 */ |
|
555 TBool CCustomResolverCacheTest::WaitForEvict(TUid aResolverUid) |
|
556 { |
|
557 TBool ret = EFalse; |
|
558 // No point of waiting for 20s for cache timeout. |
|
559 TInt waitMicroSec = KCustomResolverCacheTimeout + KOneSecond; |
|
560 for (TInt i = 0; (i < 2) && !ret; i++) |
|
561 { |
|
562 AsyncEvents.ClearAll(); |
|
563 YieldToOtherCActive(waitMicroSec); |
|
564 // Check which async event has stopped the activescheduler |
|
565 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
566 ret = ! HasResolverUid(aResolverUid); |
|
567 } |
|
568 return ret; |
|
569 } |
|
570 |
|
571 //========================================================== |
|
572 // utilities to access internal data of CCustomResolverCache. |
|
573 // This is possible because CCustomResolverCacheTest is a friend. |
|
574 //=========================================================== |
|
575 |
|
576 TInt CCustomResolverCacheTest::CacheSize() |
|
577 { |
|
578 return ResolverCache()->iResolvers.Count(); |
|
579 } |
|
580 |
|
581 TBool CCustomResolverCacheTest::HasResolverUid(TUid aUid) |
|
582 { |
|
583 for (TInt i = 0; i < ResolverCache()->iResolvers.Count(); i++) |
|
584 { |
|
585 if (ResolverCache()->iResolvers[i].iResolverUid == aUid) |
|
586 { |
|
587 return ETrue; |
|
588 } |
|
589 } |
|
590 return EFalse; |
|
591 } |
|
592 |
|
593 TBool CCustomResolverCacheTest::QueueIsSorted() |
|
594 { |
|
595 CCustomResolverCache* theResolverCache = ResolverCache(); |
|
596 for (TInt i = 1; i < theResolverCache->iResolvers.Count(); i++) |
|
597 { |
|
598 if (theResolverCache->iResolvers[i-1].iResolverUid.iUid >= |
|
599 theResolverCache->iResolvers[i].iResolverUid.iUid) |
|
600 { |
|
601 test.Printf(_L("Sort error: i-1 %d, 0x%8X, 0x%8X\n"), i-1, |
|
602 theResolverCache->iResolvers[i-1].iResolverUid.iUid, |
|
603 theResolverCache->iResolvers[i].iResolverUid.iUid ); |
|
604 return EFalse; |
|
605 } |
|
606 } |
|
607 return ETrue; |
|
608 } |
|
609 |
|
610 /** |
|
611 @SYMTestCaseID SYSLIB-ECOM-CT-4012 |
|
612 @SYMTestCaseDesc If a cached resolver is superseded by a new version, it |
|
613 is evicted from cache. |
|
614 @SYMTestPriority High |
|
615 @SYMTestActions 1. Use a custom resolver to get it in cache. |
|
616 2. copy the upgrade version of the resolver to C: and wait for |
|
617 its discovery. |
|
618 @SYMTestExpectedResults 1. a/. The resolver is the base version. |
|
619 b/. It is added in the cache. |
|
620 2. a/. Cache mgr receives upgrade notification (from CRegistryData). |
|
621 b/. The resolver entry disappears from cache and the cache timer is |
|
622 still running. |
|
623 @SYMCR CR1182 |
|
624 */ |
|
625 void CCustomResolverCacheTest::TestUpgradingCachedResolverL() |
|
626 { |
|
627 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-4012 ")); |
|
628 // get the customer resolver in cache. It should be version 1. |
|
629 test (UseResolverCheckVersionL(KMyResolverUid, 1)); |
|
630 // Check that KMyResolverUid is added to cache. |
|
631 test(HasResolverUid(KMyResolverUid)); |
|
632 |
|
633 // Need an extra item in cache to get Bullseye to check off |
|
634 // a conditional. It is not an active ingredient of this test. |
|
635 UseResolverCheckVersionL(KDummyResolverUid1, 0); |
|
636 |
|
637 // Copy the upgrade to C: drive |
|
638 EComTestUtils::FileManCopyFileL(KRscUpgradeInZ, KRscUpgradeInC); |
|
639 EComTestUtils::FileManCopyFileL(KDllUpgradeInZ, KDllUpgradeInC); |
|
640 |
|
641 // Let CDiscoverer discover the resource file. |
|
642 AsyncEvents.ClearAll(); |
|
643 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
644 |
|
645 // Check which async event has stopped the activescheduler |
|
646 test( AsyncEvents.IsSet(EAsyncEvent_ImplUpgrade) ); |
|
647 |
|
648 // And the cache entry should be gone. |
|
649 test(! HasResolverUid(KMyResolverUid)); |
|
650 |
|
651 // cleanup. NB: we never loaded the DLL in C: drive so |
|
652 // no need to worry about lazy dll unloading. |
|
653 EComTestUtils::FileManDeleteFileL(KRscUpgradeInC); |
|
654 EComTestUtils::FileManDeleteFileL(KDllUpgradeInC); |
|
655 } |
|
656 |
|
657 /** |
|
658 @SYMTestCaseID SYSLIB-ECOM-CT-4013 |
|
659 @SYMTestCaseDesc Verify a cached DLL cannot be deleted until it |
|
660 is removed from cache. This test serves as a sanity check that |
|
661 ECOM does need these notifications to trigger unloading DLL |
|
662 on SWI and BUR events. |
|
663 @SYMTestPriority Medium |
|
664 @SYMTestActions 1. Use a RW drive resolver to get it in cache. |
|
665 2. Try to delete the DLL within default cache timeout period. |
|
666 3. Try again after it is evicted from cache. |
|
667 @SYMTestExpectedResults 1. The resolver is added in cache. |
|
668 2. Get KErrAccessDenied error. |
|
669 3. The delete is either KErrNone or KErrNotFound because in step 2 |
|
670 even though the return code is -21, the file may be actually gone. |
|
671 @SYMCR CR1182 |
|
672 */ |
|
673 void CCustomResolverCacheTest::TestDeletingCachedResolverL() |
|
674 { |
|
675 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CT-4013 ")); |
|
676 // NB: lazy Dll unloading interferes with this test. |
|
677 // Best to run this test at the end. |
|
678 WaitForLazyUnloadingL(); |
|
679 |
|
680 // There is only 1 version of 200126CD. No need to check version. |
|
681 // So ignore the return code. |
|
682 UseResolverCheckVersionL(KDummyResolverUid1, 0); |
|
683 |
|
684 // Check that it is added to cache. |
|
685 test( HasResolverUid(KDummyResolverUid1) ); |
|
686 |
|
687 TInt err(KErrNone); |
|
688 TRAP(err, EComTestUtils::FileManDeleteFileL(KDummyDllInC)); |
|
689 |
|
690 #ifndef __WINSCW__ |
|
691 // On hw you can delete the DLL while it is loaded. |
|
692 if (err == KErrNone) |
|
693 { |
|
694 test.Printf(_L("Delete test: RFs allows deletion of loaded DLL on hw. Test not run.\n")); |
|
695 EComTestUtils::FileManCopyFileL(KDummyDllInZ, KDummyDllInC); |
|
696 return; |
|
697 } |
|
698 #endif |
|
699 |
|
700 test(err == KErrAccessDenied); |
|
701 |
|
702 // Wait for its eviction after cache timeout. |
|
703 AsyncEvents.ClearAll(); |
|
704 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
705 |
|
706 // Check which async event has stopped the activescheduler |
|
707 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
708 // Check the resolver is evicted |
|
709 test( !HasResolverUid(KDummyResolverUid1) ); |
|
710 |
|
711 TRAP(err, EComTestUtils::FileManDeleteFileL(KDummyDllInC)); |
|
712 test(err == KErrNone || err == KErrNotFound); |
|
713 |
|
714 // restore the file |
|
715 EComTestUtils::FileManCopyFileL(KDummyDllInZ, KDummyDllInC); |
|
716 } |
|
717 |
|
718 /** |
|
719 @SYMTestCaseID SYSLIB-ECOM-UT-4015 |
|
720 @SYMTestCaseDesc Verify cache queue does not grow beyond the max |
|
721 queue size. Verify when a resolver is added to a full cache, |
|
722 the one to evict is the least recently used. |
|
723 |
|
724 There are 3 versions of this test. In Pattern1, the LRU entry |
|
725 has UID value which is the smallest of the 5 resolvers. |
|
726 In pattern 2, UID of the LRU is greatest. In pattern 3, UID of the |
|
727 LRU is the second smallest. |
|
728 @SYMTestPriority High |
|
729 @SYMTestActions 1. Use 4 different resolvers to fill up the cache. |
|
730 2. Use a fifth one to bump off the least recently used entry. |
|
731 Run these two steps with the LRU entry in different positions in the |
|
732 queue, i.e. it is first, second, and last in the queue. |
|
733 @SYMTestExpectedResults 1. The cache has 4 entries and is sorted in UID order. |
|
734 2. The oldest entry is gone from cache. The last one used is in cache. |
|
735 @SYMCR CR1182 |
|
736 */ |
|
737 void CCustomResolverCacheTest::TestCacheQueueFullPattern1L() |
|
738 { |
|
739 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4015 ")); |
|
740 RArray<TUid> resolverlist(1); |
|
741 CleanupClosePushL(resolverlist); |
|
742 |
|
743 // NB: the following insertion order caused the problem found in |
|
744 // INC115472. Hence there will be a check in DoQueueFullTestL |
|
745 // that the cache queue is sorted correctly. |
|
746 // |
|
747 // Condition for inc115472 is first insert an UID of 0xA??????? |
|
748 // in an empty queue. Next insert an UID 0x2???????. The overflow |
|
749 // error causes them to be placed in the wrong order. |
|
750 resolverlist.AppendL(KDummyResolverUid2); |
|
751 resolverlist.AppendL(KDummyResolverUid1); |
|
752 resolverlist.AppendL(KExampleResolverUid); |
|
753 resolverlist.AppendL(KMyResolverUid); |
|
754 resolverlist.AppendL(KDummyResolverUid3); |
|
755 DoQueueFullTestL(resolverlist); |
|
756 CleanupStack::PopAndDestroy(&resolverlist); |
|
757 } |
|
758 |
|
759 // In pattern 2 the oldest entry in cache has the largest UID value. |
|
760 void CCustomResolverCacheTest::TestCacheQueueFullPattern2L() |
|
761 { |
|
762 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4015 ")); |
|
763 RArray<TUid> resolverlist(1); |
|
764 CleanupClosePushL(resolverlist); |
|
765 resolverlist.AppendL(KDummyResolverUid1); |
|
766 resolverlist.AppendL(KDummyResolverUid2); |
|
767 resolverlist.AppendL(KDummyResolverUid3); |
|
768 resolverlist.AppendL(KExampleResolverUid); |
|
769 resolverlist.AppendL(KMyResolverUid); |
|
770 DoQueueFullTestL(resolverlist); |
|
771 CleanupStack::PopAndDestroy(&resolverlist); |
|
772 } |
|
773 |
|
774 // In pattern 3 the UID of the oldest entry has the second smallest value. |
|
775 void CCustomResolverCacheTest::TestCacheQueueFullPattern3L() |
|
776 { |
|
777 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4015 ")); |
|
778 RArray<TUid> resolverlist(1); |
|
779 CleanupClosePushL(resolverlist); |
|
780 resolverlist.AppendL(KDummyResolverUid3); |
|
781 resolverlist.AppendL(KDummyResolverUid1); |
|
782 resolverlist.AppendL(KDummyResolverUid2); |
|
783 resolverlist.AppendL(KExampleResolverUid); |
|
784 resolverlist.AppendL(KMyResolverUid); |
|
785 DoQueueFullTestL(resolverlist); |
|
786 CleanupStack::PopAndDestroy(&resolverlist); |
|
787 } |
|
788 |
|
789 void CCustomResolverCacheTest::DoQueueFullTestL(const RArray<TUid>& aResolverList) |
|
790 { |
|
791 // ensure cache is empty. |
|
792 test(CacheSize() == 0); |
|
793 |
|
794 TInt maxQueueSize = ResolverCache()->iMaxCacheSize; |
|
795 test(aResolverList.Count() > maxQueueSize); |
|
796 |
|
797 // Put 4 resolvers in the cache. Pause in between so that the time tick |
|
798 // of each entry is different. CacheMissPerfTestL in t_resolverperf exercises |
|
799 // the code path that time ticks are the same. |
|
800 const TInt KInBetweenDelay = 100000; |
|
801 TInt i; |
|
802 for (i = 0; i < maxQueueSize; i++) |
|
803 { |
|
804 UseResolverCheckVersionL(aResolverList[i], 0); |
|
805 User::AfterHighRes(KInBetweenDelay); |
|
806 } |
|
807 |
|
808 // Check cache is full. |
|
809 test(CacheSize() == maxQueueSize); |
|
810 // Check cache is sorted properly |
|
811 test( QueueIsSorted() ); |
|
812 |
|
813 // Add one more to cache. |
|
814 UseResolverCheckVersionL(aResolverList[maxQueueSize], 0); |
|
815 |
|
816 // Check that cache size is still full - not exceeding limit. |
|
817 test(CacheSize() == maxQueueSize); |
|
818 |
|
819 // Want to check LRU is gone and the last resolver is now in cache. |
|
820 test(! HasResolverUid(aResolverList[0])); |
|
821 test( QueueIsSorted() ); |
|
822 // Because of the above 3 checks, this is really redundant. |
|
823 test(HasResolverUid(aResolverList[maxQueueSize])); |
|
824 |
|
825 // Because the timestamps of the cache entries are staggered |
|
826 // 100 ms apart, the mgr can only kick out 1 item at each timer expiry. |
|
827 // So let the cache mgr exercise this code path. |
|
828 TInt n = 0; |
|
829 while (CacheSize() > 0) |
|
830 { |
|
831 AsyncEvents.ClearAll(); |
|
832 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
833 // Check which async event has stopped the activescheduler |
|
834 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
835 n++; |
|
836 } |
|
837 |
|
838 // n should be five. aResolverList[0] is bumped due to queue full. |
|
839 // So the first timer expire will not find any expired entry. |
|
840 test.Printf(_L("Gone through %d loops to clear out cache.\n"), n); |
|
841 |
|
842 test(n > maxQueueSize); |
|
843 } |
|
844 |
|
845 /** |
|
846 @SYMTestCaseID SYSLIB-ECOM-UT-4016 |
|
847 @SYMTestCaseDesc Verify resolver is unloaded after the specified timeout. |
|
848 @SYMTestPriority Medium |
|
849 @SYMTestActions 1. Use a resolver to get it in cache. |
|
850 2. Measure how long the entry stays in cache before it is evicted. |
|
851 @SYMTestExpectedResults The time should be >= default timeout but |
|
852 <= (timeout + 0.5s). |
|
853 @SYMCR CR1182 |
|
854 */ |
|
855 void CCustomResolverCacheTest::TestCacheTimerAccuracyL() |
|
856 { |
|
857 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4016 ")); |
|
858 TTime start; |
|
859 start.UniversalTime(); |
|
860 |
|
861 UseResolverCheckVersionL(KMyResolverUid, 0); |
|
862 test( HasResolverUid(KMyResolverUid) ); |
|
863 |
|
864 // Wait for cache timeout |
|
865 AsyncEvents.ClearAll(); |
|
866 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
867 // Check which async event has stopped the activescheduler |
|
868 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
869 |
|
870 TInt microseconds = CalcElapsedMicroseconds(start); |
|
871 test.Printf(_L("Resolver is cached for %d microseconds\n"), microseconds); |
|
872 |
|
873 TInt tickperiod; |
|
874 User::LeaveIfError(HAL::Get(HALData::ESystemTickPeriod, tickperiod)); |
|
875 TInt lowerLimit = KCustomResolverCacheTimeout - tickperiod; |
|
876 test(microseconds > lowerLimit); |
|
877 |
|
878 // The upper bound is tricky because there is no gaurantee on |
|
879 // CTimer accuracy. |
|
880 test(microseconds < (KCustomResolverCacheTimeout + KHalfSecond)); |
|
881 } |
|
882 |
|
883 /** |
|
884 @SYMTestCaseID SYSLIB-ECOM-UT-4017 |
|
885 @SYMTestCaseDesc Verify after a cache hit the time to live of the entry |
|
886 is extended. |
|
887 @SYMTestPriority High |
|
888 @SYMTestActions 1. Record start time. |
|
889 2. Use a resolver to put it in cache. |
|
890 3. After 1 s use it again. |
|
891 4 Wait for its eviction. |
|
892 5. Check how long the entry stays in cache. |
|
893 @SYMTestExpectedResults The time should be >= 5 seconds. |
|
894 @SYMCR CR1182 |
|
895 */ |
|
896 void CCustomResolverCacheTest::TestTimestampUpdateOnCacheHitL() |
|
897 { |
|
898 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4017 ")); |
|
899 // Check that the resolver is not in cache. |
|
900 test(! HasResolverUid(KMyResolverUid) ); |
|
901 |
|
902 TTime start; |
|
903 start.UniversalTime(); |
|
904 |
|
905 UseResolverCheckVersionL(KMyResolverUid, 0); |
|
906 test( HasResolverUid(KMyResolverUid) ); |
|
907 |
|
908 // Delay one second and use it again. |
|
909 User::AfterHighRes(KOneSecond); |
|
910 UseResolverCheckVersionL(KMyResolverUid, 0); |
|
911 |
|
912 // Wait for its eviction |
|
913 while ( HasResolverUid(KMyResolverUid) ) |
|
914 { |
|
915 AsyncEvents.ClearAll(); |
|
916 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
917 // Check which async event has stopped the activescheduler |
|
918 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
919 } |
|
920 |
|
921 TInt microseconds = CalcElapsedMicroseconds(start); |
|
922 test.Printf(_L("With cache hit, resolver is cached for %d microseconds\n"), microseconds); |
|
923 |
|
924 TInt tickperiod; |
|
925 User::LeaveIfError(HAL::Get(HALData::ESystemTickPeriod, tickperiod)); |
|
926 TInt lowerLimit = KCustomResolverCacheTimeout + KOneSecond - tickperiod; |
|
927 test(microseconds > lowerLimit); |
|
928 } |
|
929 |
|
930 /** |
|
931 @SYMTestCaseID SYSLIB-ECOM-UT-4018 |
|
932 @SYMTestCaseDesc Verify at SWI start RW resolvers are evicted from cache. |
|
933 Verify during SWI ROM resolvers are cached but RW resolvers are not. |
|
934 @SYMTestPriority High |
|
935 @SYMTestActions 1. Add a RW resolver to cache. |
|
936 2. Send a SWI start signal. |
|
937 3. Use a RW resolver. |
|
938 4 Use a ROM resolver. |
|
939 @SYMTestExpectedResults 1. The RW resolver is in cache. |
|
940 2. The cache entry is evicted. |
|
941 3. The RW resolver is not cached. |
|
942 4. The ROM resolver is cached. |
|
943 @SYMCR CR1182 |
|
944 */ |
|
945 void CCustomResolverCacheTest::TestSWIDisableRwResolverCachingL() |
|
946 { |
|
947 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4018 ")); |
|
948 // The TPropertyManager protocol to setup to use a system category P&S. |
|
949 TInt r = PropertyManager::DeleteProperty(KUidSystemCategory, |
|
950 KSAUidSoftwareInstallKeyValue); |
|
951 test(r == KErrNone); |
|
952 r = PropertyManager::DefineProperty(KUidSystemCategory, |
|
953 KSAUidSoftwareInstallKeyValue, RProperty::EInt); |
|
954 test(r == KErrNone); |
|
955 |
|
956 // Use a resolver in C: drive. |
|
957 UseResolverCheckVersionL(KDummyResolverUid1, 0); |
|
958 // Check that it is added to cache. |
|
959 test( HasResolverUid(KDummyResolverUid1) ); |
|
960 |
|
961 // Need a ROM entry in cache to get Bullseye to check off |
|
962 // a conditional. It is not an active ingredient of this test. |
|
963 UseResolverCheckVersionL(KMyResolverUid, 0); |
|
964 |
|
965 // SWI start |
|
966 r = PropertyManager::SetProperty(KUidSystemCategory, |
|
967 KSAUidSoftwareInstallKeyValue,ESASwisInstall); |
|
968 test(r == KErrNone); |
|
969 |
|
970 // Let CSwiChangeNotifier receive the notification |
|
971 AsyncEvents.ClearAll(); |
|
972 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
973 // Check we receive the correct event |
|
974 test( AsyncEvents.IsSet(EAsyncEvent_SwiStart) ); |
|
975 |
|
976 // Check the RW resolver is evicted |
|
977 test(! HasResolverUid(KDummyResolverUid1) ); |
|
978 |
|
979 // during SWI RW resolver will not be cached. |
|
980 UseResolverCheckVersionL(KDummyResolverUid1, 0); |
|
981 test(! HasResolverUid(KDummyResolverUid1) ); |
|
982 |
|
983 // But ROM resolvers are still cached. |
|
984 UseResolverCheckVersionL(KDummyResolverUid2, 0); |
|
985 test( HasResolverUid(KDummyResolverUid2) ); |
|
986 |
|
987 // And the ROM resolvers are evicted after 4 s as usual. |
|
988 // Note that we have KMyResolverUid and KDummyResolverUid2 in cache |
|
989 TBool b = WaitForEvict(KDummyResolverUid2); |
|
990 if (! b) |
|
991 { // got KMyResolverUid only, need a second wait. |
|
992 b = WaitForEvict(KDummyResolverUid2); |
|
993 } |
|
994 test(b); |
|
995 |
|
996 // Just for completeness. Do not really need this |
|
997 // for Bullseye Coverage. |
|
998 r = PropertyManager::SetProperty(KUidSystemCategory, |
|
999 KSAUidSoftwareInstallKeyValue,ESASwisNone); |
|
1000 test(r == KErrNone); |
|
1001 // Let CSwiChangeNotifier receive the notification |
|
1002 AsyncEvents.ClearAll(); |
|
1003 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
1004 // Check we receive the correct event |
|
1005 test( AsyncEvents.IsSet(EAsyncEvent_SwiEnd) ); |
|
1006 } |
|
1007 |
|
1008 /** |
|
1009 @SYMTestCaseID SYSLIB-ECOM-UT-4019 |
|
1010 @SYMTestCaseDesc Verify at BUR start RW resolvers are evicted from cache. |
|
1011 Verify during BUR ROM resolvers are cached but RW resolvers are not. |
|
1012 @SYMTestPriority High |
|
1013 @SYMTestActions 1. Add a RW resolver to cache. |
|
1014 2. Send a BUR start signal. |
|
1015 3. Use a RW resolver. |
|
1016 4 Use a ROM resolver. |
|
1017 @SYMTestExpectedResults 1. The RW resolver is in cache. |
|
1018 2. The cache entry is evicted. |
|
1019 3. The RW resolver is not cached. |
|
1020 4. The ROM resolver is cached. |
|
1021 @SYMCR CR1182 |
|
1022 */ |
|
1023 void CCustomResolverCacheTest::TestBurDisableRwResolverCachingL() |
|
1024 { |
|
1025 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4019 ")); |
|
1026 // setup backup session wrapper |
|
1027 CBaBackupSessionWrapper* ba = CBaBackupSessionWrapper::NewL(); |
|
1028 CleanupStack::PushL(ba); |
|
1029 TBackupOperationAttributes attribs; |
|
1030 attribs.iFileFlag=MBackupObserver::EReleaseLockNoAccess; |
|
1031 attribs.iOperation=MBackupOperationObserver::EStart; |
|
1032 |
|
1033 // The backup notifier of ECOM is not registered with |
|
1034 // BA server at construction time. It delays 15 s. |
|
1035 // So we have to wait this long. |
|
1036 WaitAsyncL(16); |
|
1037 |
|
1038 // Use a resolver in C: drive. |
|
1039 UseResolverCheckVersionL(KDummyResolverUid1, 0); |
|
1040 // Check that it is added to cache. |
|
1041 test( HasResolverUid(KDummyResolverUid1) ); |
|
1042 |
|
1043 // Need a ROM entry in cache to get Bullseye to check off |
|
1044 // a conditional. It is not an active ingredient of this test. |
|
1045 UseResolverCheckVersionL(KMyResolverUid, 0); |
|
1046 |
|
1047 // backup start |
|
1048 ba->NotifyBackupOperationL(attribs); |
|
1049 // Let backup notifier receive the backup start |
|
1050 AsyncEvents.ClearAll(); |
|
1051 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
1052 // Check we receive the backup start notification |
|
1053 test( AsyncEvents.IsSet(EAsyncEvent_BurStart) ); |
|
1054 |
|
1055 // Check the RW resolver is evicted |
|
1056 test(! HasResolverUid(KDummyResolverUid1) ); |
|
1057 |
|
1058 // during BUR RW resolver will not be cached. |
|
1059 UseResolverCheckVersionL(KDummyResolverUid1, 0); |
|
1060 test(! HasResolverUid(KDummyResolverUid1) ); |
|
1061 |
|
1062 // But ROM resolvers are still cached. |
|
1063 UseResolverCheckVersionL(KDummyResolverUid2, 0); |
|
1064 test( HasResolverUid(KDummyResolverUid2) ); |
|
1065 |
|
1066 // And the ROM resolvers are evicted after 4 s as usual. |
|
1067 // Note that we have KMyResolverUid and KDummyResolverUid2 in cache |
|
1068 TBool b = WaitForEvict(KDummyResolverUid2); |
|
1069 if (! b) |
|
1070 { // got KMyResolverUid only, need a second wait. |
|
1071 b = WaitForEvict(KDummyResolverUid2); |
|
1072 } |
|
1073 test(b); |
|
1074 |
|
1075 // Do this for Bullseye Coverage of production code. |
|
1076 // NB: attribs.iFileFlag stays the same |
|
1077 attribs.iOperation=MBackupOperationObserver::EEnd; |
|
1078 ba->NotifyBackupOperationL(attribs); |
|
1079 // Let backup notifier receive it |
|
1080 AsyncEvents.ClearAll(); |
|
1081 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
1082 // Check we receive the backup notification |
|
1083 test( AsyncEvents.IsSet(EAsyncEvent_BurEnd) ); |
|
1084 |
|
1085 CleanupStack::PopAndDestroy(ba); |
|
1086 |
|
1087 // to earn another Bullseye check mark. |
|
1088 CEComServer::NotifyEvents(iEComServer, ECallBackId_None, NULL); |
|
1089 } |
|
1090 |
|
1091 /** |
|
1092 @SYMTestCaseID SYSLIB-ECOM-UT-4021 |
|
1093 @SYMTestCaseDesc Verify the cache timer and data to keep track of |
|
1094 cache entry time to live are immune to device clock change. |
|
1095 @SYMTestPriority High |
|
1096 @SYMTestActions 1. Put two resolvers in cache at 20 ticks apart. |
|
1097 2. Spring clock forward by 5 s (1 + default cache timeout). |
|
1098 3. Measure how long the first resolver is cached. |
|
1099 4. Measure how long the second resolver is cached. |
|
1100 Repeat steps 1 to 4 in setting clock backward. |
|
1101 @SYMTestExpectedResults Both resolvers are cached for ~ 4 s |
|
1102 (default cache timeout value). |
|
1103 @SYMCR CR1182 |
|
1104 */ |
|
1105 void CCustomResolverCacheTest::TestClockChangeHasNoEffectOnCacheTimeoutL() |
|
1106 { |
|
1107 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4021 ")); |
|
1108 TInt tp; |
|
1109 User::LeaveIfError(HAL::Get(HALData::ESystemTickPeriod, tp)); |
|
1110 TInt delayInBetween = tp * 20; |
|
1111 test.Printf(_L("ESystemTickPeriod: %d; delayInBetween: %d;\n"), tp, delayInBetween); |
|
1112 |
|
1113 |
|
1114 TTime beforeDelay; |
|
1115 beforeDelay.UniversalTime(); |
|
1116 |
|
1117 UseResolverCheckVersionL(KDummyResolverUid1, 0); |
|
1118 test( HasResolverUid(KDummyResolverUid1) ); |
|
1119 |
|
1120 User::AfterHighRes(delayInBetween); |
|
1121 TInt elapsedBeforeTimeChange = CalcElapsedMicroseconds(beforeDelay); |
|
1122 |
|
1123 UseResolverCheckVersionL(KDummyResolverUid2, 0); |
|
1124 test( HasResolverUid(KDummyResolverUid2) ); |
|
1125 |
|
1126 TTimeIntervalMicroSeconds AmountOfChange( |
|
1127 MAKE_TINT64(0, KCustomResolverCacheTimeout+KOneSecond) ); |
|
1128 |
|
1129 // Now set device clock forward |
|
1130 TTime t; |
|
1131 t.UniversalTime(); |
|
1132 t += AmountOfChange; |
|
1133 User::LeaveIfError( User::SetUTCTime(t) ); |
|
1134 |
|
1135 t.UniversalTime(); // need this, apparently SetUTCTime does rounding |
|
1136 |
|
1137 // Wait for cache timeout |
|
1138 AsyncEvents.ClearAll(); |
|
1139 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
1140 // Check which async event has stopped the activescheduler |
|
1141 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
1142 |
|
1143 TInt microseconds = CalcElapsedMicroseconds(t); |
|
1144 // compensate for the 20 ticks delay |
|
1145 microseconds += elapsedBeforeTimeChange; |
|
1146 test.Printf(_L("Clock forward: 1st resolver is cached for %d microseconds\n"), microseconds); |
|
1147 test(! HasResolverUid(KDummyResolverUid1) ); |
|
1148 // Check duration is between 4 to 4.5 s. |
|
1149 TInt lowerLimit = KCustomResolverCacheTimeout - (tp*3); |
|
1150 TInt upperLimit = (KCustomResolverCacheTimeout + KHalfSecond); |
|
1151 test.Printf(_L("lowerLimit: %d; upperLimit: %d\n"), lowerLimit, upperLimit); |
|
1152 test(microseconds > lowerLimit); |
|
1153 |
|
1154 // upper limit is tricky because there is no guarantee on CTimer |
|
1155 // accuracy. |
|
1156 test(microseconds <= upperLimit); |
|
1157 |
|
1158 // Wait for eviction of the second resolver |
|
1159 AsyncEvents.ClearAll(); |
|
1160 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
1161 // Check which async event has stopped the activescheduler |
|
1162 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
1163 |
|
1164 microseconds = CalcElapsedMicroseconds(t); |
|
1165 test.Printf(_L("Clock forward: 2nd resolver is cached for %d microseconds\n"), microseconds); |
|
1166 test(! HasResolverUid(KDummyResolverUid2) ); |
|
1167 // Check duration is between 4 to 4.5 s. |
|
1168 test(microseconds > lowerLimit); |
|
1169 test(microseconds <= upperLimit); |
|
1170 |
|
1171 // |
|
1172 // Repeat for setting clock backward. |
|
1173 // |
|
1174 beforeDelay.UniversalTime(); |
|
1175 |
|
1176 UseResolverCheckVersionL(KDummyResolverUid1, 0); |
|
1177 test( HasResolverUid(KDummyResolverUid1) ); |
|
1178 |
|
1179 User::AfterHighRes(delayInBetween); |
|
1180 elapsedBeforeTimeChange = CalcElapsedMicroseconds(beforeDelay); |
|
1181 |
|
1182 UseResolverCheckVersionL(KDummyResolverUid2, 0); |
|
1183 test( HasResolverUid(KDummyResolverUid2) ); |
|
1184 |
|
1185 // Now set device clock backward |
|
1186 t.UniversalTime(); |
|
1187 t -= AmountOfChange; |
|
1188 User::LeaveIfError( User::SetUTCTime(t) ); |
|
1189 t.UniversalTime(); |
|
1190 |
|
1191 // Wait for cache timeout |
|
1192 AsyncEvents.ClearAll(); |
|
1193 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
1194 // Check which async event has stopped the activescheduler |
|
1195 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
1196 |
|
1197 microseconds = CalcElapsedMicroseconds(t); |
|
1198 // compensate for the 20 ticks delay |
|
1199 microseconds += elapsedBeforeTimeChange; |
|
1200 test.Printf(_L("Clock backward: 1st resolver is cached for %d microseconds\n"), microseconds); |
|
1201 test(! HasResolverUid(KDummyResolverUid1) ); |
|
1202 // Check duration is between 4 to 4.5 s. |
|
1203 test(microseconds > lowerLimit); |
|
1204 test(microseconds <= (KCustomResolverCacheTimeout + KHalfSecond)); |
|
1205 |
|
1206 // Wait for eviction of the second resolver |
|
1207 AsyncEvents.ClearAll(); |
|
1208 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
1209 // Check which async event has stopped the activescheduler |
|
1210 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
1211 |
|
1212 microseconds = CalcElapsedMicroseconds(t); |
|
1213 test.Printf(_L("Clock backward: 2nd resolver is cached for %d microseconds\n"), microseconds); |
|
1214 test(! HasResolverUid(KDummyResolverUid2) ); |
|
1215 // Check duration is between 4 to 4.5 s. |
|
1216 test(microseconds > lowerLimit); |
|
1217 test(microseconds <= (KCustomResolverCacheTimeout + KHalfSecond)); |
|
1218 } |
|
1219 |
|
1220 /** |
|
1221 @SYMTestCaseID SYSLIB-ECOM-UT-4022 |
|
1222 @SYMTestCaseDesc Verify caching runs normally if queue size is zero. |
|
1223 @SYMTestPriority Medium |
|
1224 @SYMTestActions 1. Set max. cache size to 0. |
|
1225 2. Use a custom resolver. |
|
1226 @SYMTestExpectedResults No leave on the list request and cache is empty. |
|
1227 @SYMCR CR1182 |
|
1228 */ |
|
1229 void CCustomResolverCacheTest::TestCacheSizeZeroL() |
|
1230 { |
|
1231 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4022 ")); |
|
1232 ResolverCache()->iMaxCacheSize = 0; |
|
1233 UseResolverCheckVersionL(KMyResolverUid, 0); |
|
1234 test(! HasResolverUid(KMyResolverUid) ); |
|
1235 } |
|
1236 |
|
1237 /** |
|
1238 @SYMTestCaseID SYSLIB-ECOM-UT-4023 |
|
1239 @SYMTestCaseDesc Verify caching runs normally if cache timeout is zero. |
|
1240 @SYMTestPriority Medium |
|
1241 @SYMTestActions 1. Set cache time-to-live to zero. |
|
1242 2. Use a custom resolver. |
|
1243 @SYMTestExpectedResults No leave on the list request and cache is empty. |
|
1244 @SYMCR CR1182 |
|
1245 */ |
|
1246 void CCustomResolverCacheTest::TestCacheTimeoutZeroL() |
|
1247 { |
|
1248 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4023 ")); |
|
1249 TInt systemTickPeriod = ResolverCache()->iSystemTickPeriod; |
|
1250 // mimic CCustomResolverCache calculate the time-to-live value. |
|
1251 const TInt KZeroTimeout = 0; |
|
1252 ResolverCache()->iEntryTimeToLive = (KZeroTimeout + |
|
1253 systemTickPeriod - 1) / systemTickPeriod; |
|
1254 |
|
1255 // run the test |
|
1256 UseResolverCheckVersionL(KMyResolverUid, 0); |
|
1257 test(! HasResolverUid(KMyResolverUid) ); |
|
1258 } |
|
1259 |
|
1260 /** |
|
1261 @SYMTestCaseID SYSLIB-ECOM-UT-4024 |
|
1262 @SYMTestCaseDesc CCustomResolverCache uses system tick to track entry |
|
1263 time-to-live. The counter wraps around every 777 days. This test |
|
1264 checks when wrap around occurs cached entry is purged correctly. |
|
1265 @SYMTestPriority Medium |
|
1266 @SYMTestActions 1. Use a resolver to get it in cache. |
|
1267 2. Set its time-of-use to 0xFFFFFFFF. |
|
1268 3. Wait for cache timer expire. |
|
1269 @SYMTestExpectedResults The entry is evicted on first timer expiry and |
|
1270 the entry stays in cache for ~ 4s. |
|
1271 @SYMCR CR1182 |
|
1272 */ |
|
1273 void CCustomResolverCacheTest::TestCounterWrapAroundL() |
|
1274 { |
|
1275 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4024 ")); |
|
1276 TTime start; |
|
1277 start.UniversalTime(); |
|
1278 |
|
1279 UseResolverCheckVersionL(KMyResolverUid, 0); |
|
1280 RResolverCacheEntry& entry = ResolverCache()->iResolvers[0]; |
|
1281 test( entry.iResolverUid == KMyResolverUid ); |
|
1282 |
|
1283 // Set time-of-use to edge of wrap around |
|
1284 entry.iLastUse.iTicks = KMaxTUint; |
|
1285 |
|
1286 // Wait for cache timeout |
|
1287 AsyncEvents.ClearAll(); |
|
1288 YieldToOtherCActive(KIndefiniteWait); // 20 s |
|
1289 // Check which async event has stopped the activescheduler |
|
1290 test( AsyncEvents.IsSet(EAsyncEvent_CacheTimer) ); |
|
1291 |
|
1292 TInt microseconds = CalcElapsedMicroseconds(start); |
|
1293 test.Printf(_L("Wrap around: resolver is cached for %d microseconds\n"), microseconds); |
|
1294 |
|
1295 TInt tickperiod; |
|
1296 User::LeaveIfError(HAL::Get(HALData::ESystemTickPeriod, tickperiod)); |
|
1297 TInt lowerLimit = KCustomResolverCacheTimeout - tickperiod; |
|
1298 test(microseconds > lowerLimit); |
|
1299 // Upper limit must have a wide margin because there is no gaurantee |
|
1300 // on CTimer accuracy. |
|
1301 test(microseconds < (KCustomResolverCacheTimeout + KHalfSecond)); |
|
1302 } |
|
1303 |
|
1304 /** |
|
1305 @SYMTestCaseID SYSLIB-ECOM-UT-4025 |
|
1306 @SYMTestCaseDesc Verify if cannot find the NewL method in the proxy |
|
1307 instantiation table, ECOM returns KEComErrNoResolver |
|
1308 @SYMTestPriority Medium |
|
1309 @SYMTestActions Use a resolver whose proxy table has the wrong Impl. Uid. |
|
1310 @SYMTestExpectedResults Get KEComErrNoResolver error |
|
1311 @SYMCR CR1182 |
|
1312 */ |
|
1313 void CCustomResolverCacheTest::TestResolverWithBadProxyTable() |
|
1314 { |
|
1315 test.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-UT-4025 ")); |
|
1316 const TUid KBadResolverUid = {0x10009DDF}; |
|
1317 TRAPD(err, UseResolverCheckVersionL(KBadResolverUid, 0) ); |
|
1318 test(err == KEComErrNoResolver); |
|
1319 } |
|
1320 |
|
1321 /** wrapper to run all the Basic and OOM tests */ |
|
1322 void CCustomResolverCacheTest::RunAllTestsL() |
|
1323 { |
|
1324 CopyPluginsL(); |
|
1325 |
|
1326 test.Next(_L("Basic TestCounterWrapAroundL")); |
|
1327 DoBasicTestL(&CCustomResolverCacheTest::TestCounterWrapAroundL); |
|
1328 |
|
1329 test.Next(_L("Basic TestUpgradingCachedResolverL")); |
|
1330 DoBasicTestL(&CCustomResolverCacheTest::TestUpgradingCachedResolverL); |
|
1331 |
|
1332 test.Next(_L("Basic TestCacheQueueFullPattern1L")); |
|
1333 DoBasicTestL(&CCustomResolverCacheTest::TestCacheQueueFullPattern1L); |
|
1334 |
|
1335 test.Next(_L("Basic TestCacheQueueFullPattern2L")); |
|
1336 DoBasicTestL(&CCustomResolverCacheTest::TestCacheQueueFullPattern2L); |
|
1337 |
|
1338 test.Next(_L("Basic TestCacheQueueFullPattern3L")); |
|
1339 DoBasicTestL(&CCustomResolverCacheTest::TestCacheQueueFullPattern3L); |
|
1340 |
|
1341 test.Next(_L("Basic TestCacheTimerAccuracyL")); |
|
1342 DoBasicTestL(&CCustomResolverCacheTest::TestCacheTimerAccuracyL); |
|
1343 |
|
1344 test.Next(_L("Basic TestTimestampUpdateOnCacheHitL")); |
|
1345 DoBasicTestL(&CCustomResolverCacheTest::TestTimestampUpdateOnCacheHitL); |
|
1346 |
|
1347 test.Next(_L("Basic TestSWIDisableRwResolverCachingL")); |
|
1348 DoBasicTestL(&CCustomResolverCacheTest::TestSWIDisableRwResolverCachingL); |
|
1349 |
|
1350 test.Next(_L("Basic TestBurDisableRwResolverCachingL")); |
|
1351 DoBasicTestL(&CCustomResolverCacheTest::TestBurDisableRwResolverCachingL); |
|
1352 |
|
1353 test.Next(_L("Basic TestClockChangeHasNoEffectOnCacheTimeoutL")); |
|
1354 DoBasicTestL(&CCustomResolverCacheTest::TestClockChangeHasNoEffectOnCacheTimeoutL); |
|
1355 |
|
1356 test.Next(_L("Basic TestCacheSizeZeroL")); |
|
1357 DoBasicTestL(&CCustomResolverCacheTest::TestCacheSizeZeroL); |
|
1358 |
|
1359 test.Next(_L("Basic TestCacheTimeoutZeroL")); |
|
1360 DoBasicTestL(&CCustomResolverCacheTest::TestCacheTimeoutZeroL); |
|
1361 |
|
1362 test.Next(_L("Basic TestResolverWithBadProxyTable")); |
|
1363 DoBasicTestL(&CCustomResolverCacheTest::TestResolverWithBadProxyTable); |
|
1364 |
|
1365 // Only run OOM on tests which do not involve rescan dir. |
|
1366 test.Next(_L("OOM TestCacheQueueFullPattern3L")); |
|
1367 DoOOMTestL(&CCustomResolverCacheTest::TestCacheQueueFullPattern3L); |
|
1368 |
|
1369 test.Next(_L("OOM TestCacheTimerAccuracyL")); |
|
1370 DoOOMTestL(&CCustomResolverCacheTest::TestCacheTimerAccuracyL); |
|
1371 |
|
1372 test.Next(_L("OOM TestTimestampUpdateOnCacheHitL")); |
|
1373 DoOOMTestL(&CCustomResolverCacheTest::TestTimestampUpdateOnCacheHitL); |
|
1374 |
|
1375 // Do all tests affected by Lazy DLL unload last. |
|
1376 test.Next(_L("Basic TestDeletingCachedResolverL")); |
|
1377 DoBasicTestL(&CCustomResolverCacheTest::TestDeletingCachedResolverL); |
|
1378 } |
|
1379 |
|
1380 static TInt KillEComServer() |
|
1381 { |
|
1382 //Need to ensure that the EComServer process is killed before even starting this test by using |
|
1383 //the EComTestUtils library |
|
1384 _LIT(KEComServerProcessName,"ecomserver"); |
|
1385 TRAPD(err, EComTestUtils::KillProcessL(KEComServerProcessName)); |
|
1386 return err; |
|
1387 } |
|
1388 |
|
1389 GLDEF_C TInt E32Main() |
|
1390 { |
|
1391 __UHEAP_MARK; |
|
1392 |
|
1393 beginningOfTest.UniversalTime(); |
|
1394 |
|
1395 test.Printf(_L("\n")); |
|
1396 test.Title(); |
|
1397 test.Start( _L("Custom Resolver Cache") ); |
|
1398 |
|
1399 |
|
1400 TheTrapCleanup = CTrapCleanup::New(); |
|
1401 test(TheTrapCleanup != NULL); |
|
1402 |
|
1403 // Connect the file server instance |
|
1404 test(KErrNone == TheFs.Connect()); |
|
1405 |
|
1406 TheActiveScheduler = new CDerivedActiveScheduler; |
|
1407 test(TheActiveScheduler != NULL); |
|
1408 CActiveScheduler::Install(TheActiveScheduler); |
|
1409 |
|
1410 TInt err = ::KillEComServer(); |
|
1411 test(err == KErrNotFound || err == KErrNone); |
|
1412 |
|
1413 // Call the main tests |
|
1414 TRAP(err, CCustomResolverCacheTest::RunAllTestsL()); |
|
1415 if (err != KErrNone) test.Printf(_L("RunAllTestsL() error, %d\n"), err); |
|
1416 test(err == KErrNone); |
|
1417 |
|
1418 // remove the RAMOnly files |
|
1419 TRAP_IGNORE( WaitForLazyUnloadingL() ); |
|
1420 DeleteTestPlugin(); |
|
1421 User::After(KOneSecond * 3); |
|
1422 |
|
1423 delete TheActiveScheduler; |
|
1424 delete TheTrapCleanup; |
|
1425 |
|
1426 TheFs.Close(); |
|
1427 |
|
1428 test.End(); |
|
1429 test.Close(); |
|
1430 |
|
1431 __UHEAP_MARKEND; |
|
1432 return (KErrNone); |
|
1433 } |