os/kernelhwsrv/kerneltest/e32test/buffer/t_bma.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
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".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\buffer\t_bma.cpp
    15 // Overview:
    16 // Test the bitmap allocation abilities of the CBitMapAllocator class.
    17 // API Information:
    18 // CBitMapAllocator.
    19 // Details:
    20 // - Create an instance of CBitMapAllocator class with positive size using New and NewL methods, 
    21 // verify that object is created and deleted successfully, test the heap allocation failure. 
    22 // - Verify that the heap has not been corrupted by the test.
    23 // - Test Alloc, AllocFromTop, AllocAt, Free, and AllocFromTopFrom methods of 
    24 // CBitMapAllocator class are as expected.
    25 // - Allocate all available memory using Alloc, AllocFromTop, AllocFromTopFrom
    26 // and check that available free space is zero.
    27 // - Allocate more than available memory using Alloc, AllocFromTop,
    28 // AllocFromTopFrom and check the return value is KErrorNoMemory.
    29 // - Free the memory and check that available free space is equal to the size.
    30 // - Allocate at specified blocks, check the allocation and available free block 
    31 // is as expected.
    32 // - Free the block and check the available space is as expected. 
    33 // - Check the alignment of blocks after allocation is as expected.
    34 // - Perform all of the above tests for CBitMapAllocator size of 1, 4, 32, 33, 68, 96, 64, 65 and 63 bits.
    35 // - Allocate some contiguous pages of RAM from the kernel's free page pool with pattern of 
    36 // increasingly large gaps and test that the pages are allocated as specified.
    37 // - Check KErrorNoMemory is returned when extracting a page beyond the available space.
    38 // - Perform a test specifically for defect EXT-5AMDKP, Alloc, Free and ExtractRamPages. Test for 
    39 // expected results.
    40 // - Test whether the heap has been corrupted by any of the tests.
    41 // Platforms/Drives/Compatibility:
    42 // All 
    43 // Assumptions/Requirement/Pre-requisites:
    44 // Failures and causes:
    45 // Base Port information:
    46 // 
    47 //
    48 
    49 #include <e32test.h>
    50 #include <e32base.h>
    51 #include <e32base_private.h>
    52 #include <e32def.h>
    53 #include <e32def_private.h>
    54 
    55 const TInt KMaxAllocations=50;
    56 
    57 LOCAL_D RTest test(_L("T_BMA"));
    58 
    59 LOCAL_C void testNew(TInt aSize)
    60 //
    61 //	Test New
    62 //
    63 	{
    64 
    65 	test.Start(_L("New"));
    66 	__UHEAP_MARK;
    67 	CBitMapAllocator* pBitMapAllocator=CBitMapAllocator::New(aSize);
    68 	test(pBitMapAllocator!=NULL);
    69 	test(pBitMapAllocator->Size()==pBitMapAllocator->Avail());
    70 	delete pBitMapAllocator;
    71 	__UHEAP_CHECK(0);
    72 	for (TInt i=1;i<KMaxAllocations;i++)
    73 		{
    74 		test.Printf(_L("Try %d\n"),i);
    75 		__UHEAP_SETFAIL(RHeap::EDeterministic,i);
    76 		pBitMapAllocator=CBitMapAllocator::New(aSize);
    77 		if (pBitMapAllocator!=NULL)
    78 			break;
    79 		__UHEAP_CHECK(0);
    80 		}
    81 	delete pBitMapAllocator;
    82 	__UHEAP_MARKEND;
    83 	__UHEAP_RESET;
    84 	test.End();
    85 	}
    86 
    87 LOCAL_C void testNewL(TInt aSize)
    88 //
    89 //	Test NewL
    90 //
    91 	{
    92 
    93 	test.Start(_L("NewL"));
    94 	__UHEAP_MARK;
    95 	CBitMapAllocator* pBitMapAllocator=CBitMapAllocator::NewL(aSize);
    96 	test(pBitMapAllocator!=NULL);
    97 	test(pBitMapAllocator->Size()==pBitMapAllocator->Avail());
    98 	delete pBitMapAllocator;
    99 	__UHEAP_CHECK(0);
   100 	test.Next(_L("Repetitive NewL"));
   101 	for (TInt i=1;i<KMaxAllocations;i++)
   102 		{
   103 		test.Printf(_L("Try %d\n"),i);
   104 		__UHEAP_SETFAIL(RHeap::EDeterministic,i);
   105 		TRAPD(r,pBitMapAllocator=CBitMapAllocator::NewL(aSize));
   106 		if (r==KErrNone)
   107 			break;
   108 		__UHEAP_CHECK(0);
   109 		}
   110 	delete pBitMapAllocator;
   111 	__UHEAP_MARKEND;
   112 	__UHEAP_RESET;
   113   	test.End();	
   114 	}
   115 
   116 LOCAL_C void testAlloc(TInt aSize)
   117 //
   118 //	Test Alloc, AllocFromTop, AllocAt, and Free, and AllocFromTopFrom
   119 //
   120 	{
   121 
   122 	CBitMapAllocator* pBitMapAllocator=CBitMapAllocator::New(aSize);
   123 	test(pBitMapAllocator!=NULL);
   124 	test.Start(_L("Alloc all available"));
   125 	TInt available=pBitMapAllocator->Avail();
   126 	TInt i=0;
   127 	for (;i<available;i++)
   128 		{
   129 		TInt j=pBitMapAllocator->Alloc();
   130 		test(j==i);
   131 		}
   132 	test(pBitMapAllocator->Avail()==0);
   133 //
   134 	test.Next(_L("Try to alloc more than available"));
   135 	i=pBitMapAllocator->Alloc();
   136 	test(i==KErrNoMemory);
   137 //
   138 	test.Next(_L("Free"));
   139 	for (i=0;i<available;i++)
   140 		pBitMapAllocator->Free(i);
   141 	test(pBitMapAllocator->Avail()==pBitMapAllocator->Size());
   142 //
   143 	test.Next(_L("AllocFromTop"));	
   144 	for (i=available-1;i>=0;i--)
   145 		{
   146 		TInt j=pBitMapAllocator->AllocFromTop();
   147 		test(j==i);
   148 		}
   149 	test(pBitMapAllocator->Avail()==0);
   150 //
   151 	test.Next(_L("Try to AllocFromTop more than available"));
   152 	i=pBitMapAllocator->AllocFromTop();
   153 	test(i==KErrNoMemory);
   154 //
   155 	test.Next(_L("Free (again)"));
   156 	for (i=0;i<available;i++)
   157 		pBitMapAllocator->Free(i);
   158 	test(pBitMapAllocator->Avail()==pBitMapAllocator->Size());
   159 //
   160 	test.Next(_L("AllocAt"));
   161 	pBitMapAllocator->AllocAt(aSize-1);
   162 	test(pBitMapAllocator->Avail()==pBitMapAllocator->Size()-1);
   163 //
   164 //	test.Next(_L("AllocAt an already allocated cell"));	// this test should cause a Panic.
   165 //	pBitMapAllocator->AllocAt(aSize-1);
   166 //	test(pBitMapAllocator->Avail()==pBitMapAllocator->Size()-1);
   167 //
   168 	test.Next(_L("Free (again)"));
   169 	pBitMapAllocator->Free(aSize-1);
   170 	test(pBitMapAllocator->Avail()==pBitMapAllocator->Size());
   171 //
   172 	test.Next(_L("AllocFromTopFrom"));
   173 	TInt x;
   174 	for (x=available-1;x>0;x--)
   175 		{
   176 		for (i=x;i>=0;i--)
   177 			{
   178 			TInt j=pBitMapAllocator->AllocFromTopFrom(x);
   179 			test(j==i);
   180 			test(!pBitMapAllocator->IsFree(j));
   181 			}
   182 		test(pBitMapAllocator->Avail()==available-x-1);
   183 
   184 		test.Next(_L("Try to AllocFromTopFrom more than available"));
   185 		i=pBitMapAllocator->AllocFromTopFrom(x);
   186 		test(i==KErrNoMemory);
   187 //
   188 		TInt y;
   189 		for (y=0;y<=x;y++)
   190 			{
   191 			for (i=0;i<=x;i++)
   192 				{
   193 				if (pBitMapAllocator->Avail()<=available-x-1)
   194 					pBitMapAllocator->Free(y);
   195 				TInt j=pBitMapAllocator->AllocFromTopFrom(i);
   196 				if (i<y)
   197 					test(j==KErrNoMemory);
   198 				else
   199 					{
   200 					test(j==y);
   201 					test(!pBitMapAllocator->IsFree(j));
   202 					}
   203 				}
   204 			}
   205 	
   206 //
   207 		test.Next(_L("Free (again)"));
   208 		for (i=0;i<=x;i++)
   209 			pBitMapAllocator->Free(i);
   210 		test(pBitMapAllocator->Avail()==pBitMapAllocator->Size());
   211 		}
   212 //
   213 	for (x=available-1;x>0;x--)
   214 		{
   215 		for (i=x;i>=0;i--)
   216 			{
   217 			TInt j=pBitMapAllocator->AllocFromTopFrom(x);
   218 			test(j==i);
   219 			}
   220 		test(pBitMapAllocator->Avail()==available-x-1);
   221 
   222 		test.Next(_L("Try to AllocFromTopFrom more than available"));
   223 		i=pBitMapAllocator->AllocFromTopFrom(x);
   224 		test(i==KErrNoMemory);
   225 	//
   226 		test.Next(_L("Free (again)"));
   227 		for (i=0;i<=x;i++)
   228 			pBitMapAllocator->Free(i);
   229 		test(pBitMapAllocator->Avail()==pBitMapAllocator->Size());
   230 		}
   231 	test.End();
   232 	delete pBitMapAllocator;
   233 	}
   234 
   235 LOCAL_C void testBlock(TInt aSize)
   236 //
   237 // Test Alloc(TInt, TInt&), AllocAligned, AllocAlignedBlock, AllocAt(TInt, TInt),
   238 // IsFree(TInt, TInt), Free(TInt, TInt)
   239 //
   240 	{
   241 	CBitMapAllocator* pB=CBitMapAllocator::New(aSize);
   242 	test(pB!=NULL);
   243 	test.Start(_L("AllocAt block, Free block, IsFree block"));
   244 	TInt available=pB->Avail();
   245 	test(available==aSize);
   246 	TInt start, len;
   247 	for(start=0; start<available; start++)
   248 		{
   249 		for(len=1; len<=available-start; len++)
   250 			{
   251 			pB->AllocAt(start,len);
   252 			test(pB->Avail()==available-len);
   253 			for(TInt i=0; i<available; i++)
   254 				{
   255 				if (i>=start && i<start+len)
   256 					{
   257 					if(pB->IsFree(i))
   258 						test(0);
   259 					}
   260 				else
   261 					{
   262 					if(!pB->IsFree(i))
   263 						test(0);
   264 					}
   265 				}
   266 			if (start)
   267 				test(pB->IsFree(0,start));
   268 			test(!pB->IsFree(0,start+1));
   269 			if (start+len<available)
   270 				{
   271 				test(pB->IsFree(start+len,available-(start+len)));
   272 				test(!pB->IsFree(start+len-1,available-(start+len-1)));
   273 				}
   274 			pB->Free(start,len);
   275 			test(pB->Avail()==available);
   276 			test(pB->IsFree(start,len));
   277 			test(pB->IsFree(0,available));
   278 			}
   279 		}
   280 	test.End();
   281 	test.Start(_L("Alloc consecutive block"));
   282 	TInt askfor, init, pos, consec;
   283 	for(askfor=1; askfor<=available; askfor++)
   284 		{
   285 		test.Printf(_L("Ask for %d\n"),askfor);
   286 		for(init=0; init<available; init++)
   287 			{
   288 			if (init)
   289 				pB->AllocAt(0,init);
   290 			for(pos=init+1; pos<available; pos++)
   291 				{
   292 				pB->AllocAt(pos);
   293 				TInt firstfree=pB->Alloc(askfor, consec);
   294 				if (firstfree!=init)
   295 					test(0);
   296 				TInt number=(pos-init>askfor)?askfor:pos-init;
   297 				if (consec!=number)
   298 					test(0);
   299 				if (number<pos-init)
   300 					{
   301 					firstfree=pB->Alloc(pos-init-number,consec);
   302 					if(firstfree!=init+number)
   303 						test(0);
   304 					if(consec!=pos-init-number)
   305 						test(0);
   306 					}
   307 				test(pB->Avail()==available-pos-1);
   308 				TInt freeto=available;
   309 				if (pos<available-1)
   310 					{
   311 					firstfree=pB->Alloc(askfor,consec);
   312 					number=(available-pos-1>askfor)?askfor:available-pos-1;
   313 					if (firstfree!=pos+1)
   314 						test(0);
   315 					if (consec!=number)
   316 						test(0);
   317 					freeto=pos+1+number;
   318 					}
   319 				test(pB->Avail()==available-freeto);
   320 				if (available==freeto)
   321 					{
   322 					firstfree=pB->Alloc(1,consec);
   323 					if (firstfree!=KErrNoMemory)
   324 						test(0);
   325 					if (consec!=0)
   326 						test(0);
   327 					}
   328 				pB->Free(init,freeto-init);
   329 				}
   330 			if (init)
   331 				pB->Free(0,init);
   332 			test(pB->Avail()==available);
   333 			}
   334 		}
   335 	test.End();
   336 	test.Start(_L("AllocAligned"));
   337 	TInt alignment, alignstep;
   338 	for(alignment=0, alignstep=1; alignstep<available; alignment++, alignstep<<=1 )
   339 		{
   340 		TInt numaligned=(available+alignstep-1)/alignstep;
   341 		TInt next=0;
   342 		TInt r;
   343 		do	{
   344 			r=pB->AllocAligned(alignment);
   345 			if (r>=0)
   346 				{
   347 				if (r!=next)
   348 					test(0);
   349 				next+=alignstep;
   350 				}
   351 			else if (r!=KErrNoMemory)
   352 				test(0);
   353 			} while(r>=0);
   354 		if (pB->Avail()!=available-numaligned)
   355 			test(0);
   356 		for(TInt i=0; i<available; i++)
   357 			{
   358 			if (i==((i>>alignment)<<alignment) )
   359 				{
   360 				if (pB->IsFree(i))
   361 					test(0);
   362 				pB->Free(i);
   363 				}
   364 			else
   365 				{
   366 				if (!pB->IsFree(i))
   367 					test(0);
   368 				}
   369 			}
   370 		test(pB->Avail()==available);
   371 		}
   372 	test.End();
   373 	test.Start(_L("AllocAlignedBlock"));
   374 	for(alignment=0, alignstep=1; alignstep<available; alignment++, alignstep<<=1 )
   375 		{
   376 		TInt numalignedblocks=available/alignstep;
   377 		TInt next=0;
   378 		TInt r;
   379 		do	{
   380 			r=pB->AllocAlignedBlock(alignment);
   381 			if (r>=0)
   382 				{
   383 				if (r!=next)
   384 					test(0);
   385 				next+=alignstep;
   386 				}
   387 			else if (r!=KErrNoMemory)
   388 				test(0);
   389 			} while(r>=0);
   390 		if (pB->Avail()!=available-numalignedblocks*alignstep)
   391 			test(0);
   392 		if (pB->Avail()!=0)
   393 			{
   394 			if ( !pB->IsFree(numalignedblocks*alignstep,pB->Avail()) )
   395 				test(0);
   396 			r=pB->Alloc();
   397 			if (r!=numalignedblocks*alignstep)
   398 				test(0);
   399 			pB->Free(r);
   400 			}
   401 		pB->Free(0,numalignedblocks*alignstep);
   402 		if (pB->Avail()!=available)
   403 			test(0);
   404 		TInt freepos, blockpos, c;
   405 		for (freepos=0; freepos<available; freepos+=alignstep)
   406 			{
   407 			for (blockpos=0; blockpos<alignstep; blockpos++)
   408 				{
   409 				c=0;
   410 				for(TInt i=blockpos; i<freepos; i+=alignstep)
   411 					{
   412 					pB->AllocAt(i);
   413 					c++;
   414 					}
   415 				if (pB->Avail()!=available-c)
   416 					test(0);
   417 				r=pB->AllocAlignedBlock(alignment);
   418 				if (available-freepos<alignstep)
   419 					{
   420 					if (r!=KErrNoMemory)
   421 						test(0);
   422 					if (pB->Avail()!=available-c)
   423 						test(0);
   424 					}
   425 				else
   426 					{
   427 					if (r!=freepos)
   428 						test(0);
   429 					if (pB->Avail()!=available-c-alignstep)
   430 						test(0);
   431 					pB->Free(freepos,alignstep);
   432 					if (pB->Avail()!=available-c)
   433 						test(0);
   434 					}
   435 				for(TInt j=blockpos; j<freepos; j+=alignstep)
   436 					pB->Free(j);
   437 				if (pB->Avail()!=available)
   438 					test(0);
   439 				}
   440 			}
   441 		}
   442 	delete pB;
   443 	test.End();
   444 	}
   445 
   446 LOCAL_C void testContiguousAllocation(TInt aSize)
   447 	{//test RemoveRamPages()
   448 	//set up bitmap with pattern of increasingly large gaps -
   449 	//page 1      - in use,page  2        - free
   450 	//pages 3,4   - in use,pages 5,6      - free
   451 	//pages 7,8,9 - in use,pages 10,11,12 - free  ...etc
   452 	test.Start(_L("Create swiss cheese effect..."));
   453 
   454  	CBitMapAllocator* pB=CBitMapAllocator::New(aSize);
   455 	test(pB!=NULL);
   456 
   457 	TInt available=pB->Avail();
   458 	test(available==aSize);
   459 
   460 	TInt i=0;
   461 	TInt j=0;
   462 	TInt k=1;
   463 	while(k<46)
   464 		{
   465 		for(j=0;j<k;j++)
   466 			{
   467 			pB->AllocAt(i+j);
   468 			test(!pB->IsFree(i+j));
   469 			}
   470 		i+=2*k;
   471 		k++;
   472 		}
   473 
   474 	TInt ret=KErrNone;
   475 	TInt pageNo=0;
   476 	for(i=1;i<45;i++)
   477 		{
   478 		ret=pB->ExtractRamPages(i,pageNo);	//look for a gap of size i pages and allocate it
   479 		test(pageNo==i*i);				//test the right page no is returned
   480 		test.Printf(_L("OK  -pageNo is :%d\r\n"),pageNo);
   481 		for(j=i*i;j<i*i + i;j++)		//test that the pages are actually allocated
   482 			test(!pB->IsFree(j));
   483 		}
   484 
   485 	ret=pB->ExtractRamPages(45,pageNo);//there's not a big enough space in the bitmap for this to succeed
   486 	test(ret==KErrNoMemory);
   487 	delete pB;
   488 	test.End();
   489 	}
   490 
   491 LOCAL_C void testAll(TInt aSize)
   492 //
   493 //	Test all BMA functions using a BMA of size aSize
   494 //
   495 	{
   496 
   497 	TBuf<0x40> b;
   498 	b.Format(_L("BitMapAllocator size = %d"),aSize);
   499 	test.Start(b);
   500 //
   501 	testNew(aSize);
   502 	testNewL(aSize);
   503 	testAlloc(aSize);
   504 	testBlock(aSize);
   505 //
   506 	test.End();
   507 	}
   508 
   509 GLDEF_C TInt E32Main()
   510 //
   511 // Test bitmap allocator
   512 //
   513 	{
   514 	test.Title();
   515 	__UHEAP_MARK;
   516 //
   517 	test.Start(_L("1 bit"));
   518 	testAll(1);
   519 
   520 	test.Next(_L("4 bit"));
   521 	testAll(4);
   522 //
   523 	test.Next(_L("32 bit"));
   524 	testAll(32);
   525 //
   526 	test.Next(_L("33 bit"));
   527 	testAll(33);
   528 //
   529 	test.Next(_L("68 bit"));
   530 	testAll(68);
   531 //
   532 	test.Next(_L("96 bit"));
   533 	testAll(96);
   534 //
   535 	test.Next(_L("64 bit"));
   536 	testAll(64);
   537 //
   538 	test.Next(_L("65 bit"));
   539 	testAll(65);
   540 //
   541 	test.Next(_L("63 bit"));
   542 	testAll(63);
   543 
   544 	testContiguousAllocation(2048);
   545 
   546 	test.Next(_L("test defect EXT-5AMDKP"));
   547 
   548 	CBitMapAllocator* pB = CBitMapAllocator::New(64);
   549 	test(pB != NULL);
   550 	pB->AllocAt(0, 32);
   551 	pB->Free(2, 2);
   552 	pB->Free(5, 2);
   553 	pB->Free(8, 2);
   554 	pB->Free(12, 3);
   555 	pB->Free(30, 2);
   556 	TInt page = -1;
   557 	pB->ExtractRamPages(3, page);
   558 	test(page == 12);
   559 	pB->ExtractRamPages(4, page);
   560 	test(page == 30);
   561 	pB->ExtractRamPages(1, page);
   562 	test(page == 2);
   563 	pB->ExtractRamPages(5, page);
   564 	test(page == 34);
   565 	pB->ExtractRamPages(2, page);
   566 	test(page == 5);
   567 	delete pB;	
   568 		
   569 	__UHEAP_MARKEND;
   570 	test.End();
   571 	return(KErrNone);
   572 	}
   573