Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\system\t_ctrap.cpp
16 // Test the CCleanup, CTrapCleanup and TAutoClose classes
18 // CCleanup, CTrapCleanup, TAutoClose
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
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
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
42 // Platforms/Drives/Compatibility:
44 // Assumptions/Requirement/Pre-requisites:
45 // Failures and causes:
46 // Base Port information:
50 #define __E32TEST_EXTENSION__
56 #include <e32def_private.h>
59 const TInt KInitialCount=2;
60 const TInt KInitialCountAll=3;
61 const TInt KLeaveValue=0x12345678;
62 const TInt KMaxAlloc=6;
64 static const TInt KHeapSize = 0x2000;
66 enum TWhat {EPop,EPopAndDestroy,EMulti,ENull};
68 class CTest : public CBase
76 class CTest2: public CBase
82 class CTest3: public CBase
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);}
97 static void Cleanup(TAny* aPtr);
102 LOCAL_D RTest test(_L("T_CTRAP"));
104 LOCAL_D CBufFlat* gP2;
107 LOCAL_C void ReallocateStackL()
110 for(TInt i = 0; i < KMaxAlloc; ++i)
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
116 test.Printf(_L("ReallocateStackL(): PopAndDestroy KMaxAlloc pointers\n"));
117 CleanupStack::PopAndDestroy(KMaxAlloc);
122 TInt err = KErrNoMemory;
124 test.Printf(_L("~CTest2(): call ReallocateStackL()\n"));
126 TRAP(err, ReallocateStackL() );
131 RDebug::Printf("~CTest3(): Modify Cleanup stack by pushing items");
134 for(TInt i = 0; i < KMaxAlloc; ++i)
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
142 LOCAL_C void ModifyStack()
144 CTest3* ptr6 = new(ELeave)CTest3;
145 CleanupStack::PushL(ptr6);
147 RDebug::Printf("ModifyStack(): PopAndDestroy ptr6");
148 CleanupStack::PopAndDestroy();
151 LOCAL_C TInt PanicStackModifiedFn(TAny* aNopFn)
154 CTrapCleanup* cleanup = CTrapCleanup::New();
156 aNopFn = NULL; //avoid warnings for unused "aNopFn" variable
158 TInt err = KErrNoMemory;
160 RDebug::Printf("PanicStackModifiedFn(): call TRAP(err, ModifyStack())");
164 TRAP(err, ModifyStack());
171 LOCAL_C void PushAndCleanupL()
173 CTest2* ptr1 = new(ELeave)CTest2;
174 CleanupStack::PushL(ptr1);
176 CTest2* ptr2 = new(ELeave)CTest2;
177 CleanupStack::PushL(ptr2);
179 CTest2* ptr3 = new(ELeave)CTest2;
180 CleanupStack::PushL(ptr3);
182 test.Printf(_L("PushAndCleanupL(): PopAndDestroy ptr3, ptr2 and ptr1\n"));
183 CleanupStack::PopAndDestroy(3);
185 CTest2* ptr4 = new(ELeave)CTest2;
186 CleanupStack::PushL(ptr4);
188 CTest2* ptr5 = new(ELeave)CTest2;
189 CleanupStack::PushL(ptr5);
191 test.Printf(_L("PushAndCleanupL(): PopAndDestroy ptr5 and ptr4\n"));
192 CleanupStack::PopAndDestroy();
193 CleanupStack::PopAndDestroy();
196 LOCAL_C void testDestructorStackReallocation()
199 CTrapCleanup* cleanup = CTrapCleanup::New();
201 TInt err = KErrNoMemory;
205 TRAP(err, PushAndCleanupL());
212 test.Printf(_L("Verify cleanup stack modification during cleanup operation causes EClnStackModified panic\n"));
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)
221 TInt r = panicThread.Create(_L("Panic EClnStackModified Thread"), PanicStackModifiedFn, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
225 TRequestStatus panicThreadStatus;
226 panicThread.Logon(panicThreadStatus);
228 //don't want just in time debugging as we trap panics
229 TBool justInTime=User::JustInTime();
230 User::SetJustInTime(EFalse);
232 panicThread.Resume();
234 User::WaitForRequest(panicThreadStatus);
236 test_Equal(EExitPanic, panicThread.ExitType());
237 test_Equal(EClnStackModified, panicThread.ExitReason());
239 User::SetJustInTime(justInTime);
241 CLOSE_AND_WAIT(panicThread);
244 LOCAL_C void createMultiL()
246 // Create an object on the cleanup list and leave
250 CBufFlat* pT=CBufFlat::NewL(8);
251 User::LeaveIfNull(pT);
252 CleanupStack::PushL(pT);
254 User::Leave(KLeaveValue+1);
257 LOCAL_C void createL(TWhat aWhat,TBool aLeave)
259 // Create objects and then either leave or return.
260 // Optionally pop them again.
264 gP1=User::AllocL(0x10);
265 test.Printf(_L("createL 1"));
266 CleanupStack::PushL(gP1);
267 test.Printf(_L("createL 2"));
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"));
277 test.Printf(_L("createL 7"));
280 test.Printf(_L("createL 8"));
282 test.Printf(_L("createL 9"));
283 CleanupStack::Pop(1);
284 test.Printf(_L("createL 10"));
286 if (aWhat==EPopAndDestroy)
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"));
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"));
302 test.Printf(_L("createL 17"));
306 test.Printf(_L("createL 18"));
307 User::Leave(KLeaveValue);
309 test.Printf(_L("createL 19"));
312 LOCAL_C void createAllL(TBool aLeave)
314 // Call all functions which autmatically put objects on the cleanup list.
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);
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);
341 LOCAL_C void testSingleLevelCellsCleanup()
343 // Test single level cells cleanup
347 test.Start(_L("Creating"));
350 CCleanup* pC=CCleanup::New();
355 test.Next(_L("PopAll when empty"));
359 pC->PopAndDestroyAll();
362 test.Next(_L("Push and pop"));
363 TAny* p=User::Alloc(0x10);
375 test.Next(_L("Push and pop N"));
376 TAny* p1=User::Alloc(0x10);
379 TAny* p2=User::Alloc(0x10);
393 test.Next(_L("Push and pop all"));
394 p1=User::Alloc(0x10);
397 p2=User::Alloc(0x10);
400 TAny* p3=User::Alloc(0x10);
414 test.Next(_L("Push and pop and destroy"));
424 test.Next(_L("Push and pop and destroy N"));
425 p1=User::Alloc(0x10);
428 p2=User::Alloc(0x10);
434 pC->PopAndDestroy(2);
439 test.Next(_L("Push and pop and destroy all"));
440 p1=User::Alloc(0x10);
443 p2=User::Alloc(0x10);
446 p3=User::Alloc(0x10);
453 pC->PopAndDestroyAll();
464 LOCAL_C void testSingleLevelObjCleanup()
466 // Test single level object cleanup
470 test.Start(_L("Creating"));
473 CCleanup* pC=CCleanup::New();
478 test.Next(_L("Push and pop"));
479 CBufFlat* p=CBufFlat::NewL(8);
491 test.Next(_L("Push and pop N"));
492 CBufFlat* p1=CBufFlat::NewL(8);
495 CBufFlat* p2=CBufFlat::NewL(8);
509 test.Next(_L("Push and pop all"));
510 p1=CBufFlat::NewL(8);
513 p2=CBufFlat::NewL(8);
516 CBufFlat* p3=CBufFlat::NewL(8);
530 test.Next(_L("Push and pop and destroy"));
540 test.Next(_L("Push and pop and destroy N"));
541 p1=CBufFlat::NewL(8);
544 p2=CBufFlat::NewL(8);
550 pC->PopAndDestroy(2);
555 test.Next(_L("Push and pop and destroy all"));
556 p1=CBufFlat::NewL(8);
559 p2=CBufFlat::NewL(8);
562 p3=CBufFlat::NewL(8);
569 pC->PopAndDestroyAll();
580 LOCAL_C void testSingleLevelItemCleanup()
582 // Test single level object cleanup
586 test.Start(_L("Creating"));
589 CCleanup* pC=CCleanup::New();
594 test.Next(_L("Push and pop"));
606 test.Next(_L("Push and pop N"));
621 test.Next(_L("Push and pop all"));
638 test.Next(_L("Push and pop and destroy"));
646 test.Next(_L("Push and pop and destroy N"));
652 pC->PopAndDestroy(2);
657 test.Next(_L("Push and pop and destroy all"));
665 pC->PopAndDestroyAll();
678 LOCAL_C void testSingleLevelMixCleanup()
680 // Test single level mixed cleanup
684 test.Start(_L("Creating"));
687 CCleanup* pC=CCleanup::New();
692 test.Next(_L("PushO PushC PushI and pop N"));
693 CBufFlat* p1=CBufFlat::NewL(8);
696 TAny* p2=User::Alloc(0x10);
715 test.Next(_L("PushO PushI PushC PushO and pop all"));
716 p1=CBufFlat::NewL(8);
720 p2=User::Alloc(0x10);
723 CBufFlat* p3=CBufFlat::NewL(8);
740 test.Next(_L("PushO PushC PushI and pop and destroy N"));
741 p1=CBufFlat::NewL(8);
744 p2=User::Alloc(0x10);
752 pC->PopAndDestroy(3);
758 test.Next(_L("PushO PushI PushC PushO and pop and destroy all"));
759 p1=CBufFlat::NewL(8);
763 p2=User::Alloc(0x10);
766 p3=CBufFlat::NewL(8);
774 pC->PopAndDestroyAll();
786 LOCAL_C void testMultiLevelCellsCleanup()
788 // Test multi level cells cleanup
792 test.Start(_L("Creating"));
795 CCleanup* pC=CCleanup::New();
800 test.Next(_L("Nest push push nest push popall popall"));
801 TAny* p1=User::Alloc(0x10);
804 TAny* p2=User::Alloc(0x10);
807 TAny* p3=User::Alloc(0x10);
824 test.Next(_L("Nest push push nest push popallD popallD"));
825 p1=User::Alloc(0x10);
828 p2=User::Alloc(0x10);
831 p3=User::Alloc(0x10);
839 pC->PopAndDestroyAll();
841 pC->PopAndDestroyAll();
852 LOCAL_C void testMultiLevelObjCleanup()
854 // Test multi level object cleanup
858 test.Start(_L("Creating"));
861 CCleanup* pC=CCleanup::New();
866 test.Next(_L("Nest push push nest push popall popall"));
867 CBufFlat* p1=CBufFlat::NewL(8);
870 CBufFlat* p2=CBufFlat::NewL(8);
873 CBufFlat* p3=CBufFlat::NewL(8);
890 test.Next(_L("Nest push push nest push popallD popallD"));
891 p1=CBufFlat::NewL(8);
894 p2=CBufFlat::NewL(8);
897 p3=CBufFlat::NewL(8);
905 pC->PopAndDestroyAll();
907 pC->PopAndDestroyAll();
918 LOCAL_C void testMultiLevelItemCleanup()
920 // Test multi level item cleanup
924 test.Start(_L("Creating"));
927 CCleanup* pC=CCleanup::New();
932 test.Next(_L("Nest push push nest push popall popall"));
956 test.Next(_L("Nest push push nest push popallD popallD"));
965 pC->PopAndDestroyAll();
969 pC->PopAndDestroyAll();
982 LOCAL_C void testMultiLevelMixCleanup()
984 // Test multi level mixed cleanup
988 test.Start(_L("Creating"));
991 CCleanup* pC=CCleanup::New();
996 test.Next(_L("Nest pushO pushC nest pushI popall popall"));
997 CBufFlat* p1=CBufFlat::NewL(8);
1000 TAny* p2=User::Alloc(0x10);
1021 test.Next(_L("Nest pushO pushC nest pushI popallD popallD"));
1022 p1=CBufFlat::NewL(8);
1025 p2=User::Alloc(0x10);
1034 pC->PopAndDestroyAll();
1037 pC->PopAndDestroyAll();
1049 LOCAL_C void testSpecialCaseCleanup()
1051 // Test special case cleanup
1055 test.Start(_L("Creating"));
1058 CCleanup* pC=CCleanup::New();
1060 __UHEAP_CHECK(KInitialCount);
1062 test.Next(_L("Nest push push push fail"));
1063 CBufFlat* p1=CBufFlat::NewL(8);
1065 __UHEAP_CHECK(KInitialCount+1);
1066 CBufFlat* p2=CBufFlat::NewL(8);
1068 __UHEAP_CHECK(KInitialCount+2);
1069 CBufFlat* p3=CBufFlat::NewL(8);
1071 __UHEAP_CHECK(KInitialCount+3);
1072 CBufFlat* p4=CBufFlat::NewL(8);
1074 __UHEAP_CHECK(KInitialCount+4);
1075 CBufFlat* p5=CBufFlat::NewL(8);
1077 __UHEAP_CHECK(KInitialCount+5);
1078 CBufFlat* p6=CBufFlat::NewL(8);
1080 __UHEAP_CHECK(KInitialCount+6);
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.
1093 __UHEAP_FAILNEXT(1);
1094 TRAPD(r,pC->PushL(p6));
1096 test(r==KErrNoMemory);
1098 __UHEAP_CHECK(KInitialCount+6);
1099 pC->PopAndDestroyAll();
1100 __UHEAP_CHECK(KInitialCount);
1102 test.Next(_L("Nest push push push push popallD"));
1103 p1=CBufFlat::NewL(8);
1105 __UHEAP_CHECK(KInitialCount+1);
1106 p2=CBufFlat::NewL(8);
1108 __UHEAP_CHECK(KInitialCount+2);
1109 p3=CBufFlat::NewL(8);
1111 __UHEAP_CHECK(KInitialCount+3);
1112 p4=CBufFlat::NewL(8);
1114 __UHEAP_CHECK(KInitialCount+4);
1121 pC->PopAndDestroyAll();
1122 __UHEAP_CHECK(KInitialCount+1);
1123 pC->PopAndDestroyAll();
1124 __UHEAP_CHECK(KInitialCount);
1126 test.Next(_L("Destroy cleanup object"));
1128 p1=CBufFlat::NewL(8);
1130 __UHEAP_CHECK(KInitialCount+1);
1131 p2=CBufFlat::NewL(8);
1133 __UHEAP_CHECK(KInitialCount+2);
1134 p3=CBufFlat::NewL(8);
1136 __UHEAP_CHECK(KInitialCount+3);
1137 p4=CBufFlat::NewL(8);
1139 __UHEAP_CHECK(KInitialCount+4);
1154 LOCAL_C void testUnTrap()
1156 // Test cleanup with normal exits
1160 test.Start(_L("Creating"));
1163 CTrapCleanup* pT=CTrapCleanup::New();
1165 __UHEAP_CHECK(KInitialCountAll);
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"));
1173 test.Next(_L("PushC PushO EPop cleanup empty 2"));
1175 test.Next(_L("PushC PushO EPop cleanup empty 3"));
1177 test.Next(_L("PushC PushO EPop cleanup empty 4"));
1179 test.Next(_L("PushC PushO EPop cleanup empty 5"));
1182 test.Next(_L("PushC PushO EPopAndDestroy cleanup empty"));
1183 TRAP(r,createL(EPopAndDestroy,EFalse))
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))
1198 test.Next(_L("Test all LC functions"));
1199 TRAP(r,createAllL(EFalse))
1201 __UHEAP_CHECK(KInitialCountAll);
1209 LOCAL_C void testLeave()
1211 // Test cleanup with leave exits
1215 test.Start(_L("Creating"));
1218 CTrapCleanup* pT=CTrapCleanup::New();
1220 __UHEAP_CHECK(KInitialCountAll);
1224 test.Next(_L("PushC PushO EPop cleanup empty and leave"));
1225 TRAPD(r,createL(EPop,ETrue))
1226 test(r==KLeaveValue);
1232 test.Next(_L("PushC PushO EPopAndDestroy cleanup empty and leave"));
1233 TRAP(r,createL(EPopAndDestroy,ETrue))
1234 test(r==KLeaveValue);
1237 test.Next(_L("PushC PushO ENull cleanup 2 objects and leave"));
1238 TRAP(r,createL(ENull,ETrue))
1239 test(r==KLeaveValue);
1243 test.Next(_L("Test all LC functions and leave"));
1244 TRAP(r,createAllL(ETrue))
1245 test(r==KLeaveValue);
1246 __UHEAP_CHECK(KInitialCountAll);
1254 LOCAL_C void testMultiLeave()
1256 // Test cleanup with multiple leave exits
1260 test.Start(_L("Creating"));
1263 CTrapCleanup* pT=CTrapCleanup::New();
1268 test.Next(_L("PushC PushO nest PushO cleanup leave leave"));
1269 TRAPD(r,createL(EMulti,ETrue))
1270 test(r==KLeaveValue);
1280 LOCAL_C void addNullItemL()
1282 CleanupStack::PushL((TAny*)0);
1285 LOCAL_C void addCellL()
1290 LOCAL_C void useCleanupStackL()
1294 CleanupStack::PopAndDestroy();
1295 CleanupStack::Pop();
1298 LOCAL_C void reentrantCleanup(TAny*)
1300 // A cleanup operation which uses a trap harness and the cleanup stack
1303 TRAPD(ignore,useCleanupStackL())
1306 LOCAL_C void addReentrantItemL()
1308 CleanupStack::PushL(TCleanupItem(reentrantCleanup));
1311 LOCAL_C void addItemsL(TInt aCount)
1313 // add number of reentrant items to make stack fail
1317 addReentrantItemL();
1318 #if !defined(_DEBUG)
1319 User::Leave(KErrNoMemory); // heap failure not available
1323 const TInt KInitialStackSize=8; // from UC_CLN.CPP
1324 const TInt KGrowItems=KInitialStackSize-3;
1326 LOCAL_C void testReentrancyL()
1328 // Test the Cleanup stack can go re-entrant
1332 test.Next(_L("PopAndDestroy()"));
1336 addReentrantItemL();
1337 CleanupStack::PopAndDestroy(2);
1338 CleanupStack::Pop();
1341 test.Next(_L("cleanup after a leave"));
1343 TRAPD(r,addReentrantItemL();User::Leave(KLeaveValue);)
1344 test(r==KLeaveValue);
1345 CleanupStack::Pop();
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)
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);
1356 CleanupStack::Pop(KGrowItems);
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);
1363 User::Free(forceAlloc);
1366 LOCAL_C void testReentrancy()
1368 // Test the Cleanup stack can go re-entrant
1372 test.Start(_L("Creating"));
1375 CTrapCleanup* pT=CTrapCleanup::New();
1378 TRAPD(r,testReentrancyL());
1387 LOCAL_C void testAutoCloseL()
1389 // A leaving function for testAutoClose()
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"));
1397 test.Next(_L("Leave before object goes out of scope"));
1398 User::Leave(KErrGeneral);
1402 LOCAL_C void testAutoClose()
1404 // Test the TAutoClose class
1408 // Kill the granules
1411 for (i=0; i<20; i++)
1413 for (i=0; i<20; i++)
1417 test.Start(_L("Make a TAutoClose object"));
1419 TAutoClose<RTimer> tim;
1420 tim.iObj.CreateLocal();
1422 test.Next(_L("Let it fall out of scope"));
1424 test.Next(_L("Check the object has closed"));
1427 TRAPD(r, testAutoCloseL());
1428 test.Next(_L("Check object has been closed and cleaned up after leave"));
1433 void CTest::ConstructL()
1435 // Allocate a cell with CBase::new
1439 TLex* pL=new(ELeave) TLex;
1440 CleanupStack::PushL(pL);
1443 void RItem::Cleanup(TAny* aPtr)
1445 // Invoke the Close member on the RItem at aPtr
1449 ((RItem*)aPtr)->Close();
1452 LOCAL_C TInt getStackPointer()
1454 static TUint8 there;
1456 return &here-&there;
1458 LOCAL_C void sheLeavesMeL(TBool sheLeavesMeNot)
1460 if (!sheLeavesMeNot)
1461 User::Leave(KErrBadName); // Montague
1464 // Variables for stack balance test need to be global or clever compiler optimisations
1465 // Can interfere with stack balance calculations.
1466 TInt StackBalanceLoopCounter;
1467 TInt StackBalanceResult=KErrNone;
1468 TInt StackBalanceBefore;
1469 TInt StackBalanceAfter;
1471 // Split into two functions because x86gcc makes a local stack optimisation for the second
1472 // loop which unbalances the stack frame of the first loop.
1473 LOCAL_C TInt StackBalanceNotLeaving()
1475 StackBalanceBefore=getStackPointer();
1476 for (StackBalanceLoopCounter=0; StackBalanceLoopCounter<20;StackBalanceLoopCounter++)
1478 TRAP(StackBalanceResult,sheLeavesMeL(ETrue));
1480 StackBalanceAfter=getStackPointer();
1481 return StackBalanceAfter-StackBalanceBefore;
1483 LOCAL_C TInt StackBalanceLeaving()
1485 StackBalanceBefore=getStackPointer();
1486 for (StackBalanceLoopCounter=0; StackBalanceLoopCounter<20;StackBalanceLoopCounter++)
1488 TRAP(StackBalanceResult,sheLeavesMeL(EFalse));
1490 StackBalanceAfter=getStackPointer();
1491 return StackBalanceAfter-StackBalanceBefore;
1494 LOCAL_C void testStackBalance()
1496 // Ensure that we get the stack properly balanced
1500 test.Start(_L("Stack balance without Leaving"));
1501 TInt balance = StackBalanceNotLeaving();
1502 test.Printf(_L("Stack balance: %d bytes\n"), balance);
1506 test.Next(_L("Stack balance after Leave"));
1507 balance = StackBalanceLeaving();
1508 test.Printf(_L("Stack balance: %d bytes\n"), balance);
1513 void Inc(TAny* aPtr)
1518 void testTrapIgnore()
1520 test.Start(_L("Create cleanup"));
1521 CCleanup* pC=CCleanup::New();
1525 test.Next(_L("TRAP_IGNORE with no leave"));
1527 CleanupStack::PushL(TCleanupItem(Inc,&count));
1528 CleanupStack::Pop();
1532 test.Next(_L("TRAP_IGNORE with leave"));
1534 CleanupStack::PushL(TCleanupItem(Inc,&count));
1535 User::Leave(KErrGeneral);
1543 GLDEF_C TInt E32Main()
1547 test.Start(_L("Test destructor causing stack reallocation"));
1548 testDestructorStackReallocation();
1550 test.Next(_L("CCleanup single level tests just alloc cells"));
1551 testSingleLevelCellsCleanup();
1553 test.Next(_L("CCleanup single level tests just objects"));
1554 testSingleLevelObjCleanup();
1556 test.Next(_L("CCleanup single level tests just items"));
1557 testSingleLevelItemCleanup();
1559 test.Next(_L("CCleanup single level tests mixed"));
1560 testSingleLevelMixCleanup();
1562 test.Next(_L("CCleanup multi level tests just alloc cells"));
1563 testMultiLevelCellsCleanup();
1565 test.Next(_L("CCleanup multi level tests just objects"));
1566 testMultiLevelObjCleanup();
1568 test.Next(_L("CCleanup multi level tests just items"));
1569 testMultiLevelItemCleanup();
1571 test.Next(_L("CCleanup multi level tests mixed"));
1572 testMultiLevelMixCleanup();
1574 test.Next(_L("CCleanup special case test"));
1575 testSpecialCaseCleanup();
1577 test.Next(_L("Install trap handler"));
1578 CTrapCleanup* pT=CTrapCleanup::New();
1581 test.Next(_L("Untrap handling tests"));
1584 test.Next(_L("Leave handling tests"));
1587 test.Next(_L("Multi level leave handling tests"));
1590 test.Next(_L("Test TAutoClose"));
1593 test.Next(_L("Test Re-entrancy of cleanup stack"));
1596 test.Next(_L("Test stack safety of TRAP and Leave"));
1599 test.Next(_L("Test TRAP_IGNORE"));