os/kernelhwsrv/kerneltest/e32test/heap/t_heapdb.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\heap\t_heapdb.cpp
    15 // Tests the _DEBUG build dependent aspects of RHeap
    16 // Overview:
    17 // Tests debug build dependent aspects of RHeap.  
    18 // API Information:
    19 // RHeap.
    20 // Details:
    21 // Test1:
    22 // - Allocate a variety of user heap objects and verify the nesting level, allocation count, 
    23 // allocation level and length are correct. Also check for heap corruption.
    24 // Test 2:
    25 // - Some assorted indirect calls to alloc, and verify the nesting level, allocation count, 
    26 // allocation level and length are correct. Also check for heap corruption.
    27 // Test3:
    28 // - Allocate a variety of objects and verify that the UHEAP_CHECKALL count is correct.
    29 // - Verify the nesting of UHEAP_MARK and UHEAP_MARKEND macros.
    30 // - Check the validity of the current thread's default heap.
    31 // Test4:
    32 // - Allocate memory for different heaps, check the total number of allocated cells
    33 // for different heaps and for the current nested level is as expected.
    34 // Test5:
    35 // - Simulate heap allocation failures, allocate the memory from user and 
    36 // kernel heap and check results are as expected.
    37 // Platforms/Drives/Compatibility:
    38 // All
    39 // Assumptions/Requirement/Pre-requisites:
    40 // Failures and causes:
    41 // Base Port information:
    42 // 
    43 //
    44 
    45 #include <e32test.h>
    46 #include <e32def.h>
    47 #include <e32def_private.h>
    48 
    49 LOCAL_D RTest test(_L("T_HEAPDB"));
    50 
    51 #if defined(_DEBUG)
    52 
    53 RHeap::SHeapCellInfo CellInfo[4];
    54 
    55 class RTestHeap : public RHeap
    56 	{
    57 public:
    58 	void AttachInfo(SHeapCellInfo* aInfo)
    59 		{iTestData = aInfo;}
    60 	};
    61 
    62 void AttachToHeap(RHeap* aHeap, TInt aInfo)
    63 	{
    64 	if (!aHeap)
    65 		aHeap = (RHeap*)&User::Allocator();
    66 	((RTestHeap*)aHeap)->AttachInfo(CellInfo + aInfo);
    67 	}
    68 
    69 void TestCellInfo(TInt aInfo, TInt aNest, TInt aAllocCount, TInt aLevelAlloc, TInt aSize, TAny* aAddr)
    70 	{
    71 	RHeap::SHeapCellInfo& ci = CellInfo[aInfo];
    72 	RHeap::SDebugCell& cell = *ci.iStranded;
    73 	test(cell.nestingLevel == aNest);
    74 	test(cell.allocCount == aAllocCount);
    75 	test(ci.iLevelAlloc == aLevelAlloc);
    76 	test(cell.len == aSize + RHeap::EAllocCellSize);
    77 	test((&cell+1) == aAddr);
    78 	}
    79 
    80 const TInt KMaxFailureRate=100;
    81 const TInt KThreadMemError=-50;
    82 const TInt KCellSize=(sizeof(RHeap::SCell)); // Size of free cell header	
    83 const TInt KHeadSize=(sizeof(RHeap::SDebugCell)); // Size of allocated cell header with space for heaven info
    84 
    85 LOCAL_D TInt heapCount=1;
    86 LOCAL_D RSemaphore threadSemaphore;
    87 LOCAL_D TBool array1[KMaxFailureRate+1];
    88 LOCAL_D	TBool array2[KMaxFailureRate+1];
    89 
    90 LOCAL_C TInt ThreadEntryPoint(TAny*)
    91 	{
    92 	threadSemaphore.Wait();
    93 	if (User::Alloc(4)==NULL)
    94 		return(KThreadMemError);
    95 	else
    96 		return(KErrNone);
    97 	} 
    98 
    99 class TestRHeapDebug
   100 	{
   101 public:
   102 	void Test1(void);
   103 	void Test2(void);
   104 	void Test3(void);
   105 	void Test4(void);
   106 	void Test5(void);
   107 	};
   108 
   109 LOCAL_C RHeap* allocHeap(TInt aSize)
   110 //
   111 // Allocate a chunk heap with max size aSize
   112 //
   113 	{
   114 
   115 	TName n;
   116 	n.Format(_L("TESTHEAP%d"),heapCount++);
   117 	return(User::ChunkHeap(&n,aSize,aSize));
   118 	}
   119 
   120 void TestRHeapDebug::Test1(void)
   121 	{
   122 
   123 	TAny* p;
   124 
   125 	///////////////////////
   126 	// Test heaven cell is found for each method of allocating memory
   127 	////////////////////////
   128 
   129 	// new(TInt aSize)
   130 	__UHEAP_MARK;
   131 	__UHEAP_CHECKALL(0);
   132 	__UHEAP_CHECK(0);
   133 	p=new TUint; 
   134 	__UHEAP_CHECKALL(1);
   135 	__UHEAP_CHECK(1);
   136 	__UHEAP_MARKEND;
   137 	__UHEAP_CHECK(0);
   138 	__UHEAP_CHECKALL(1);
   139 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
   140 	User::Free(p);
   141 
   142 	// new(TInt aSize,TInt anExtraSize)
   143 	__UHEAP_MARK;
   144 	p=new(4) TUint; 
   145 	__UHEAP_MARKEND;
   146 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
   147 	User::Free(p);
   148 
   149 	// 	new(TInt aSize,TLeave)
   150 	__UHEAP_MARK;
   151 	p=new(ELeave) TUint; 
   152 	__UHEAP_MARKEND;
   153 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
   154 	User::Free(p);
   155 
   156 	// Alloc
   157 	__UHEAP_MARK;
   158 	p=User::Alloc(32); 
   159 	__UHEAP_MARKEND;
   160 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
   161 	User::Free(p);
   162 
   163 	// AllocL
   164 	__UHEAP_MARK;
   165 	p=User::AllocL(32);
   166 	__UHEAP_MARKEND;
   167 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
   168 	User::Free(p);
   169 
   170 	// ReAlloc with Null parameter
   171 	__UHEAP_MARK;
   172 	p=User::ReAlloc(NULL, 32); 
   173 	__UHEAP_MARKEND;
   174 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
   175 	User::Free(p);
   176 
   177 	// ReAllocL with Null parameter
   178 	__UHEAP_MARK;
   179 	p=User::ReAllocL(NULL, 32); 
   180 	__UHEAP_MARKEND;
   181 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
   182 	User::Free(p);
   183 
   184 	// ReAlloc with non Null parameter
   185 	__UHEAP_MARK;
   186 	p=User::Alloc(128);	   
   187 	p=User::ReAlloc(p, 4); 
   188 	__UHEAP_MARKEND;
   189 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
   190 	User::Free(p);
   191 					
   192 	// ReAlloc with non Null parameter such that cell is moved in memory
   193 	__UHEAP_MARK;
   194 	p=User::Alloc(128);	   
   195 	TAny* temp=User::Alloc(128);
   196 	p=User::ReAlloc(p, 526);   
   197 	User::Free(temp);
   198 	__UHEAP_MARKEND;
   199 	TestCellInfo(0, 1, 3, 1, User::AllocLen(p), p);
   200 	User::Free(p);
   201 
   202 	// ReAllocL with non Null parameter
   203 	__UHEAP_MARK;
   204 	p=User::Alloc(32);	   
   205 	p=User::ReAllocL(p, 128); 
   206 	__UHEAP_MARKEND;
   207 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
   208 	User::Free(p);
   209 	}
   210 
   211 
   212 void TestRHeapDebug::Test2(void)
   213 	{ 
   214 	// Some assorted indirect calls to alloc
   215 
   216 	__UHEAP_MARK;
   217 	CBufFlat* pBuf=CBufFlat::NewL(10); 
   218 	__UHEAP_MARKEND;
   219 	TestCellInfo(0, 1, 1, 1, User::AllocLen(pBuf), pBuf);
   220 	delete pBuf;
   221 
   222 	__UHEAP_MARK;
   223 	HBufC8* pHBufC=HBufC8::New(10);	
   224 	__UHEAP_MARKEND;
   225 	TestCellInfo(0, 1, 1, 1, User::AllocLen(pHBufC), pHBufC);
   226 	delete pHBufC;
   227 
   228 // can also create a HBufC8 from a descriptor by using TDesC::Alloc
   229 	}
   230 
   231 
   232 void TestRHeapDebug::Test3(void)
   233 	{ 
   234 
   235 	//  Check num of cells detected is correct and CHECKTOTALNUM is ok
   236 	// NOTE: CHECKTOTALNUM counts the TOTAL number of allocations in the heap regardless of
   237 	// any MARKSTARTs
   238 	// NOTE: the alloc count commences from the FIRST occurrence of a MARKSTART, so if one is nested
   239 	// in another the alloc count will only start from the second MARKSTART if it applies to a 
   240 	// different heap.
   241 	__UHEAP_MARK;
   242 	__UHEAP_CHECKALL(0);
   243 	TAny* p1= new TUint; 
   244 	__UHEAP_CHECKALL(1);
   245 	TAny* p2= new(20) TUint;
   246 	__UHEAP_CHECKALL(2);
   247 	TAny* p3= User::Alloc(15); 
   248 	__UHEAP_CHECKALL(3);
   249 	__UHEAP_MARK;
   250 	__UHEAP_CHECK(0);
   251 	TAny* p4=User::Alloc(1); 
   252 	TAny* p5 =new TUint; 
   253 	__UHEAP_CHECK(2);
   254 	__UHEAP_CHECKALL(5);
   255 	__UHEAP_MARKEND;
   256 	TestCellInfo(0, 2, 4, 2, User::AllocLen(p4), p4);
   257 	__UHEAP_CHECKALL(5);
   258 	__UHEAP_CHECK(3);
   259 	__UHEAP_MARKENDC(3);
   260 	User::Free(p1);
   261 	User::Free(p2);
   262 	User::Free(p3);
   263 	User::Free(p4);
   264 	User::Free(p5);
   265 
   266 	// Check some nesting out
   267 	p1=new TUint;
   268 	__UHEAP_MARK;
   269 	p2=new TUint; 
   270 	__UHEAP_MARK;
   271 	p3=new TUint; 
   272 	__UHEAP_MARK;
   273 	p4=new TUint; 
   274 	__UHEAP_MARKEND;
   275 	TestCellInfo(0, 3, 3, 1, User::AllocLen(p4), p4);
   276 	__UHEAP_MARKEND;
   277 	TestCellInfo(0, 2, 2, 1, User::AllocLen(p3), p3);
   278 	__UHEAP_MARKEND;
   279 	TestCellInfo(0, 1, 1, 1, User::AllocLen(p2), p2);
   280 	User::Free(p1);
   281 	User::Free(p2);
   282 	User::Free(p3);
   283 	User::Free(p4);
   284 	User::Check();
   285 	}
   286 
   287 void TestRHeapDebug::Test4(void)
   288 	{
   289 	// Test with different heaps
   290 	TAny* p1=new TUint;
   291 	__UHEAP_MARK;	// Default start
   292 	__UHEAP_CHECKALL(1);
   293 	__UHEAP_CHECK(0);
   294 	TAny* p2=new TUint;	  
   295 	RHeap* pHeap1=allocHeap(1000); 
   296 	AttachToHeap(pHeap1,1);
   297 	__RHEAP_MARK(pHeap1); // Heap1 start
   298 	__RHEAP_CHECKALL(pHeap1,0);
   299 	__RHEAP_CHECK(pHeap1,0);
   300 	TAny* p3=pHeap1->Alloc(4); 
   301 	__RHEAP_CHECKALL(pHeap1,1);
   302 	__RHEAP_CHECK(pHeap1,1);
   303 	__RHEAP_CHECKALL(pHeap1,1);
   304 	__UHEAP_CHECKALL(3);
   305 	RHeap* pHeap2=allocHeap(1000);
   306 	AttachToHeap(pHeap2,2);
   307 	RHeap* pHeap3=allocHeap(1000);
   308 	AttachToHeap(pHeap3,3);
   309 	__UHEAP_CHECKALL(5);
   310 	__RHEAP_MARK(pHeap2); // Heap2 start
   311 	__RHEAP_MARK(pHeap3); // Heap3 start
   312 	TAny* p4=pHeap2->Alloc(8); 
   313 	TAny* p5=pHeap2->Alloc(37);
   314 	TAny* p6=pHeap3->Alloc(32);	
   315 	TAny* p7=pHeap1->Alloc(43);	
   316 	__UHEAP_CHECKALL(5);
   317 	__RHEAP_CHECKALL(pHeap1,2);
   318 	__RHEAP_CHECKALL(pHeap2,2);
   319 	__RHEAP_CHECKALL(pHeap3,1);
   320 	__RHEAP_MARKEND(pHeap3); // Heap3 end
   321 	TestCellInfo(3, 1, 1, 1, pHeap3->AllocLen(p6), p6);
   322 	__RHEAP_MARKEND(pHeap2); // Heap2 end
   323 	TestCellInfo(2, 1, 1, 2, pHeap2->AllocLen(p4), p4);
   324 	pHeap1->Free(p3);
   325 	__RHEAP_MARKEND(pHeap1); // Heap1 end
   326 	TestCellInfo(1, 1, 2, 1, pHeap1->AllocLen(p7), p7);
   327 	User::Free(p1);
   328 	User::Free(p2);
   329 	pHeap2->Free(p4);
   330 	pHeap2->Free(p5);
   331 	pHeap3->Free(p6);
   332 	pHeap1->Free(p7);
   333 	__UHEAP_CHECKALL(3);   
   334 	pHeap2->Close();
   335 	pHeap3->Close();
   336 	__UHEAP_MARKEND;
   337 	pHeap1->Close();
   338 	__UHEAP_CHECKALL(0);
   339 	}
   340 
   341 void TestRHeapDebug::Test5()
   342 // Check the alloc failure macros
   343 	{
   344 	TAny *p, *p1;
   345 	RHeap* pHeap=allocHeap(1000);
   346 
   347 	// DETERMINISTIC FAILURE
   348 	__UHEAP_RESET;
   349 	__UHEAP_FAILNEXT(1);
   350 	test(User::Alloc(1)==NULL);
   351 	p=User::Alloc(1);
   352 	test(p!=NULL);
   353 	User::FreeZ(p);
   354 	__UHEAP_RESET;
   355 
   356 	__RHEAP_RESET(pHeap);
   357 	__RHEAP_FAILNEXT(pHeap,1);
   358 	test(pHeap->Alloc(1)==NULL);
   359 	p=pHeap->Alloc(1);
   360 	test(p!=NULL);
   361 	pHeap->FreeZ(p);
   362    	__RHEAP_RESET(pHeap);
   363 
   364 	__KHEAP_RESET;
   365 	__KHEAP_FAILNEXT(1);
   366 	RSemaphore semaphore;
   367 	test(semaphore.CreateLocal(1)==KErrNoMemory); // allocated from the kernel heap
   368 	test(semaphore.CreateLocal(1)==KErrNone);
   369 	semaphore.Close();
   370 	__KHEAP_RESET;
   371 
   372 	__UHEAP_SETFAIL(RHeap::EDeterministic,0);
   373 	test(User::Alloc(1)==NULL);
   374 	__UHEAP_RESET;
   375 
   376 	__RHEAP_SETFAIL(pHeap,RHeap::EDeterministic,0);
   377 	test(pHeap->Alloc(1)==NULL);
   378 	__RHEAP_RESET(pHeap);
   379 
   380 	__KHEAP_SETFAIL(RHeap::EDeterministic,0);
   381 	test(semaphore.CreateLocal(1)==KErrNoMemory);
   382 	__KHEAP_RESET;
   383 
   384 	TInt determinism;
   385 	for(determinism=1; determinism<=KMaxFailureRate; determinism++)
   386 		{
   387 		__UHEAP_SETFAIL(RHeap::EDeterministic,determinism);
   388 		__RHEAP_SETFAIL(pHeap,RHeap::EDeterministic,determinism);
   389 		for(TInt ii=1; ii<=determinism; ii++)
   390 			{
   391 			p=User::Alloc(1);
   392 			p1=pHeap->Alloc(1);
   393 			if(ii%determinism==0)
   394 				{
   395 				test(p==NULL);
   396 				test(p1==NULL);
   397 				}
   398 			else
   399 				{
   400 				test(p!=NULL);
   401 				test(p1!=NULL);
   402 				pHeap->Free(p1); 
   403 				User::Free(p);
   404 				}
   405 			}
   406 		}
   407 	__UHEAP_RESET;
   408 	__RHEAP_RESET(pHeap);
   409 
   410 	// Test SetKernelAllocFail
   411 	// its not possible to test SetKernelAllocFail as above as it is not possible to control the
   412 	// number of calls to Alloc for the dernel heap - but the following will definitely fail:
   413 	__KHEAP_SETFAIL(RHeap::EDeterministic,1);
   414 	RSemaphore r; 
   415 	test(r.CreateLocal(1)==KErrNoMemory); // allocated from the kernel heap
   416 	__KHEAP_SETFAIL(RHeap::EDeterministic,50);
   417 	test(r.CreateLocal(1)==KErrNone);
   418 	r.Close();
   419 	__KHEAP_RESET;
   420 
   421 	// RANDOM TESTS
   422 	TInt numOccurences1, numOccurences2;
   423 
   424 	__UHEAP_SETFAIL(RHeap::ERandom,1);
   425 	test(User::Alloc(1)==NULL);
   426 	__UHEAP_RESET;
   427 
   428 	__RHEAP_SETFAIL(pHeap,RHeap::ERandom,1);
   429 	test(pHeap->Alloc(1)==NULL);
   430 	__RHEAP_RESET(pHeap);
   431 
   432 //	__KHEAP_SETFAIL(RHeap::ERandom,1);
   433 //	test(semaphore.CreateLocal(1)==KErrNoMemory);
   434 //	__KHEAP_RESET;
   435 
   436 	__UHEAP_SETFAIL(RHeap::ETrueRandom,1);
   437 	test(User::Alloc(1)==NULL);
   438 	__UHEAP_RESET;
   439 
   440 	__RHEAP_SETFAIL(pHeap,RHeap::ETrueRandom,1);
   441 	test(pHeap->Alloc(1)==NULL);
   442 	__RHEAP_RESET(pHeap);
   443 
   444 //	__KHEAP_SETFAIL(RHeap::ETrueRandom,1);
   445 //	test(semaphore.CreateLocal(1)==KErrNoMemory);
   446 //	__KHEAP_RESET;
   447 
   448 	for(determinism=1; determinism<=KMaxFailureRate; determinism++)
   449 		{
   450 		__UHEAP_SETFAIL(RHeap::ERandom,determinism);
   451 		__RHEAP_SETFAIL(pHeap,RHeap::ERandom,determinism);
   452         TInt ii;
   453 		for(ii=1; ii<=determinism; ii++)
   454 			{
   455 			p=User::Alloc(1);
   456 			p1=pHeap->Alloc(1);
   457 			array1[ii]=(p==NULL);
   458 			array2[ii]=(p==NULL);
   459 			if(p)
   460 				User::Free(p);
   461 			if(p1)
   462 				pHeap->Free(p1);
   463 			}
   464 		numOccurences1=0;
   465 		numOccurences2=0;
   466 		for(ii=1; ii<=determinism; ii++)
   467 			{
   468 			if(array1[ii])
   469 				numOccurences1++;					
   470 			if(array2[ii])
   471 				numOccurences2++;
   472 			}
   473 		test(numOccurences1==1);
   474 		test(numOccurences2==1);
   475 		}
   476 	__UHEAP_RESET;
   477 	__RHEAP_RESET(pHeap);		
   478 
   479 	__UHEAP_SETFAIL(RHeap::ERandom,5);
   480 	TInt ii;
   481 	for(ii=1; ii<=50; ii++)
   482 		{
   483 		p=User::Alloc(1);
   484 		array1[ii]=(p==NULL);
   485 		if(p)	
   486 			User::Free(p);
   487 		}
   488 	numOccurences1=0;
   489 	numOccurences2=0;
   490 	for(ii=1; ii<=50; ii++)
   491 		{
   492 		if(array1[ii])
   493 			{
   494 			numOccurences1++;
   495 			numOccurences2++;
   496 			}
   497 		if(ii%5==0)
   498 			{
   499 			test(numOccurences1==1);
   500 			numOccurences1=0;
   501 			}
   502 		}
   503 	test(numOccurences2==50/5);	
   504 	
   505 	// Cannot really test random failure of the kernel heap accurately
   506 
   507 	pHeap->Close();
   508 	//client.Disconnect();
   509 
   510 	// Test failing the heap of a child thread
   511 	// 1st test that it allocates normally
   512 	TRequestStatus stat;
   513 	RThread thread;
   514 	test(threadSemaphore.CreateLocal(0)==KErrNone);
   515 	test(thread.Create(_L("Thread"),ThreadEntryPoint,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
   516 	thread.Logon(stat);
   517 	thread.Resume();
   518 	threadSemaphore.Signal();
   519 	User::WaitForRequest(stat);
   520 	test(thread.ExitReason()==KErrNone);
   521 	thread.Close();
   522 #if defined(CAN_TEST_THREADS)
   523 	// Now make the thread's heap fail
   524 	test(thread.Create(_L("Thread"),ThreadEntryPoint,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
   525 	thread.Logon(stat);
   526 	thread.Resume();
   527 	TH_FAILNEXT(thread.Handle());
   528 	threadSemaphore.Signal();
   529 	User::WaitForRequest(stat);
   530 	test(thread.ExitReason()==KThreadMemError);
   531 	thread.Close();
   532 	threadSemaphore.Close();
   533 #endif
   534 	}	
   535 
   536 GLDEF_C TInt E32Main(void)
   537     {
   538 
   539 	test.Title();
   540 	AttachToHeap(NULL,0);
   541 	test.Start(_L("Test1"));
   542 	TestRHeapDebug T;
   543 	T.Test1();	 
   544 	test.Next(_L("Test2"));
   545 	T.Test2();
   546 	test.Next(_L("Test3"));
   547 	T.Test3();
   548 	test.Next(_L("Test4"));
   549 	T.Test4();
   550 	test.Next(_L("Test5"));
   551 	T.Test5();
   552 	test.End();
   553 	return(0);
   554     }
   555 #else
   556 GLDEF_C TInt E32Main()
   557 //
   558 // Test unavailable in release build.
   559 //
   560     {
   561 
   562 	test.Title();	
   563 	test.Start(_L("No tests for release builds"));
   564 	test.End();
   565 	return(0);
   566     }
   567 #endif
   568 
   569 
   570