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