|
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32test\system\t_ctrap.cpp |
|
15 // Overview: |
|
16 // Test the CCleanup, CTrapCleanup and TAutoClose classes |
|
17 // API Information: |
|
18 // CCleanup, CTrapCleanup, TAutoClose |
|
19 // Details: |
|
20 // - Test cleanup stack reallocation during cleanup. |
|
21 // - Test cleanup stack modifications during the cleanup operation |
|
22 // will cause a panic. |
|
23 // - Test single-level cleanup of cells, objects, items and a mix: |
|
24 // Create a CCleanup object, call a combination of methods, verify |
|
25 // the results are as expected and verify the heap has not been |
|
26 // corrupted. |
|
27 // - Test multi-level cleanup of cells, objects, items and a mix: |
|
28 // Create a CCleanup object, call a combination of methods, verify |
|
29 // the results are as expected and verify the heap has not been |
|
30 // corrupted. |
|
31 // - Test a variety of special case cleanup tasks. Verify that the |
|
32 // results are as expected. |
|
33 // - Test CTrapCleanup cleanup of objects that either exit normally |
|
34 // or leave. Also test the cleanup of multiple objects that leave. |
|
35 // Verify results are as expected. |
|
36 // - Test TAutoClose: create a TAutoClose object, verify that it is |
|
37 // closed when it goes out of scope, push it on the cleanup stack, |
|
38 // verify cleanup results are as expected. |
|
39 // - Test that the Cleanup stack can go re-entrant. |
|
40 // - Ensure that the stack is properly balanced with and without |
|
41 // leaving. |
|
42 // Platforms/Drives/Compatibility: |
|
43 // All. |
|
44 // Assumptions/Requirement/Pre-requisites: |
|
45 // Failures and causes: |
|
46 // Base Port information: |
|
47 // |
|
48 // |
|
49 |
|
50 #define __E32TEST_EXTENSION__ |
|
51 |
|
52 #include <e32test.h> |
|
53 #include <e32panic.h> |
|
54 #include <e32debug.h> |
|
55 #include <e32def.h> |
|
56 #include <e32def_private.h> |
|
57 |
|
58 |
|
59 const TInt KInitialCount=2; |
|
60 const TInt KInitialCountAll=3; |
|
61 const TInt KLeaveValue=0x12345678; |
|
62 const TInt KMaxAlloc=6; |
|
63 |
|
64 static const TInt KHeapSize = 0x2000; |
|
65 |
|
66 enum TWhat {EPop,EPopAndDestroy,EMulti,ENull}; |
|
67 |
|
68 class CTest : public CBase |
|
69 { |
|
70 public: |
|
71 void ConstructL(); |
|
72 private: |
|
73 TInt iData; |
|
74 }; |
|
75 |
|
76 class CTest2: public CBase |
|
77 { |
|
78 public: |
|
79 ~CTest2(); |
|
80 }; |
|
81 |
|
82 class CTest3: public CBase |
|
83 { |
|
84 public: |
|
85 ~CTest3(); |
|
86 }; |
|
87 |
|
88 class RItem |
|
89 { |
|
90 public: |
|
91 RItem() : iOpen(EFalse) {} |
|
92 void Open() {iOpen=ETrue;} |
|
93 void Close() {iOpen=EFalse;} |
|
94 operator TCleanupItem() {return TCleanupItem(Cleanup,this);} |
|
95 TBool IsOpen() const {return(iOpen);} |
|
96 private: |
|
97 static void Cleanup(TAny* aPtr); |
|
98 private: |
|
99 TBool iOpen; |
|
100 }; |
|
101 |
|
102 LOCAL_D RTest test(_L("T_CTRAP")); |
|
103 LOCAL_D TAny* gP1; |
|
104 LOCAL_D CBufFlat* gP2; |
|
105 |
|
106 |
|
107 LOCAL_C void ReallocateStackL() |
|
108 { |
|
109 TInt n = 0; |
|
110 for(TInt i = 0; i < KMaxAlloc; ++i) |
|
111 { |
|
112 HBufC *p1 = HBufC::NewLC(4); //Stack re-allocation will be performed due to the additional objects pushed |
|
113 //into the cleanup stack |
|
114 n = p1->Length(); //include this line to avoid warnigs for unused "p1" variable |
|
115 } |
|
116 test.Printf(_L("ReallocateStackL(): PopAndDestroy KMaxAlloc pointers\n")); |
|
117 CleanupStack::PopAndDestroy(KMaxAlloc); |
|
118 } |
|
119 |
|
120 CTest2::~CTest2() |
|
121 { |
|
122 TInt err = KErrNoMemory; |
|
123 |
|
124 test.Printf(_L("~CTest2(): call ReallocateStackL()\n")); |
|
125 |
|
126 TRAP(err, ReallocateStackL() ); |
|
127 } |
|
128 |
|
129 CTest3::~CTest3() |
|
130 { |
|
131 RDebug::Printf("~CTest3(): Modify Cleanup stack by pushing items"); |
|
132 |
|
133 TInt n = 0; |
|
134 for(TInt i = 0; i < KMaxAlloc; ++i) |
|
135 { |
|
136 HBufC *p1 = HBufC::NewLC(4); //Stack re-allocation will be performed due to the additional objects pushed |
|
137 //into the cleanup stack |
|
138 n = p1->Length(); //include this line to avoid warnigs for unused "p1" variable |
|
139 } |
|
140 } |
|
141 |
|
142 LOCAL_C void ModifyStack() |
|
143 { |
|
144 CTest3* ptr6 = new(ELeave)CTest3; |
|
145 CleanupStack::PushL(ptr6); |
|
146 |
|
147 RDebug::Printf("ModifyStack(): PopAndDestroy ptr6"); |
|
148 CleanupStack::PopAndDestroy(); |
|
149 } |
|
150 |
|
151 LOCAL_C TInt PanicStackModifiedFn(TAny* aNopFn) |
|
152 { |
|
153 __UHEAP_MARK; |
|
154 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
155 |
|
156 aNopFn = NULL; //avoid warnings for unused "aNopFn" variable |
|
157 |
|
158 TInt err = KErrNoMemory; |
|
159 |
|
160 RDebug::Printf("PanicStackModifiedFn(): call TRAP(err, ModifyStack())"); |
|
161 |
|
162 if(NULL != cleanup) |
|
163 { |
|
164 TRAP(err, ModifyStack()); |
|
165 delete cleanup; |
|
166 } |
|
167 __UHEAP_MARKEND; |
|
168 return err; |
|
169 } |
|
170 |
|
171 LOCAL_C void PushAndCleanupL() |
|
172 { |
|
173 CTest2* ptr1 = new(ELeave)CTest2; |
|
174 CleanupStack::PushL(ptr1); |
|
175 |
|
176 CTest2* ptr2 = new(ELeave)CTest2; |
|
177 CleanupStack::PushL(ptr2); |
|
178 |
|
179 CTest2* ptr3 = new(ELeave)CTest2; |
|
180 CleanupStack::PushL(ptr3); |
|
181 |
|
182 test.Printf(_L("PushAndCleanupL(): PopAndDestroy ptr3, ptr2 and ptr1\n")); |
|
183 CleanupStack::PopAndDestroy(3); |
|
184 |
|
185 CTest2* ptr4 = new(ELeave)CTest2; |
|
186 CleanupStack::PushL(ptr4); |
|
187 |
|
188 CTest2* ptr5 = new(ELeave)CTest2; |
|
189 CleanupStack::PushL(ptr5); |
|
190 |
|
191 test.Printf(_L("PushAndCleanupL(): PopAndDestroy ptr5 and ptr4\n")); |
|
192 CleanupStack::PopAndDestroy(); |
|
193 CleanupStack::PopAndDestroy(); |
|
194 } |
|
195 |
|
196 LOCAL_C void testDestructorStackReallocation() |
|
197 { |
|
198 __UHEAP_MARK; |
|
199 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
200 |
|
201 TInt err = KErrNoMemory; |
|
202 |
|
203 if(NULL != cleanup) |
|
204 { |
|
205 TRAP(err, PushAndCleanupL()); |
|
206 delete cleanup; |
|
207 } |
|
208 __UHEAP_MARKEND; |
|
209 |
|
210 test_KErrNone(err); |
|
211 |
|
212 test.Printf(_L("Verify cleanup stack modification during cleanup operation causes EClnStackModified panic\n")); |
|
213 |
|
214 // |
|
215 //To verify the above case a new thread is created which does modify the cleanup stack during cleanup. |
|
216 //The exit reason is then checked for the appropriate value(EClnStackModified) |
|
217 // |
|
218 |
|
219 RThread panicThread; |
|
220 |
|
221 TInt r = panicThread.Create(_L("Panic EClnStackModified Thread"), PanicStackModifiedFn, KDefaultStackSize, KHeapSize, KHeapSize, NULL); |
|
222 |
|
223 test_KErrNone(r); |
|
224 |
|
225 TRequestStatus panicThreadStatus; |
|
226 panicThread.Logon(panicThreadStatus); |
|
227 |
|
228 //don't want just in time debugging as we trap panics |
|
229 TBool justInTime=User::JustInTime(); |
|
230 User::SetJustInTime(EFalse); |
|
231 |
|
232 panicThread.Resume(); |
|
233 |
|
234 User::WaitForRequest(panicThreadStatus); |
|
235 |
|
236 test_Equal(EExitPanic, panicThread.ExitType()); |
|
237 test_Equal(EClnStackModified, panicThread.ExitReason()); |
|
238 |
|
239 User::SetJustInTime(justInTime); |
|
240 |
|
241 CLOSE_AND_WAIT(panicThread); |
|
242 } |
|
243 |
|
244 LOCAL_C void createMultiL() |
|
245 // |
|
246 // Create an object on the cleanup list and leave |
|
247 // |
|
248 { |
|
249 |
|
250 CBufFlat* pT=CBufFlat::NewL(8); |
|
251 User::LeaveIfNull(pT); |
|
252 CleanupStack::PushL(pT); |
|
253 __UHEAP_CHECK(3); |
|
254 User::Leave(KLeaveValue+1); |
|
255 } |
|
256 |
|
257 LOCAL_C void createL(TWhat aWhat,TBool aLeave) |
|
258 // |
|
259 // Create objects and then either leave or return. |
|
260 // Optionally pop them again. |
|
261 // |
|
262 { |
|
263 |
|
264 gP1=User::AllocL(0x10); |
|
265 test.Printf(_L("createL 1")); |
|
266 CleanupStack::PushL(gP1); |
|
267 test.Printf(_L("createL 2")); |
|
268 __UHEAP_CHECK(1); |
|
269 test.Printf(_L("createL 3")); |
|
270 gP2=CBufFlat::NewL(8); |
|
271 test.Printf(_L("createL 4")); |
|
272 User::LeaveIfNull(gP2); |
|
273 test.Printf(_L("createL 5")); |
|
274 CleanupStack::PushL(gP2); |
|
275 test.Printf(_L("createL 6")); |
|
276 __UHEAP_CHECK(2); |
|
277 test.Printf(_L("createL 7")); |
|
278 if (aWhat==EPop) |
|
279 { |
|
280 test.Printf(_L("createL 8")); |
|
281 CleanupStack::Pop(); |
|
282 test.Printf(_L("createL 9")); |
|
283 CleanupStack::Pop(1); |
|
284 test.Printf(_L("createL 10")); |
|
285 } |
|
286 if (aWhat==EPopAndDestroy) |
|
287 { |
|
288 test.Printf(_L("createL 11")); |
|
289 CleanupStack::PopAndDestroy(); |
|
290 test.Printf(_L("createL 12")); |
|
291 CleanupStack::PopAndDestroy(1); |
|
292 test.Printf(_L("createL 13")); |
|
293 } |
|
294 if (aWhat==EMulti) |
|
295 { |
|
296 test.Printf(_L("createL 14")); |
|
297 TRAPD(r,createMultiL()) |
|
298 test.Printf(_L("createL 15")); |
|
299 test(r==(KLeaveValue+1)); |
|
300 test.Printf(_L("createL 16")); |
|
301 __UHEAP_CHECK(2); |
|
302 test.Printf(_L("createL 17")); |
|
303 } |
|
304 if (aLeave) |
|
305 { |
|
306 test.Printf(_L("createL 18")); |
|
307 User::Leave(KLeaveValue); |
|
308 } |
|
309 test.Printf(_L("createL 19")); |
|
310 } |
|
311 |
|
312 LOCAL_C void createAllL(TBool aLeave) |
|
313 // |
|
314 // Call all functions which autmatically put objects on the cleanup list. |
|
315 // |
|
316 { |
|
317 |
|
318 __UHEAP_CHECK(KInitialCountAll); |
|
319 TLex* pL=new(ELeave) TLex; // ::new, 1 cell |
|
320 CleanupStack::PushL(pL); // Push |
|
321 __UHEAP_CHECK(KInitialCountAll+1); |
|
322 CTest* pT=new(ELeave) CTest; // CBase::new, 1 cell |
|
323 CleanupStack::PushL(pT); // Push |
|
324 __UHEAP_CHECK(KInitialCountAll+2); |
|
325 pT->ConstructL(); // 1 more cell // Push |
|
326 __UHEAP_CHECK(KInitialCountAll+3); |
|
327 User::AllocLC(0x10); // Test RHeap::AllocLC as well // Push |
|
328 __UHEAP_CHECK(KInitialCountAll+4); |
|
329 _L("Hello").AllocLC(); // Test HBufC::NewLC() as well // Push |
|
330 __UHEAP_CHECK(KInitialCountAll+5); |
|
331 HBufC* pH=HBufC::NewMaxLC(8); // Push |
|
332 test(pH->Length()==8); |
|
333 __UHEAP_CHECK(KInitialCountAll+6); |
|
334 if (aLeave) |
|
335 User::Leave(KLeaveValue); |
|
336 // new behavior for TCleanupTrapHander requires Pushes to the |
|
337 // cleanup stack to be balanced by Pops |
|
338 CleanupStack::PopAndDestroy(6); |
|
339 } |
|
340 |
|
341 LOCAL_C void testSingleLevelCellsCleanup() |
|
342 // |
|
343 // Test single level cells cleanup |
|
344 // |
|
345 { |
|
346 |
|
347 test.Start(_L("Creating")); |
|
348 // |
|
349 __UHEAP_MARK; |
|
350 CCleanup* pC=CCleanup::New(); |
|
351 test(pC!=NULL); |
|
352 // |
|
353 __UHEAP_MARK; |
|
354 // |
|
355 test.Next(_L("PopAll when empty")); |
|
356 pC->NextLevel(); |
|
357 pC->PopAll(); |
|
358 pC->NextLevel(); |
|
359 pC->PopAndDestroyAll(); |
|
360 __UHEAP_CHECK(0); |
|
361 // |
|
362 test.Next(_L("Push and pop")); |
|
363 TAny* p=User::Alloc(0x10); |
|
364 test(p!=NULL); |
|
365 __UHEAP_CHECK(1); |
|
366 pC->NextLevel(); |
|
367 pC->PushL(p); |
|
368 pC->Pop(); |
|
369 __UHEAP_CHECK(1); |
|
370 User::Free(p); |
|
371 __UHEAP_CHECK(0); |
|
372 pC->PopAll(); |
|
373 __UHEAP_CHECK(0); |
|
374 // |
|
375 test.Next(_L("Push and pop N")); |
|
376 TAny* p1=User::Alloc(0x10); |
|
377 test(p1!=NULL); |
|
378 __UHEAP_CHECK(1); |
|
379 TAny* p2=User::Alloc(0x10); |
|
380 test(p2!=NULL); |
|
381 __UHEAP_CHECK(2); |
|
382 pC->NextLevel(); |
|
383 pC->PushL(p1); |
|
384 pC->PushL(p2); |
|
385 pC->Pop(2); |
|
386 __UHEAP_CHECK(2); |
|
387 User::Free(p1); |
|
388 User::Free(p2); |
|
389 __UHEAP_CHECK(0); |
|
390 pC->PopAll(); |
|
391 __UHEAP_CHECK(0); |
|
392 // |
|
393 test.Next(_L("Push and pop all")); |
|
394 p1=User::Alloc(0x10); |
|
395 test(p1!=NULL); |
|
396 __UHEAP_CHECK(1); |
|
397 p2=User::Alloc(0x10); |
|
398 test(p2!=NULL); |
|
399 __UHEAP_CHECK(2); |
|
400 TAny* p3=User::Alloc(0x10); |
|
401 test(p3!=NULL); |
|
402 __UHEAP_CHECK(3); |
|
403 pC->NextLevel(); |
|
404 pC->PushL(p1); |
|
405 pC->PushL(p2); |
|
406 pC->PushL(p3); |
|
407 pC->PopAll(); |
|
408 __UHEAP_CHECK(3); |
|
409 User::Free(p1); |
|
410 User::Free(p2); |
|
411 User::Free(p3); |
|
412 __UHEAP_CHECK(0); |
|
413 // |
|
414 test.Next(_L("Push and pop and destroy")); |
|
415 p=User::Alloc(0x10); |
|
416 test(p!=NULL); |
|
417 __UHEAP_CHECK(1); |
|
418 pC->NextLevel(); |
|
419 pC->PushL(p); |
|
420 pC->PopAndDestroy(); |
|
421 __UHEAP_CHECK(0); |
|
422 pC->PopAll(); |
|
423 // |
|
424 test.Next(_L("Push and pop and destroy N")); |
|
425 p1=User::Alloc(0x10); |
|
426 test(p1!=NULL); |
|
427 __UHEAP_CHECK(1); |
|
428 p2=User::Alloc(0x10); |
|
429 test(p2!=NULL); |
|
430 __UHEAP_CHECK(2); |
|
431 pC->NextLevel(); |
|
432 pC->PushL(p1); |
|
433 pC->PushL(p2); |
|
434 pC->PopAndDestroy(2); |
|
435 __UHEAP_CHECK(0); |
|
436 pC->PopAll(); |
|
437 __UHEAP_CHECK(0); |
|
438 // |
|
439 test.Next(_L("Push and pop and destroy all")); |
|
440 p1=User::Alloc(0x10); |
|
441 test(p1!=NULL); |
|
442 __UHEAP_CHECK(1); |
|
443 p2=User::Alloc(0x10); |
|
444 test(p2!=NULL); |
|
445 __UHEAP_CHECK(2); |
|
446 p3=User::Alloc(0x10); |
|
447 test(p3!=NULL); |
|
448 __UHEAP_CHECK(3); |
|
449 pC->NextLevel(); |
|
450 pC->PushL(p1); |
|
451 pC->PushL(p2); |
|
452 pC->PushL(p3); |
|
453 pC->PopAndDestroyAll(); |
|
454 __UHEAP_CHECK(0); |
|
455 // |
|
456 __UHEAP_MARKEND; |
|
457 // |
|
458 delete pC; |
|
459 __UHEAP_MARKEND; |
|
460 // |
|
461 test.End(); |
|
462 } |
|
463 |
|
464 LOCAL_C void testSingleLevelObjCleanup() |
|
465 // |
|
466 // Test single level object cleanup |
|
467 // |
|
468 { |
|
469 |
|
470 test.Start(_L("Creating")); |
|
471 // |
|
472 __UHEAP_MARK; |
|
473 CCleanup* pC=CCleanup::New(); |
|
474 test(pC!=NULL); |
|
475 // |
|
476 __UHEAP_MARK; |
|
477 // |
|
478 test.Next(_L("Push and pop")); |
|
479 CBufFlat* p=CBufFlat::NewL(8); |
|
480 test(p!=NULL); |
|
481 __UHEAP_CHECK(1); |
|
482 pC->NextLevel(); |
|
483 pC->PushL(p); |
|
484 pC->Pop(); |
|
485 __UHEAP_CHECK(1); |
|
486 User::Free(p); |
|
487 __UHEAP_CHECK(0); |
|
488 pC->PopAll(); |
|
489 __UHEAP_CHECK(0); |
|
490 // |
|
491 test.Next(_L("Push and pop N")); |
|
492 CBufFlat* p1=CBufFlat::NewL(8); |
|
493 test(p1!=NULL); |
|
494 __UHEAP_CHECK(1); |
|
495 CBufFlat* p2=CBufFlat::NewL(8); |
|
496 test(p2!=NULL); |
|
497 __UHEAP_CHECK(2); |
|
498 pC->NextLevel(); |
|
499 pC->PushL(p1); |
|
500 pC->PushL(p2); |
|
501 pC->Pop(2); |
|
502 __UHEAP_CHECK(2); |
|
503 User::Free(p1); |
|
504 User::Free(p2); |
|
505 __UHEAP_CHECK(0); |
|
506 pC->PopAll(); |
|
507 __UHEAP_CHECK(0); |
|
508 // |
|
509 test.Next(_L("Push and pop all")); |
|
510 p1=CBufFlat::NewL(8); |
|
511 test(p1!=NULL); |
|
512 __UHEAP_CHECK(1); |
|
513 p2=CBufFlat::NewL(8); |
|
514 test(p2!=NULL); |
|
515 __UHEAP_CHECK(2); |
|
516 CBufFlat* p3=CBufFlat::NewL(8); |
|
517 test(p3!=NULL); |
|
518 __UHEAP_CHECK(3); |
|
519 pC->NextLevel(); |
|
520 pC->PushL(p1); |
|
521 pC->PushL(p2); |
|
522 pC->PushL(p3); |
|
523 pC->PopAll(); |
|
524 __UHEAP_CHECK(3); |
|
525 User::Free(p1); |
|
526 User::Free(p2); |
|
527 User::Free(p3); |
|
528 __UHEAP_CHECK(0); |
|
529 // |
|
530 test.Next(_L("Push and pop and destroy")); |
|
531 p=CBufFlat::NewL(8); |
|
532 test(p!=NULL); |
|
533 __UHEAP_CHECK(1); |
|
534 pC->NextLevel(); |
|
535 pC->PushL(p); |
|
536 pC->PopAndDestroy(); |
|
537 __UHEAP_CHECK(0); |
|
538 pC->PopAll(); |
|
539 // |
|
540 test.Next(_L("Push and pop and destroy N")); |
|
541 p1=CBufFlat::NewL(8); |
|
542 test(p1!=NULL); |
|
543 __UHEAP_CHECK(1); |
|
544 p2=CBufFlat::NewL(8); |
|
545 test(p2!=NULL); |
|
546 __UHEAP_CHECK(2); |
|
547 pC->NextLevel(); |
|
548 pC->PushL(p1); |
|
549 pC->PushL(p2); |
|
550 pC->PopAndDestroy(2); |
|
551 __UHEAP_CHECK(0); |
|
552 pC->PopAll(); |
|
553 __UHEAP_CHECK(0); |
|
554 // |
|
555 test.Next(_L("Push and pop and destroy all")); |
|
556 p1=CBufFlat::NewL(8); |
|
557 test(p1!=NULL); |
|
558 __UHEAP_CHECK(1); |
|
559 p2=CBufFlat::NewL(8); |
|
560 test(p2!=NULL); |
|
561 __UHEAP_CHECK(2); |
|
562 p3=CBufFlat::NewL(8); |
|
563 test(p3!=NULL); |
|
564 __UHEAP_CHECK(3); |
|
565 pC->NextLevel(); |
|
566 pC->PushL(p1); |
|
567 pC->PushL(p2); |
|
568 pC->PushL(p3); |
|
569 pC->PopAndDestroyAll(); |
|
570 __UHEAP_CHECK(0); |
|
571 // |
|
572 __UHEAP_MARKEND; |
|
573 // |
|
574 delete pC; |
|
575 __UHEAP_MARKEND; |
|
576 // |
|
577 test.End(); |
|
578 } |
|
579 |
|
580 LOCAL_C void testSingleLevelItemCleanup() |
|
581 // |
|
582 // Test single level object cleanup |
|
583 // |
|
584 { |
|
585 |
|
586 test.Start(_L("Creating")); |
|
587 // |
|
588 __UHEAP_MARK; |
|
589 CCleanup* pC=CCleanup::New(); |
|
590 test(pC!=NULL); |
|
591 // |
|
592 __UHEAP_MARK; |
|
593 // |
|
594 test.Next(_L("Push and pop")); |
|
595 RItem r; |
|
596 r.Open(); |
|
597 test(r.IsOpen()); |
|
598 pC->NextLevel(); |
|
599 pC->PushL(r); |
|
600 pC->Pop(); |
|
601 test(r.IsOpen()); |
|
602 r.Close(); |
|
603 test(!r.IsOpen()); |
|
604 pC->PopAll(); |
|
605 // |
|
606 test.Next(_L("Push and pop N")); |
|
607 RItem r1; |
|
608 r1.Open(); |
|
609 RItem r2; |
|
610 r2.Open(); |
|
611 pC->NextLevel(); |
|
612 pC->PushL(r1); |
|
613 pC->PushL(r2); |
|
614 pC->Pop(2); |
|
615 test(r1.IsOpen()); |
|
616 test(r2.IsOpen()); |
|
617 r1.Close(); |
|
618 r2.Close(); |
|
619 pC->PopAll(); |
|
620 // |
|
621 test.Next(_L("Push and pop all")); |
|
622 r1.Open(); |
|
623 r2.Open(); |
|
624 RItem r3; |
|
625 r3.Open(); |
|
626 pC->NextLevel(); |
|
627 pC->PushL(r1); |
|
628 pC->PushL(r2); |
|
629 pC->PushL(r3); |
|
630 pC->PopAll(); |
|
631 test(r1.IsOpen()); |
|
632 test(r2.IsOpen()); |
|
633 test(r3.IsOpen()); |
|
634 r1.Close(); |
|
635 r2.Close(); |
|
636 r3.Close(); |
|
637 // |
|
638 test.Next(_L("Push and pop and destroy")); |
|
639 r.Open(); |
|
640 pC->NextLevel(); |
|
641 pC->PushL(r); |
|
642 pC->PopAndDestroy(); |
|
643 test(!r.IsOpen()); |
|
644 pC->PopAll(); |
|
645 // |
|
646 test.Next(_L("Push and pop and destroy N")); |
|
647 r1.Open(); |
|
648 r2.Open(); |
|
649 pC->NextLevel(); |
|
650 pC->PushL(r1); |
|
651 pC->PushL(r2); |
|
652 pC->PopAndDestroy(2); |
|
653 test(!r1.IsOpen()); |
|
654 test(!r2.IsOpen()); |
|
655 pC->PopAll(); |
|
656 // |
|
657 test.Next(_L("Push and pop and destroy all")); |
|
658 r1.Open(); |
|
659 r2.Open(); |
|
660 r3.Open(); |
|
661 pC->NextLevel(); |
|
662 pC->PushL(r1); |
|
663 pC->PushL(r2); |
|
664 pC->PushL(r3); |
|
665 pC->PopAndDestroyAll(); |
|
666 test(!r1.IsOpen()); |
|
667 test(!r2.IsOpen()); |
|
668 test(!r3.IsOpen()); |
|
669 // |
|
670 __UHEAP_MARKEND; |
|
671 // |
|
672 delete pC; |
|
673 __UHEAP_MARKEND; |
|
674 // |
|
675 test.End(); |
|
676 } |
|
677 |
|
678 LOCAL_C void testSingleLevelMixCleanup() |
|
679 // |
|
680 // Test single level mixed cleanup |
|
681 // |
|
682 { |
|
683 |
|
684 test.Start(_L("Creating")); |
|
685 // |
|
686 __UHEAP_MARK; |
|
687 CCleanup* pC=CCleanup::New(); |
|
688 test(pC!=NULL); |
|
689 // |
|
690 __UHEAP_MARK; |
|
691 // |
|
692 test.Next(_L("PushO PushC PushI and pop N")); |
|
693 CBufFlat* p1=CBufFlat::NewL(8); |
|
694 test(p1!=NULL); |
|
695 __UHEAP_CHECK(1); |
|
696 TAny* p2=User::Alloc(0x10); |
|
697 test(p2!=NULL); |
|
698 __UHEAP_CHECK(2); |
|
699 RItem r; |
|
700 r.Open(); |
|
701 pC->NextLevel(); |
|
702 pC->PushL(p1); |
|
703 pC->PushL(p2); |
|
704 pC->PushL(r); |
|
705 pC->Pop(3); |
|
706 __UHEAP_CHECK(2); |
|
707 test(r.IsOpen()); |
|
708 User::Free(p1); |
|
709 User::Free(p2); |
|
710 r.Close(); |
|
711 __UHEAP_CHECK(0); |
|
712 pC->PopAll(); |
|
713 __UHEAP_CHECK(0); |
|
714 // |
|
715 test.Next(_L("PushO PushI PushC PushO and pop all")); |
|
716 p1=CBufFlat::NewL(8); |
|
717 test(p1!=NULL); |
|
718 __UHEAP_CHECK(1); |
|
719 r.Open(); |
|
720 p2=User::Alloc(0x10); |
|
721 test(p2!=NULL); |
|
722 __UHEAP_CHECK(2); |
|
723 CBufFlat* p3=CBufFlat::NewL(8); |
|
724 test(p3!=NULL); |
|
725 __UHEAP_CHECK(3); |
|
726 pC->NextLevel(); |
|
727 pC->PushL(p1); |
|
728 pC->PushL(r); |
|
729 pC->PushL(p2); |
|
730 pC->PushL(p3); |
|
731 pC->PopAll(); |
|
732 __UHEAP_CHECK(3); |
|
733 test(r.IsOpen()); |
|
734 User::Free(p1); |
|
735 User::Free(p2); |
|
736 User::Free(p3); |
|
737 r.Close(); |
|
738 __UHEAP_CHECK(0); |
|
739 // |
|
740 test.Next(_L("PushO PushC PushI and pop and destroy N")); |
|
741 p1=CBufFlat::NewL(8); |
|
742 test(p1!=NULL); |
|
743 __UHEAP_CHECK(1); |
|
744 p2=User::Alloc(0x10); |
|
745 test(p2!=NULL); |
|
746 __UHEAP_CHECK(2); |
|
747 r.Open(); |
|
748 pC->NextLevel(); |
|
749 pC->PushL(p1); |
|
750 pC->PushL(p2); |
|
751 pC->PushL(r); |
|
752 pC->PopAndDestroy(3); |
|
753 test(!r.IsOpen()); |
|
754 __UHEAP_CHECK(0); |
|
755 pC->PopAll(); |
|
756 __UHEAP_CHECK(0); |
|
757 // |
|
758 test.Next(_L("PushO PushI PushC PushO and pop and destroy all")); |
|
759 p1=CBufFlat::NewL(8); |
|
760 test(p1!=NULL); |
|
761 __UHEAP_CHECK(1); |
|
762 r.Open(); |
|
763 p2=User::Alloc(0x10); |
|
764 test(p2!=NULL); |
|
765 __UHEAP_CHECK(2); |
|
766 p3=CBufFlat::NewL(8); |
|
767 test(p3!=NULL); |
|
768 __UHEAP_CHECK(3); |
|
769 pC->NextLevel(); |
|
770 pC->PushL(p1); |
|
771 pC->PushL(r); |
|
772 pC->PushL(p2); |
|
773 pC->PushL(p3); |
|
774 pC->PopAndDestroyAll(); |
|
775 test(!r.IsOpen()); |
|
776 __UHEAP_CHECK(0); |
|
777 // |
|
778 __UHEAP_MARKEND; |
|
779 // |
|
780 delete pC; |
|
781 __UHEAP_MARKEND; |
|
782 // |
|
783 test.End(); |
|
784 } |
|
785 |
|
786 LOCAL_C void testMultiLevelCellsCleanup() |
|
787 // |
|
788 // Test multi level cells cleanup |
|
789 // |
|
790 { |
|
791 |
|
792 test.Start(_L("Creating")); |
|
793 // |
|
794 __UHEAP_MARK; |
|
795 CCleanup* pC=CCleanup::New(); |
|
796 test(pC!=NULL); |
|
797 // |
|
798 __UHEAP_MARK; |
|
799 // |
|
800 test.Next(_L("Nest push push nest push popall popall")); |
|
801 TAny* p1=User::Alloc(0x10); |
|
802 test(p1!=NULL); |
|
803 __UHEAP_CHECK(1); |
|
804 TAny* p2=User::Alloc(0x10); |
|
805 test(p2!=NULL); |
|
806 __UHEAP_CHECK(2); |
|
807 TAny* p3=User::Alloc(0x10); |
|
808 test(p3!=NULL); |
|
809 __UHEAP_CHECK(3); |
|
810 pC->NextLevel(); |
|
811 pC->PushL(p1); |
|
812 pC->PushL(p2); |
|
813 pC->NextLevel(); |
|
814 pC->PushL(p3); |
|
815 pC->PopAll(); |
|
816 __UHEAP_CHECK(3); |
|
817 pC->PopAll(); |
|
818 __UHEAP_CHECK(3); |
|
819 User::Free(p1); |
|
820 User::Free(p2); |
|
821 User::Free(p3); |
|
822 __UHEAP_CHECK(0); |
|
823 // |
|
824 test.Next(_L("Nest push push nest push popallD popallD")); |
|
825 p1=User::Alloc(0x10); |
|
826 test(p1!=NULL); |
|
827 __UHEAP_CHECK(1); |
|
828 p2=User::Alloc(0x10); |
|
829 test(p2!=NULL); |
|
830 __UHEAP_CHECK(2); |
|
831 p3=User::Alloc(0x10); |
|
832 test(p3!=NULL); |
|
833 __UHEAP_CHECK(3); |
|
834 pC->NextLevel(); |
|
835 pC->PushL(p1); |
|
836 pC->PushL(p2); |
|
837 pC->NextLevel(); |
|
838 pC->PushL(p3); |
|
839 pC->PopAndDestroyAll(); |
|
840 __UHEAP_CHECK(2); |
|
841 pC->PopAndDestroyAll(); |
|
842 __UHEAP_CHECK(0); |
|
843 // |
|
844 __UHEAP_MARKEND; |
|
845 // |
|
846 delete pC; |
|
847 __UHEAP_MARKEND; |
|
848 // |
|
849 test.End(); |
|
850 } |
|
851 |
|
852 LOCAL_C void testMultiLevelObjCleanup() |
|
853 // |
|
854 // Test multi level object cleanup |
|
855 // |
|
856 { |
|
857 |
|
858 test.Start(_L("Creating")); |
|
859 // |
|
860 __UHEAP_MARK; |
|
861 CCleanup* pC=CCleanup::New(); |
|
862 test(pC!=NULL); |
|
863 // |
|
864 __UHEAP_MARK; |
|
865 // |
|
866 test.Next(_L("Nest push push nest push popall popall")); |
|
867 CBufFlat* p1=CBufFlat::NewL(8); |
|
868 test(p1!=NULL); |
|
869 __UHEAP_CHECK(1); |
|
870 CBufFlat* p2=CBufFlat::NewL(8); |
|
871 test(p2!=NULL); |
|
872 __UHEAP_CHECK(2); |
|
873 CBufFlat* p3=CBufFlat::NewL(8); |
|
874 test(p3!=NULL); |
|
875 __UHEAP_CHECK(3); |
|
876 pC->NextLevel(); |
|
877 pC->PushL(p1); |
|
878 pC->PushL(p2); |
|
879 pC->NextLevel(); |
|
880 pC->PushL(p3); |
|
881 pC->PopAll(); |
|
882 __UHEAP_CHECK(3); |
|
883 pC->PopAll(); |
|
884 __UHEAP_CHECK(3); |
|
885 User::Free(p1); |
|
886 User::Free(p2); |
|
887 User::Free(p3); |
|
888 __UHEAP_CHECK(0); |
|
889 // |
|
890 test.Next(_L("Nest push push nest push popallD popallD")); |
|
891 p1=CBufFlat::NewL(8); |
|
892 test(p1!=NULL); |
|
893 __UHEAP_CHECK(1); |
|
894 p2=CBufFlat::NewL(8); |
|
895 test(p2!=NULL); |
|
896 __UHEAP_CHECK(2); |
|
897 p3=CBufFlat::NewL(8); |
|
898 test(p3!=NULL); |
|
899 __UHEAP_CHECK(3); |
|
900 pC->NextLevel(); |
|
901 pC->PushL(p1); |
|
902 pC->PushL(p2); |
|
903 pC->NextLevel(); |
|
904 pC->PushL(p3); |
|
905 pC->PopAndDestroyAll(); |
|
906 __UHEAP_CHECK(2); |
|
907 pC->PopAndDestroyAll(); |
|
908 __UHEAP_CHECK(0); |
|
909 // |
|
910 __UHEAP_MARKEND; |
|
911 // |
|
912 delete pC; |
|
913 __UHEAP_MARKEND; |
|
914 // |
|
915 test.End(); |
|
916 } |
|
917 |
|
918 LOCAL_C void testMultiLevelItemCleanup() |
|
919 // |
|
920 // Test multi level item cleanup |
|
921 // |
|
922 { |
|
923 |
|
924 test.Start(_L("Creating")); |
|
925 // |
|
926 __UHEAP_MARK; |
|
927 CCleanup* pC=CCleanup::New(); |
|
928 test(pC!=NULL); |
|
929 // |
|
930 __UHEAP_MARK; |
|
931 // |
|
932 test.Next(_L("Nest push push nest push popall popall")); |
|
933 RItem r1; |
|
934 r1.Open(); |
|
935 RItem r2; |
|
936 r2.Open(); |
|
937 RItem r3; |
|
938 r3.Open(); |
|
939 pC->NextLevel(); |
|
940 pC->PushL(r1); |
|
941 pC->PushL(r2); |
|
942 pC->NextLevel(); |
|
943 pC->PushL(r3); |
|
944 pC->PopAll(); |
|
945 test(r1.IsOpen()); |
|
946 test(r2.IsOpen()); |
|
947 test(r3.IsOpen()); |
|
948 pC->PopAll(); |
|
949 test(r1.IsOpen()); |
|
950 test(r2.IsOpen()); |
|
951 test(r3.IsOpen()); |
|
952 r1.Close(); |
|
953 r2.Close(); |
|
954 r3.Close(); |
|
955 // |
|
956 test.Next(_L("Nest push push nest push popallD popallD")); |
|
957 r1.Open(); |
|
958 r2.Open(); |
|
959 r3.Open(); |
|
960 pC->NextLevel(); |
|
961 pC->PushL(r1); |
|
962 pC->PushL(r2); |
|
963 pC->NextLevel(); |
|
964 pC->PushL(r3); |
|
965 pC->PopAndDestroyAll(); |
|
966 test(r1.IsOpen()); |
|
967 test(r2.IsOpen()); |
|
968 test(!r3.IsOpen()); |
|
969 pC->PopAndDestroyAll(); |
|
970 test(!r1.IsOpen()); |
|
971 test(!r2.IsOpen()); |
|
972 test(!r3.IsOpen()); |
|
973 // |
|
974 __UHEAP_MARKEND; |
|
975 // |
|
976 delete pC; |
|
977 __UHEAP_MARKEND; |
|
978 // |
|
979 test.End(); |
|
980 } |
|
981 |
|
982 LOCAL_C void testMultiLevelMixCleanup() |
|
983 // |
|
984 // Test multi level mixed cleanup |
|
985 // |
|
986 { |
|
987 |
|
988 test.Start(_L("Creating")); |
|
989 // |
|
990 __UHEAP_MARK; |
|
991 CCleanup* pC=CCleanup::New(); |
|
992 test(pC!=NULL); |
|
993 // |
|
994 __UHEAP_MARK; |
|
995 // |
|
996 test.Next(_L("Nest pushO pushC nest pushI popall popall")); |
|
997 CBufFlat* p1=CBufFlat::NewL(8); |
|
998 test(p1!=NULL); |
|
999 __UHEAP_CHECK(1); |
|
1000 TAny* p2=User::Alloc(0x10); |
|
1001 test(p2!=NULL); |
|
1002 __UHEAP_CHECK(2); |
|
1003 RItem r3; |
|
1004 r3.Open(); |
|
1005 pC->NextLevel(); |
|
1006 pC->PushL(p1); |
|
1007 pC->PushL(p2); |
|
1008 pC->NextLevel(); |
|
1009 pC->PushL(r3); |
|
1010 pC->PopAll(); |
|
1011 __UHEAP_CHECK(2); |
|
1012 test(r3.IsOpen()); |
|
1013 pC->PopAll(); |
|
1014 __UHEAP_CHECK(2); |
|
1015 test(r3.IsOpen()); |
|
1016 User::Free(p1); |
|
1017 User::Free(p2); |
|
1018 r3.Close(); |
|
1019 __UHEAP_CHECK(0); |
|
1020 // |
|
1021 test.Next(_L("Nest pushO pushC nest pushI popallD popallD")); |
|
1022 p1=CBufFlat::NewL(8); |
|
1023 test(p1!=NULL); |
|
1024 __UHEAP_CHECK(1); |
|
1025 p2=User::Alloc(0x10); |
|
1026 test(p2!=NULL); |
|
1027 __UHEAP_CHECK(2); |
|
1028 r3.Open(); |
|
1029 pC->NextLevel(); |
|
1030 pC->PushL(p1); |
|
1031 pC->PushL(p2); |
|
1032 pC->NextLevel(); |
|
1033 pC->PushL(r3); |
|
1034 pC->PopAndDestroyAll(); |
|
1035 __UHEAP_CHECK(2); |
|
1036 test(!r3.IsOpen()); |
|
1037 pC->PopAndDestroyAll(); |
|
1038 test(!r3.IsOpen()); |
|
1039 __UHEAP_CHECK(0); |
|
1040 // |
|
1041 __UHEAP_MARKEND; |
|
1042 // |
|
1043 delete pC; |
|
1044 __UHEAP_MARKEND; |
|
1045 // |
|
1046 test.End(); |
|
1047 } |
|
1048 |
|
1049 LOCAL_C void testSpecialCaseCleanup() |
|
1050 // |
|
1051 // Test special case cleanup |
|
1052 // |
|
1053 { |
|
1054 |
|
1055 test.Start(_L("Creating")); |
|
1056 // |
|
1057 __UHEAP_MARK; |
|
1058 CCleanup* pC=CCleanup::New(); |
|
1059 test(pC!=NULL); |
|
1060 __UHEAP_CHECK(KInitialCount); |
|
1061 // |
|
1062 test.Next(_L("Nest push push push fail")); |
|
1063 CBufFlat* p1=CBufFlat::NewL(8); |
|
1064 test(p1!=NULL); |
|
1065 __UHEAP_CHECK(KInitialCount+1); |
|
1066 CBufFlat* p2=CBufFlat::NewL(8); |
|
1067 test(p2!=NULL); |
|
1068 __UHEAP_CHECK(KInitialCount+2); |
|
1069 CBufFlat* p3=CBufFlat::NewL(8); |
|
1070 test(p3!=NULL); |
|
1071 __UHEAP_CHECK(KInitialCount+3); |
|
1072 CBufFlat* p4=CBufFlat::NewL(8); |
|
1073 test(p4!=NULL); |
|
1074 __UHEAP_CHECK(KInitialCount+4); |
|
1075 CBufFlat* p5=CBufFlat::NewL(8); |
|
1076 test(p5!=NULL); |
|
1077 __UHEAP_CHECK(KInitialCount+5); |
|
1078 CBufFlat* p6=CBufFlat::NewL(8); |
|
1079 test(p6!=NULL); |
|
1080 __UHEAP_CHECK(KInitialCount+6); |
|
1081 pC->NextLevel(); |
|
1082 pC->PushL(p1); |
|
1083 pC->PushL(p2); |
|
1084 pC->PushL(p3); |
|
1085 pC->PushL(p4); |
|
1086 pC->PushL(p5); |
|
1087 // |
|
1088 // The granularity is 4 so this should try and grow the array |
|
1089 // since room is always made for a free slot. We set the allocator |
|
1090 // to fail so that we can test that the free slot is re-established |
|
1091 // when we do the cleanup. This test only works in debug mode. |
|
1092 // |
|
1093 __UHEAP_FAILNEXT(1); |
|
1094 TRAPD(r,pC->PushL(p6)); |
|
1095 #if defined(_DEBUG) |
|
1096 test(r==KErrNoMemory); |
|
1097 #endif |
|
1098 __UHEAP_CHECK(KInitialCount+6); |
|
1099 pC->PopAndDestroyAll(); |
|
1100 __UHEAP_CHECK(KInitialCount); |
|
1101 // |
|
1102 test.Next(_L("Nest push push push push popallD")); |
|
1103 p1=CBufFlat::NewL(8); |
|
1104 test(p1!=NULL); |
|
1105 __UHEAP_CHECK(KInitialCount+1); |
|
1106 p2=CBufFlat::NewL(8); |
|
1107 test(p2!=NULL); |
|
1108 __UHEAP_CHECK(KInitialCount+2); |
|
1109 p3=CBufFlat::NewL(8); |
|
1110 test(p3!=NULL); |
|
1111 __UHEAP_CHECK(KInitialCount+3); |
|
1112 p4=CBufFlat::NewL(8); |
|
1113 test(p4!=NULL); |
|
1114 __UHEAP_CHECK(KInitialCount+4); |
|
1115 pC->NextLevel(); |
|
1116 pC->PushL(p1); |
|
1117 pC->NextLevel(); |
|
1118 pC->PushL(p2); |
|
1119 pC->PushL(p3); |
|
1120 pC->PushL(p4); |
|
1121 pC->PopAndDestroyAll(); |
|
1122 __UHEAP_CHECK(KInitialCount+1); |
|
1123 pC->PopAndDestroyAll(); |
|
1124 __UHEAP_CHECK(KInitialCount); |
|
1125 // |
|
1126 test.Next(_L("Destroy cleanup object")); |
|
1127 // |
|
1128 p1=CBufFlat::NewL(8); |
|
1129 test(p1!=NULL); |
|
1130 __UHEAP_CHECK(KInitialCount+1); |
|
1131 p2=CBufFlat::NewL(8); |
|
1132 test(p2!=NULL); |
|
1133 __UHEAP_CHECK(KInitialCount+2); |
|
1134 p3=CBufFlat::NewL(8); |
|
1135 test(p3!=NULL); |
|
1136 __UHEAP_CHECK(KInitialCount+3); |
|
1137 p4=CBufFlat::NewL(8); |
|
1138 test(p4!=NULL); |
|
1139 __UHEAP_CHECK(KInitialCount+4); |
|
1140 pC->NextLevel(); |
|
1141 pC->PushL(p1); |
|
1142 pC->NextLevel(); |
|
1143 pC->PushL(p2); |
|
1144 pC->PushL(p3); |
|
1145 pC->PushL(p4); |
|
1146 delete pC; |
|
1147 __UHEAP_CHECK(0); |
|
1148 // |
|
1149 __UHEAP_MARKEND; |
|
1150 // |
|
1151 test.End(); |
|
1152 } |
|
1153 |
|
1154 LOCAL_C void testUnTrap() |
|
1155 // |
|
1156 // Test cleanup with normal exits |
|
1157 // |
|
1158 { |
|
1159 |
|
1160 test.Start(_L("Creating")); |
|
1161 // |
|
1162 __UHEAP_MARK; |
|
1163 CTrapCleanup* pT=CTrapCleanup::New(); |
|
1164 test(pT!=NULL); |
|
1165 __UHEAP_CHECK(KInitialCountAll); |
|
1166 // |
|
1167 __UHEAP_MARK; |
|
1168 // |
|
1169 test.Next(_L("PushC PushO EPop cleanup empty")); |
|
1170 TRAPD(r,createL(EPop,EFalse)) |
|
1171 test.Next(_L("PushC PushO EPop cleanup empty 1")); |
|
1172 test(r==KErrNone); |
|
1173 test.Next(_L("PushC PushO EPop cleanup empty 2")); |
|
1174 __UHEAP_CHECK(2); |
|
1175 test.Next(_L("PushC PushO EPop cleanup empty 3")); |
|
1176 User::Free(gP1); |
|
1177 test.Next(_L("PushC PushO EPop cleanup empty 4")); |
|
1178 delete gP2; |
|
1179 test.Next(_L("PushC PushO EPop cleanup empty 5")); |
|
1180 __UHEAP_CHECK(0); |
|
1181 // |
|
1182 test.Next(_L("PushC PushO EPopAndDestroy cleanup empty")); |
|
1183 TRAP(r,createL(EPopAndDestroy,EFalse)) |
|
1184 test(r==KErrNone); |
|
1185 __UHEAP_CHECK(0); |
|
1186 // |
|
1187 /* |
|
1188 // Change of behavior for TCleanupTrapHandler means that the current |
|
1189 // cleanup stack must be empty when UnTrap is called. IE. calls to |
|
1190 // Push should be balanced with a Pop within the same function. |
|
1191 test.Next(_L("PushC PushO ENull cleanup 2 objects")); |
|
1192 TRAP(r,createL(ENull,EFalse)) |
|
1193 test(r==KErrNone); |
|
1194 __UHEAP_CHECK(0); |
|
1195 */ |
|
1196 __UHEAP_MARKEND; |
|
1197 // |
|
1198 test.Next(_L("Test all LC functions")); |
|
1199 TRAP(r,createAllL(EFalse)) |
|
1200 test(r==KErrNone); |
|
1201 __UHEAP_CHECK(KInitialCountAll); |
|
1202 // |
|
1203 delete pT; |
|
1204 __UHEAP_MARKEND; |
|
1205 // |
|
1206 test.End(); |
|
1207 } |
|
1208 |
|
1209 LOCAL_C void testLeave() |
|
1210 // |
|
1211 // Test cleanup with leave exits |
|
1212 // |
|
1213 { |
|
1214 |
|
1215 test.Start(_L("Creating")); |
|
1216 // |
|
1217 __UHEAP_MARK; |
|
1218 CTrapCleanup* pT=CTrapCleanup::New(); |
|
1219 test(pT!=NULL); |
|
1220 __UHEAP_CHECK(KInitialCountAll); |
|
1221 // |
|
1222 __UHEAP_MARK; |
|
1223 // |
|
1224 test.Next(_L("PushC PushO EPop cleanup empty and leave")); |
|
1225 TRAPD(r,createL(EPop,ETrue)) |
|
1226 test(r==KLeaveValue); |
|
1227 __UHEAP_CHECK(2); |
|
1228 User::Free(gP1); |
|
1229 delete gP2; |
|
1230 __UHEAP_CHECK(0); |
|
1231 // |
|
1232 test.Next(_L("PushC PushO EPopAndDestroy cleanup empty and leave")); |
|
1233 TRAP(r,createL(EPopAndDestroy,ETrue)) |
|
1234 test(r==KLeaveValue); |
|
1235 __UHEAP_CHECK(0); |
|
1236 // |
|
1237 test.Next(_L("PushC PushO ENull cleanup 2 objects and leave")); |
|
1238 TRAP(r,createL(ENull,ETrue)) |
|
1239 test(r==KLeaveValue); |
|
1240 __UHEAP_CHECK(0); |
|
1241 __UHEAP_MARKEND; |
|
1242 // |
|
1243 test.Next(_L("Test all LC functions and leave")); |
|
1244 TRAP(r,createAllL(ETrue)) |
|
1245 test(r==KLeaveValue); |
|
1246 __UHEAP_CHECK(KInitialCountAll); |
|
1247 // |
|
1248 delete pT; |
|
1249 __UHEAP_MARKEND; |
|
1250 // |
|
1251 test.End(); |
|
1252 } |
|
1253 |
|
1254 LOCAL_C void testMultiLeave() |
|
1255 // |
|
1256 // Test cleanup with multiple leave exits |
|
1257 // |
|
1258 { |
|
1259 |
|
1260 test.Start(_L("Creating")); |
|
1261 // |
|
1262 __UHEAP_MARK; |
|
1263 CTrapCleanup* pT=CTrapCleanup::New(); |
|
1264 test(pT!=NULL); |
|
1265 // |
|
1266 __UHEAP_MARK; |
|
1267 // |
|
1268 test.Next(_L("PushC PushO nest PushO cleanup leave leave")); |
|
1269 TRAPD(r,createL(EMulti,ETrue)) |
|
1270 test(r==KLeaveValue); |
|
1271 __UHEAP_CHECK(0); |
|
1272 __UHEAP_MARKEND; |
|
1273 // |
|
1274 delete pT; |
|
1275 __UHEAP_MARKEND; |
|
1276 // |
|
1277 test.End(); |
|
1278 } |
|
1279 |
|
1280 LOCAL_C void addNullItemL() |
|
1281 { |
|
1282 CleanupStack::PushL((TAny*)0); |
|
1283 } |
|
1284 |
|
1285 LOCAL_C void addCellL() |
|
1286 { |
|
1287 User::AllocLC(4); |
|
1288 } |
|
1289 |
|
1290 LOCAL_C void useCleanupStackL() |
|
1291 { |
|
1292 addNullItemL(); |
|
1293 addCellL(); |
|
1294 CleanupStack::PopAndDestroy(); |
|
1295 CleanupStack::Pop(); |
|
1296 } |
|
1297 |
|
1298 LOCAL_C void reentrantCleanup(TAny*) |
|
1299 // |
|
1300 // A cleanup operation which uses a trap harness and the cleanup stack |
|
1301 // |
|
1302 { |
|
1303 TRAPD(ignore,useCleanupStackL()) |
|
1304 } |
|
1305 |
|
1306 LOCAL_C void addReentrantItemL() |
|
1307 { |
|
1308 CleanupStack::PushL(TCleanupItem(reentrantCleanup)); |
|
1309 } |
|
1310 |
|
1311 LOCAL_C void addItemsL(TInt aCount) |
|
1312 // |
|
1313 // add number of reentrant items to make stack fail |
|
1314 // |
|
1315 { |
|
1316 while (--aCount>=0) |
|
1317 addReentrantItemL(); |
|
1318 #if !defined(_DEBUG) |
|
1319 User::Leave(KErrNoMemory); // heap failure not available |
|
1320 #endif |
|
1321 } |
|
1322 |
|
1323 const TInt KInitialStackSize=8; // from UC_CLN.CPP |
|
1324 const TInt KGrowItems=KInitialStackSize-3; |
|
1325 |
|
1326 LOCAL_C void testReentrancyL() |
|
1327 // |
|
1328 // Test the Cleanup stack can go re-entrant |
|
1329 // |
|
1330 { |
|
1331 |
|
1332 test.Next(_L("PopAndDestroy()")); |
|
1333 __UHEAP_MARK; |
|
1334 addNullItemL(); |
|
1335 addCellL(); |
|
1336 addReentrantItemL(); |
|
1337 CleanupStack::PopAndDestroy(2); |
|
1338 CleanupStack::Pop(); |
|
1339 __UHEAP_MARKEND; |
|
1340 // |
|
1341 test.Next(_L("cleanup after a leave")); |
|
1342 addNullItemL(); |
|
1343 TRAPD(r,addReentrantItemL();User::Leave(KLeaveValue);) |
|
1344 test(r==KLeaveValue); |
|
1345 CleanupStack::Pop(); |
|
1346 // |
|
1347 test.Next(_L("cleanup after stack failure")); |
|
1348 // Ensuring stack reallocate fails by placing following cell |
|
1349 TInt* forceAlloc=(TInt*)User::AllocL(4); |
|
1350 for (TInt i=0;i<KGrowItems;++i) |
|
1351 addNullItemL(); |
|
1352 __UHEAP_SETFAIL(RHeap::EDeterministic,1); // fail everything |
|
1353 TRAP(r,addItemsL(1);) // will leave as stack full and cannot grow |
|
1354 test(r==KErrNoMemory); |
|
1355 __UHEAP_RESET; |
|
1356 CleanupStack::Pop(KGrowItems); |
|
1357 // |
|
1358 test.Next(_L("multiple re-entrancy & stack failure")); |
|
1359 __UHEAP_SETFAIL(RHeap::EDeterministic,1); // fail everything |
|
1360 TRAP(r,addItemsL(KGrowItems+1);); |
|
1361 test(r==KErrNoMemory); |
|
1362 __UHEAP_RESET; |
|
1363 User::Free(forceAlloc); |
|
1364 } |
|
1365 |
|
1366 LOCAL_C void testReentrancy() |
|
1367 // |
|
1368 // Test the Cleanup stack can go re-entrant |
|
1369 // |
|
1370 { |
|
1371 |
|
1372 test.Start(_L("Creating")); |
|
1373 // |
|
1374 __UHEAP_MARK; |
|
1375 CTrapCleanup* pT=CTrapCleanup::New(); |
|
1376 test(pT!=NULL); |
|
1377 // |
|
1378 TRAPD(r,testReentrancyL()); |
|
1379 test(r==KErrNone); |
|
1380 // |
|
1381 delete pT; |
|
1382 __UHEAP_MARKEND; |
|
1383 // |
|
1384 test.End(); |
|
1385 } |
|
1386 |
|
1387 LOCAL_C void testAutoCloseL() |
|
1388 // |
|
1389 // A leaving function for testAutoClose() |
|
1390 // |
|
1391 { |
|
1392 test.Next(_L("Create a TAutoClose object")); |
|
1393 TAutoClose<RTimer> tim; |
|
1394 tim.iObj.CreateLocal(); |
|
1395 test.Next(_L("Push it on the cleanup stack")); |
|
1396 tim.PushL(); |
|
1397 test.Next(_L("Leave before object goes out of scope")); |
|
1398 User::Leave(KErrGeneral); |
|
1399 tim.Pop(); |
|
1400 } |
|
1401 |
|
1402 LOCAL_C void testAutoClose() |
|
1403 // |
|
1404 // Test the TAutoClose class |
|
1405 // |
|
1406 { |
|
1407 |
|
1408 // Kill the granules |
|
1409 RTimer s[20]; |
|
1410 TInt i; |
|
1411 for (i=0; i<20; i++) |
|
1412 s[i].CreateLocal(); |
|
1413 for (i=0; i<20; i++) |
|
1414 s[i].Close(); |
|
1415 |
|
1416 __KHEAP_MARK; |
|
1417 test.Start(_L("Make a TAutoClose object")); |
|
1418 { |
|
1419 TAutoClose<RTimer> tim; |
|
1420 tim.iObj.CreateLocal(); |
|
1421 |
|
1422 test.Next(_L("Let it fall out of scope")); |
|
1423 } |
|
1424 test.Next(_L("Check the object has closed")); |
|
1425 __KHEAP_CHECK(0); |
|
1426 |
|
1427 TRAPD(r, testAutoCloseL()); |
|
1428 test.Next(_L("Check object has been closed and cleaned up after leave")); |
|
1429 __KHEAP_MARKEND; |
|
1430 test.End(); |
|
1431 } |
|
1432 |
|
1433 void CTest::ConstructL() |
|
1434 // |
|
1435 // Allocate a cell with CBase::new |
|
1436 // |
|
1437 { |
|
1438 |
|
1439 TLex* pL=new(ELeave) TLex; |
|
1440 CleanupStack::PushL(pL); |
|
1441 } |
|
1442 |
|
1443 void RItem::Cleanup(TAny* aPtr) |
|
1444 // |
|
1445 // Invoke the Close member on the RItem at aPtr |
|
1446 // |
|
1447 { |
|
1448 |
|
1449 ((RItem*)aPtr)->Close(); |
|
1450 } |
|
1451 |
|
1452 LOCAL_C TInt getStackPointer() |
|
1453 { |
|
1454 static TUint8 there; |
|
1455 TUint8 here; |
|
1456 return &here-&there; |
|
1457 } |
|
1458 LOCAL_C void sheLeavesMe(TBool sheLeavesMeNot) |
|
1459 { |
|
1460 if (!sheLeavesMeNot) |
|
1461 User::Leave(KErrBadName); // Montague |
|
1462 } |
|
1463 |
|
1464 LOCAL_C void testStackBalance() |
|
1465 // |
|
1466 // Ensure that we get the stack properly balanced |
|
1467 // |
|
1468 { |
|
1469 |
|
1470 TInt i; |
|
1471 TInt r=KErrNone; |
|
1472 test.Start(_L("Stack balance without leaving")); |
|
1473 TInt before=getStackPointer(); |
|
1474 for (i=0; i<20;i++) |
|
1475 TRAP(r,sheLeavesMe(ETrue)); |
|
1476 TInt after=getStackPointer(); |
|
1477 test(r==KErrNone); |
|
1478 test(before==after); |
|
1479 // |
|
1480 test.Next(_L("Stack balance after Leave")); |
|
1481 before=getStackPointer(); |
|
1482 for (i=0; i<20;i++) |
|
1483 TRAP(r,sheLeavesMe(EFalse)); |
|
1484 after=getStackPointer(); |
|
1485 test(r==KErrBadName); |
|
1486 test(before==after); |
|
1487 // |
|
1488 test.End(); |
|
1489 } |
|
1490 |
|
1491 void Inc(TAny* aPtr) |
|
1492 { |
|
1493 ++(*(TInt*)aPtr); |
|
1494 } |
|
1495 |
|
1496 void testTrapIgnore() |
|
1497 { |
|
1498 test.Start(_L("Create cleanup")); |
|
1499 CCleanup* pC=CCleanup::New(); |
|
1500 test(pC!=NULL); |
|
1501 TInt count = 0; |
|
1502 |
|
1503 test.Next(_L("TRAP_IGNORE with no leave")); |
|
1504 TRAP_IGNORE( |
|
1505 CleanupStack::PushL(TCleanupItem(Inc,&count)); |
|
1506 CleanupStack::Pop(); |
|
1507 ); |
|
1508 test(count==0); |
|
1509 |
|
1510 test.Next(_L("TRAP_IGNORE with leave")); |
|
1511 TRAP_IGNORE( |
|
1512 CleanupStack::PushL(TCleanupItem(Inc,&count)); |
|
1513 User::Leave(KErrGeneral); |
|
1514 ); |
|
1515 test(count==1); |
|
1516 |
|
1517 delete pC; |
|
1518 test.End(); |
|
1519 } |
|
1520 |
|
1521 GLDEF_C TInt E32Main() |
|
1522 { |
|
1523 test.Title(); |
|
1524 |
|
1525 test.Start(_L("Test destructor causing stack reallocation")); |
|
1526 testDestructorStackReallocation(); |
|
1527 |
|
1528 test.Next(_L("CCleanup single level tests just alloc cells")); |
|
1529 testSingleLevelCellsCleanup(); |
|
1530 |
|
1531 test.Next(_L("CCleanup single level tests just objects")); |
|
1532 testSingleLevelObjCleanup(); |
|
1533 |
|
1534 test.Next(_L("CCleanup single level tests just items")); |
|
1535 testSingleLevelItemCleanup(); |
|
1536 |
|
1537 test.Next(_L("CCleanup single level tests mixed")); |
|
1538 testSingleLevelMixCleanup(); |
|
1539 |
|
1540 test.Next(_L("CCleanup multi level tests just alloc cells")); |
|
1541 testMultiLevelCellsCleanup(); |
|
1542 |
|
1543 test.Next(_L("CCleanup multi level tests just objects")); |
|
1544 testMultiLevelObjCleanup(); |
|
1545 |
|
1546 test.Next(_L("CCleanup multi level tests just items")); |
|
1547 testMultiLevelItemCleanup(); |
|
1548 |
|
1549 test.Next(_L("CCleanup multi level tests mixed")); |
|
1550 testMultiLevelMixCleanup(); |
|
1551 |
|
1552 test.Next(_L("CCleanup special case test")); |
|
1553 testSpecialCaseCleanup(); |
|
1554 |
|
1555 test.Next(_L("Install trap handler")); |
|
1556 CTrapCleanup* pT=CTrapCleanup::New(); |
|
1557 test(pT!=NULL); |
|
1558 |
|
1559 test.Next(_L("Untrap handling tests")); |
|
1560 testUnTrap(); |
|
1561 |
|
1562 test.Next(_L("Leave handling tests")); |
|
1563 testLeave(); |
|
1564 |
|
1565 test.Next(_L("Multi level leave handling tests")); |
|
1566 testMultiLeave(); |
|
1567 |
|
1568 test.Next(_L("Test TAutoClose")); |
|
1569 testAutoClose(); |
|
1570 |
|
1571 test.Next(_L("Test Re-entrancy of cleanup stack")); |
|
1572 testReentrancy(); |
|
1573 |
|
1574 test.Next(_L("Test stack safety of TRAP and Leave")); |
|
1575 testStackBalance(); |
|
1576 |
|
1577 test.Next(_L("Test TRAP_IGNORE")); |
|
1578 testTrapIgnore(); |
|
1579 |
|
1580 test.End(); |
|
1581 return(0); |
|
1582 } |
|
1583 |