kerneltest/e32test/heap/t_heap.cpp
changeset 0 a41df078684a
child 19 4a8fed1c0ef6
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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_heap.cpp
       
    15 // Overview:
       
    16 // Tests RHeap class.
       
    17 // API Information:
       
    18 // RHeap
       
    19 // Details:
       
    20 // - Test that the expected methods are in the DLL by calling each one.
       
    21 // - Test heap auto expansion and compression by calling Alloc and Compress
       
    22 // and verifying the results are as expected.
       
    23 // - Verify the heap dump Base, Size, MinLength, Top and len values.
       
    24 // - Test the RHeap AllocSize, Alloc, AllocLen, Count and Free methods. Verify
       
    25 // results are as expected. Check heap object and confirm Invariant status.
       
    26 // - For an RHeap object, test and verify the results of: allocate some cells, 
       
    27 // free them with Reset, allocate some cells again, free them with Free, 
       
    28 // allocate some cells again, free them backwards, allocate again, free the 
       
    29 // odd cells then the even cells, allocate again, free one half then the other.
       
    30 // Check heap object and confirm Invariant status.
       
    31 // - For an RHeap object, test and verify the results of: attempt to resize a
       
    32 // block above the space available, resize the block to 0, resize positively, 
       
    33 // allocate a block, fill with data, allocate another block or two then resize
       
    34 // the original block such that it has to be moved in memory, then check the 
       
    35 // blocks' contents, test data was copied on reallocation, resize blocks and
       
    36 // verify data integrity, expand and shrink, verify data.
       
    37 // Check heap object and confirm Invariant status.
       
    38 // - For an RHeap object, test and verify the results of: Alloc some cells,
       
    39 // verify the Count, Check the object, Free some cells, verify the Count, 
       
    40 // Check and Reset the object, corrupt the heap data and reset the object.
       
    41 // - Test the leaving methods: AllocL and ReAllocL. Verify the results are as
       
    42 // expected.
       
    43 // - Test the RHeap methods: Alloc, Count, Size, Free and Close. Verify results
       
    44 // are as expected.
       
    45 // - Test sharing a chunk heap between two separate threads.  Each thread
       
    46 // accesses the shared heap in a timed loop, to ensure that some true
       
    47 // concurrency.
       
    48 // - Test sharing a chunk heap between two separate threads. Run each thread in
       
    49 // a timed loop, to ensure that some true concurrency. Each thread accesses
       
    50 // the shared heap and results are verified.  The heap size is used to verify
       
    51 // no leaks and that the largest available space is still available. The heap
       
    52 // is checked to verify that no cells remain allocated after the tests are
       
    53 // complete.
       
    54 // - Test sharing a heap between two threads.  The thread whose heap it was is
       
    55 // killed first.  Each thread accesses the shared heap and results are
       
    56 // verified.
       
    57 // Platforms/Drives/Compatibility:
       
    58 // All
       
    59 // Assumptions/Requirement/Pre-requisites:
       
    60 // Failures and causes:
       
    61 // Base Port information:
       
    62 // 
       
    63 //
       
    64 
       
    65 #include <e32test.h>
       
    66 #include <e32hal.h>
       
    67 #include <e32def.h>
       
    68 #include <e32def_private.h>
       
    69 
       
    70 // Sets data for Test6
       
    71 #define SetData(size)	pHeap->Reset();\
       
    72 						Cell1=pHeap->Alloc(size);\
       
    73 						Cell2=pHeap->Alloc(size);\
       
    74 						Cell3=pHeap->Alloc(size);\
       
    75 						for(pC=(TText8*)Cell1; pC<(TText8*)Cell1+pHeap->AllocLen(Cell1); *pC++='x');\
       
    76 						for(pC=(TText8*)Cell2; pC<(TText8*)Cell2+pHeap->AllocLen(Cell2); *pC++='y');\
       
    77 						for(pC=(TText8*)Cell3; pC<(TText8*)Cell3+pHeap->AllocLen(Cell3); *pC++='z');\
       
    78 						OrigLen=pHeap->AllocLen(Cell2);			
       
    79 
       
    80 // Tests cell contents for Test6
       
    81 #define TestCells(Cell2Len)	for(pC=(TText8*)Cell1; pC<(TText8*)Cell1+pHeap->AllocLen(Cell1); test(*pC++=='x'));\
       
    82 							for(pC=(TText8*)Cell2; pC<(TText8*)Cell2+Cell2Len; test(*pC++=='y'));\
       
    83 							for(pC=(TText8*)Cell3; pC<(TText8*)Cell3+pHeap->AllocLen(Cell3); test(*pC++=='z'));\
       
    84 							pHeap->Check();
       
    85 
       
    86 #ifdef __EABI__
       
    87 	IMPORT_D extern const TInt KHeapMinCellSize;
       
    88 #else
       
    89     const TInt KHeapMinCellSize = 0;
       
    90 #endif
       
    91 
       
    92 const TInt KHeadSize = (TInt)RHeap::EAllocCellSize;
       
    93 const TInt KAlign = _FOFF(RHeap::_s_align, d);
       
    94 const TInt KMinCellLength = _ALIGN_UP((KHeapMinCellSize + Max(TInt(RHeap::EFreeCellSize),TInt(RHeap::EAllocCellSize))),KAlign) - RHeap::EAllocCellSize;
       
    95 const TInt KMinFreeSize = _ALIGN_UP((KHeapMinCellSize + Max(TInt(RHeap::EFreeCellSize),TInt(RHeap::EAllocCellSize))),KAlign);
       
    96 
       
    97 TInt PageSize;
       
    98 
       
    99 class RTestHeap : public RHeap
       
   100 	{
       
   101 public:
       
   102 	void __DbgTest(void* pRHeapDump) const;
       
   103 	};
       
   104 
       
   105 struct RHeapDump
       
   106 	{
       
   107 	TUint				iMinLength;
       
   108 	RChunk				iChunk;
       
   109 	TUint8				*iBase;
       
   110 	TUint8				*iTop;
       
   111 	RHeap::SCell		iFree;
       
   112 	};
       
   113 
       
   114 #pragma warning ( disable :4705 ) // statement has no effect
       
   115 RHeapDump OrigDump;
       
   116 #pragma warning ( default :4705 )
       
   117 
       
   118 #if defined(_DEBUG)
       
   119 void RTestHeap::__DbgTest(void* aPtr) const
       
   120 	{
       
   121 	RHeapDump& d = *(RHeapDump*)aPtr;
       
   122 	d.iMinLength=iMinLength;
       
   123 	d.iChunk.SetHandle(iChunkHandle);
       
   124 	d.iBase=iBase;
       
   125 	d.iTop=iTop;
       
   126 	d.iFree=iFree;
       
   127 	}
       
   128 #endif
       
   129 
       
   130 
       
   131 #if defined(_DEBUG)
       
   132 TBool Invariant(RHeap* aHeap)
       
   133 	{
       
   134 	RHeapDump dump;
       
   135 	((RTestHeap*)aHeap)->__DbgTest(&dump);
       
   136 	if(dump.iMinLength!=OrigDump.iMinLength) 		return(EFalse);
       
   137 	// Note: iChunk is a class
       
   138 	if(dump.iBase!=OrigDump.iBase)			return(EFalse);
       
   139 	if(*dump.iBase!=*OrigDump.iBase)		return(EFalse);
       
   140 	if(dump.iTop!=OrigDump.iTop)			return(EFalse);
       
   141 	if(dump.iTop[-1]!=OrigDump.iTop[-1])	return(EFalse);	
       
   142 	if(dump.iFree.len!=OrigDump.iFree.len)	return(EFalse);
       
   143 	// iFree.Next changes during allocation/freeing etc.
       
   144 	return(ETrue);
       
   145 	}
       
   146 #define INV(x) x;
       
   147 #else
       
   148 #define INV(x)
       
   149 #endif
       
   150 
       
   151 LOCAL_D RTest test(_L("T_HEAP"));
       
   152 LOCAL_D TInt heapCount=1;
       
   153 LOCAL_D RHeap *gHeapPtr;
       
   154 LOCAL_D RHeap *gHeapPtr2;
       
   155 
       
   156 class TestRHeap
       
   157 	{
       
   158 public:
       
   159 	void Test1(void);
       
   160 	void Test2(void);
       
   161 	void Test3(void);
       
   162 	void Test4(void);
       
   163 	void Test5(void);
       
   164 	void Test7(void);
       
   165 	void Test8(void);
       
   166 	void TestCompressAll(void);
       
   167 	void TestOffset(void);
       
   168 private:
       
   169 	TInt RHeapCalcReduce(TInt aCellSize, TInt aGrowBy);
       
   170 	};
       
   171 
       
   172 LOCAL_C RHeap* allocHeap(TInt aSize)
       
   173 //
       
   174 // Allocate a chunk heap with max size aSize
       
   175 //
       
   176 	{
       
   177 
       
   178 	TName n;
       
   179 	n.Format(_L("TESTHEAP%d"),heapCount++);
       
   180 	return(User::ChunkHeap(&n,aSize,aSize));
       
   181 	}
       
   182 
       
   183 ////////////////////////////////////////////////////////////////////////////////////////
       
   184 // Test that methods are in the DLL
       
   185 ////////////////////////////////////////////////////////////////////////////////////////
       
   186 void TestRHeap::Test1(void)
       
   187 	{ 
       
   188 	TAny* aCell;
       
   189 	TInt aVar;
       
   190 	RHeap* pHeap=allocHeap(3000); // tests first constructor indirectly 
       
   191 	// constructor with Chunk not tested
       
   192 	pHeap->Base();
       
   193 	pHeap->Size();
       
   194 	pHeap->Available(aVar);
       
   195 	pHeap->Check();
       
   196 	pHeap->Count();												 	
       
   197 	pHeap->Count(aVar);
       
   198 	aCell=pHeap->Alloc(50);
       
   199 	pHeap->Free(aCell);
       
   200 	aCell=pHeap->AllocL(50);
       
   201 	pHeap->AllocLen(aCell);
       
   202 	pHeap->ReAlloc(aCell, 100);
       
   203 	pHeap->ReAllocL(aCell, 150);
       
   204 	pHeap->Reset();
       
   205 	pHeap->Close();
       
   206 	}
       
   207 
       
   208 ///////////////////////////////////////////////////////////////////////////////
       
   209 // Test Assorted Methods 1
       
   210 //////////////////////////////////////////////////////////////////////////////
       
   211 void TestRHeap::Test2(void)
       
   212 	{
       
   213 #if defined(_DEBUG)
       
   214 	RHeapDump dump;
       
   215 	RHeap* pHeap=allocHeap(3000);
       
   216 
       
   217 	((RTestHeap*)pHeap)->__DbgTest(&OrigDump);
       
   218 	((RTestHeap*)pHeap)->__DbgTest(&dump);
       
   219 	test(dump.iBase==pHeap->Base());
       
   220 	test((dump.iTop-dump.iBase)==pHeap->Size());
       
   221 	pHeap->Check();
       
   222 	test(Invariant(pHeap));
       
   223 	pHeap->Close();
       
   224 #endif
       
   225 	}
       
   226 
       
   227 ///////////////////////////////////////////////////////////////////////////////
       
   228 // Test Assorted Methods 2
       
   229 //////////////////////////////////////////////////////////////////////////////		 
       
   230 void TestRHeap::Test3(void)
       
   231 	{  
       
   232 	TInt CellLen;
       
   233 	TInt OrigBiggestBlock, BiggestBlock;
       
   234 	TAny* aCell;
       
   235 	TInt FreeCount, AllocCount, AllocSize;
       
   236 	RHeap* pHeap=allocHeap(5000);
       
   237 
       
   238 #if defined(_DEBUG)
       
   239 	((RTestHeap*)pHeap)->__DbgTest(&OrigDump);
       
   240 #endif
       
   241 
       
   242 	// test AllocSize
       
   243 	AllocCount=pHeap->Count(FreeCount);
       
   244 	test(pHeap->AllocSize(AllocSize)==pHeap->Count());
       
   245 	test(AllocSize==0);
       
   246 	test(AllocCount==pHeap->Count());
       
   247 	test(AllocCount==0);
       
   248 	test(FreeCount==1);
       
   249 
       
   250 	TAny* p1=pHeap->Alloc(1);
       
   251 	test(pHeap->AllocSize(AllocSize)==1);
       
   252 	test(AllocSize==pHeap->AllocLen(p1));
       
   253 	 
       
   254 	TAny* p2=pHeap->Alloc(8);
       
   255 	test(pHeap->AllocSize(AllocSize)==2);
       
   256 	test(AllocSize==pHeap->AllocLen(p1)+pHeap->AllocLen(p2));
       
   257 
       
   258 	TAny* p3=pHeap->Alloc(127);
       
   259 	test(pHeap->AllocSize(AllocSize)==3);
       
   260 	test(AllocSize==pHeap->AllocLen(p1)+pHeap->AllocLen(p2)+pHeap->AllocLen(p3));
       
   261 
       
   262 	pHeap->Free(p2);
       
   263 	test(pHeap->AllocSize(AllocSize)==2);
       
   264 	test(AllocSize==pHeap->AllocLen(p1)+pHeap->AllocLen(p3));
       
   265 
       
   266 	pHeap->Free(p1);
       
   267 	test(pHeap->AllocSize(AllocSize)==1);
       
   268 	test(AllocSize==pHeap->AllocLen(p3));
       
   269 
       
   270 	pHeap->Free(p3);
       
   271 	test(pHeap->AllocSize(AllocSize)==0);
       
   272 	test(AllocSize==0);
       
   273 
       
   274 	pHeap->Available(OrigBiggestBlock);
       
   275 
       
   276 	// Request too large a block 
       
   277 	test((aCell=pHeap->Alloc(OrigBiggestBlock+1))==NULL);
       
   278 	AllocCount=pHeap->Count(FreeCount);
       
   279 	test(AllocCount==0);
       
   280 	test(FreeCount==1);
       
   281 
       
   282 
       
   283 	// Request block same size as that available
       
   284 	test((aCell=pHeap->Alloc(OrigBiggestBlock))!=NULL);
       
   285 	test(pHeap->Available(BiggestBlock)==0);  
       
   286 	test(BiggestBlock==0);
       
   287 	test(pHeap->AllocLen(aCell)==OrigBiggestBlock);
       
   288 	AllocCount=pHeap->Count(FreeCount);
       
   289 	test(AllocCount==pHeap->Count());
       
   290 	test(AllocCount==1);
       
   291 	test(FreeCount==0);
       
   292 	pHeap->Check();
       
   293 	// Free the block
       
   294 	pHeap->FreeZ(aCell);
       
   295 	test(aCell==NULL);
       
   296 	pHeap->Available(BiggestBlock);
       
   297 	test(BiggestBlock==OrigBiggestBlock);
       
   298 	AllocCount=pHeap->Count(FreeCount);
       
   299 	test(AllocCount==0);
       
   300 	test(FreeCount==1);
       
   301 
       
   302 
       
   303 	// Request a block much smaller than that available
       
   304 	test((aCell=pHeap->Alloc(1))!=NULL);
       
   305 	CellLen=pHeap->AllocLen(aCell);
       
   306 	pHeap->Available(BiggestBlock);
       
   307 	test(pHeap->Available(BiggestBlock)==BiggestBlock);
       
   308 	test((BiggestBlock+CellLen+KHeadSize)==OrigBiggestBlock);
       
   309 	// NOTE: if a block of 1000 was initially available, getting a cell of length 100 DOES NOT
       
   310 	// leave 900 available as some of the 1000(KHeadSize) is used up storing the length of the
       
   311 	// allocated block
       
   312 	AllocCount=pHeap->Count(FreeCount);
       
   313 	test(AllocCount==1);
       
   314 	test(FreeCount==1);
       
   315 	pHeap->Check();
       
   316 	// Free the block
       
   317 	pHeap->Free(aCell);
       
   318 	test(aCell!=NULL);
       
   319 	pHeap->Available(BiggestBlock);
       
   320 	test(BiggestBlock==OrigBiggestBlock);
       
   321 	AllocCount=pHeap->Count(FreeCount);
       
   322 	test(AllocCount==0);
       
   323 	test(FreeCount==1);
       
   324 
       
   325 
       
   326 	// Request a block only just smaller than that available
       
   327 	test((aCell=pHeap->Alloc(OrigBiggestBlock-1))!=NULL);
       
   328 	CellLen=pHeap->AllocLen(aCell);
       
   329 	AllocCount=pHeap->Count(FreeCount);
       
   330 	test(AllocCount==1);
       
   331 	test(FreeCount==0);
       
   332 	pHeap->Check();
       
   333 	// Free the block
       
   334 	pHeap->Free(aCell);
       
   335 	pHeap->Available(BiggestBlock);
       
   336 	test(BiggestBlock==OrigBiggestBlock);
       
   337 	AllocCount=pHeap->Count(FreeCount);
       
   338 	test(AllocCount==0);
       
   339 	test(FreeCount==1);
       
   340 
       
   341 
       
   342 	//Request a block of 0 size	   Note: 0 may not necessarily be allocated (probably will be 4)
       
   343 	test((aCell=pHeap->Alloc(0))!=NULL);
       
   344 	pHeap->Available(BiggestBlock);
       
   345 	AllocCount=pHeap->Count(FreeCount);
       
   346 	test(AllocCount==1);
       
   347 	test(FreeCount==1);
       
   348 	pHeap->Check();
       
   349 	//Free the block
       
   350 	pHeap->Free(aCell);
       
   351 	pHeap->Available(BiggestBlock);
       
   352 	test(BiggestBlock==OrigBiggestBlock);	 
       
   353 	AllocCount=pHeap->Count(FreeCount);
       
   354 	test(AllocCount==0);
       
   355 	test(FreeCount==1);
       
   356 	pHeap->Check();
       
   357 	INV(test(Invariant(pHeap)));
       
   358 
       
   359 	// close heap so we don't exceed chunk limit
       
   360 	pHeap->Close();
       
   361 	}
       
   362 
       
   363 ///////////////////////////////////////////////////////////////////////////////
       
   364 // Test Assorted Methods 3 - Here we go loopy loo, here we go loopy li
       
   365 //////////////////////////////////////////////////////////////////////////////				  
       
   366 void TestRHeap::Test4(void)
       
   367 	{ 
       
   368 	TInt OrigBiggestBlock, BiggestBlock, FreeCount, AllocCount;
       
   369 	RHeap* pHeap=allocHeap(5000);
       
   370 
       
   371 	pHeap->Available(OrigBiggestBlock);
       
   372 #if defined(_DEBUG)
       
   373 	((RTestHeap*)pHeap)->__DbgTest(&OrigDump);
       
   374 #endif
       
   375 	
       
   376 	for(TInt ArraySize=1; ArraySize<=100; ArraySize++)
       
   377 		{	  
       
   378 		TAny** ArrayOfCells;
       
   379 		ArrayOfCells= new TAny*[ArraySize];
       
   380 		TInt ArrayIndex;
       
   381 	
       
   382 		// Allocate some cells
       
   383 		for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++)
       
   384 			ArrayOfCells[ArrayIndex]=pHeap->Alloc(OrigBiggestBlock/(ArraySize*3)); 
       
   385 		pHeap->Available(BiggestBlock);
       
   386 		test(BiggestBlock!=OrigBiggestBlock);
       
   387 		AllocCount=pHeap->Count(FreeCount);
       
   388 		test((TInt)AllocCount==ArraySize);
       
   389 		test(FreeCount==1);
       
   390 		pHeap->Check();
       
   391 		// Now free them with Reset
       
   392 		pHeap->Reset();
       
   393 		pHeap->Available(BiggestBlock);
       
   394 		test(BiggestBlock==OrigBiggestBlock);
       
   395 		AllocCount=pHeap->Count(FreeCount);
       
   396 		test(AllocCount==0);
       
   397 		test(FreeCount==1);
       
   398 	
       
   399 	
       
   400 		// Allocate some cells again	 
       
   401 		for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++)
       
   402 			ArrayOfCells[ArrayIndex]=pHeap->Alloc(OrigBiggestBlock/(ArraySize*3)); 
       
   403 		pHeap->Available(BiggestBlock);
       
   404 		test(BiggestBlock!=OrigBiggestBlock);
       
   405 		AllocCount=pHeap->Count(FreeCount);
       
   406 		test((TInt)AllocCount==ArraySize);
       
   407 		test(FreeCount==1);
       
   408 		pHeap->Check();
       
   409 		// Free them with Free
       
   410 		for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++)
       
   411 			pHeap->Free(ArrayOfCells[ArrayIndex]);
       
   412 		pHeap->Available(BiggestBlock);
       
   413 		test(BiggestBlock==OrigBiggestBlock);
       
   414 		AllocCount=pHeap->Count(FreeCount);
       
   415 		test(AllocCount==0);
       
   416 		test(FreeCount==1);
       
   417 	
       
   418 	
       
   419 		// Allocate some cells again	 
       
   420 		for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++)
       
   421 			ArrayOfCells[ArrayIndex]=pHeap->Alloc(OrigBiggestBlock/(ArraySize*3));
       
   422 		pHeap->Available(BiggestBlock);
       
   423 		test(BiggestBlock!=OrigBiggestBlock); 
       
   424 		AllocCount=pHeap->Count(FreeCount);
       
   425 		test((TInt)AllocCount==ArraySize);
       
   426 		test(FreeCount==1);
       
   427 		pHeap->Check();
       
   428 		// Free them backwards
       
   429 		for(ArrayIndex=ArraySize-1; ArrayIndex>=0; ArrayIndex--)
       
   430 			pHeap->Free(ArrayOfCells[ArrayIndex]);
       
   431 		pHeap->Available(BiggestBlock);
       
   432 		test(BiggestBlock==OrigBiggestBlock);
       
   433 		AllocCount=pHeap->Count(FreeCount);
       
   434 		test(AllocCount==0);
       
   435 		test(FreeCount==1);
       
   436 
       
   437 
       
   438 		// Allocate some cells again	 
       
   439 		for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++)
       
   440 			ArrayOfCells[ArrayIndex]=pHeap->Alloc(OrigBiggestBlock/(ArraySize*3));
       
   441 		pHeap->Available(BiggestBlock);
       
   442 		test(BiggestBlock!=OrigBiggestBlock);
       
   443 		AllocCount=pHeap->Count(FreeCount);
       
   444 		test((TInt)AllocCount==ArraySize);
       
   445 		test(FreeCount==1);
       
   446 		pHeap->Check();
       
   447 		// Free the odd cells then the even cells
       
   448 		for(ArrayIndex=0; ArrayIndex<ArraySize; ArrayIndex+=2)
       
   449 			pHeap->Free(ArrayOfCells[ArrayIndex]);
       
   450 		pHeap->Check();
       
   451 		for(ArrayIndex=1; ArrayIndex<ArraySize; ArrayIndex+=2)
       
   452 			pHeap->Free(ArrayOfCells[ArrayIndex]);
       
   453 		pHeap->Check();
       
   454 		pHeap->Available(BiggestBlock);
       
   455 		test(BiggestBlock==OrigBiggestBlock);
       
   456 		AllocCount=pHeap->Count(FreeCount);
       
   457 		test(AllocCount==0);
       
   458 		test(FreeCount==1);
       
   459 	
       
   460 	
       
   461 		// Allocate some cells again	 
       
   462 		for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++)
       
   463 			ArrayOfCells[ArrayIndex]=pHeap->Alloc(OrigBiggestBlock/(ArraySize*3));
       
   464 		pHeap->Available(BiggestBlock);
       
   465 		test(BiggestBlock!=OrigBiggestBlock);
       
   466 		AllocCount=pHeap->Count(FreeCount);
       
   467 		test((TInt)AllocCount==ArraySize);
       
   468 		test(FreeCount==1);
       
   469 		pHeap->Check();
       
   470 		// Free one half then the other
       
   471 		for(ArrayIndex=ArraySize-1; ArrayIndex>=ArraySize/2; ArrayIndex--)
       
   472 			pHeap->Free(ArrayOfCells[ArrayIndex]);
       
   473 		for(ArrayIndex=0; ArrayIndex<ArraySize/2; ArrayIndex++)
       
   474 			pHeap->Free(ArrayOfCells[ArrayIndex]);
       
   475 		AllocCount=pHeap->Count(FreeCount);
       
   476 		test(AllocCount==0);
       
   477 		test(FreeCount==1);
       
   478 	
       
   479 		delete [] ArrayOfCells;
       
   480 		pHeap->Check();
       
   481 		INV(test(Invariant(pHeap)))
       
   482 		}
       
   483 
       
   484 	// close heap so we don't exceed chunk limit
       
   485 	pHeap->Close();
       
   486 	}
       
   487 
       
   488 	
       
   489 ///////////////////////////////////////////////////////////////////////////////
       
   490 // Test ReAlloc
       
   491 //////////////////////////////////////////////////////////////////////////////
       
   492 void TestRHeap::Test5(void)
       
   493 	{
       
   494 	TInt BiggestBlock, CellSize;
       
   495 
       
   496 	RHeap* pHeap=allocHeap(5000);
       
   497 #if defined(_DEBUG)
       
   498 	((RTestHeap*)pHeap)->__DbgTest(&OrigDump);
       
   499 #endif
       
   500 	pHeap->Available(BiggestBlock);
       
   501 	TAny* aCell=pHeap->Alloc(BiggestBlock);
       
   502 
       
   503 	// Attempt to resize the block above the space available
       
   504 	test(pHeap->ReAlloc(aCell, BiggestBlock*2)==NULL);
       
   505 
       
   506 	// Resize the block to 0
       
   507 	aCell=pHeap->ReAlloc(aCell, 0);
       
   508 	CellSize=pHeap->AllocLen(aCell);  // test?
       
   509 
       
   510 	// Resize positively
       
   511 	for(TInt aSize=0; aSize<=BiggestBlock; aSize++, pHeap->Available(BiggestBlock))
       
   512 		{
       
   513 		test(pHeap->ReAlloc(aCell, aSize)!=NULL); 
       
   514 		CellSize=pHeap->AllocLen(aCell);
       
   515 		test(CellSize>=aSize);
       
   516 		if (aSize<KMinCellLength)
       
   517 			test(CellSize==KMinCellLength);
       
   518 		else
       
   519 			test(CellSize<aSize+KAlign);
       
   520 		}
       
   521 
       
   522 	// Note: when increasing a cell size the size is rounded up to the nearest 4 but when 
       
   523 	// decreasing a cell the size is rounded down to the nearest 8 - this is due to the fact
       
   524 	// that when memory is released its size must be big enough to hold a free cell header which
       
   525 	// is greater(8) than an allocated header(4)
       
   526 	// i.e. size = 16, resize to 17 => result  is 20. But resize to 15 stays as 16, resize to 9
       
   527 	// stays as 16 but resize as 8 will resize to 8
       
   528 
       
   529 	for(TInt aSize2=(TInt)pHeap->AllocLen(aCell); aSize2>=0; aSize2--)
       
   530 		{
       
   531 		test(pHeap->ReAlloc(aCell, aSize2)!=NULL);
       
   532 		test(((TInt)pHeap->AllocLen(aCell)>=aSize2)&&((TInt)pHeap->AllocLen(aCell)<=aSize2+KMinFreeSize));
       
   533 		}
       
   534   
       
   535 	pHeap->Check();
       
   536 	pHeap->Reset();
       
   537 	// Allocate a block, fill with data, allocate another block or two then resize the original
       
   538 	// block such that it has to be moved in memory, then check the blocks' contents 
       
   539 	TAny* Cell1=pHeap->Alloc(16);
       
   540 	TText8* pC;
       
   541 	TInt Cell1Size=pHeap->AllocLen(Cell1);
       
   542 	for(pC=(TText8*)Cell1; pC<(TText8*)Cell1+Cell1Size; *pC++='x')
       
   543 		;
       
   544 	TAny* Cell2=pHeap->Alloc(16);
       
   545 	TInt Cell2Size=pHeap->AllocLen(Cell2);
       
   546 	for(pC=(TText8*)Cell2; pC<(TText8*)Cell2+pHeap->AllocLen(Cell2); *pC++='y')
       
   547 		;
       
   548 	Cell1=pHeap->ReAlloc(Cell1, 128);
       
   549 	// Test data was copied on reallocation
       
   550 	for(pC=(TText8*)Cell1; pC<(TText8*)Cell1+Cell1Size; test(*pC++=='x'))
       
   551 		; 
       
   552 	// Test other data wasn't corrupted
       
   553 	for(pC=(TText8*)Cell2; pC<(TText8*)Cell2+pHeap->AllocLen(Cell2); test(*pC++=='y'))
       
   554 		;
       
   555 
       
   556 	// Allocate another block
       
   557 	TAny* Cell3=pHeap->Alloc(8);
       
   558 	for(pC=(TText8*)Cell3; pC<(TText8*)Cell3+pHeap->AllocLen(Cell3); *pC++='z')
       
   559 		;
       
   560 	// test existing blocks to be safe
       
   561 	for(pC=(TText8*)Cell1; pC<(TText8*)Cell1+Cell1Size; test(*pC++=='x'))
       
   562 		;
       
   563 	for(pC=(TText8*)Cell2; pC<(TText8*)Cell2+Cell2Size; test(*pC++=='y'))
       
   564 		;
       
   565 	// Resize previous blocks
       
   566 	Cell1=pHeap->ReAlloc(Cell1, 16); // Shrink previously expanded block
       
   567 	Cell2=pHeap->ReAlloc(Cell2, 64); 
       
   568 	// Now test data
       
   569 	for(pC=(TText8*)Cell1; pC<(TText8*)Cell1+Cell1Size; test(*pC++=='x'))
       
   570 		;
       
   571 	for(pC=(TText8*)Cell2; pC<(TText8*)Cell2+Cell2Size; test(*pC++=='y'))
       
   572 		;
       
   573 	for(pC=(TText8*)Cell3; pC<(TText8*)Cell3+pHeap->AllocLen(Cell3); test(*pC++=='z'))
       
   574 		;
       
   575 
       
   576 	// Re-expand Cell1
       
   577 	Cell1=pHeap->ReAlloc(Cell1, 1028);
       
   578 	for(pC=(TText8*)Cell1; pC<(TText8*)Cell1+Cell1Size; test(*pC++=='x'))
       
   579 		;
       
   580 	for(pC=(TText8*)Cell2; pC<(TText8*)Cell2+Cell2Size; test(*pC++=='y'))
       
   581 		;
       
   582 	for(pC=(TText8*)Cell3; pC<(TText8*)Cell3+pHeap->AllocLen(Cell3); test(*pC++=='z'))
       
   583 		;
       
   584 
       
   585 	// Shrink cells back to original size
       
   586 	Cell1=pHeap->ReAlloc(Cell1, Cell1Size);
       
   587 	Cell2=pHeap->ReAlloc(Cell2, Cell2Size);  
       
   588 	for(pC=(TText8*)Cell1; pC<(TText8*)Cell1+Cell1Size; test(*pC++=='x'))
       
   589 		;
       
   590 	for(pC=(TText8*)Cell2; pC<(TText8*)Cell2+Cell2Size; test(*pC++=='y'))
       
   591 		;
       
   592 	for(pC=(TText8*)Cell3; pC<(TText8*)Cell3+pHeap->AllocLen(Cell3); test(*pC++=='z'))
       
   593 		;
       
   594 
       
   595 	pHeap->Check();
       
   596 	INV(test(Invariant(pHeap)));
       
   597 
       
   598 	// close heap so we don't exceed chunk limit
       
   599 	pHeap->Close();
       
   600 	}
       
   601 
       
   602 
       
   603 ///////////////////////////////////////////////////////////////////////////////
       
   604 // Test walking methods (more thoroughly than previously)
       
   605 //////////////////////////////////////////////////////////////////////////////				  
       
   606 void TestRHeap::Test7(void)
       
   607 	{ 
       
   608 	TInt NumAllocated=0, NumFree=1, i;
       
   609 	RHeap* pHeap=allocHeap(5000);
       
   610 
       
   611 	TAny** ArrayOfCells;
       
   612 	ArrayOfCells= new TAny*[100];
       
   613 
       
   614 	for(i=0; i<100; i++)
       
   615 		{
       
   616 		ArrayOfCells[i]=pHeap->Alloc(8);
       
   617 		NumAllocated++;
       
   618 		test(NumAllocated==pHeap->Count(NumFree));
       
   619 		test(NumFree==1);
       
   620 		}
       
   621 	pHeap->Check();
       
   622 
       
   623 	for(i=0; i<100; i+=2)
       
   624 		{
       
   625 		TInt temp;
       
   626 		pHeap->Free(ArrayOfCells[i]);
       
   627 		NumAllocated--;
       
   628 		NumFree++;
       
   629 		test(NumAllocated==pHeap->Count(temp));
       
   630 		test(NumFree==temp);
       
   631 		}
       
   632 	pHeap->Check();
       
   633 	pHeap->Reset();
       
   634 
       
   635 
       
   636 	///////////////////////////////////////////
       
   637 	// Corrupt data and see what happens
       
   638 	///////////////////////////////////////////
       
   639 	// Corrupt  allocated cell header
       
   640 	ArrayOfCells[0]=pHeap->Alloc(32);
       
   641 	TUint32* pC=(TUint32*)ArrayOfCells[0]-KHeadSize; 
       
   642 	*pC=0xa5a5a5a5u; 
       
   643 	// pHeap->Check();
       
   644 
       
   645 	// Corrupt free cell header 
       
   646 	pHeap->Reset();
       
   647 	ArrayOfCells[0]=pHeap->Alloc(32);
       
   648 	pC=(TUint32*)ArrayOfCells[0]+(pHeap->AllocLen(ArrayOfCells[0])>>2);
       
   649 	*pC=0xa1a1a1a1u;	
       
   650 	//pHeap->Check();	 // Check doesn't pick it up but an access violation is generated
       
   651 
       
   652 	// Write past end of heap
       
   653 	pHeap->Reset();
       
   654 	TInt Avail;
       
   655 	ArrayOfCells[0]=pHeap->Alloc(pHeap->Available(Avail));
       
   656 	pC=(TUint32*)ArrayOfCells[0]+(pHeap->AllocLen(ArrayOfCells[0])>>2);
       
   657 	//*pC=0xa1a1a1a1u;	// This line isn't picked up by Check (wouldn't expect it to) but the call
       
   658 	//pHeap->Check();	// to delete below consequently crashes 
       
   659 
       
   660 	delete [] ArrayOfCells;
       
   661 
       
   662 	// close heap so we don't exceed chunk limit
       
   663 	pHeap->Close();
       
   664 	}
       
   665 
       
   666 //////////////////////////////////////
       
   667 // Test the leave methods
       
   668 //////////////////////////////////////
       
   669 void TestRHeap::Test8(void)
       
   670 	{ 
       
   671 
       
   672 	TAny* aCell=NULL;
       
   673 	RHeap* pHeap=allocHeap(1000); 
       
   674 	TRAPD(ret,aCell=pHeap->AllocL(100))
       
   675 	test(ret==KErrNone);
       
   676 	TRAP(ret,aCell=pHeap->AllocL(PageSize))
       
   677    	test(ret==KErrNoMemory);
       
   678 	TRAP(ret,aCell=pHeap->ReAllocL(aCell,32))
       
   679 	test(ret==KErrNone);
       
   680 	TRAP(ret,aCell=pHeap->ReAllocL(NULL,10000))
       
   681 	test(ret==KErrNoMemory);
       
   682 
       
   683 	// close heap so we don't exceed chunk limit
       
   684 	pHeap->Close();
       
   685 	}
       
   686 
       
   687 class RMyHeap : public RHeap
       
   688 	{
       
   689 public:
       
   690 	void MyCompressAll(){}
       
   691 private:
       
   692 	RMyHeap();
       
   693 	};
       
   694 
       
   695 #include "TestRHeapShrink.h"
       
   696 
       
   697 /**
       
   698 	Calculates whether or not the heap with iGrowBy=aGrowBy will be reduced if a 
       
   699 	cell of size aCellSize bytes is the top free cell.
       
   700 	It must be calculated as both the page size and min cell size could vary
       
   701 	between different platforms/builds.  Also, KHeapMinCellSize is 'patchdata' and can be
       
   702 	different for particular ROM builds
       
   703 	ASSUMPTIONS:-
       
   704 		1 - The cell of aCellSize starts past the RHeap's iMinLength (i.e. all of it can be 
       
   705 		removed without the RHeap becoming smaller than iMinLength
       
   706 		2 - The default value of aAlign was passed to RHeap contructor
       
   707 	These should be safe as this is onl used by t_heap TestRHeap::CompressAll()
       
   708 	@return The number of bytes the heap will be reduced by
       
   709 */
       
   710 TInt TestRHeap::RHeapCalcReduce(TInt aCellSize, TInt aGrowBy)
       
   711 	{
       
   712 	TInt ret = 0;
       
   713 	TInt pageSize = 0;
       
   714 	test(UserHal::PageSizeInBytes(pageSize)==KErrNone);
       
   715 	
       
   716 	// adjust aGrowBy to match what RHeap would have aligned its iGrowBy to 
       
   717 	// see RHeap::RHeap()
       
   718 	aGrowBy = _ALIGN_UP(aGrowBy, pageSize);
       
   719 	if (aCellSize >= KHeapShrinkHysRatio*(aGrowBy>>8))
       
   720 		{
       
   721 		//calc for amount to reduce heap from RHeap::Reduce()
       
   722 		// assumes that cell of aCellSize starts past the RHeap's iMinLength
       
   723 		ret=_ALIGN_DOWN(aCellSize, pageSize);
       
   724 		}
       
   725 	return ret;
       
   726 	}
       
   727 
       
   728 void TestRHeap::TestCompressAll()
       
   729 	{
       
   730 
       
   731 	TPtrC myHeapName=_L("MyHeap");
       
   732 	// myHeap will have default GrowBy of KMinHeapGrowBy
       
   733 	RMyHeap* myHeap=(RMyHeap*)User::ChunkHeap(&myHeapName,0x100,0x2000);
       
   734 const TInt KnormHeapGrowBy = 0x2000;
       
   735 	RHeap* normHeap=User::ChunkHeap(NULL,0x100,0x20000,KnormHeapGrowBy);
       
   736 
       
   737 	TAny* ptrMy1=myHeap->Alloc(0x102);
       
   738 	test(ptrMy1!=NULL);
       
   739 	TAny* ptrMy2=myHeap->Alloc(0x1001);
       
   740 	test(ptrMy2!=NULL);
       
   741 	TInt r=myHeap->Count();
       
   742 	test(r==2);
       
   743 
       
   744 	TAny* ptrNorm1=normHeap->Alloc(0x8002);
       
   745 	test(ptrNorm1!=NULL);
       
   746 	TAny* ptrNorm2=normHeap->Alloc(0x12fff);
       
   747 	test(ptrNorm2!=NULL);
       
   748 	TAny* ptrNorm3=normHeap->Alloc(0x334f);
       
   749 	test(ptrNorm3!=NULL);
       
   750 	r=normHeap->Count();
       
   751 	test(r==3);
       
   752 
       
   753 	TInt oldMyHeapSize=myHeap->Size(); 	
       
   754 	TInt oldNormHeapSize=normHeap->Size();
       
   755 	 	
       
   756 	myHeap->MyCompressAll();
       
   757 
       
   758 	r=myHeap->Count();
       
   759 	test(r==2);
       
   760 	r=myHeap->Size();
       
   761 	test(r==oldMyHeapSize);
       
   762 	r=normHeap->Count();
       
   763 	test(r==3);
       
   764 	r=normHeap->Size();
       
   765 	test(r==oldNormHeapSize);
       
   766 
       
   767 	// Remove the cell on the top of the normHeap
       
   768 	normHeap->Free(ptrNorm3);
       
   769 	// check myHeap unaffected
       
   770 	r=myHeap->Count();
       
   771 	test(r==2);
       
   772 	r=myHeap->Size();
       
   773 	test(r==oldMyHeapSize);
       
   774 	//check normHeap updated after free of top cell
       
   775 	r=normHeap->Count();
       
   776 	test(r==2);
       
   777 	r=normHeap->Size();
       
   778 
       
   779 	// Calc the amount, if any, the overall size of normHeap will have been shrunk by
       
   780 	// will depend on value of KHeapShrinkHysRatio.
       
   781 	// 1st calc current total size of the allocated cells
       
   782 	TInt normAllocdSize = 	normHeap->AllocLen(ptrNorm1)+RHeap::EAllocCellSize +
       
   783 							normHeap->AllocLen(ptrNorm2)+RHeap::EAllocCellSize;
       
   784 	TInt normReduce = RHeapCalcReduce(oldNormHeapSize-normAllocdSize,KnormHeapGrowBy);
       
   785 	oldNormHeapSize -= normReduce;
       
   786 	test(r==oldNormHeapSize);
       
   787 
       
   788 	normHeap->Free(ptrNorm2);
       
   789 	myHeap->Free(ptrMy2);
       
   790 	r=myHeap->Count();
       
   791 	test(r==1);
       
   792 	r=myHeap->Size();
       
   793 
       
   794 	// Calc the current total size of the allocated cells
       
   795 	TInt myAllocdSize = myHeap->AllocLen(ptrMy1)+RHeap::EAllocCellSize;
       
   796 	TInt myReduce=RHeapCalcReduce(oldMyHeapSize-myAllocdSize,1);
       
   797 	oldMyHeapSize -= myReduce;
       
   798 	test(r==oldMyHeapSize);
       
   799 
       
   800 	r=normHeap->Count();
       
   801 	test(r==1);
       
   802 	r=normHeap->Size();
       
   803 
       
   804 	// cell represented by ptrNorm3 may have already caused the heap
       
   805 	// size to be reduced so ensure normReduce is factored into calcs
       
   806 	test(r==oldNormHeapSize-(0x16000-normReduce));
       
   807 
       
   808 	myHeap->Close();
       
   809 	normHeap->Close();
       
   810 	}
       
   811 
       
   812 
       
   813 void TestRHeap::TestOffset()
       
   814 	{
       
   815 	TInt size = 0x100000;
       
   816 	const TInt offset = 0x8;
       
   817 	const TUint8 magic = 0x74; // arbitrary magic value
       
   818 	RChunk chunk;
       
   819 	RHeap* heap;
       
   820 	
       
   821 	chunk.CreateLocal(0, size);
       
   822 	size = chunk.MaxSize();	// X86 has 4MB chunk size
       
   823 	
       
   824 	// try and create a heap with a large offset - no room to make RHeap, should fail
       
   825 	heap = UserHeap::OffsetChunkHeap(chunk, 0, size);
       
   826 	test(heap==NULL);
       
   827 	
       
   828 	// write some magic numbers into the offset-reserved area
       
   829 	chunk.Adjust(offset);
       
   830 	TUint8* reserved = chunk.Base();
       
   831 	TUint8* limit = reserved + offset;
       
   832 	for (; reserved<limit; reserved++)
       
   833 		*reserved = magic;
       
   834 	
       
   835 	// make a heap with an offset
       
   836 	heap = UserHeap::OffsetChunkHeap(chunk, 0, offset);
       
   837 	test(heap!=NULL);
       
   838 	test(chunk.Base() + offset == (TUint8*)heap);
       
   839 	TInt origsize = heap->Size();
       
   840 
       
   841 	// force the heap to grow to the maximum size by allocating 1kb blocks
       
   842 	// and then allocating whatever is left. Check this really is the end
       
   843 	// of the chunk.
       
   844 	TUint8* temp = NULL;
       
   845 	TUint8* last = NULL;
       
   846 	do
       
   847 		{
       
   848 		last = temp;
       
   849 		temp = (TUint8*)heap->Alloc(1024);
       
   850 		}
       
   851 	while (temp != NULL);
       
   852 	TInt biggestblock, space;
       
   853 	space = heap->Available(biggestblock);
       
   854 	if (space>0)
       
   855 		{
       
   856 		last = (TUint8*)heap->Alloc(space);
       
   857 		test(last!=NULL);
       
   858 		// Check that the last allocation doesn't pass the end of the chunk
       
   859 		test(last+space <= chunk.Base()+size);
       
   860 		// but that it is within the alignment requirement, as less than this
       
   861 		// would be short of the end
       
   862 		test(last+space > chunk.Base()+size-RHeap::ECellAlignment);
       
   863 		}
       
   864 	else
       
   865 		{
       
   866 		test(last+1024 == chunk.Base()+size);
       
   867 		}
       
   868 	
       
   869 	// try writing at the top end of it to make sure it's backed
       
   870 	*(chunk.Base()+size-1) = 1;
       
   871 	
       
   872 	// test resetting the heap
       
   873 	heap->Reset();
       
   874 	test(origsize == heap->Size());
       
   875 	
       
   876 	// check reducing the heap works
       
   877 	last = (TUint8*)heap->Alloc(size>>2);
       
   878 	TInt midsize = heap->Size();
       
   879 	temp = (TUint8*)heap->Alloc(size>>2);
       
   880 	heap->Free(temp);
       
   881 	heap->Compress();
       
   882 	test(midsize == heap->Size());
       
   883 	heap->Free(last);
       
   884 	heap->Compress();
       
   885 	test(origsize == heap->Size());
       
   886 	
       
   887 	// check the magic numbers are still there
       
   888 	for (reserved = chunk.Base(); reserved<limit; reserved++)
       
   889 		test(*reserved==magic);
       
   890 	
       
   891 	heap->Close();
       
   892 	}
       
   893 
       
   894 
       
   895 RSemaphore sem;
       
   896 LOCAL_C void syncThreads(TAny* anArg)
       
   897 //
       
   898 // get the threads both running at the same time
       
   899 //
       
   900 	{
       
   901 	if ((TInt)anArg==1)
       
   902 		sem.Wait();
       
   903 	else
       
   904 		sem.Signal();
       
   905 	}
       
   906 
       
   907 TInt comeInNumber=0;
       
   908 LOCAL_C TInt sharedHeapTest1(TAny* anArg)
       
   909 //
       
   910 // Shared heap test thread.
       
   911 //
       
   912 	{
       
   913 
       
   914 	RHeap* pH = (RHeap*)&User::Allocator();
       
   915 	if (gHeapPtr && pH!=gHeapPtr)
       
   916 		return(KErrGeneral);
       
   917 	gHeapPtr2 = pH;
       
   918 
       
   919 	syncThreads(anArg);
       
   920 
       
   921 	TAny* a[0x100];
       
   922 	TInt mod=((TInt)anArg)*3;
       
   923 
       
   924 	// Run in a timed loop, to ensure that we get some true concurrency
       
   925 	RTimer timer;
       
   926 	TTime now;
       
   927 	TRequestStatus done;
       
   928 	test(timer.CreateLocal()==KErrNone);
       
   929 	now.HomeTime();
       
   930 	timer.At(done,now+TTimeIntervalSeconds(20));
       
   931 
       
   932 	while (done==KRequestPending && comeInNumber!=(TInt)anArg)
       
   933 		{
       
   934 		TInt i=0;
       
   935 		for (;i<0x100;i++)
       
   936 			{
       
   937 			a[i]=User::Alloc(0x10);
       
   938 			test(a[i]!=NULL);
       
   939 			Mem::Fill(a[i],0x10,(((TInt)anArg)<<4)|(i&0x0F));	// marker
       
   940 			if ((i%mod)==0)
       
   941 				pH->Check();
       
   942 			}
       
   943 		for (i=0;i<0x100;i++)
       
   944 			{
       
   945 			User::Free(a[i]);
       
   946 			if ((i%mod)==0)
       
   947 				pH->Check();
       
   948 			}
       
   949 		}
       
   950 	timer.Cancel();
       
   951 	return((TInt)anArg);
       
   952 	}
       
   953 
       
   954 LOCAL_C void bumpKernelGranularity()
       
   955 //
       
   956 // Push up the kernels granularities
       
   957 //
       
   958 	{
       
   959 
       
   960 	RThread t[4];
       
   961 	TInt r;
       
   962 	TUint i=0;
       
   963 	for (;i<4;i++)
       
   964 		{
       
   965 		TName n;
       
   966 		n.Format(_L("Temp%d"),i);
       
   967 		r=t[i].Create(n,sharedHeapTest1,KDefaultStackSize,NULL,NULL);
       
   968 		test(r==KErrNone);
       
   969 		}
       
   970 	for (i=0;i<4;i++)
       
   971 		{
       
   972 		t[i].Kill(KErrNone);
       
   973 		t[i].Close();
       
   974 		}
       
   975 	}
       
   976 
       
   977 LOCAL_C void createTestThreads(TThreadFunction aFunction,RHeap* aHeap)
       
   978 //
       
   979 // Create two test threads using the supplied entry point and heap
       
   980 //
       
   981 	{
       
   982 
       
   983 
       
   984 	test.Next(_L("Create t1"));
       
   985 	RThread t1;
       
   986 	TInt r=t1.Create(_L("Shared1"),aFunction,KDefaultStackSize,aHeap,(TAny*)1);
       
   987 	test(r==KErrNone);
       
   988 	TRequestStatus tStat1;
       
   989 	t1.Logon(tStat1);
       
   990 	test(tStat1==KRequestPending);
       
   991 
       
   992 	test.Next(_L("Create t2"));
       
   993 	RThread t2;
       
   994 	r=t2.Create(_L("Shared2"),aFunction,KDefaultStackSize,aHeap,(TAny*)2);
       
   995 	test(r==KErrNone);
       
   996 	TRequestStatus tStat2;
       
   997 	t2.Logon(tStat2);
       
   998 	test(tStat2==KRequestPending);
       
   999 
       
  1000 	test.Next(_L("Wait for t1 or t2 - approx 20 seconds"));
       
  1001 	t1.Resume();
       
  1002 	t2.Resume();
       
  1003 	User::WaitForRequest(tStat1,tStat2);
       
  1004 	User::WaitForRequest(tStat1==KRequestPending ? tStat1 : tStat2);
       
  1005 	test(tStat1==1);
       
  1006 	test(tStat2==2);
       
  1007 	CLOSE_AND_WAIT(t1);
       
  1008 	CLOSE_AND_WAIT(t2);
       
  1009 	}
       
  1010 
       
  1011 LOCAL_C void SharedHeapTest1()
       
  1012 //
       
  1013 // Shared heap test using normal chunk heap
       
  1014 //
       
  1015 	{
       
  1016 
       
  1017 	sem.CreateLocal(0);	// create synchronisation semaphore
       
  1018 	test.Start(_L("Create chunk to share"));
       
  1019 	TPtrC sharedHeap=_L("SharedHeap");
       
  1020 	TInt minsize = ((RHeap&)User::Allocator()).Size();
       
  1021 	gHeapPtr=User::ChunkHeap(&sharedHeap,minsize/*0x20000*/,0x40000);
       
  1022 	test(gHeapPtr!=NULL);
       
  1023 	TInt count=gHeapPtr->Count();
       
  1024 	createTestThreads(sharedHeapTest1,gHeapPtr);
       
  1025 	test(count==gHeapPtr->Count());
       
  1026 	gHeapPtr->Close();
       
  1027 	test.End();
       
  1028 	}
       
  1029 
       
  1030 LOCAL_C void SharedHeapTest2()
       
  1031 //
       
  1032 // Shared heap test using the current threads heap. Can test kernel
       
  1033 // cleanup since granularity will have been handled by running
       
  1034 // SharedHeapTest2().
       
  1035 //
       
  1036 	{
       
  1037 
       
  1038 	test.Start(_L("Current chunk to share"));
       
  1039 	test.Next(_L("Bump up granularities"));
       
  1040 //
       
  1041 // First create a number of threads to push up the kernels granularities
       
  1042 //
       
  1043 	bumpKernelGranularity();
       
  1044 //
       
  1045 	__KHEAP_MARK;
       
  1046 	gHeapPtr = (RHeap*)&User::Allocator();
       
  1047 	TInt biggest1;
       
  1048 	TInt avail1=gHeapPtr->Available(biggest1);
       
  1049 	TInt size1=gHeapPtr->Size();
       
  1050 
       
  1051 	createTestThreads(sharedHeapTest1,NULL);
       
  1052 	
       
  1053 	TInt biggest2;
       
  1054 	TInt avail2=gHeapPtr->Available(biggest2);
       
  1055 	TInt size2=gHeapPtr->Size();
       
  1056 	test.Printf(_L("Before: size %d, %d available (biggest %d)\r\n"),size1,avail1,biggest1);
       
  1057 	test.Printf(_L("After:  size %d, %d available (biggest %d)\r\n"),size2,avail2,biggest2);
       
  1058 	test((size1-avail1)==(size2-avail2));	// no leaks
       
  1059 	if (avail1==biggest1)	// if it was a single block of free space before
       
  1060 		test(avail2==biggest2);	// then it should still be a single block
       
  1061 	__KHEAP_MARKEND;
       
  1062 	test.End();
       
  1063 	}
       
  1064 
       
  1065 LOCAL_C void SharedHeapTest3()
       
  1066 //
       
  1067 // Shared heap test borrowing a thread's default heap and
       
  1068 // killing threads in different orders.
       
  1069 //
       
  1070 	{
       
  1071 
       
  1072 	test.Start(_L("Create t1 whose heap will be shared"));
       
  1073 	gHeapPtr = NULL;
       
  1074 	RThread t1;
       
  1075 	TInt r=t1.Create(_L("Owner_T1"),sharedHeapTest1,KDefaultStackSize,0x20000,0x40000,(TAny*)1);
       
  1076 	test(r==KErrNone);
       
  1077 	TRequestStatus tStat1;
       
  1078 	t1.Logon(tStat1);
       
  1079 	test(tStat1==KRequestPending);
       
  1080 	t1.SetPriority(EPriorityMore); //t1 gets to wait on semaphore sem, before we start t2
       
  1081 	t1.Resume();
       
  1082 	test.Next(_L("Create t2 sharing t1's heap"));
       
  1083 	RThread t2;
       
  1084 	r=t2.Create(_L("Sharer_T2"),sharedHeapTest1,KDefaultStackSize,gHeapPtr2,(TAny*)2);
       
  1085 	test(r==KErrNone);
       
  1086 	TRequestStatus tStat2;
       
  1087 	t2.Logon(tStat2);
       
  1088 	test(tStat2==KRequestPending);
       
  1089 
       
  1090 	test.Next(_L("Get t1 to exit while t2 continues running"));
       
  1091 	test(tStat1==KRequestPending);
       
  1092 	test(tStat2==KRequestPending);
       
  1093 	t1.SetPriority(EPriorityNormal); //back to the same priority as t2
       
  1094 	t2.Resume();
       
  1095 	test(tStat1==KRequestPending);
       
  1096 	test(tStat2==KRequestPending);
       
  1097 	comeInNumber=1;
       
  1098 	test.Next(_L("Wait for t1"));
       
  1099 	User::WaitForRequest(tStat1);
       
  1100 	test(tStat1==1);
       
  1101 	test(t1.ExitType()==EExitKill);
       
  1102 	test(t1.ExitReason()==1);
       
  1103 	test(tStat2==KRequestPending);
       
  1104 	test(t2.ExitType()==EExitPending);
       
  1105 	test.Next(_L("Wait for t2"));
       
  1106 	User::WaitForRequest(tStat2);
       
  1107 	test(tStat2==2);
       
  1108 	test(t2.ExitType()==EExitKill);
       
  1109 	test(t2.ExitReason()==2);
       
  1110 	CLOSE_AND_WAIT(t2);
       
  1111 	CLOSE_AND_WAIT(t1);
       
  1112 	test.End();
       
  1113 	}
       
  1114 
       
  1115 LOCAL_C void TestAuto()
       
  1116 //
       
  1117 // Test heap auto expansion and compression
       
  1118 //
       
  1119 	{
       
  1120 
       
  1121 	test.Start(_L("Create chunk to"));
       
  1122 	TPtrC autoHeap=_L("AutoHeap");
       
  1123 	gHeapPtr=User::ChunkHeap(&autoHeap,0x1800,0x6000);
       
  1124 	test(gHeapPtr!=NULL);
       
  1125 	TInt biggest;
       
  1126 	TInt avail=gHeapPtr->Available(biggest);
       
  1127 	test(avail==biggest);
       
  1128 	TAny *p1=gHeapPtr->Alloc(biggest);
       
  1129 	test(p1!=NULL);
       
  1130 	TAny *p2=gHeapPtr->Alloc(biggest);
       
  1131 	test(p2!=NULL);
       
  1132 	TAny *p3=gHeapPtr->Alloc(biggest);
       
  1133 	test(p3!=NULL);
       
  1134 	TAny *p4=gHeapPtr->Alloc(biggest);
       
  1135 	test(p4==NULL);
       
  1136 	TInt comp=gHeapPtr->Compress();
       
  1137 	test(comp==0);
       
  1138 	gHeapPtr->Free(p2);
       
  1139 	comp=gHeapPtr->Compress();
       
  1140 	test(comp==0);
       
  1141 	gHeapPtr->Free(p3);
       
  1142 	comp=gHeapPtr->Compress();
       
  1143 // stop wins compiler warning of constant expression as KHeapShrinkHysRatio
       
  1144 // isn't constant for non-emulator builds but ROM 'patchdata'
       
  1145 #pragma warning(disable : 4127)
       
  1146 	// When hysteresis value > 4.0*GrowBy then Free() calls
       
  1147 	// won't shrink heap but normally will shrink heap
       
  1148 	if (KHeapShrinkHysRatio <= 1024)
       
  1149 		test(comp==0);
       
  1150 	else
       
  1151 		test(comp==0x4000);
       
  1152 #pragma warning(default : 4127)
       
  1153 	gHeapPtr->Free(p1);
       
  1154 	comp=gHeapPtr->Compress();
       
  1155 	test(comp==0);
       
  1156 	TInt biggest1;
       
  1157 	TInt avail1=gHeapPtr->Available(biggest1);
       
  1158 	test(avail1==avail1);
       
  1159 	test(biggest==biggest1);
       
  1160 	test(gHeapPtr->Count()==0);
       
  1161 	gHeapPtr->Close();
       
  1162 	test.End();
       
  1163 	}
       
  1164 
       
  1165 
       
  1166 GLDEF_C TInt E32Main(void)
       
  1167 	{
       
  1168 
       
  1169 	test.Title();
       
  1170 
       
  1171 	__KHEAP_MARK;
       
  1172 
       
  1173 	test.Start(_L("Test 1"));
       
  1174 	UserHal::PageSizeInBytes(PageSize);
       
  1175         TestRHeap T;
       
  1176 	T.Test1();
       
  1177 	test.Next(_L("Test auto expand and compress"));
       
  1178 	TestAuto();
       
  1179 	test.Next(_L("Test 2"));
       
  1180 	T.Test2();
       
  1181 	test.Next(_L("Test 3"));
       
  1182 	T.Test3();
       
  1183 	test.Next(_L("Test 4"));
       
  1184 	T.Test4();
       
  1185 	test.Next(_L("Test 5"));
       
  1186 	T.Test5();
       
  1187 	test.Next(_L("Test 7"));
       
  1188 	T.Test7();
       
  1189 	test.Next(_L("Test 8"));
       
  1190 	T.Test8();
       
  1191 	test.Next(_L("Test CompressAll()"));
       
  1192 	T.TestCompressAll();
       
  1193 	test.Next(_L("Test offset heap"));
       
  1194 	T.TestOffset();
       
  1195 	test.Next(_L("Shared heap test 1"));
       
  1196 	SharedHeapTest1();
       
  1197 	test.Next(_L("Shared heap test 2"));
       
  1198 	SharedHeapTest2();
       
  1199 	test.Next(_L("Shared heap test 3"));
       
  1200 	SharedHeapTest3();
       
  1201 	sem.Close();
       
  1202 
       
  1203 	__KHEAP_CHECK(0);
       
  1204 	__KHEAP_MARKEND;
       
  1205 //
       
  1206 	test.End();
       
  1207 	return(0);
       
  1208     }
       
  1209