sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\buffer\t_bma.cpp sl@0: // Overview: sl@0: // Test the bitmap allocation abilities of the CBitMapAllocator class. sl@0: // API Information: sl@0: // CBitMapAllocator. sl@0: // Details: sl@0: // - Create an instance of CBitMapAllocator class with positive size using New and NewL methods, sl@0: // verify that object is created and deleted successfully, test the heap allocation failure. sl@0: // - Verify that the heap has not been corrupted by the test. sl@0: // - Test Alloc, AllocFromTop, AllocAt, Free, and AllocFromTopFrom methods of sl@0: // CBitMapAllocator class are as expected. sl@0: // - Allocate all available memory using Alloc, AllocFromTop, AllocFromTopFrom sl@0: // and check that available free space is zero. sl@0: // - Allocate more than available memory using Alloc, AllocFromTop, sl@0: // AllocFromTopFrom and check the return value is KErrorNoMemory. sl@0: // - Free the memory and check that available free space is equal to the size. sl@0: // - Allocate at specified blocks, check the allocation and available free block sl@0: // is as expected. sl@0: // - Free the block and check the available space is as expected. sl@0: // - Check the alignment of blocks after allocation is as expected. sl@0: // - Perform all of the above tests for CBitMapAllocator size of 1, 4, 32, 33, 68, 96, 64, 65 and 63 bits. sl@0: // - Allocate some contiguous pages of RAM from the kernel's free page pool with pattern of sl@0: // increasingly large gaps and test that the pages are allocated as specified. sl@0: // - Check KErrorNoMemory is returned when extracting a page beyond the available space. sl@0: // - Perform a test specifically for defect EXT-5AMDKP, Alloc, Free and ExtractRamPages. Test for sl@0: // expected results. sl@0: // - Test whether the heap has been corrupted by any of the tests. sl@0: // Platforms/Drives/Compatibility: sl@0: // All sl@0: // Assumptions/Requirement/Pre-requisites: sl@0: // Failures and causes: sl@0: // Base Port information: sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: const TInt KMaxAllocations=50; sl@0: sl@0: LOCAL_D RTest test(_L("T_BMA")); sl@0: sl@0: LOCAL_C void testNew(TInt aSize) sl@0: // sl@0: // Test New sl@0: // sl@0: { sl@0: sl@0: test.Start(_L("New")); sl@0: __UHEAP_MARK; sl@0: CBitMapAllocator* pBitMapAllocator=CBitMapAllocator::New(aSize); sl@0: test(pBitMapAllocator!=NULL); sl@0: test(pBitMapAllocator->Size()==pBitMapAllocator->Avail()); sl@0: delete pBitMapAllocator; sl@0: __UHEAP_CHECK(0); sl@0: for (TInt i=1;iSize()==pBitMapAllocator->Avail()); sl@0: delete pBitMapAllocator; sl@0: __UHEAP_CHECK(0); sl@0: test.Next(_L("Repetitive NewL")); sl@0: for (TInt i=1;iAvail(); sl@0: TInt i=0; sl@0: for (;iAlloc(); sl@0: test(j==i); sl@0: } sl@0: test(pBitMapAllocator->Avail()==0); sl@0: // sl@0: test.Next(_L("Try to alloc more than available")); sl@0: i=pBitMapAllocator->Alloc(); sl@0: test(i==KErrNoMemory); sl@0: // sl@0: test.Next(_L("Free")); sl@0: for (i=0;iFree(i); sl@0: test(pBitMapAllocator->Avail()==pBitMapAllocator->Size()); sl@0: // sl@0: test.Next(_L("AllocFromTop")); sl@0: for (i=available-1;i>=0;i--) sl@0: { sl@0: TInt j=pBitMapAllocator->AllocFromTop(); sl@0: test(j==i); sl@0: } sl@0: test(pBitMapAllocator->Avail()==0); sl@0: // sl@0: test.Next(_L("Try to AllocFromTop more than available")); sl@0: i=pBitMapAllocator->AllocFromTop(); sl@0: test(i==KErrNoMemory); sl@0: // sl@0: test.Next(_L("Free (again)")); sl@0: for (i=0;iFree(i); sl@0: test(pBitMapAllocator->Avail()==pBitMapAllocator->Size()); sl@0: // sl@0: test.Next(_L("AllocAt")); sl@0: pBitMapAllocator->AllocAt(aSize-1); sl@0: test(pBitMapAllocator->Avail()==pBitMapAllocator->Size()-1); sl@0: // sl@0: // test.Next(_L("AllocAt an already allocated cell")); // this test should cause a Panic. sl@0: // pBitMapAllocator->AllocAt(aSize-1); sl@0: // test(pBitMapAllocator->Avail()==pBitMapAllocator->Size()-1); sl@0: // sl@0: test.Next(_L("Free (again)")); sl@0: pBitMapAllocator->Free(aSize-1); sl@0: test(pBitMapAllocator->Avail()==pBitMapAllocator->Size()); sl@0: // sl@0: test.Next(_L("AllocFromTopFrom")); sl@0: TInt x; sl@0: for (x=available-1;x>0;x--) sl@0: { sl@0: for (i=x;i>=0;i--) sl@0: { sl@0: TInt j=pBitMapAllocator->AllocFromTopFrom(x); sl@0: test(j==i); sl@0: test(!pBitMapAllocator->IsFree(j)); sl@0: } sl@0: test(pBitMapAllocator->Avail()==available-x-1); sl@0: sl@0: test.Next(_L("Try to AllocFromTopFrom more than available")); sl@0: i=pBitMapAllocator->AllocFromTopFrom(x); sl@0: test(i==KErrNoMemory); sl@0: // sl@0: TInt y; sl@0: for (y=0;y<=x;y++) sl@0: { sl@0: for (i=0;i<=x;i++) sl@0: { sl@0: if (pBitMapAllocator->Avail()<=available-x-1) sl@0: pBitMapAllocator->Free(y); sl@0: TInt j=pBitMapAllocator->AllocFromTopFrom(i); sl@0: if (iIsFree(j)); sl@0: } sl@0: } sl@0: } sl@0: sl@0: // sl@0: test.Next(_L("Free (again)")); sl@0: for (i=0;i<=x;i++) sl@0: pBitMapAllocator->Free(i); sl@0: test(pBitMapAllocator->Avail()==pBitMapAllocator->Size()); sl@0: } sl@0: // sl@0: for (x=available-1;x>0;x--) sl@0: { sl@0: for (i=x;i>=0;i--) sl@0: { sl@0: TInt j=pBitMapAllocator->AllocFromTopFrom(x); sl@0: test(j==i); sl@0: } sl@0: test(pBitMapAllocator->Avail()==available-x-1); sl@0: sl@0: test.Next(_L("Try to AllocFromTopFrom more than available")); sl@0: i=pBitMapAllocator->AllocFromTopFrom(x); sl@0: test(i==KErrNoMemory); sl@0: // sl@0: test.Next(_L("Free (again)")); sl@0: for (i=0;i<=x;i++) sl@0: pBitMapAllocator->Free(i); sl@0: test(pBitMapAllocator->Avail()==pBitMapAllocator->Size()); sl@0: } sl@0: test.End(); sl@0: delete pBitMapAllocator; sl@0: } sl@0: sl@0: LOCAL_C void testBlock(TInt aSize) sl@0: // sl@0: // Test Alloc(TInt, TInt&), AllocAligned, AllocAlignedBlock, AllocAt(TInt, TInt), sl@0: // IsFree(TInt, TInt), Free(TInt, TInt) sl@0: // sl@0: { sl@0: CBitMapAllocator* pB=CBitMapAllocator::New(aSize); sl@0: test(pB!=NULL); sl@0: test.Start(_L("AllocAt block, Free block, IsFree block")); sl@0: TInt available=pB->Avail(); sl@0: test(available==aSize); sl@0: TInt start, len; sl@0: for(start=0; startAllocAt(start,len); sl@0: test(pB->Avail()==available-len); sl@0: for(TInt i=0; i=start && iIsFree(i)) sl@0: test(0); sl@0: } sl@0: else sl@0: { sl@0: if(!pB->IsFree(i)) sl@0: test(0); sl@0: } sl@0: } sl@0: if (start) sl@0: test(pB->IsFree(0,start)); sl@0: test(!pB->IsFree(0,start+1)); sl@0: if (start+lenIsFree(start+len,available-(start+len))); sl@0: test(!pB->IsFree(start+len-1,available-(start+len-1))); sl@0: } sl@0: pB->Free(start,len); sl@0: test(pB->Avail()==available); sl@0: test(pB->IsFree(start,len)); sl@0: test(pB->IsFree(0,available)); sl@0: } sl@0: } sl@0: test.End(); sl@0: test.Start(_L("Alloc consecutive block")); sl@0: TInt askfor, init, pos, consec; sl@0: for(askfor=1; askfor<=available; askfor++) sl@0: { sl@0: test.Printf(_L("Ask for %d\n"),askfor); sl@0: for(init=0; initAllocAt(0,init); sl@0: for(pos=init+1; posAllocAt(pos); sl@0: TInt firstfree=pB->Alloc(askfor, consec); sl@0: if (firstfree!=init) sl@0: test(0); sl@0: TInt number=(pos-init>askfor)?askfor:pos-init; sl@0: if (consec!=number) sl@0: test(0); sl@0: if (numberAlloc(pos-init-number,consec); sl@0: if(firstfree!=init+number) sl@0: test(0); sl@0: if(consec!=pos-init-number) sl@0: test(0); sl@0: } sl@0: test(pB->Avail()==available-pos-1); sl@0: TInt freeto=available; sl@0: if (posAlloc(askfor,consec); sl@0: number=(available-pos-1>askfor)?askfor:available-pos-1; sl@0: if (firstfree!=pos+1) sl@0: test(0); sl@0: if (consec!=number) sl@0: test(0); sl@0: freeto=pos+1+number; sl@0: } sl@0: test(pB->Avail()==available-freeto); sl@0: if (available==freeto) sl@0: { sl@0: firstfree=pB->Alloc(1,consec); sl@0: if (firstfree!=KErrNoMemory) sl@0: test(0); sl@0: if (consec!=0) sl@0: test(0); sl@0: } sl@0: pB->Free(init,freeto-init); sl@0: } sl@0: if (init) sl@0: pB->Free(0,init); sl@0: test(pB->Avail()==available); sl@0: } sl@0: } sl@0: test.End(); sl@0: test.Start(_L("AllocAligned")); sl@0: TInt alignment, alignstep; sl@0: for(alignment=0, alignstep=1; alignstepAllocAligned(alignment); sl@0: if (r>=0) sl@0: { sl@0: if (r!=next) sl@0: test(0); sl@0: next+=alignstep; sl@0: } sl@0: else if (r!=KErrNoMemory) sl@0: test(0); sl@0: } while(r>=0); sl@0: if (pB->Avail()!=available-numaligned) sl@0: test(0); sl@0: for(TInt i=0; i>alignment)<IsFree(i)) sl@0: test(0); sl@0: pB->Free(i); sl@0: } sl@0: else sl@0: { sl@0: if (!pB->IsFree(i)) sl@0: test(0); sl@0: } sl@0: } sl@0: test(pB->Avail()==available); sl@0: } sl@0: test.End(); sl@0: test.Start(_L("AllocAlignedBlock")); sl@0: for(alignment=0, alignstep=1; alignstepAllocAlignedBlock(alignment); sl@0: if (r>=0) sl@0: { sl@0: if (r!=next) sl@0: test(0); sl@0: next+=alignstep; sl@0: } sl@0: else if (r!=KErrNoMemory) sl@0: test(0); sl@0: } while(r>=0); sl@0: if (pB->Avail()!=available-numalignedblocks*alignstep) sl@0: test(0); sl@0: if (pB->Avail()!=0) sl@0: { sl@0: if ( !pB->IsFree(numalignedblocks*alignstep,pB->Avail()) ) sl@0: test(0); sl@0: r=pB->Alloc(); sl@0: if (r!=numalignedblocks*alignstep) sl@0: test(0); sl@0: pB->Free(r); sl@0: } sl@0: pB->Free(0,numalignedblocks*alignstep); sl@0: if (pB->Avail()!=available) sl@0: test(0); sl@0: TInt freepos, blockpos, c; sl@0: for (freepos=0; freeposAllocAt(i); sl@0: c++; sl@0: } sl@0: if (pB->Avail()!=available-c) sl@0: test(0); sl@0: r=pB->AllocAlignedBlock(alignment); sl@0: if (available-freeposAvail()!=available-c) sl@0: test(0); sl@0: } sl@0: else sl@0: { sl@0: if (r!=freepos) sl@0: test(0); sl@0: if (pB->Avail()!=available-c-alignstep) sl@0: test(0); sl@0: pB->Free(freepos,alignstep); sl@0: if (pB->Avail()!=available-c) sl@0: test(0); sl@0: } sl@0: for(TInt j=blockpos; jFree(j); sl@0: if (pB->Avail()!=available) sl@0: test(0); sl@0: } sl@0: } sl@0: } sl@0: delete pB; sl@0: test.End(); sl@0: } sl@0: sl@0: LOCAL_C void testContiguousAllocation(TInt aSize) sl@0: {//test RemoveRamPages() sl@0: //set up bitmap with pattern of increasingly large gaps - sl@0: //page 1 - in use,page 2 - free sl@0: //pages 3,4 - in use,pages 5,6 - free sl@0: //pages 7,8,9 - in use,pages 10,11,12 - free ...etc sl@0: test.Start(_L("Create swiss cheese effect...")); sl@0: sl@0: CBitMapAllocator* pB=CBitMapAllocator::New(aSize); sl@0: test(pB!=NULL); sl@0: sl@0: TInt available=pB->Avail(); sl@0: test(available==aSize); sl@0: sl@0: TInt i=0; sl@0: TInt j=0; sl@0: TInt k=1; sl@0: while(k<46) sl@0: { sl@0: for(j=0;jAllocAt(i+j); sl@0: test(!pB->IsFree(i+j)); sl@0: } sl@0: i+=2*k; sl@0: k++; sl@0: } sl@0: sl@0: TInt ret=KErrNone; sl@0: TInt pageNo=0; sl@0: for(i=1;i<45;i++) sl@0: { sl@0: ret=pB->ExtractRamPages(i,pageNo); //look for a gap of size i pages and allocate it sl@0: test(pageNo==i*i); //test the right page no is returned sl@0: test.Printf(_L("OK -pageNo is :%d\r\n"),pageNo); sl@0: for(j=i*i;jIsFree(j)); sl@0: } sl@0: sl@0: ret=pB->ExtractRamPages(45,pageNo);//there's not a big enough space in the bitmap for this to succeed sl@0: test(ret==KErrNoMemory); sl@0: delete pB; sl@0: test.End(); sl@0: } sl@0: sl@0: LOCAL_C void testAll(TInt aSize) sl@0: // sl@0: // Test all BMA functions using a BMA of size aSize sl@0: // sl@0: { sl@0: sl@0: TBuf<0x40> b; sl@0: b.Format(_L("BitMapAllocator size = %d"),aSize); sl@0: test.Start(b); sl@0: // sl@0: testNew(aSize); sl@0: testNewL(aSize); sl@0: testAlloc(aSize); sl@0: testBlock(aSize); sl@0: // sl@0: test.End(); sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: // sl@0: // Test bitmap allocator sl@0: // sl@0: { sl@0: test.Title(); sl@0: __UHEAP_MARK; sl@0: // sl@0: test.Start(_L("1 bit")); sl@0: testAll(1); sl@0: sl@0: test.Next(_L("4 bit")); sl@0: testAll(4); sl@0: // sl@0: test.Next(_L("32 bit")); sl@0: testAll(32); sl@0: // sl@0: test.Next(_L("33 bit")); sl@0: testAll(33); sl@0: // sl@0: test.Next(_L("68 bit")); sl@0: testAll(68); sl@0: // sl@0: test.Next(_L("96 bit")); sl@0: testAll(96); sl@0: // sl@0: test.Next(_L("64 bit")); sl@0: testAll(64); sl@0: // sl@0: test.Next(_L("65 bit")); sl@0: testAll(65); sl@0: // sl@0: test.Next(_L("63 bit")); sl@0: testAll(63); sl@0: sl@0: testContiguousAllocation(2048); sl@0: sl@0: test.Next(_L("test defect EXT-5AMDKP")); sl@0: sl@0: CBitMapAllocator* pB = CBitMapAllocator::New(64); sl@0: test(pB != NULL); sl@0: pB->AllocAt(0, 32); sl@0: pB->Free(2, 2); sl@0: pB->Free(5, 2); sl@0: pB->Free(8, 2); sl@0: pB->Free(12, 3); sl@0: pB->Free(30, 2); sl@0: TInt page = -1; sl@0: pB->ExtractRamPages(3, page); sl@0: test(page == 12); sl@0: pB->ExtractRamPages(4, page); sl@0: test(page == 30); sl@0: pB->ExtractRamPages(1, page); sl@0: test(page == 2); sl@0: pB->ExtractRamPages(5, page); sl@0: test(page == 34); sl@0: pB->ExtractRamPages(2, page); sl@0: test(page == 5); sl@0: delete pB; sl@0: sl@0: __UHEAP_MARKEND; sl@0: test.End(); sl@0: return(KErrNone); sl@0: } sl@0: