1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/system/t_ctrap.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1605 @@
1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\system\t_ctrap.cpp
1.18 +// Overview:
1.19 +// Test the CCleanup, CTrapCleanup and TAutoClose classes
1.20 +// API Information:
1.21 +// CCleanup, CTrapCleanup, TAutoClose
1.22 +// Details:
1.23 +// - Test cleanup stack reallocation during cleanup.
1.24 +// - Test cleanup stack modifications during the cleanup operation
1.25 +// will cause a panic.
1.26 +// - Test single-level cleanup of cells, objects, items and a mix:
1.27 +// Create a CCleanup object, call a combination of methods, verify
1.28 +// the results are as expected and verify the heap has not been
1.29 +// corrupted.
1.30 +// - Test multi-level cleanup of cells, objects, items and a mix:
1.31 +// Create a CCleanup object, call a combination of methods, verify
1.32 +// the results are as expected and verify the heap has not been
1.33 +// corrupted.
1.34 +// - Test a variety of special case cleanup tasks. Verify that the
1.35 +// results are as expected.
1.36 +// - Test CTrapCleanup cleanup of objects that either exit normally
1.37 +// or leave. Also test the cleanup of multiple objects that leave.
1.38 +// Verify results are as expected.
1.39 +// - Test TAutoClose: create a TAutoClose object, verify that it is
1.40 +// closed when it goes out of scope, push it on the cleanup stack,
1.41 +// verify cleanup results are as expected.
1.42 +// - Test that the Cleanup stack can go re-entrant.
1.43 +// - Ensure that the stack is properly balanced with and without
1.44 +// leaving.
1.45 +// Platforms/Drives/Compatibility:
1.46 +// All.
1.47 +// Assumptions/Requirement/Pre-requisites:
1.48 +// Failures and causes:
1.49 +// Base Port information:
1.50 +//
1.51 +//
1.52 +
1.53 +#define __E32TEST_EXTENSION__
1.54 +
1.55 +#include <e32test.h>
1.56 +#include <e32panic.h>
1.57 +#include <e32debug.h>
1.58 +#include <e32def.h>
1.59 +#include <e32def_private.h>
1.60 +
1.61 +
1.62 +const TInt KInitialCount=2;
1.63 +const TInt KInitialCountAll=3;
1.64 +const TInt KLeaveValue=0x12345678;
1.65 +const TInt KMaxAlloc=6;
1.66 +
1.67 +static const TInt KHeapSize = 0x2000;
1.68 +
1.69 +enum TWhat {EPop,EPopAndDestroy,EMulti,ENull};
1.70 +
1.71 +class CTest : public CBase
1.72 + {
1.73 +public:
1.74 + void ConstructL();
1.75 +private:
1.76 + TInt iData;
1.77 + };
1.78 +
1.79 +class CTest2: public CBase
1.80 + {
1.81 +public:
1.82 + ~CTest2();
1.83 + };
1.84 +
1.85 +class CTest3: public CBase
1.86 + {
1.87 +public:
1.88 + ~CTest3();
1.89 + };
1.90 +
1.91 +class RItem
1.92 + {
1.93 +public:
1.94 + RItem() : iOpen(EFalse) {}
1.95 + void Open() {iOpen=ETrue;}
1.96 + void Close() {iOpen=EFalse;}
1.97 + operator TCleanupItem() {return TCleanupItem(Cleanup,this);}
1.98 + TBool IsOpen() const {return(iOpen);}
1.99 +private:
1.100 + static void Cleanup(TAny* aPtr);
1.101 +private:
1.102 + TBool iOpen;
1.103 + };
1.104 +
1.105 +LOCAL_D RTest test(_L("T_CTRAP"));
1.106 +LOCAL_D TAny* gP1;
1.107 +LOCAL_D CBufFlat* gP2;
1.108 +
1.109 +
1.110 +LOCAL_C void ReallocateStackL()
1.111 + {
1.112 + TInt n = 0;
1.113 + for(TInt i = 0; i < KMaxAlloc; ++i)
1.114 + {
1.115 + HBufC *p1 = HBufC::NewLC(4); //Stack re-allocation will be performed due to the additional objects pushed
1.116 + //into the cleanup stack
1.117 + n = p1->Length(); //include this line to avoid warnigs for unused "p1" variable
1.118 + }
1.119 + test.Printf(_L("ReallocateStackL(): PopAndDestroy KMaxAlloc pointers\n"));
1.120 + CleanupStack::PopAndDestroy(KMaxAlloc);
1.121 + }
1.122 +
1.123 +CTest2::~CTest2()
1.124 + {
1.125 + TInt err = KErrNoMemory;
1.126 +
1.127 + test.Printf(_L("~CTest2(): call ReallocateStackL()\n"));
1.128 +
1.129 + TRAP(err, ReallocateStackL() );
1.130 + }
1.131 +
1.132 +CTest3::~CTest3()
1.133 + {
1.134 + RDebug::Printf("~CTest3(): Modify Cleanup stack by pushing items");
1.135 +
1.136 + TInt n = 0;
1.137 + for(TInt i = 0; i < KMaxAlloc; ++i)
1.138 + {
1.139 + HBufC *p1 = HBufC::NewLC(4); //Stack re-allocation will be performed due to the additional objects pushed
1.140 + //into the cleanup stack
1.141 + n = p1->Length(); //include this line to avoid warnigs for unused "p1" variable
1.142 + }
1.143 + }
1.144 +
1.145 +LOCAL_C void ModifyStack()
1.146 + {
1.147 + CTest3* ptr6 = new(ELeave)CTest3;
1.148 + CleanupStack::PushL(ptr6);
1.149 +
1.150 + RDebug::Printf("ModifyStack(): PopAndDestroy ptr6");
1.151 + CleanupStack::PopAndDestroy();
1.152 + }
1.153 +
1.154 +LOCAL_C TInt PanicStackModifiedFn(TAny* aNopFn)
1.155 + {
1.156 + __UHEAP_MARK;
1.157 + CTrapCleanup* cleanup = CTrapCleanup::New();
1.158 +
1.159 + aNopFn = NULL; //avoid warnings for unused "aNopFn" variable
1.160 +
1.161 + TInt err = KErrNoMemory;
1.162 +
1.163 + RDebug::Printf("PanicStackModifiedFn(): call TRAP(err, ModifyStack())");
1.164 +
1.165 + if(NULL != cleanup)
1.166 + {
1.167 + TRAP(err, ModifyStack());
1.168 + delete cleanup;
1.169 + }
1.170 + __UHEAP_MARKEND;
1.171 + return err;
1.172 + }
1.173 +
1.174 +LOCAL_C void PushAndCleanupL()
1.175 + {
1.176 + CTest2* ptr1 = new(ELeave)CTest2;
1.177 + CleanupStack::PushL(ptr1);
1.178 +
1.179 + CTest2* ptr2 = new(ELeave)CTest2;
1.180 + CleanupStack::PushL(ptr2);
1.181 +
1.182 + CTest2* ptr3 = new(ELeave)CTest2;
1.183 + CleanupStack::PushL(ptr3);
1.184 +
1.185 + test.Printf(_L("PushAndCleanupL(): PopAndDestroy ptr3, ptr2 and ptr1\n"));
1.186 + CleanupStack::PopAndDestroy(3);
1.187 +
1.188 + CTest2* ptr4 = new(ELeave)CTest2;
1.189 + CleanupStack::PushL(ptr4);
1.190 +
1.191 + CTest2* ptr5 = new(ELeave)CTest2;
1.192 + CleanupStack::PushL(ptr5);
1.193 +
1.194 + test.Printf(_L("PushAndCleanupL(): PopAndDestroy ptr5 and ptr4\n"));
1.195 + CleanupStack::PopAndDestroy();
1.196 + CleanupStack::PopAndDestroy();
1.197 + }
1.198 +
1.199 +LOCAL_C void testDestructorStackReallocation()
1.200 + {
1.201 + __UHEAP_MARK;
1.202 + CTrapCleanup* cleanup = CTrapCleanup::New();
1.203 +
1.204 + TInt err = KErrNoMemory;
1.205 +
1.206 + if(NULL != cleanup)
1.207 + {
1.208 + TRAP(err, PushAndCleanupL());
1.209 + delete cleanup;
1.210 + }
1.211 + __UHEAP_MARKEND;
1.212 +
1.213 + test_KErrNone(err);
1.214 +
1.215 + test.Printf(_L("Verify cleanup stack modification during cleanup operation causes EClnStackModified panic\n"));
1.216 +
1.217 + //
1.218 + //To verify the above case a new thread is created which does modify the cleanup stack during cleanup.
1.219 + //The exit reason is then checked for the appropriate value(EClnStackModified)
1.220 + //
1.221 +
1.222 + RThread panicThread;
1.223 +
1.224 + TInt r = panicThread.Create(_L("Panic EClnStackModified Thread"), PanicStackModifiedFn, KDefaultStackSize, KHeapSize, KHeapSize, NULL);
1.225 +
1.226 + test_KErrNone(r);
1.227 +
1.228 + TRequestStatus panicThreadStatus;
1.229 + panicThread.Logon(panicThreadStatus);
1.230 +
1.231 + //don't want just in time debugging as we trap panics
1.232 + TBool justInTime=User::JustInTime();
1.233 + User::SetJustInTime(EFalse);
1.234 +
1.235 + panicThread.Resume();
1.236 +
1.237 + User::WaitForRequest(panicThreadStatus);
1.238 +
1.239 + test_Equal(EExitPanic, panicThread.ExitType());
1.240 + test_Equal(EClnStackModified, panicThread.ExitReason());
1.241 +
1.242 + User::SetJustInTime(justInTime);
1.243 +
1.244 + CLOSE_AND_WAIT(panicThread);
1.245 + }
1.246 +
1.247 +LOCAL_C void createMultiL()
1.248 +//
1.249 +// Create an object on the cleanup list and leave
1.250 +//
1.251 + {
1.252 +
1.253 + CBufFlat* pT=CBufFlat::NewL(8);
1.254 + User::LeaveIfNull(pT);
1.255 + CleanupStack::PushL(pT);
1.256 + __UHEAP_CHECK(3);
1.257 + User::Leave(KLeaveValue+1);
1.258 + }
1.259 +
1.260 +LOCAL_C void createL(TWhat aWhat,TBool aLeave)
1.261 +//
1.262 +// Create objects and then either leave or return.
1.263 +// Optionally pop them again.
1.264 +//
1.265 + {
1.266 +
1.267 + gP1=User::AllocL(0x10);
1.268 + test.Printf(_L("createL 1"));
1.269 + CleanupStack::PushL(gP1);
1.270 + test.Printf(_L("createL 2"));
1.271 + __UHEAP_CHECK(1);
1.272 + test.Printf(_L("createL 3"));
1.273 + gP2=CBufFlat::NewL(8);
1.274 + test.Printf(_L("createL 4"));
1.275 + User::LeaveIfNull(gP2);
1.276 + test.Printf(_L("createL 5"));
1.277 + CleanupStack::PushL(gP2);
1.278 + test.Printf(_L("createL 6"));
1.279 + __UHEAP_CHECK(2);
1.280 + test.Printf(_L("createL 7"));
1.281 + if (aWhat==EPop)
1.282 + {
1.283 + test.Printf(_L("createL 8"));
1.284 + CleanupStack::Pop();
1.285 + test.Printf(_L("createL 9"));
1.286 + CleanupStack::Pop(1);
1.287 + test.Printf(_L("createL 10"));
1.288 + }
1.289 + if (aWhat==EPopAndDestroy)
1.290 + {
1.291 + test.Printf(_L("createL 11"));
1.292 + CleanupStack::PopAndDestroy();
1.293 + test.Printf(_L("createL 12"));
1.294 + CleanupStack::PopAndDestroy(1);
1.295 + test.Printf(_L("createL 13"));
1.296 + }
1.297 + if (aWhat==EMulti)
1.298 + {
1.299 + test.Printf(_L("createL 14"));
1.300 + TRAPD(r,createMultiL())
1.301 + test.Printf(_L("createL 15"));
1.302 + test(r==(KLeaveValue+1));
1.303 + test.Printf(_L("createL 16"));
1.304 + __UHEAP_CHECK(2);
1.305 + test.Printf(_L("createL 17"));
1.306 + }
1.307 + if (aLeave)
1.308 + {
1.309 + test.Printf(_L("createL 18"));
1.310 + User::Leave(KLeaveValue);
1.311 + }
1.312 + test.Printf(_L("createL 19"));
1.313 + }
1.314 +
1.315 +LOCAL_C void createAllL(TBool aLeave)
1.316 +//
1.317 +// Call all functions which autmatically put objects on the cleanup list.
1.318 +//
1.319 + {
1.320 +
1.321 + __UHEAP_CHECK(KInitialCountAll);
1.322 + TLex* pL=new(ELeave) TLex; // ::new, 1 cell
1.323 + CleanupStack::PushL(pL); // Push
1.324 + __UHEAP_CHECK(KInitialCountAll+1);
1.325 + CTest* pT=new(ELeave) CTest; // CBase::new, 1 cell
1.326 + CleanupStack::PushL(pT); // Push
1.327 + __UHEAP_CHECK(KInitialCountAll+2);
1.328 + pT->ConstructL(); // 1 more cell // Push
1.329 + __UHEAP_CHECK(KInitialCountAll+3);
1.330 + User::AllocLC(0x10); // Test RHeap::AllocLC as well // Push
1.331 + __UHEAP_CHECK(KInitialCountAll+4);
1.332 + _L("Hello").AllocLC(); // Test HBufC::NewLC() as well // Push
1.333 + __UHEAP_CHECK(KInitialCountAll+5);
1.334 + HBufC* pH=HBufC::NewMaxLC(8); // Push
1.335 + test(pH->Length()==8);
1.336 + __UHEAP_CHECK(KInitialCountAll+6);
1.337 + if (aLeave)
1.338 + User::Leave(KLeaveValue);
1.339 + // new behavior for TCleanupTrapHander requires Pushes to the
1.340 + // cleanup stack to be balanced by Pops
1.341 + CleanupStack::PopAndDestroy(6);
1.342 + }
1.343 +
1.344 +LOCAL_C void testSingleLevelCellsCleanup()
1.345 +//
1.346 +// Test single level cells cleanup
1.347 +//
1.348 + {
1.349 +
1.350 + test.Start(_L("Creating"));
1.351 +//
1.352 + __UHEAP_MARK;
1.353 + CCleanup* pC=CCleanup::New();
1.354 + test(pC!=NULL);
1.355 +//
1.356 + __UHEAP_MARK;
1.357 +//
1.358 + test.Next(_L("PopAll when empty"));
1.359 + pC->NextLevel();
1.360 + pC->PopAll();
1.361 + pC->NextLevel();
1.362 + pC->PopAndDestroyAll();
1.363 + __UHEAP_CHECK(0);
1.364 +//
1.365 + test.Next(_L("Push and pop"));
1.366 + TAny* p=User::Alloc(0x10);
1.367 + test(p!=NULL);
1.368 + __UHEAP_CHECK(1);
1.369 + pC->NextLevel();
1.370 + pC->PushL(p);
1.371 + pC->Pop();
1.372 + __UHEAP_CHECK(1);
1.373 + User::Free(p);
1.374 + __UHEAP_CHECK(0);
1.375 + pC->PopAll();
1.376 + __UHEAP_CHECK(0);
1.377 +//
1.378 + test.Next(_L("Push and pop N"));
1.379 + TAny* p1=User::Alloc(0x10);
1.380 + test(p1!=NULL);
1.381 + __UHEAP_CHECK(1);
1.382 + TAny* p2=User::Alloc(0x10);
1.383 + test(p2!=NULL);
1.384 + __UHEAP_CHECK(2);
1.385 + pC->NextLevel();
1.386 + pC->PushL(p1);
1.387 + pC->PushL(p2);
1.388 + pC->Pop(2);
1.389 + __UHEAP_CHECK(2);
1.390 + User::Free(p1);
1.391 + User::Free(p2);
1.392 + __UHEAP_CHECK(0);
1.393 + pC->PopAll();
1.394 + __UHEAP_CHECK(0);
1.395 +//
1.396 + test.Next(_L("Push and pop all"));
1.397 + p1=User::Alloc(0x10);
1.398 + test(p1!=NULL);
1.399 + __UHEAP_CHECK(1);
1.400 + p2=User::Alloc(0x10);
1.401 + test(p2!=NULL);
1.402 + __UHEAP_CHECK(2);
1.403 + TAny* p3=User::Alloc(0x10);
1.404 + test(p3!=NULL);
1.405 + __UHEAP_CHECK(3);
1.406 + pC->NextLevel();
1.407 + pC->PushL(p1);
1.408 + pC->PushL(p2);
1.409 + pC->PushL(p3);
1.410 + pC->PopAll();
1.411 + __UHEAP_CHECK(3);
1.412 + User::Free(p1);
1.413 + User::Free(p2);
1.414 + User::Free(p3);
1.415 + __UHEAP_CHECK(0);
1.416 +//
1.417 + test.Next(_L("Push and pop and destroy"));
1.418 + p=User::Alloc(0x10);
1.419 + test(p!=NULL);
1.420 + __UHEAP_CHECK(1);
1.421 + pC->NextLevel();
1.422 + pC->PushL(p);
1.423 + pC->PopAndDestroy();
1.424 + __UHEAP_CHECK(0);
1.425 + pC->PopAll();
1.426 +//
1.427 + test.Next(_L("Push and pop and destroy N"));
1.428 + p1=User::Alloc(0x10);
1.429 + test(p1!=NULL);
1.430 + __UHEAP_CHECK(1);
1.431 + p2=User::Alloc(0x10);
1.432 + test(p2!=NULL);
1.433 + __UHEAP_CHECK(2);
1.434 + pC->NextLevel();
1.435 + pC->PushL(p1);
1.436 + pC->PushL(p2);
1.437 + pC->PopAndDestroy(2);
1.438 + __UHEAP_CHECK(0);
1.439 + pC->PopAll();
1.440 + __UHEAP_CHECK(0);
1.441 +//
1.442 + test.Next(_L("Push and pop and destroy all"));
1.443 + p1=User::Alloc(0x10);
1.444 + test(p1!=NULL);
1.445 + __UHEAP_CHECK(1);
1.446 + p2=User::Alloc(0x10);
1.447 + test(p2!=NULL);
1.448 + __UHEAP_CHECK(2);
1.449 + p3=User::Alloc(0x10);
1.450 + test(p3!=NULL);
1.451 + __UHEAP_CHECK(3);
1.452 + pC->NextLevel();
1.453 + pC->PushL(p1);
1.454 + pC->PushL(p2);
1.455 + pC->PushL(p3);
1.456 + pC->PopAndDestroyAll();
1.457 + __UHEAP_CHECK(0);
1.458 +//
1.459 + __UHEAP_MARKEND;
1.460 +//
1.461 + delete pC;
1.462 + __UHEAP_MARKEND;
1.463 +//
1.464 + test.End();
1.465 + }
1.466 +
1.467 +LOCAL_C void testSingleLevelObjCleanup()
1.468 +//
1.469 +// Test single level object cleanup
1.470 +//
1.471 + {
1.472 +
1.473 + test.Start(_L("Creating"));
1.474 +//
1.475 + __UHEAP_MARK;
1.476 + CCleanup* pC=CCleanup::New();
1.477 + test(pC!=NULL);
1.478 +//
1.479 + __UHEAP_MARK;
1.480 +//
1.481 + test.Next(_L("Push and pop"));
1.482 + CBufFlat* p=CBufFlat::NewL(8);
1.483 + test(p!=NULL);
1.484 + __UHEAP_CHECK(1);
1.485 + pC->NextLevel();
1.486 + pC->PushL(p);
1.487 + pC->Pop();
1.488 + __UHEAP_CHECK(1);
1.489 + User::Free(p);
1.490 + __UHEAP_CHECK(0);
1.491 + pC->PopAll();
1.492 + __UHEAP_CHECK(0);
1.493 +//
1.494 + test.Next(_L("Push and pop N"));
1.495 + CBufFlat* p1=CBufFlat::NewL(8);
1.496 + test(p1!=NULL);
1.497 + __UHEAP_CHECK(1);
1.498 + CBufFlat* p2=CBufFlat::NewL(8);
1.499 + test(p2!=NULL);
1.500 + __UHEAP_CHECK(2);
1.501 + pC->NextLevel();
1.502 + pC->PushL(p1);
1.503 + pC->PushL(p2);
1.504 + pC->Pop(2);
1.505 + __UHEAP_CHECK(2);
1.506 + User::Free(p1);
1.507 + User::Free(p2);
1.508 + __UHEAP_CHECK(0);
1.509 + pC->PopAll();
1.510 + __UHEAP_CHECK(0);
1.511 +//
1.512 + test.Next(_L("Push and pop all"));
1.513 + p1=CBufFlat::NewL(8);
1.514 + test(p1!=NULL);
1.515 + __UHEAP_CHECK(1);
1.516 + p2=CBufFlat::NewL(8);
1.517 + test(p2!=NULL);
1.518 + __UHEAP_CHECK(2);
1.519 + CBufFlat* p3=CBufFlat::NewL(8);
1.520 + test(p3!=NULL);
1.521 + __UHEAP_CHECK(3);
1.522 + pC->NextLevel();
1.523 + pC->PushL(p1);
1.524 + pC->PushL(p2);
1.525 + pC->PushL(p3);
1.526 + pC->PopAll();
1.527 + __UHEAP_CHECK(3);
1.528 + User::Free(p1);
1.529 + User::Free(p2);
1.530 + User::Free(p3);
1.531 + __UHEAP_CHECK(0);
1.532 +//
1.533 + test.Next(_L("Push and pop and destroy"));
1.534 + p=CBufFlat::NewL(8);
1.535 + test(p!=NULL);
1.536 + __UHEAP_CHECK(1);
1.537 + pC->NextLevel();
1.538 + pC->PushL(p);
1.539 + pC->PopAndDestroy();
1.540 + __UHEAP_CHECK(0);
1.541 + pC->PopAll();
1.542 +//
1.543 + test.Next(_L("Push and pop and destroy N"));
1.544 + p1=CBufFlat::NewL(8);
1.545 + test(p1!=NULL);
1.546 + __UHEAP_CHECK(1);
1.547 + p2=CBufFlat::NewL(8);
1.548 + test(p2!=NULL);
1.549 + __UHEAP_CHECK(2);
1.550 + pC->NextLevel();
1.551 + pC->PushL(p1);
1.552 + pC->PushL(p2);
1.553 + pC->PopAndDestroy(2);
1.554 + __UHEAP_CHECK(0);
1.555 + pC->PopAll();
1.556 + __UHEAP_CHECK(0);
1.557 +//
1.558 + test.Next(_L("Push and pop and destroy all"));
1.559 + p1=CBufFlat::NewL(8);
1.560 + test(p1!=NULL);
1.561 + __UHEAP_CHECK(1);
1.562 + p2=CBufFlat::NewL(8);
1.563 + test(p2!=NULL);
1.564 + __UHEAP_CHECK(2);
1.565 + p3=CBufFlat::NewL(8);
1.566 + test(p3!=NULL);
1.567 + __UHEAP_CHECK(3);
1.568 + pC->NextLevel();
1.569 + pC->PushL(p1);
1.570 + pC->PushL(p2);
1.571 + pC->PushL(p3);
1.572 + pC->PopAndDestroyAll();
1.573 + __UHEAP_CHECK(0);
1.574 +//
1.575 + __UHEAP_MARKEND;
1.576 +//
1.577 + delete pC;
1.578 + __UHEAP_MARKEND;
1.579 +//
1.580 + test.End();
1.581 + }
1.582 +
1.583 +LOCAL_C void testSingleLevelItemCleanup()
1.584 +//
1.585 +// Test single level object cleanup
1.586 +//
1.587 + {
1.588 +
1.589 + test.Start(_L("Creating"));
1.590 +//
1.591 + __UHEAP_MARK;
1.592 + CCleanup* pC=CCleanup::New();
1.593 + test(pC!=NULL);
1.594 +//
1.595 + __UHEAP_MARK;
1.596 +//
1.597 + test.Next(_L("Push and pop"));
1.598 + RItem r;
1.599 + r.Open();
1.600 + test(r.IsOpen());
1.601 + pC->NextLevel();
1.602 + pC->PushL(r);
1.603 + pC->Pop();
1.604 + test(r.IsOpen());
1.605 + r.Close();
1.606 + test(!r.IsOpen());
1.607 + pC->PopAll();
1.608 +//
1.609 + test.Next(_L("Push and pop N"));
1.610 + RItem r1;
1.611 + r1.Open();
1.612 + RItem r2;
1.613 + r2.Open();
1.614 + pC->NextLevel();
1.615 + pC->PushL(r1);
1.616 + pC->PushL(r2);
1.617 + pC->Pop(2);
1.618 + test(r1.IsOpen());
1.619 + test(r2.IsOpen());
1.620 + r1.Close();
1.621 + r2.Close();
1.622 + pC->PopAll();
1.623 +//
1.624 + test.Next(_L("Push and pop all"));
1.625 + r1.Open();
1.626 + r2.Open();
1.627 + RItem r3;
1.628 + r3.Open();
1.629 + pC->NextLevel();
1.630 + pC->PushL(r1);
1.631 + pC->PushL(r2);
1.632 + pC->PushL(r3);
1.633 + pC->PopAll();
1.634 + test(r1.IsOpen());
1.635 + test(r2.IsOpen());
1.636 + test(r3.IsOpen());
1.637 + r1.Close();
1.638 + r2.Close();
1.639 + r3.Close();
1.640 +//
1.641 + test.Next(_L("Push and pop and destroy"));
1.642 + r.Open();
1.643 + pC->NextLevel();
1.644 + pC->PushL(r);
1.645 + pC->PopAndDestroy();
1.646 + test(!r.IsOpen());
1.647 + pC->PopAll();
1.648 +//
1.649 + test.Next(_L("Push and pop and destroy N"));
1.650 + r1.Open();
1.651 + r2.Open();
1.652 + pC->NextLevel();
1.653 + pC->PushL(r1);
1.654 + pC->PushL(r2);
1.655 + pC->PopAndDestroy(2);
1.656 + test(!r1.IsOpen());
1.657 + test(!r2.IsOpen());
1.658 + pC->PopAll();
1.659 +//
1.660 + test.Next(_L("Push and pop and destroy all"));
1.661 + r1.Open();
1.662 + r2.Open();
1.663 + r3.Open();
1.664 + pC->NextLevel();
1.665 + pC->PushL(r1);
1.666 + pC->PushL(r2);
1.667 + pC->PushL(r3);
1.668 + pC->PopAndDestroyAll();
1.669 + test(!r1.IsOpen());
1.670 + test(!r2.IsOpen());
1.671 + test(!r3.IsOpen());
1.672 +//
1.673 + __UHEAP_MARKEND;
1.674 +//
1.675 + delete pC;
1.676 + __UHEAP_MARKEND;
1.677 +//
1.678 + test.End();
1.679 + }
1.680 +
1.681 +LOCAL_C void testSingleLevelMixCleanup()
1.682 +//
1.683 +// Test single level mixed cleanup
1.684 +//
1.685 + {
1.686 +
1.687 + test.Start(_L("Creating"));
1.688 +//
1.689 + __UHEAP_MARK;
1.690 + CCleanup* pC=CCleanup::New();
1.691 + test(pC!=NULL);
1.692 +//
1.693 + __UHEAP_MARK;
1.694 +//
1.695 + test.Next(_L("PushO PushC PushI and pop N"));
1.696 + CBufFlat* p1=CBufFlat::NewL(8);
1.697 + test(p1!=NULL);
1.698 + __UHEAP_CHECK(1);
1.699 + TAny* p2=User::Alloc(0x10);
1.700 + test(p2!=NULL);
1.701 + __UHEAP_CHECK(2);
1.702 + RItem r;
1.703 + r.Open();
1.704 + pC->NextLevel();
1.705 + pC->PushL(p1);
1.706 + pC->PushL(p2);
1.707 + pC->PushL(r);
1.708 + pC->Pop(3);
1.709 + __UHEAP_CHECK(2);
1.710 + test(r.IsOpen());
1.711 + User::Free(p1);
1.712 + User::Free(p2);
1.713 + r.Close();
1.714 + __UHEAP_CHECK(0);
1.715 + pC->PopAll();
1.716 + __UHEAP_CHECK(0);
1.717 +//
1.718 + test.Next(_L("PushO PushI PushC PushO and pop all"));
1.719 + p1=CBufFlat::NewL(8);
1.720 + test(p1!=NULL);
1.721 + __UHEAP_CHECK(1);
1.722 + r.Open();
1.723 + p2=User::Alloc(0x10);
1.724 + test(p2!=NULL);
1.725 + __UHEAP_CHECK(2);
1.726 + CBufFlat* p3=CBufFlat::NewL(8);
1.727 + test(p3!=NULL);
1.728 + __UHEAP_CHECK(3);
1.729 + pC->NextLevel();
1.730 + pC->PushL(p1);
1.731 + pC->PushL(r);
1.732 + pC->PushL(p2);
1.733 + pC->PushL(p3);
1.734 + pC->PopAll();
1.735 + __UHEAP_CHECK(3);
1.736 + test(r.IsOpen());
1.737 + User::Free(p1);
1.738 + User::Free(p2);
1.739 + User::Free(p3);
1.740 + r.Close();
1.741 + __UHEAP_CHECK(0);
1.742 +//
1.743 + test.Next(_L("PushO PushC PushI and pop and destroy N"));
1.744 + p1=CBufFlat::NewL(8);
1.745 + test(p1!=NULL);
1.746 + __UHEAP_CHECK(1);
1.747 + p2=User::Alloc(0x10);
1.748 + test(p2!=NULL);
1.749 + __UHEAP_CHECK(2);
1.750 + r.Open();
1.751 + pC->NextLevel();
1.752 + pC->PushL(p1);
1.753 + pC->PushL(p2);
1.754 + pC->PushL(r);
1.755 + pC->PopAndDestroy(3);
1.756 + test(!r.IsOpen());
1.757 + __UHEAP_CHECK(0);
1.758 + pC->PopAll();
1.759 + __UHEAP_CHECK(0);
1.760 +//
1.761 + test.Next(_L("PushO PushI PushC PushO and pop and destroy all"));
1.762 + p1=CBufFlat::NewL(8);
1.763 + test(p1!=NULL);
1.764 + __UHEAP_CHECK(1);
1.765 + r.Open();
1.766 + p2=User::Alloc(0x10);
1.767 + test(p2!=NULL);
1.768 + __UHEAP_CHECK(2);
1.769 + p3=CBufFlat::NewL(8);
1.770 + test(p3!=NULL);
1.771 + __UHEAP_CHECK(3);
1.772 + pC->NextLevel();
1.773 + pC->PushL(p1);
1.774 + pC->PushL(r);
1.775 + pC->PushL(p2);
1.776 + pC->PushL(p3);
1.777 + pC->PopAndDestroyAll();
1.778 + test(!r.IsOpen());
1.779 + __UHEAP_CHECK(0);
1.780 +//
1.781 + __UHEAP_MARKEND;
1.782 +//
1.783 + delete pC;
1.784 + __UHEAP_MARKEND;
1.785 +//
1.786 + test.End();
1.787 + }
1.788 +
1.789 +LOCAL_C void testMultiLevelCellsCleanup()
1.790 +//
1.791 +// Test multi level cells cleanup
1.792 +//
1.793 + {
1.794 +
1.795 + test.Start(_L("Creating"));
1.796 +//
1.797 + __UHEAP_MARK;
1.798 + CCleanup* pC=CCleanup::New();
1.799 + test(pC!=NULL);
1.800 +//
1.801 + __UHEAP_MARK;
1.802 +//
1.803 + test.Next(_L("Nest push push nest push popall popall"));
1.804 + TAny* p1=User::Alloc(0x10);
1.805 + test(p1!=NULL);
1.806 + __UHEAP_CHECK(1);
1.807 + TAny* p2=User::Alloc(0x10);
1.808 + test(p2!=NULL);
1.809 + __UHEAP_CHECK(2);
1.810 + TAny* p3=User::Alloc(0x10);
1.811 + test(p3!=NULL);
1.812 + __UHEAP_CHECK(3);
1.813 + pC->NextLevel();
1.814 + pC->PushL(p1);
1.815 + pC->PushL(p2);
1.816 + pC->NextLevel();
1.817 + pC->PushL(p3);
1.818 + pC->PopAll();
1.819 + __UHEAP_CHECK(3);
1.820 + pC->PopAll();
1.821 + __UHEAP_CHECK(3);
1.822 + User::Free(p1);
1.823 + User::Free(p2);
1.824 + User::Free(p3);
1.825 + __UHEAP_CHECK(0);
1.826 +//
1.827 + test.Next(_L("Nest push push nest push popallD popallD"));
1.828 + p1=User::Alloc(0x10);
1.829 + test(p1!=NULL);
1.830 + __UHEAP_CHECK(1);
1.831 + p2=User::Alloc(0x10);
1.832 + test(p2!=NULL);
1.833 + __UHEAP_CHECK(2);
1.834 + p3=User::Alloc(0x10);
1.835 + test(p3!=NULL);
1.836 + __UHEAP_CHECK(3);
1.837 + pC->NextLevel();
1.838 + pC->PushL(p1);
1.839 + pC->PushL(p2);
1.840 + pC->NextLevel();
1.841 + pC->PushL(p3);
1.842 + pC->PopAndDestroyAll();
1.843 + __UHEAP_CHECK(2);
1.844 + pC->PopAndDestroyAll();
1.845 + __UHEAP_CHECK(0);
1.846 +//
1.847 + __UHEAP_MARKEND;
1.848 +//
1.849 + delete pC;
1.850 + __UHEAP_MARKEND;
1.851 +//
1.852 + test.End();
1.853 + }
1.854 +
1.855 +LOCAL_C void testMultiLevelObjCleanup()
1.856 +//
1.857 +// Test multi level object cleanup
1.858 +//
1.859 + {
1.860 +
1.861 + test.Start(_L("Creating"));
1.862 +//
1.863 + __UHEAP_MARK;
1.864 + CCleanup* pC=CCleanup::New();
1.865 + test(pC!=NULL);
1.866 +//
1.867 + __UHEAP_MARK;
1.868 +//
1.869 + test.Next(_L("Nest push push nest push popall popall"));
1.870 + CBufFlat* p1=CBufFlat::NewL(8);
1.871 + test(p1!=NULL);
1.872 + __UHEAP_CHECK(1);
1.873 + CBufFlat* p2=CBufFlat::NewL(8);
1.874 + test(p2!=NULL);
1.875 + __UHEAP_CHECK(2);
1.876 + CBufFlat* p3=CBufFlat::NewL(8);
1.877 + test(p3!=NULL);
1.878 + __UHEAP_CHECK(3);
1.879 + pC->NextLevel();
1.880 + pC->PushL(p1);
1.881 + pC->PushL(p2);
1.882 + pC->NextLevel();
1.883 + pC->PushL(p3);
1.884 + pC->PopAll();
1.885 + __UHEAP_CHECK(3);
1.886 + pC->PopAll();
1.887 + __UHEAP_CHECK(3);
1.888 + User::Free(p1);
1.889 + User::Free(p2);
1.890 + User::Free(p3);
1.891 + __UHEAP_CHECK(0);
1.892 +//
1.893 + test.Next(_L("Nest push push nest push popallD popallD"));
1.894 + p1=CBufFlat::NewL(8);
1.895 + test(p1!=NULL);
1.896 + __UHEAP_CHECK(1);
1.897 + p2=CBufFlat::NewL(8);
1.898 + test(p2!=NULL);
1.899 + __UHEAP_CHECK(2);
1.900 + p3=CBufFlat::NewL(8);
1.901 + test(p3!=NULL);
1.902 + __UHEAP_CHECK(3);
1.903 + pC->NextLevel();
1.904 + pC->PushL(p1);
1.905 + pC->PushL(p2);
1.906 + pC->NextLevel();
1.907 + pC->PushL(p3);
1.908 + pC->PopAndDestroyAll();
1.909 + __UHEAP_CHECK(2);
1.910 + pC->PopAndDestroyAll();
1.911 + __UHEAP_CHECK(0);
1.912 +//
1.913 + __UHEAP_MARKEND;
1.914 +//
1.915 + delete pC;
1.916 + __UHEAP_MARKEND;
1.917 +//
1.918 + test.End();
1.919 + }
1.920 +
1.921 +LOCAL_C void testMultiLevelItemCleanup()
1.922 +//
1.923 +// Test multi level item cleanup
1.924 +//
1.925 + {
1.926 +
1.927 + test.Start(_L("Creating"));
1.928 +//
1.929 + __UHEAP_MARK;
1.930 + CCleanup* pC=CCleanup::New();
1.931 + test(pC!=NULL);
1.932 +//
1.933 + __UHEAP_MARK;
1.934 +//
1.935 + test.Next(_L("Nest push push nest push popall popall"));
1.936 + RItem r1;
1.937 + r1.Open();
1.938 + RItem r2;
1.939 + r2.Open();
1.940 + RItem r3;
1.941 + r3.Open();
1.942 + pC->NextLevel();
1.943 + pC->PushL(r1);
1.944 + pC->PushL(r2);
1.945 + pC->NextLevel();
1.946 + pC->PushL(r3);
1.947 + pC->PopAll();
1.948 + test(r1.IsOpen());
1.949 + test(r2.IsOpen());
1.950 + test(r3.IsOpen());
1.951 + pC->PopAll();
1.952 + test(r1.IsOpen());
1.953 + test(r2.IsOpen());
1.954 + test(r3.IsOpen());
1.955 + r1.Close();
1.956 + r2.Close();
1.957 + r3.Close();
1.958 +//
1.959 + test.Next(_L("Nest push push nest push popallD popallD"));
1.960 + r1.Open();
1.961 + r2.Open();
1.962 + r3.Open();
1.963 + pC->NextLevel();
1.964 + pC->PushL(r1);
1.965 + pC->PushL(r2);
1.966 + pC->NextLevel();
1.967 + pC->PushL(r3);
1.968 + pC->PopAndDestroyAll();
1.969 + test(r1.IsOpen());
1.970 + test(r2.IsOpen());
1.971 + test(!r3.IsOpen());
1.972 + pC->PopAndDestroyAll();
1.973 + test(!r1.IsOpen());
1.974 + test(!r2.IsOpen());
1.975 + test(!r3.IsOpen());
1.976 +//
1.977 + __UHEAP_MARKEND;
1.978 +//
1.979 + delete pC;
1.980 + __UHEAP_MARKEND;
1.981 +//
1.982 + test.End();
1.983 + }
1.984 +
1.985 +LOCAL_C void testMultiLevelMixCleanup()
1.986 +//
1.987 +// Test multi level mixed cleanup
1.988 +//
1.989 + {
1.990 +
1.991 + test.Start(_L("Creating"));
1.992 +//
1.993 + __UHEAP_MARK;
1.994 + CCleanup* pC=CCleanup::New();
1.995 + test(pC!=NULL);
1.996 +//
1.997 + __UHEAP_MARK;
1.998 +//
1.999 + test.Next(_L("Nest pushO pushC nest pushI popall popall"));
1.1000 + CBufFlat* p1=CBufFlat::NewL(8);
1.1001 + test(p1!=NULL);
1.1002 + __UHEAP_CHECK(1);
1.1003 + TAny* p2=User::Alloc(0x10);
1.1004 + test(p2!=NULL);
1.1005 + __UHEAP_CHECK(2);
1.1006 + RItem r3;
1.1007 + r3.Open();
1.1008 + pC->NextLevel();
1.1009 + pC->PushL(p1);
1.1010 + pC->PushL(p2);
1.1011 + pC->NextLevel();
1.1012 + pC->PushL(r3);
1.1013 + pC->PopAll();
1.1014 + __UHEAP_CHECK(2);
1.1015 + test(r3.IsOpen());
1.1016 + pC->PopAll();
1.1017 + __UHEAP_CHECK(2);
1.1018 + test(r3.IsOpen());
1.1019 + User::Free(p1);
1.1020 + User::Free(p2);
1.1021 + r3.Close();
1.1022 + __UHEAP_CHECK(0);
1.1023 +//
1.1024 + test.Next(_L("Nest pushO pushC nest pushI popallD popallD"));
1.1025 + p1=CBufFlat::NewL(8);
1.1026 + test(p1!=NULL);
1.1027 + __UHEAP_CHECK(1);
1.1028 + p2=User::Alloc(0x10);
1.1029 + test(p2!=NULL);
1.1030 + __UHEAP_CHECK(2);
1.1031 + r3.Open();
1.1032 + pC->NextLevel();
1.1033 + pC->PushL(p1);
1.1034 + pC->PushL(p2);
1.1035 + pC->NextLevel();
1.1036 + pC->PushL(r3);
1.1037 + pC->PopAndDestroyAll();
1.1038 + __UHEAP_CHECK(2);
1.1039 + test(!r3.IsOpen());
1.1040 + pC->PopAndDestroyAll();
1.1041 + test(!r3.IsOpen());
1.1042 + __UHEAP_CHECK(0);
1.1043 +//
1.1044 + __UHEAP_MARKEND;
1.1045 +//
1.1046 + delete pC;
1.1047 + __UHEAP_MARKEND;
1.1048 +//
1.1049 + test.End();
1.1050 + }
1.1051 +
1.1052 +LOCAL_C void testSpecialCaseCleanup()
1.1053 +//
1.1054 +// Test special case cleanup
1.1055 +//
1.1056 + {
1.1057 +
1.1058 + test.Start(_L("Creating"));
1.1059 +//
1.1060 + __UHEAP_MARK;
1.1061 + CCleanup* pC=CCleanup::New();
1.1062 + test(pC!=NULL);
1.1063 + __UHEAP_CHECK(KInitialCount);
1.1064 +//
1.1065 + test.Next(_L("Nest push push push fail"));
1.1066 + CBufFlat* p1=CBufFlat::NewL(8);
1.1067 + test(p1!=NULL);
1.1068 + __UHEAP_CHECK(KInitialCount+1);
1.1069 + CBufFlat* p2=CBufFlat::NewL(8);
1.1070 + test(p2!=NULL);
1.1071 + __UHEAP_CHECK(KInitialCount+2);
1.1072 + CBufFlat* p3=CBufFlat::NewL(8);
1.1073 + test(p3!=NULL);
1.1074 + __UHEAP_CHECK(KInitialCount+3);
1.1075 + CBufFlat* p4=CBufFlat::NewL(8);
1.1076 + test(p4!=NULL);
1.1077 + __UHEAP_CHECK(KInitialCount+4);
1.1078 + CBufFlat* p5=CBufFlat::NewL(8);
1.1079 + test(p5!=NULL);
1.1080 + __UHEAP_CHECK(KInitialCount+5);
1.1081 + CBufFlat* p6=CBufFlat::NewL(8);
1.1082 + test(p6!=NULL);
1.1083 + __UHEAP_CHECK(KInitialCount+6);
1.1084 + pC->NextLevel();
1.1085 + pC->PushL(p1);
1.1086 + pC->PushL(p2);
1.1087 + pC->PushL(p3);
1.1088 + pC->PushL(p4);
1.1089 + pC->PushL(p5);
1.1090 +//
1.1091 +// The granularity is 4 so this should try and grow the array
1.1092 +// since room is always made for a free slot. We set the allocator
1.1093 +// to fail so that we can test that the free slot is re-established
1.1094 +// when we do the cleanup. This test only works in debug mode.
1.1095 +//
1.1096 + __UHEAP_FAILNEXT(1);
1.1097 + TRAPD(r,pC->PushL(p6));
1.1098 +#if defined(_DEBUG)
1.1099 + test(r==KErrNoMemory);
1.1100 +#endif
1.1101 + __UHEAP_CHECK(KInitialCount+6);
1.1102 + pC->PopAndDestroyAll();
1.1103 + __UHEAP_CHECK(KInitialCount);
1.1104 +//
1.1105 + test.Next(_L("Nest push push push push popallD"));
1.1106 + p1=CBufFlat::NewL(8);
1.1107 + test(p1!=NULL);
1.1108 + __UHEAP_CHECK(KInitialCount+1);
1.1109 + p2=CBufFlat::NewL(8);
1.1110 + test(p2!=NULL);
1.1111 + __UHEAP_CHECK(KInitialCount+2);
1.1112 + p3=CBufFlat::NewL(8);
1.1113 + test(p3!=NULL);
1.1114 + __UHEAP_CHECK(KInitialCount+3);
1.1115 + p4=CBufFlat::NewL(8);
1.1116 + test(p4!=NULL);
1.1117 + __UHEAP_CHECK(KInitialCount+4);
1.1118 + pC->NextLevel();
1.1119 + pC->PushL(p1);
1.1120 + pC->NextLevel();
1.1121 + pC->PushL(p2);
1.1122 + pC->PushL(p3);
1.1123 + pC->PushL(p4);
1.1124 + pC->PopAndDestroyAll();
1.1125 + __UHEAP_CHECK(KInitialCount+1);
1.1126 + pC->PopAndDestroyAll();
1.1127 + __UHEAP_CHECK(KInitialCount);
1.1128 +//
1.1129 + test.Next(_L("Destroy cleanup object"));
1.1130 +//
1.1131 + p1=CBufFlat::NewL(8);
1.1132 + test(p1!=NULL);
1.1133 + __UHEAP_CHECK(KInitialCount+1);
1.1134 + p2=CBufFlat::NewL(8);
1.1135 + test(p2!=NULL);
1.1136 + __UHEAP_CHECK(KInitialCount+2);
1.1137 + p3=CBufFlat::NewL(8);
1.1138 + test(p3!=NULL);
1.1139 + __UHEAP_CHECK(KInitialCount+3);
1.1140 + p4=CBufFlat::NewL(8);
1.1141 + test(p4!=NULL);
1.1142 + __UHEAP_CHECK(KInitialCount+4);
1.1143 + pC->NextLevel();
1.1144 + pC->PushL(p1);
1.1145 + pC->NextLevel();
1.1146 + pC->PushL(p2);
1.1147 + pC->PushL(p3);
1.1148 + pC->PushL(p4);
1.1149 + delete pC;
1.1150 + __UHEAP_CHECK(0);
1.1151 +//
1.1152 + __UHEAP_MARKEND;
1.1153 +//
1.1154 + test.End();
1.1155 + }
1.1156 +
1.1157 +LOCAL_C void testUnTrap()
1.1158 +//
1.1159 +// Test cleanup with normal exits
1.1160 +//
1.1161 + {
1.1162 +
1.1163 + test.Start(_L("Creating"));
1.1164 +//
1.1165 + __UHEAP_MARK;
1.1166 + CTrapCleanup* pT=CTrapCleanup::New();
1.1167 + test(pT!=NULL);
1.1168 + __UHEAP_CHECK(KInitialCountAll);
1.1169 +//
1.1170 + __UHEAP_MARK;
1.1171 +//
1.1172 + test.Next(_L("PushC PushO EPop cleanup empty"));
1.1173 + TRAPD(r,createL(EPop,EFalse))
1.1174 + test.Next(_L("PushC PushO EPop cleanup empty 1"));
1.1175 + test(r==KErrNone);
1.1176 + test.Next(_L("PushC PushO EPop cleanup empty 2"));
1.1177 + __UHEAP_CHECK(2);
1.1178 + test.Next(_L("PushC PushO EPop cleanup empty 3"));
1.1179 + User::Free(gP1);
1.1180 + test.Next(_L("PushC PushO EPop cleanup empty 4"));
1.1181 + delete gP2;
1.1182 + test.Next(_L("PushC PushO EPop cleanup empty 5"));
1.1183 + __UHEAP_CHECK(0);
1.1184 +//
1.1185 + test.Next(_L("PushC PushO EPopAndDestroy cleanup empty"));
1.1186 + TRAP(r,createL(EPopAndDestroy,EFalse))
1.1187 + test(r==KErrNone);
1.1188 + __UHEAP_CHECK(0);
1.1189 +//
1.1190 +/*
1.1191 +// Change of behavior for TCleanupTrapHandler means that the current
1.1192 +// cleanup stack must be empty when UnTrap is called. IE. calls to
1.1193 +// Push should be balanced with a Pop within the same function.
1.1194 + test.Next(_L("PushC PushO ENull cleanup 2 objects"));
1.1195 + TRAP(r,createL(ENull,EFalse))
1.1196 + test(r==KErrNone);
1.1197 + __UHEAP_CHECK(0);
1.1198 +*/
1.1199 + __UHEAP_MARKEND;
1.1200 +//
1.1201 + test.Next(_L("Test all LC functions"));
1.1202 + TRAP(r,createAllL(EFalse))
1.1203 + test(r==KErrNone);
1.1204 + __UHEAP_CHECK(KInitialCountAll);
1.1205 +//
1.1206 + delete pT;
1.1207 + __UHEAP_MARKEND;
1.1208 +//
1.1209 + test.End();
1.1210 + }
1.1211 +
1.1212 +LOCAL_C void testLeave()
1.1213 +//
1.1214 +// Test cleanup with leave exits
1.1215 +//
1.1216 + {
1.1217 +
1.1218 + test.Start(_L("Creating"));
1.1219 +//
1.1220 + __UHEAP_MARK;
1.1221 + CTrapCleanup* pT=CTrapCleanup::New();
1.1222 + test(pT!=NULL);
1.1223 + __UHEAP_CHECK(KInitialCountAll);
1.1224 +//
1.1225 + __UHEAP_MARK;
1.1226 +//
1.1227 + test.Next(_L("PushC PushO EPop cleanup empty and leave"));
1.1228 + TRAPD(r,createL(EPop,ETrue))
1.1229 + test(r==KLeaveValue);
1.1230 + __UHEAP_CHECK(2);
1.1231 + User::Free(gP1);
1.1232 + delete gP2;
1.1233 + __UHEAP_CHECK(0);
1.1234 +//
1.1235 + test.Next(_L("PushC PushO EPopAndDestroy cleanup empty and leave"));
1.1236 + TRAP(r,createL(EPopAndDestroy,ETrue))
1.1237 + test(r==KLeaveValue);
1.1238 + __UHEAP_CHECK(0);
1.1239 +//
1.1240 + test.Next(_L("PushC PushO ENull cleanup 2 objects and leave"));
1.1241 + TRAP(r,createL(ENull,ETrue))
1.1242 + test(r==KLeaveValue);
1.1243 + __UHEAP_CHECK(0);
1.1244 + __UHEAP_MARKEND;
1.1245 +//
1.1246 + test.Next(_L("Test all LC functions and leave"));
1.1247 + TRAP(r,createAllL(ETrue))
1.1248 + test(r==KLeaveValue);
1.1249 + __UHEAP_CHECK(KInitialCountAll);
1.1250 +//
1.1251 + delete pT;
1.1252 + __UHEAP_MARKEND;
1.1253 +//
1.1254 + test.End();
1.1255 + }
1.1256 +
1.1257 +LOCAL_C void testMultiLeave()
1.1258 +//
1.1259 +// Test cleanup with multiple leave exits
1.1260 +//
1.1261 + {
1.1262 +
1.1263 + test.Start(_L("Creating"));
1.1264 +//
1.1265 + __UHEAP_MARK;
1.1266 + CTrapCleanup* pT=CTrapCleanup::New();
1.1267 + test(pT!=NULL);
1.1268 +//
1.1269 + __UHEAP_MARK;
1.1270 +//
1.1271 + test.Next(_L("PushC PushO nest PushO cleanup leave leave"));
1.1272 + TRAPD(r,createL(EMulti,ETrue))
1.1273 + test(r==KLeaveValue);
1.1274 + __UHEAP_CHECK(0);
1.1275 + __UHEAP_MARKEND;
1.1276 +//
1.1277 + delete pT;
1.1278 + __UHEAP_MARKEND;
1.1279 +//
1.1280 + test.End();
1.1281 + }
1.1282 +
1.1283 +LOCAL_C void addNullItemL()
1.1284 + {
1.1285 + CleanupStack::PushL((TAny*)0);
1.1286 + }
1.1287 +
1.1288 +LOCAL_C void addCellL()
1.1289 + {
1.1290 + User::AllocLC(4);
1.1291 + }
1.1292 +
1.1293 +LOCAL_C void useCleanupStackL()
1.1294 + {
1.1295 + addNullItemL();
1.1296 + addCellL();
1.1297 + CleanupStack::PopAndDestroy();
1.1298 + CleanupStack::Pop();
1.1299 + }
1.1300 +
1.1301 +LOCAL_C void reentrantCleanup(TAny*)
1.1302 +//
1.1303 +// A cleanup operation which uses a trap harness and the cleanup stack
1.1304 +//
1.1305 + {
1.1306 + TRAPD(ignore,useCleanupStackL())
1.1307 + }
1.1308 +
1.1309 +LOCAL_C void addReentrantItemL()
1.1310 + {
1.1311 + CleanupStack::PushL(TCleanupItem(reentrantCleanup));
1.1312 + }
1.1313 +
1.1314 +LOCAL_C void addItemsL(TInt aCount)
1.1315 +//
1.1316 +// add number of reentrant items to make stack fail
1.1317 +//
1.1318 + {
1.1319 + while (--aCount>=0)
1.1320 + addReentrantItemL();
1.1321 +#if !defined(_DEBUG)
1.1322 + User::Leave(KErrNoMemory); // heap failure not available
1.1323 +#endif
1.1324 + }
1.1325 +
1.1326 +const TInt KInitialStackSize=8; // from UC_CLN.CPP
1.1327 +const TInt KGrowItems=KInitialStackSize-3;
1.1328 +
1.1329 +LOCAL_C void testReentrancyL()
1.1330 +//
1.1331 +// Test the Cleanup stack can go re-entrant
1.1332 +//
1.1333 + {
1.1334 +
1.1335 + test.Next(_L("PopAndDestroy()"));
1.1336 + __UHEAP_MARK;
1.1337 + addNullItemL();
1.1338 + addCellL();
1.1339 + addReentrantItemL();
1.1340 + CleanupStack::PopAndDestroy(2);
1.1341 + CleanupStack::Pop();
1.1342 + __UHEAP_MARKEND;
1.1343 +//
1.1344 + test.Next(_L("cleanup after a leave"));
1.1345 + addNullItemL();
1.1346 + TRAPD(r,addReentrantItemL();User::Leave(KLeaveValue);)
1.1347 + test(r==KLeaveValue);
1.1348 + CleanupStack::Pop();
1.1349 +//
1.1350 + test.Next(_L("cleanup after stack failure"));
1.1351 + // Ensuring stack reallocate fails by placing following cell
1.1352 + TInt* forceAlloc=(TInt*)User::AllocL(4);
1.1353 + for (TInt i=0;i<KGrowItems;++i)
1.1354 + addNullItemL();
1.1355 + __UHEAP_SETFAIL(RHeap::EDeterministic,1); // fail everything
1.1356 + TRAP(r,addItemsL(1);) // will leave as stack full and cannot grow
1.1357 + test(r==KErrNoMemory);
1.1358 + __UHEAP_RESET;
1.1359 + CleanupStack::Pop(KGrowItems);
1.1360 +//
1.1361 + test.Next(_L("multiple re-entrancy & stack failure"));
1.1362 + __UHEAP_SETFAIL(RHeap::EDeterministic,1); // fail everything
1.1363 + TRAP(r,addItemsL(KGrowItems+1););
1.1364 + test(r==KErrNoMemory);
1.1365 + __UHEAP_RESET;
1.1366 + User::Free(forceAlloc);
1.1367 + }
1.1368 +
1.1369 +LOCAL_C void testReentrancy()
1.1370 +//
1.1371 +// Test the Cleanup stack can go re-entrant
1.1372 +//
1.1373 + {
1.1374 +
1.1375 + test.Start(_L("Creating"));
1.1376 +//
1.1377 + __UHEAP_MARK;
1.1378 + CTrapCleanup* pT=CTrapCleanup::New();
1.1379 + test(pT!=NULL);
1.1380 +//
1.1381 + TRAPD(r,testReentrancyL());
1.1382 + test(r==KErrNone);
1.1383 +//
1.1384 + delete pT;
1.1385 + __UHEAP_MARKEND;
1.1386 +//
1.1387 + test.End();
1.1388 + }
1.1389 +
1.1390 +LOCAL_C void testAutoCloseL()
1.1391 +//
1.1392 +// A leaving function for testAutoClose()
1.1393 +//
1.1394 + {
1.1395 + test.Next(_L("Create a TAutoClose object"));
1.1396 + TAutoClose<RTimer> tim;
1.1397 + tim.iObj.CreateLocal();
1.1398 + test.Next(_L("Push it on the cleanup stack"));
1.1399 + tim.PushL();
1.1400 + test.Next(_L("Leave before object goes out of scope"));
1.1401 + User::Leave(KErrGeneral);
1.1402 + tim.Pop();
1.1403 + }
1.1404 +
1.1405 +LOCAL_C void testAutoClose()
1.1406 +//
1.1407 +// Test the TAutoClose class
1.1408 +//
1.1409 + {
1.1410 +
1.1411 + // Kill the granules
1.1412 + RTimer s[20];
1.1413 + TInt i;
1.1414 + for (i=0; i<20; i++)
1.1415 + s[i].CreateLocal();
1.1416 + for (i=0; i<20; i++)
1.1417 + s[i].Close();
1.1418 +
1.1419 + __KHEAP_MARK;
1.1420 + test.Start(_L("Make a TAutoClose object"));
1.1421 + {
1.1422 + TAutoClose<RTimer> tim;
1.1423 + tim.iObj.CreateLocal();
1.1424 +
1.1425 + test.Next(_L("Let it fall out of scope"));
1.1426 + }
1.1427 + test.Next(_L("Check the object has closed"));
1.1428 + __KHEAP_CHECK(0);
1.1429 +
1.1430 + TRAPD(r, testAutoCloseL());
1.1431 + test.Next(_L("Check object has been closed and cleaned up after leave"));
1.1432 + __KHEAP_MARKEND;
1.1433 + test.End();
1.1434 + }
1.1435 +
1.1436 +void CTest::ConstructL()
1.1437 +//
1.1438 +// Allocate a cell with CBase::new
1.1439 +//
1.1440 + {
1.1441 +
1.1442 + TLex* pL=new(ELeave) TLex;
1.1443 + CleanupStack::PushL(pL);
1.1444 + }
1.1445 +
1.1446 +void RItem::Cleanup(TAny* aPtr)
1.1447 +//
1.1448 +// Invoke the Close member on the RItem at aPtr
1.1449 +//
1.1450 + {
1.1451 +
1.1452 + ((RItem*)aPtr)->Close();
1.1453 + }
1.1454 +
1.1455 +LOCAL_C TInt getStackPointer()
1.1456 + {
1.1457 + static TUint8 there;
1.1458 + TUint8 here;
1.1459 + return &here-&there;
1.1460 + }
1.1461 +LOCAL_C void sheLeavesMeL(TBool sheLeavesMeNot)
1.1462 + {
1.1463 + if (!sheLeavesMeNot)
1.1464 + User::Leave(KErrBadName); // Montague
1.1465 + }
1.1466 +
1.1467 +// Variables for stack balance test need to be global or clever compiler optimisations
1.1468 +// Can interfere with stack balance calculations.
1.1469 +TInt StackBalanceLoopCounter;
1.1470 +TInt StackBalanceResult=KErrNone;
1.1471 +TInt StackBalanceBefore;
1.1472 +TInt StackBalanceAfter;
1.1473 +
1.1474 +// Split into two functions because x86gcc makes a local stack optimisation for the second
1.1475 +// loop which unbalances the stack frame of the first loop.
1.1476 +LOCAL_C TInt StackBalanceNotLeaving()
1.1477 + {
1.1478 + StackBalanceBefore=getStackPointer();
1.1479 + for (StackBalanceLoopCounter=0; StackBalanceLoopCounter<20;StackBalanceLoopCounter++)
1.1480 + {
1.1481 + TRAP(StackBalanceResult,sheLeavesMeL(ETrue));
1.1482 + }
1.1483 + StackBalanceAfter=getStackPointer();
1.1484 + return StackBalanceAfter-StackBalanceBefore;
1.1485 + }
1.1486 +LOCAL_C TInt StackBalanceLeaving()
1.1487 + {
1.1488 + StackBalanceBefore=getStackPointer();
1.1489 + for (StackBalanceLoopCounter=0; StackBalanceLoopCounter<20;StackBalanceLoopCounter++)
1.1490 + {
1.1491 + TRAP(StackBalanceResult,sheLeavesMeL(EFalse));
1.1492 + }
1.1493 + StackBalanceAfter=getStackPointer();
1.1494 + return StackBalanceAfter-StackBalanceBefore;
1.1495 + }
1.1496 +
1.1497 +LOCAL_C void testStackBalance()
1.1498 +//
1.1499 +// Ensure that we get the stack properly balanced
1.1500 +//
1.1501 + {
1.1502 + // Not leaving case
1.1503 + test.Start(_L("Stack balance without Leaving"));
1.1504 + TInt balance = StackBalanceNotLeaving();
1.1505 + test.Printf(_L("Stack balance: %d bytes\n"), balance);
1.1506 + test(balance == 0);
1.1507 +
1.1508 + // Leaving case
1.1509 + test.Next(_L("Stack balance after Leave"));
1.1510 + balance = StackBalanceLeaving();
1.1511 + test.Printf(_L("Stack balance: %d bytes\n"), balance);
1.1512 + test(balance == 0);
1.1513 + test.End();
1.1514 + }
1.1515 +
1.1516 +void Inc(TAny* aPtr)
1.1517 + {
1.1518 + ++(*(TInt*)aPtr);
1.1519 + }
1.1520 +
1.1521 +void testTrapIgnore()
1.1522 + {
1.1523 + test.Start(_L("Create cleanup"));
1.1524 + CCleanup* pC=CCleanup::New();
1.1525 + test(pC!=NULL);
1.1526 + TInt count = 0;
1.1527 +
1.1528 + test.Next(_L("TRAP_IGNORE with no leave"));
1.1529 + TRAP_IGNORE(
1.1530 + CleanupStack::PushL(TCleanupItem(Inc,&count));
1.1531 + CleanupStack::Pop();
1.1532 + );
1.1533 + test(count==0);
1.1534 +
1.1535 + test.Next(_L("TRAP_IGNORE with leave"));
1.1536 + TRAP_IGNORE(
1.1537 + CleanupStack::PushL(TCleanupItem(Inc,&count));
1.1538 + User::Leave(KErrGeneral);
1.1539 + );
1.1540 + test(count==1);
1.1541 +
1.1542 + delete pC;
1.1543 + test.End();
1.1544 + }
1.1545 +
1.1546 +GLDEF_C TInt E32Main()
1.1547 + {
1.1548 + test.Title();
1.1549 +
1.1550 + test.Start(_L("Test destructor causing stack reallocation"));
1.1551 + testDestructorStackReallocation();
1.1552 +
1.1553 + test.Next(_L("CCleanup single level tests just alloc cells"));
1.1554 + testSingleLevelCellsCleanup();
1.1555 +
1.1556 + test.Next(_L("CCleanup single level tests just objects"));
1.1557 + testSingleLevelObjCleanup();
1.1558 +
1.1559 + test.Next(_L("CCleanup single level tests just items"));
1.1560 + testSingleLevelItemCleanup();
1.1561 +
1.1562 + test.Next(_L("CCleanup single level tests mixed"));
1.1563 + testSingleLevelMixCleanup();
1.1564 +
1.1565 + test.Next(_L("CCleanup multi level tests just alloc cells"));
1.1566 + testMultiLevelCellsCleanup();
1.1567 +
1.1568 + test.Next(_L("CCleanup multi level tests just objects"));
1.1569 + testMultiLevelObjCleanup();
1.1570 +
1.1571 + test.Next(_L("CCleanup multi level tests just items"));
1.1572 + testMultiLevelItemCleanup();
1.1573 +
1.1574 + test.Next(_L("CCleanup multi level tests mixed"));
1.1575 + testMultiLevelMixCleanup();
1.1576 +
1.1577 + test.Next(_L("CCleanup special case test"));
1.1578 + testSpecialCaseCleanup();
1.1579 +
1.1580 + test.Next(_L("Install trap handler"));
1.1581 + CTrapCleanup* pT=CTrapCleanup::New();
1.1582 + test(pT!=NULL);
1.1583 +
1.1584 + test.Next(_L("Untrap handling tests"));
1.1585 + testUnTrap();
1.1586 +
1.1587 + test.Next(_L("Leave handling tests"));
1.1588 + testLeave();
1.1589 +
1.1590 + test.Next(_L("Multi level leave handling tests"));
1.1591 + testMultiLeave();
1.1592 +
1.1593 + test.Next(_L("Test TAutoClose"));
1.1594 + testAutoClose();
1.1595 +
1.1596 + test.Next(_L("Test Re-entrancy of cleanup stack"));
1.1597 + testReentrancy();
1.1598 +
1.1599 + test.Next(_L("Test stack safety of TRAP and Leave"));
1.1600 + testStackBalance();
1.1601 +
1.1602 + test.Next(_L("Test TRAP_IGNORE"));
1.1603 + testTrapIgnore();
1.1604 +
1.1605 + test.End();
1.1606 + return(0);
1.1607 + }
1.1608 +