kerneltest/e32test/heap/t_heap2.cpp
changeset 109 b3a1d9898418
parent 0 a41df078684a
child 257 3e88ff8f41d5
child 293 0659d0e1a03c
equal deleted inserted replaced
102:ef2a444a7410 109:b3a1d9898418
    42 
    42 
    43 #include <e32test.h>
    43 #include <e32test.h>
    44 #include <e32hal.h>
    44 #include <e32hal.h>
    45 #include <e32def.h>
    45 #include <e32def.h>
    46 #include <e32def_private.h>
    46 #include <e32def_private.h>
       
    47 #include "dla.h"
       
    48 #include "slab.h"
       
    49 #include "page_alloc.h"
       
    50 #include "heap_hybrid.h"
    47 
    51 
    48 // Needed for KHeapShrinkHysRatio which is now ROM 'patchdata'
    52 // Needed for KHeapShrinkHysRatio which is now ROM 'patchdata'
    49 #include "TestRHeapShrink.h"
    53 #include "TestRHeapShrink.h"
    50 
    54 
    51 #define DECL_GET(T,x)		inline T x() const {return i##x;}
    55 #define DECL_GET(T,x)		inline T x() const {return i##x;}
    56        IMPORT_D extern const TInt KHeapMinCellSize;
    60        IMPORT_D extern const TInt KHeapMinCellSize;
    57 #else
    61 #else
    58        const TInt KHeapMinCellSize = 0;
    62        const TInt KHeapMinCellSize = 0;
    59 #endif
    63 #endif
    60 
    64 
       
    65 	   const TInt KAllocCellSize = (TInt)RHeap::EAllocCellSize;
       
    66 	   const TInt KSizeOfHeap = (TInt)sizeof(RHybridHeap);	   
       
    67 	   
       
    68 	   
    61 RTest test(_L("T_HEAP2"));
    69 RTest test(_L("T_HEAP2"));
    62 
    70 
    63 #define	TEST_ALIGN(p,a)		test((TLinAddr(p)&((a)-1))==0)
    71 #define	TEST_ALIGN(p,a)		test((TLinAddr(p)&((a)-1))==0)
    64 
    72 
    65 struct STestCell
    73 struct STestCell
    76 
    84 
    77 void STestCell::Set(TInt aLength)
    85 void STestCell::Set(TInt aLength)
    78 	{
    86 	{
    79 	TInt i;
    87 	TInt i;
    80 	TUint32 x = (TUint32)this ^ (TUint32)aLength ^ (TUint32)EMagic;
    88 	TUint32 x = (TUint32)this ^ (TUint32)aLength ^ (TUint32)EMagic;
    81 	aLength -= RHeap::EAllocCellSize;
       
    82 	if (aLength==0)
    89 	if (aLength==0)
    83 		return;
    90 		return;
    84 	iLength = x;
    91 	iLength = x;
    85 	aLength /= sizeof(TUint32);
    92 	aLength /= sizeof(TUint32);
    86 	for (i=0; i<aLength-1; ++i)
    93 	for (i=0; i<aLength-1; ++i)
    98 
   105 
    99 void STestCell::Verify(const TAny* aInitPtr, TInt aInitLength, TInt aLength)
   106 void STestCell::Verify(const TAny* aInitPtr, TInt aInitLength, TInt aLength)
   100 	{
   107 	{
   101 	TInt i;
   108 	TInt i;
   102 	TUint32 x = (TUint32)aInitPtr ^ (TUint32)aInitLength ^ (TUint32)EMagic;
   109 	TUint32 x = (TUint32)aInitPtr ^ (TUint32)aInitLength ^ (TUint32)EMagic;
   103 	aLength -= RHeap::EAllocCellSize;
   110 	if ( aLength < (TInt) sizeof(*this) )
   104 	if (aLength==0)
       
   105 		return;
   111 		return;
   106 	test(iLength == x);
   112 	test(iLength == x);
   107 	aLength /= sizeof(TUint32);
   113 	aLength /= sizeof(TUint32);
   108 	for (i=0; i<aLength-1; ++i)
   114 	for (i=0; i<aLength-1; ++i)
   109 		{
   115 		{
   111 		x += 41;
   117 		x += 41;
   112 		test(iData[i] == x);
   118 		test(iData[i] == x);
   113 		}
   119 		}
   114 	}
   120 	}
   115 
   121 
       
   122 
       
   123 	
   116 class RTestHeap : public RHeap
   124 class RTestHeap : public RHeap
   117 	{
   125 	{
   118 public:
       
   119 	DECL_GET(TInt,AccessCount)
       
   120 	DECL_GET(TInt,HandleCount)
       
   121 	DECL_GET(TInt*,Handles)
       
   122 	DECL_GET(TUint32,Flags)
       
   123 	DECL_GET(TInt,CellCount)
       
   124 	DECL_GET(TInt,TotalAllocSize)
       
   125 	DECL_GET(TInt,MinLength)
       
   126 	DECL_GET(TInt,Offset)
       
   127 	DECL_GET(TInt,GrowBy)
       
   128 	DECL_GET(TInt,ChunkHandle)
       
   129 	DECL_GET2(const RFastLock&,Lock,LockRef)
       
   130 	DECL_GET(TUint8*,Top)
       
   131 	DECL_GET(TInt,Align)
       
   132 	DECL_GET(TInt,MinCell)
       
   133 	DECL_GET(TInt,PageSize)
       
   134 	DECL_GET2(const SCell&,Free,FreeRef)
       
   135 public:
   126 public:
   136 	TInt CheckAllocatedCell(const TAny* aCell) const;
   127 	TInt CheckAllocatedCell(const TAny* aCell) const;
   137 	void FullCheckAllocatedCell(const TAny* aCell) const;
   128 	void FullCheckAllocatedCell(const TAny* aCell) const;
   138 	TAny* TestAlloc(TInt aSize);
   129 	TAny* TestAlloc(TInt aSize);
   139 	void TestFree(TAny* aPtr);
   130 	void TestFree(TAny* aPtr);
   140 	TAny* TestReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0);
   131 	TAny* TestReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0);
   141 	void FullCheck();
   132 	void FullCheck();
   142 	static void WalkFullCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen);
   133 	static void WalkFullCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen);
   143 	TInt FreeCellLen(const TAny* aPtr) const;
       
   144 	static RTestHeap* FixedHeap(TInt aMaxLength, TInt aAlign=0, TBool aSingleThread=ETrue);
       
   145 	void TakeChunkOwnership(RChunk aChunk);
       
   146 	TInt LastFreeCellLen(void) const;
       
   147 	TInt CalcComp(TInt aCompSize);
       
   148 	void ForceCompress(TInt aFreed);
       
   149 	};
   134 	};
   150 
   135 
   151 TInt RTestHeap::CheckAllocatedCell(const TAny* aCell) const
   136 TInt RTestHeap::CheckAllocatedCell(const TAny* aCell) const
   152 	{
   137 	{
   153 	SCell* pC = GetAddress(aCell);
   138 	TInt len = AllocLen(aCell);
   154 	TInt len = pC->len;
       
   155 	TUint8* pEnd = (TUint8*)pC + len;
       
   156 	TEST_ALIGN(aCell, iAlign);
       
   157 	TEST_ALIGN(len, iAlign);
       
   158 	test(len >= iMinCell);
       
   159 	test((TUint8*)pC>=iBase && pEnd<=iTop);
       
   160 	return len;
   139 	return len;
   161 	}
   140 	}
   162 
   141 
   163 void RTestHeap::FullCheckAllocatedCell(const TAny* aCell) const
   142 void RTestHeap::FullCheckAllocatedCell(const TAny* aCell) const
   164 	{
   143 	{
   169 	{
   148 	{
   170 	TAny* p = Alloc(aSize);
   149 	TAny* p = Alloc(aSize);
   171 	if (p)
   150 	if (p)
   172 		{
   151 		{
   173 		TInt len = CheckAllocatedCell(p);
   152 		TInt len = CheckAllocatedCell(p);
   174 		test((len-RHeap::EAllocCellSize)>=aSize);
   153 		test(len>=aSize);		
   175 		((STestCell*)p)->Set(len);
   154 		((STestCell*)p)->Set(len);
   176 		}
   155 		}
   177 	return p;
   156 	return p;
   178 	}
   157 	}
   179 
   158 
   194 		{
   173 		{
   195 		((STestCell*)aPtr)->Verify(old_len);
   174 		((STestCell*)aPtr)->Verify(old_len);
   196 		return p;
   175 		return p;
   197 		}
   176 		}
   198 	TInt new_len = CheckAllocatedCell(p);
   177 	TInt new_len = CheckAllocatedCell(p);
   199 	test((new_len-RHeap::EAllocCellSize)>=aSize);
   178 	test(new_len>=aSize);		
   200 	if (p == aPtr)
   179 	if (p == aPtr)
   201 		{
   180 		{
   202 		((STestCell*)p)->Verify(p, old_len, Min(old_len, new_len));
   181 		((STestCell*)p)->Verify(p, old_len, Min(old_len, new_len));
   203 		if (new_len != old_len)
   182 		if (new_len != old_len)
   204 			((STestCell*)p)->Set(new_len);
   183 			((STestCell*)p)->Set(new_len);
   205 		return p;
   184 		return p;
   206 		}
   185 		}
   207 	test(!(aMode & ENeverMove));
   186 	test(!(aMode & ENeverMove));
   208 	test((new_len > old_len) || (aMode & EAllowMoveOnShrink));
   187 	test((new_len > old_len) || (aMode & EAllowMoveOnShrink));
   209 	if (old_len)
   188 	if (old_len)
   210 		((STestCell*)p)->Verify(aPtr, old_len, Min(old_len, new_len));
   189 		((STestCell*)p)->Verify(aPtr, old_len, Min(old_len, aSize));		
   211 	if (new_len != old_len)
   190     ((STestCell*)p)->Set(new_len);
   212 		((STestCell*)p)->Set(new_len);
       
   213 	return p;
   191 	return p;
   214 	}
   192 	}
   215 
   193 
   216 struct SHeapCellInfo
   194 struct SHeapCellInfo
   217 	{
   195 	{
   228 	::SHeapCellInfo& info = *(::SHeapCellInfo*)aPtr;
   206 	::SHeapCellInfo& info = *(::SHeapCellInfo*)aPtr;
   229 	switch(aType)
   207 	switch(aType)
   230 		{
   208 		{
   231 		case EGoodAllocatedCell:
   209 		case EGoodAllocatedCell:
   232 			{
   210 			{
   233 			test(aCell == info.iNextCell);
   211 			TInt len = aLen;
   234 			TInt len = ((SCell*)aCell)->len;
   212 			info.iTotalAllocSize += len;
   235 			test(len == aLen);
   213 			STestCell* pT = (STestCell*)aCell;
   236 			info.iNextCell += len;
       
   237 			++info.iTotalAlloc;
   214 			++info.iTotalAlloc;
   238 			info.iTotalAllocSize += (aLen-EAllocCellSize);
       
   239 			STestCell* pT = (STestCell*)((TUint8*)aCell + EAllocCellSize);
       
   240 			pT->Verify(len);
   215 			pT->Verify(len);
   241 			break;
   216 			break;
   242 			}
   217 			}
   243 		case EGoodFreeCell:
   218 		case EGoodFreeCell:
   244 			{
   219 			{
   245 			test(aCell == info.iNextCell);
       
   246 			TInt len = ((SCell*)aCell)->len;
       
   247 			test(len == aLen);
       
   248 			info.iNextCell += len;
       
   249 			++info.iTotalFree;
   220 			++info.iTotalFree;
   250 			break;
   221 			break;
   251 			}
   222 			}
   252 		default:
   223 		default:
   253 			test.Printf(_L("TYPE=%d ??\n"),aType);
   224 			test.Printf(_L("TYPE=%d ??\n"),aType);
   259 void RTestHeap::FullCheck()
   230 void RTestHeap::FullCheck()
   260 	{
   231 	{
   261 	::SHeapCellInfo info;
   232 	::SHeapCellInfo info;
   262 	Mem::FillZ(&info, sizeof(info));
   233 	Mem::FillZ(&info, sizeof(info));
   263 	info.iHeap = this;
   234 	info.iHeap = this;
   264 	info.iNextCell = iBase;
       
   265 	DebugFunction(EWalk, (TAny*)&WalkFullCheckCell, &info);
   235 	DebugFunction(EWalk, (TAny*)&WalkFullCheckCell, &info);
   266 	test(info.iNextCell == iTop);
   236 	TInt count = AllocSize(iTotalAllocSize);
   267 	test(info.iTotalAlloc == iCellCount);
   237 	test(info.iTotalAlloc == count);
   268 	test(info.iTotalAllocSize == iTotalAllocSize);
   238 	test(info.iTotalAllocSize == iTotalAllocSize);
   269 	}
   239 
   270 
       
   271 TInt RTestHeap::FreeCellLen(const TAny* aPtr) const
       
   272 	{
       
   273 	SCell* p = iFree.next;
       
   274 	SCell* q = (SCell*)((TUint8*)aPtr - EAllocCellSize);
       
   275 	for (; p && p!=q; p = p->next) {}
       
   276 	if (p == q)
       
   277 		return p->len - EAllocCellSize;
       
   278 	return -1;
       
   279 	}
       
   280 
       
   281 TInt RTestHeap::LastFreeCellLen(void) const
       
   282 	{
       
   283 	SCell* p = iFree.next;
       
   284 	if (p==NULL)
       
   285 		return -1;	
       
   286 	for (; p->next; p=p->next){}
       
   287 	return p->len;
       
   288 	}
       
   289 
       
   290 
       
   291 /** Checks whether a call to Compress() will actually perform a reduction 
       
   292 	of the heap.
       
   293 	Relies on the free last cell on the heap being cell that has just been freed
       
   294 	plus any extra.
       
   295 	Intended for use by t_heap2.cpp - DoTest4().  
       
   296 	@param aFreedSize The size in bytes of the cell that was freed
       
   297 */
       
   298 TInt RTestHeap::CalcComp(TInt aFreedSize)
       
   299 	{	
       
   300 	TInt largestCell=0;
       
   301 	largestCell = LastFreeCellLen();
       
   302 	// if the largest cell is too small or it would have been compressed by the
       
   303 	// free operation then return 0.
       
   304 	if (largestCell < iPageSize || aFreedSize >= KHeapShrinkHysRatio*(iGrowBy>>8))
       
   305 		{
       
   306 		return 0;			
       
   307 		}
       
   308 		else
       
   309 		{
       
   310 		return _ALIGN_DOWN(aFreedSize,iPageSize);
       
   311 		}	
       
   312 	}
   240 	}
   313 	
   241 	
   314 /** compress the heap if the KHeapShrinkRatio is too large for what we are
       
   315 	expecting in DoTest4().
       
   316 */
       
   317 void RTestHeap::ForceCompress(TInt aFreed)
       
   318 	{	
       
   319 	if (aFreed < KHeapShrinkHysRatio*(iGrowBy>>8))
       
   320 		{
       
   321 		Compress();
       
   322 		}
       
   323 	}
       
   324 RTestHeap* RTestHeap::FixedHeap(TInt aMaxLength, TInt aAlign, TBool aSingleThread)
       
   325 	{
       
   326 	RChunk c;
       
   327 	TInt bottom = 0x40000;
       
   328 	TInt top = bottom + aMaxLength;
       
   329 	TInt r = c.CreateDisconnectedLocal(bottom, top, top + bottom, EOwnerThread);
       
   330 	if (r!=KErrNone)
       
   331 		return NULL;
       
   332 	TUint8* base = c.Base() + bottom;
       
   333 	RTestHeap* h = (RTestHeap*)UserHeap::FixedHeap(base, aMaxLength, aAlign, aSingleThread);
       
   334 	if (!aAlign)
       
   335 		aAlign = RHeap::ECellAlignment;
       
   336 	test((TUint8*)h == base);
       
   337 	test(h->AccessCount() == 1);
       
   338 	test(h->HandleCount() == (aSingleThread ? 0 : 1));
       
   339 	test(h->Handles() == (aSingleThread ? NULL : (TInt*)&h->LockRef()));
       
   340 	test(h->Flags() == TUint32(RAllocator::EFixedSize | (aSingleThread ? RAllocator::ESingleThreaded : 0)));
       
   341 	test(h->CellCount() == 0);
       
   342 	test(h->TotalAllocSize() == 0);
       
   343 	test(h->MaxLength() == aMaxLength);
       
   344 	test(h->MinLength() == h->Top() - (TUint8*)h);
       
   345 	test(h->Offset() == 0);
       
   346 	test(h->GrowBy() == 0);
       
   347 	test(h->ChunkHandle() == 0);
       
   348 	test(h->Align() == aAlign);
       
   349 	TInt min_cell = _ALIGN_UP((KHeapMinCellSize + Max((TInt)RHeap::EAllocCellSize, (TInt)RHeap::EFreeCellSize)), aAlign);
       
   350 	TInt hdr_len = _ALIGN_UP(sizeof(RHeap) + RHeap::EAllocCellSize, aAlign) - RHeap::EAllocCellSize;
       
   351 	TInt user_len = _ALIGN_DOWN(aMaxLength - hdr_len, aAlign);
       
   352 	test(h->Base() == base + hdr_len);
       
   353 	test(h->MinCell() == min_cell);
       
   354 	test(h->Top() - h->Base() == user_len);
       
   355 	test(h->FreeRef().next == (RHeap::SCell*)h->Base());
       
   356 	h->TakeChunkOwnership(c);
       
   357 	return h;
       
   358 	}
       
   359 
       
   360 void RTestHeap::TakeChunkOwnership(RChunk aChunk)
       
   361 	{
       
   362 	iChunkHandle = aChunk.Handle();
       
   363 	++iHandleCount;
       
   364 	iHandles = &iChunkHandle;
       
   365 	}
       
   366 
       
   367 
       
   368 #define	ACCESS_COUNT(h)		(((RTestHeap*)h)->AccessCount())
       
   369 #define	HANDLE_COUNT(h)		(((RTestHeap*)h)->HandleCount())
       
   370 #define	HANDLES(h)			(((RTestHeap*)h)->Handles())
       
   371 #define	FLAGS(h)			(((RTestHeap*)h)->Flags())
       
   372 #define	CELL_COUNT(h)		(((RTestHeap*)h)->CellCount())
       
   373 #define	TOTAL_ALLOC_SIZE(h)	(((RTestHeap*)h)->TotalAllocSize())
       
   374 #define	MIN_LENGTH(h)		(((RTestHeap*)h)->MinLength())
       
   375 #define	OFFSET(h)			(((RTestHeap*)h)->Offset())
       
   376 #define	GROW_BY(h)			(((RTestHeap*)h)->GrowBy())
       
   377 #define	CHUNK_HANDLE(h)		(((RTestHeap*)h)->ChunkHandle())
       
   378 #define	LOCK_REF(h)			(((RTestHeap*)h)->LockRef())
       
   379 #define	TOP(h)				(((RTestHeap*)h)->Top())
       
   380 #define	ALIGN(h)			(((RTestHeap*)h)->Align())
       
   381 #define	MIN_CELL(h)			(((RTestHeap*)h)->MinCell())
       
   382 #define	PAGE_SIZE(h)		(((RTestHeap*)h)->PageSize())
       
   383 #define	FREE_REF(h)			(((RTestHeap*)h)->FreeRef())
       
   384 
       
   385 void DoTest1(RHeap* aH)
       
   386 	{
       
   387 	RTestHeap* h = (RTestHeap*)aH;
       
   388 	test.Printf(_L("Test Alloc: min=%x max=%x align=%d growby=%d\n"),
       
   389 						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
       
   390 	TInt l;
       
   391 	TAny* p = NULL;
       
   392 	TUint8* next = h->Base();
       
   393 	TUint8* top = h->Top();
       
   394 	TUint8* limit = (TUint8*)h + h->MaxLength();
       
   395 	TBool fixed = h->Flags() & RAllocator::EFixedSize;
       
   396 	for (l=1; l<=1024; ++l)
       
   397 		{
       
   398 		TInt remain1 = top - next;
       
   399 		TInt xl1 = _ALIGN_UP(Max((l+RHeap::EAllocCellSize), h->MinCell()), h->Align());
       
   400 		p = h->TestAlloc(l);
       
   401 		if ( (fixed && remain1 < xl1) || (next + xl1 > limit) )
       
   402 			{
       
   403 			test(p == NULL);
       
   404 			test(top == h->Top());
       
   405 			test.Printf(_L("Alloc failed at l=%d next=%08x\n"), l, next);
       
   406 			break;
       
   407 			}
       
   408 		test(p == next + RHeap::EAllocCellSize);
       
   409 		if (xl1 > remain1)
       
   410 			{
       
   411 			// no room for this cell
       
   412 			TInt g = h->GrowBy();
       
   413 			while (xl1 > remain1)
       
   414 				{
       
   415 				top += g;
       
   416 				remain1 += g;
       
   417 				}
       
   418 			}
       
   419 		test(top == h->Top());
       
   420 		if (xl1 + h->MinCell() > remain1)
       
   421 			{
       
   422 			// this cell fits but remainder is too small or nonexistent
       
   423 			xl1 = top - next;
       
   424 			next = top;
       
   425 			test(h->FreeRef().next == NULL);
       
   426 			}
       
   427 		else
       
   428 			{
       
   429 			// this cell fits and remainder can be reused
       
   430 			next += xl1;
       
   431 			}
       
   432 		test(aH->AllocLen(p) == xl1 - RHeap::EAllocCellSize);
       
   433 		}
       
   434 	h->FullCheck();
       
   435 	}
       
   436 
       
   437 void DoTest2(RHeap* aH)
       
   438 	{
       
   439 	RTestHeap* h = (RTestHeap*)aH;
       
   440 	test.Printf(_L("Test Free: min=%x max=%x align=%d growby=%d\n"),
       
   441 						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
       
   442 	TInt al;
       
   443 	TInt min = h->MinCell();
       
   444 	TBool pad = EFalse;
       
   445 	for (al=1; al<256; (void)((pad=!pad)!=0 || (al+=al+1)) )
       
   446 		{
       
   447 		TAny* p[32];
       
   448 		TInt last_len = 0;
       
   449 		TAny* last = NULL;
       
   450 		TInt i;
       
   451 		test.Printf(_L("al=%d pad=%d\n"), al, pad);
       
   452 		TUint8* top=0;
       
   453 		TAny* spare=0;
       
   454 		TBool heapReduced = EFalse;
       
   455 		for (i=0; i<32; ++i)
       
   456 			{
       
   457 			// Check whether the cell created for the allocation of al would end up
       
   458 			// including extra bytes from the last free cell that aren't enough
       
   459 			// to create a new free cell.
       
   460 			top = h->Top();
       
   461 			TInt freeLen=h->LastFreeCellLen();
       
   462 			TInt actualAllocBytes = Max(_ALIGN_UP(al + RHeap::EAllocCellSize, h->Align()), min);
       
   463 			TInt remainingBytes = freeLen - actualAllocBytes;
       
   464 			if (remainingBytes < min)
       
   465 				{
       
   466 				// Force the heap to grow so that once this allocation is freed
       
   467 				// the free cell left will be large enough to include the al allocation
       
   468 				// and to create a new free cell if necessary.
       
   469 				actualAllocBytes = _ALIGN_UP(actualAllocBytes + min, h->Align());
       
   470 				TAny* q = h->TestAlloc(actualAllocBytes);
       
   471 				// Check heap has grown
       
   472 				test(top < h->Top());
       
   473 				top = h->Top();
       
   474 				test(q!=NULL);
       
   475 				// Have grown the heap so allocate a cell as a place holder to stop
       
   476 				// the heap being shrunk and the actual cell we want to allocate from being the
       
   477 				// wrong size
       
   478 				spare=h->TestAlloc(8);
       
   479 				h->TestFree(q);
       
   480 				// Ensure heap wasn't shrunk after free
       
   481 				test(top == h->Top());
       
   482 				}
       
   483 			top = h->Top();
       
   484 			// Allocate the new 
       
   485 			p[i] = h->TestAlloc(al);
       
   486 			test(p[i]!=NULL);
       
   487 			if (remainingBytes < min)
       
   488 				{// now safe to free any padding as p[i] now allocated and its size can't change
       
   489 				h->TestFree(spare);
       
   490 				}
       
   491 			TInt tmp1=h->AllocLen(p[i]);
       
   492 			TInt tmp2=Max(_ALIGN_UP(al+RHeap::EAllocCellSize,h->Align()), min)-RHeap::EAllocCellSize;
       
   493 			test(tmp1 == tmp2);
       
   494 			}
       
   495 		last = (TUint8*)p[31] + _ALIGN_UP(Max((al + RHeap::EAllocCellSize), min), h->Align());
       
   496 		last_len = h->FreeCellLen(last);
       
   497 		test(last_len > 0);
       
   498 		if (pad)
       
   499 			{
       
   500 			test(h->TestAlloc(last_len) == last);
       
   501 			test(h->FreeRef().next == NULL);
       
   502 			}
       
   503 		else
       
   504 			last = NULL;
       
   505 		top = h->Top();
       
   506 		for (i=0,heapReduced=EFalse; i<32; ++i)
       
   507 			{
       
   508 			h->TestFree(p[i]);
       
   509 			TInt fl = h->FreeCellLen(p[i]);
       
   510 			TInt xfl = _ALIGN_UP(Max((al + RHeap::EAllocCellSize), h->MinCell()), h->Align()) - RHeap::EAllocCellSize;
       
   511 			if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
       
   512 				{
       
   513 				top = h->Top();
       
   514 				heapReduced = ETrue;
       
   515 				}
       
   516 
       
   517 			if (i < 31 || pad)
       
   518 				test(fl == xfl);
       
   519 			else
       
   520 				{
       
   521 				if (!heapReduced)
       
   522 					test(fl == xfl + RHeap::EAllocCellSize + last_len);
       
   523 				else
       
   524 					{
       
   525 					heapReduced = EFalse;
       
   526 					}
       
   527 				}
       
   528 			test(h->TestAlloc(al)==p[i]);
       
   529 			}
       
   530 		for (i=0,heapReduced=EFalse; i<31; ++i)
       
   531 			{
       
   532 			TInt j = i+1;
       
   533 			TUint8* q;
       
   534 			// Free to adjacent cells and check that the free cell left is the combined
       
   535 			// size of the 2 adjacent cells just freed
       
   536 			h->TestFree(p[i]);
       
   537 			h->TestFree(p[j]);
       
   538 			TInt fl = h->FreeCellLen(p[i]);
       
   539 			if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
       
   540 				{
       
   541 				top = h->Top();
       
   542 				heapReduced = ETrue;
       
   543 				}
       
   544 			TInt xfl = 2 * _ALIGN_UP(Max((al + RHeap::EAllocCellSize), h->MinCell()), h->Align()) - RHeap::EAllocCellSize;
       
   545 			if (j < 31 || pad)
       
   546 				test(fl == xfl);
       
   547 			else
       
   548 				{
       
   549 				if (!heapReduced)
       
   550 					test(fl == xfl + RHeap::EAllocCellSize + last_len);
       
   551 				else
       
   552 					{
       
   553 					heapReduced = EFalse;
       
   554 					}
       
   555 				}
       
   556 			test(h->FreeCellLen(p[j]) < 0);
       
   557 			test(h->TestAlloc(fl)==p[i]);
       
   558 			test(h->Top() == top);
       
   559 			h->TestFree(p[i]);
       
   560 			test(h->FreeCellLen(p[i]) == fl);
       
   561 			// test when you alloc a cell that is larger than cells just freed
       
   562 			// that its position is not the same as the freed cells
       
   563 			// will hold for all cells except top/last one
       
   564 			if (j < 31 && !pad && fl < last_len)
       
   565 				{
       
   566 				q = (TUint8*)h->TestAlloc(fl+1);
       
   567 				if (h->Top() > top)
       
   568 					top = h->Top();
       
   569 				test(h->Top() == top);
       
   570 				test(q > p[i]);
       
   571 				h->TestFree(q);
       
   572 				if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
       
   573 					{
       
   574 					top = h->Top();
       
   575 					heapReduced = ETrue;
       
   576 					}
       
   577 				}
       
   578 			// check cell that is just smaller than space but not small enough 
       
   579 			// for a new free cell to be created, is the size of whole free cell
       
   580 			test(h->TestAlloc(fl-min+1)==p[i]);
       
   581 			test(h->Top() == top);
       
   582 			test(h->AllocLen(p[i])==fl);
       
   583 			h->TestFree(p[i]);
       
   584 			// Check cell that is small enough for new free cell and alloc'd cell to be
       
   585 			// created at p[i] cell is created at p[i]
       
   586 			test(h->TestAlloc(fl-min)==p[i]);
       
   587 			test(h->Top() == top);
       
   588 			// check free cell is at expected position
       
   589 			q = (TUint8*)p[i] + fl - min + RHeap::EAllocCellSize;
       
   590 			test(h->FreeCellLen(q) == min - RHeap::EAllocCellSize);
       
   591 			// alloc 0 length cell at q, will work as new cell of min length will be created
       
   592 			test(h->TestAlloc(0) == q);
       
   593 			test(h->Top() == top);
       
   594 			h->TestFree(p[i]);
       
   595 			test(h->FreeCellLen(p[i]) == fl - min);
       
   596 			h->TestFree(q);
       
   597 			// again check free cells are combined
       
   598 			test(h->FreeCellLen(q) < 0);
       
   599 			test(h->FreeCellLen(p[i]) == fl);
       
   600 			// check reallocating the cells places them back to same positions
       
   601 			test(h->TestAlloc(al)==p[i]);
       
   602 			test(h->Top() == top);
       
   603 			test(h->TestAlloc(al)==p[j]);
       
   604 			test(h->Top() == top);
       
   605 			if (pad)
       
   606 				test(h->FreeRef().next == NULL);
       
   607 			}
       
   608 		for (i=0,heapReduced=EFalse; i<30; ++i)
       
   609 			{
       
   610 			TInt j = i+1;
       
   611 			TInt k = i+2;
       
   612 			TUint8* q;
       
   613 			// Free 3 adjacent cells and check free cell created is combined size
       
   614 			h->TestFree(p[i]);
       
   615 			h->TestFree(p[k]);
       
   616 			h->TestFree(p[j]);
       
   617 			h->FullCheck();
       
   618 			if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
       
   619 				{
       
   620 				top = h->Top();
       
   621 				heapReduced = ETrue;
       
   622 				}
       
   623 			TInt fl = h->FreeCellLen(p[i]);
       
   624 			TInt xfl = 3 * _ALIGN_UP(Max((al + RHeap::EAllocCellSize), h->MinCell()), h->Align()) - RHeap::EAllocCellSize;
       
   625 			if (k < 31 || pad)
       
   626 				test(fl == xfl);
       
   627 			else
       
   628 				{
       
   629 				if (!heapReduced)
       
   630 					test(fl == xfl + RHeap::EAllocCellSize + last_len);
       
   631 				else
       
   632 					{
       
   633 					heapReduced = EFalse;
       
   634 					}
       
   635 				}
       
   636 			test(h->FreeCellLen(p[j]) < 0);
       
   637 			test(h->FreeCellLen(p[k]) < 0);
       
   638 			//ensure created free cell is allocated to new cell of free cell size
       
   639 			test(h->TestAlloc(fl)==p[i]);
       
   640 			test(h->Top() == top);
       
   641 			h->TestFree(p[i]);
       
   642 			test(h->FreeCellLen(p[i]) == fl);
       
   643 			if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
       
   644 				top = h->Top();
       
   645 			if (k < 31 && !pad && fl < last_len)
       
   646 				{
       
   647 				// Test new cell one larger than free cell size is allocated somewhere else
       
   648 				q = (TUint8*)h->TestAlloc(fl+1);
       
   649 				if (h->Top() > top)
       
   650 					top = h->Top();
       
   651 				test(h->Top() == top); 
       
   652 				test(q > p[i]);
       
   653 				h->TestFree(q);
       
   654 				if (h->Top() < top) // heap was reduced due to small KHeapShrinkHysRatio and big KHeapMinCellSize
       
   655 					{
       
   656 					top = h->Top();
       
   657 					heapReduced = ETrue;
       
   658 					}
       
   659 				}
       
   660 			// check allocating cell just smaller than free cell size but
       
   661 			// too large for neew free cell to be created, is size of whole free cell
       
   662 			test(h->TestAlloc(fl-min+1)==p[i]);
       
   663 			test(h->Top() == top);
       
   664 			test(h->AllocLen(p[i])==fl);
       
   665 			h->TestFree(p[i]);
       
   666 			// ensure free cell is created this time as well as alloc'd cell
       
   667 			test(h->TestAlloc(fl-min)==p[i]);
       
   668 			test(h->Top() == top);
       
   669 			q = (TUint8*)p[i] + fl - min + RHeap::EAllocCellSize;
       
   670 			test(h->FreeCellLen(q) == min - RHeap::EAllocCellSize);
       
   671 			test(h->TestAlloc(0) == q);
       
   672 			test(h->Top() == top);
       
   673 			h->TestFree(p[i]);
       
   674 			test(h->FreeCellLen(p[i]) == fl - min);
       
   675 			h->TestFree(q);
       
   676 			test(h->FreeCellLen(q) < 0);
       
   677 			test(h->FreeCellLen(p[i]) == fl);
       
   678 			// realloc all cells and check heap not expanded
       
   679 			test(h->TestAlloc(al)==p[i]);
       
   680 			test(h->Top() == top);
       
   681 			test(h->TestAlloc(al)==p[j]);
       
   682 			test(h->Top() == top);
       
   683 			test(h->TestAlloc(al)==p[k]);
       
   684 			test(h->Top() == top);
       
   685 			// If padding than no space should left on heap
       
   686 			if (pad)
       
   687 				test(h->FreeRef().next == NULL);
       
   688 			}
       
   689 		// when padding this will free padding from top of heap
       
   690 		h->TestFree(last);
       
   691 		}
       
   692 	h->FullCheck();
       
   693 	}
       
   694 
       
   695 void DoTest3(RHeap* aH)
       
   696 	{
       
   697 	RTestHeap* h = (RTestHeap*)aH;
       
   698 	test.Printf(_L("Test ReAlloc: min=%x max=%x align=%d growby=%d\n"),
       
   699 						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
       
   700 	// allocate continuous heap cell, then free them and reallocate again
       
   701 	TInt al;
       
   702 	for (al=1; al<256; al+=al+1)
       
   703 		{
       
   704 		TAny* p0 = h->TestAlloc(al);
       
   705 		TInt al0 = h->AllocLen(p0);
       
   706 		h->TestFree(p0);
       
   707 		TAny* p1 = h->TestReAlloc(NULL, al, 0);
       
   708 		TInt al1 = h->AllocLen(p1);
       
   709 		test(p1 == p0);
       
   710 		test(al1 == al0);
       
   711 		h->TestFree(p1);
       
   712 		TAny* p2 = h->TestAlloc(1);
       
   713 		TAny* p3 = h->TestReAlloc(p2, al, 0);
       
   714 		test(p3 == p0);
       
   715 		TInt al3 = h->AllocLen(p3);
       
   716 		test(al3 == al0);
       
   717 		h->TestFree(p3);
       
   718 		TAny* p4 = h->TestAlloc(1024);
       
   719 		TAny* p5 = h->TestReAlloc(p4, al, 0);
       
   720 		test(p5 == p0);
       
   721 		TInt al5 = h->AllocLen(p5);
       
   722 		test(al5 == al0);
       
   723 		h->TestFree(p5);
       
   724 		}
       
   725 	TInt i;
       
   726 	TInt j;
       
   727 	for (j=0; j<30; j+=3)
       
   728 		{
       
   729 		TAny* p[30];
       
   730 		TInt ala[30];
       
   731 		TInt fla[30];
       
   732 		h->Reset();
       
   733 		for (i=0; i<30; ++i)
       
   734 			{
       
   735 			p[i] = h->TestAlloc(8*i*i);
       
   736 			ala[i] = h->AllocLen(p[i]);
       
   737 			fla[i] = 0;
       
   738 			}
       
   739 		for (i=1; i<30; i+=3)
       
   740 			{
       
   741 			h->TestFree(p[i]);
       
   742 			fla[i] = h->FreeCellLen(p[i]);
       
   743 			test(fla[i] == ala[i]);
       
   744 			test(h->FreeCellLen(p[i-1]) < 0);
       
   745 			test(h->FreeCellLen(p[i+1]) < 0);
       
   746 			}
       
   747 		h->FullCheck();
       
   748 		TInt al1 = _ALIGN_UP(Max((RHeap::EAllocCellSize + 1), h->MinCell()), h->Align());
       
   749 		// adjust al1 for some case when reallocated heap cell will not be shrinked because remainder will not big enough
       
   750 		// to form a new free cell due to a big KHeapMinCellSize value
       
   751 		TInt alaj = ala[j] + RHeap::EAllocCellSize;
       
   752 		if (al1 < alaj && alaj - al1 < h->MinCell())
       
   753 			al1 = alaj;
       
   754 		TAny* p1 = h->TestReAlloc(p[j], 1, RHeap::ENeverMove);
       
   755 		test(p1 == p[j]);
       
   756 		test(h->AllocLen(p1) == al1 - RHeap::EAllocCellSize);
       
   757 		TAny* p1b = (TUint8*)p1 + al1;
       
   758 		test(h->FreeCellLen(p1b) == fla[j+1] + RHeap::EAllocCellSize + ala[j] - al1);
       
   759 		TInt l2 = ala[j] + fla[j+1] + RHeap::EAllocCellSize; // max without moving
       
   760 		TInt l3 = l2 - h->MinCell();
       
   761 		TAny* p3 = h->TestReAlloc(p[j], l3, RHeap::ENeverMove);
       
   762 		test(p3 == p[j]);
       
   763 		TAny* p3b = (TUint8*)p3 + h->AllocLen(p3) + RHeap::EAllocCellSize;
       
   764 		test(h->FreeCellLen(p3b) == h->MinCell() - RHeap::EAllocCellSize);
       
   765 		TAny* p2 = h->TestReAlloc(p[j], l2, RHeap::ENeverMove);
       
   766 		test(p2 == p[j]);
       
   767 		test(h->AllocLen(p2) == l2);
       
   768 		TAny* p4 = h->TestReAlloc(p[j], l2+1, RHeap::ENeverMove);
       
   769 		test(p4 == NULL);
       
   770 		test(h->AllocLen(p2) == l2);
       
   771 		TAny* p5 = h->TestReAlloc(p[j], l2+1, 0);
       
   772 		TInt k = 0;
       
   773 		for (; k<30 && fla[k] <= l2; ++k) {}
       
   774 		if (k < 30)
       
   775 			test(p5 == p[k]);
       
   776 		else
       
   777 			test(p5 >= (TUint8*)p[29] + ala[29]);
       
   778 		test(h->FreeCellLen(p2) == ala[j] + ala[j+1] + RHeap::EAllocCellSize);
       
   779 		TInt ali = _ALIGN_UP(RHeap::EAllocCellSize,h->Align());
       
   780 		TAny* p6b = (TUint8*)p[j+2] + ala[j+2] - ali + RHeap::EAllocCellSize;
       
   781 		test(h->FreeCellLen(p6b) < 0);
       
   782 		TAny* p6 = h->TestReAlloc(p[j+2], ala[j+2] - ali , 0);
       
   783 		test(p6 == p[j+2]);
       
   784 		if (h->AllocLen(p6) != ala[j+2]) // allocated heap cell size changed
       
   785 			test(h->FreeCellLen(p6b) == h->MinCell() - RHeap::EAllocCellSize);
       
   786 		TInt g = h->GrowBy();
       
   787 		TAny* p7 = h->TestReAlloc(p5, 8*g, 0);
       
   788 		test(p7 >= p5);
       
   789 		TUint8* p8 = (TUint8*)p7 - RHeap::EAllocCellSize + al1;
       
   790 		TUint8* p9 = (TUint8*)_ALIGN_UP(TLinAddr(p8), h->PageSize());
       
   791 		if (p9-p8 < h->MinCell())
       
   792 			p9 += h->PageSize();
       
   793 		TAny* p7b = h->TestReAlloc(p7, 1, 0);
       
   794 		test(p7b == p7);
       
   795 		test(h->Top() + (RHeap::EAllocCellSize & (h->Align()-1)) == p9);
       
   796 
       
   797 		h->FullCheck();
       
   798 		}
       
   799 	}
       
   800 
       
   801 // Test compression
       
   802 // {1 free cell, >1 free cell} x {reduce cell, eliminate cell, reduce cell but too small}
       
   803 //
       
   804 void DoTest4(RHeap* aH)
       
   805 	{
       
   806 	RTestHeap* h = (RTestHeap*)aH;
       
   807 	test.Printf(_L("Test Compress: min=%x max=%x align=%d growby=%d\n"),
       
   808 						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
       
   809 	TInt page_size;
       
   810 	UserHal::PageSizeInBytes(page_size);
       
   811 	test(page_size == h->PageSize());
       
   812 	TInt g = h->GrowBy();
       
   813 	TEST_ALIGN(g, page_size);
       
   814 	test(g >= page_size);
       
   815 	RChunk c;
       
   816 	c.SetHandle(h->ChunkHandle());
       
   817 	TInt align = h->Align();
       
   818 	TInt minc = h->MinCell();
       
   819 
       
   820 	TInt orig_size = c.Size();
       
   821 	TUint8* orig_top = h->Top();
       
   822 
       
   823 	// size in bytes that last free cell on the top of the heap must be 
       
   824 	// before the heap will be shrunk, size must include the no of bytes to
       
   825 	// store the cell data/header i.e RHeap::EAllocCellSize
       
   826 	TInt shrinkThres = KHeapShrinkHysRatio*(g>>8);
       
   827 
       
   828 	TInt pass;
       
   829 	for (pass=0; pass<2; ++pass)
       
   830 		{
       
   831 		TUint8* p0 = (TUint8*)h->TestAlloc(4);
       
   832 		test(p0 == h->Base() + RHeap::EAllocCellSize);
       
   833 		TInt l1 = h->Top() - (TUint8*)h->FreeRef().next;
       
   834 		TEST_ALIGN(l1, align);
       
   835 		l1 -= RHeap::EAllocCellSize;
       
   836 		TUint8* p1;
       
   837 		// Grow heap by 2*iGrowBy bytes
       
   838 		p1 = (TUint8*)h->TestAlloc(l1 + 2*g);
       
   839 		test(p1 == p0 + h->AllocLen(p0) + RHeap::EAllocCellSize);
       
   840 		test(h->Top() - orig_top == 2*g);
       
   841 		test(c.Size() - orig_size == 2*g);
       
   842 		// May compress heap, may not
       
   843 		h->TestFree(p1);
       
   844 		h->ForceCompress(2*g);
       
   845 		test(h->Top() == orig_top);
       
   846 		test(c.Size() == orig_size);
       
   847 		test((TUint8*)h->FreeRef().next == p1 - RHeap::EAllocCellSize);
       
   848 		h->FullCheck();
       
   849 		//if KHeapShrinkHysRatio is > 2.0 then heap compression will occur here
       
   850 		test(h->Compress() == 0);
       
   851 		test(h->TestAlloc(l1) == p1);
       
   852 		test(h->FreeRef().next == NULL);
       
   853 		if (pass)
       
   854 			h->TestFree(p0);	// leave another free cell on second pass
       
   855 		TInt l2 = g - RHeap::EAllocCellSize;
       
   856 		// Will grow heap by iGrowBy bytes
       
   857 		TUint8* p2 = (TUint8*)h->TestAlloc(l2);
       
   858 		test(p2 == orig_top + RHeap::EAllocCellSize);
       
   859 		test(h->Top() - orig_top == g);
       
   860 		test(c.Size() - orig_size == g);
       
   861 		// may or may not compress heap
       
   862 		h->TestFree(p2);
       
   863 		if (l2+RHeap::EAllocCellSize >= shrinkThres)
       
   864 			{
       
   865 			// When KHeapShrinkRatio small enough heap will have been compressed
       
   866 			test(h->Top() == orig_top);			
       
   867 			if (pass)
       
   868 				{
       
   869 				test((TUint8*)h->FreeRef().next == p0 - RHeap::EAllocCellSize);
       
   870 				test((TUint8*)h->FreeRef().next->next == NULL);
       
   871 				}
       
   872 			else
       
   873 				test((TUint8*)h->FreeRef().next == NULL);
       
   874 			}
       
   875 		else
       
   876 			{			
       
   877 			test(h->Top() - orig_top == g);
       
   878 			if (pass)
       
   879 				{
       
   880 				test((TUint8*)h->FreeRef().next == p0 - RHeap::EAllocCellSize);
       
   881 				test((TUint8*)h->FreeRef().next->next == orig_top);
       
   882 				}
       
   883 			else
       
   884 				test((TUint8*)h->FreeRef().next == orig_top);
       
   885 			}
       
   886 		// this compress will only do anything if the KHeapShrinkRatio is large 
       
   887 		// enough to introduce hysteresis otherwise the heap would have been compressed 
       
   888 		// by the free operation itself
       
   889 		TInt tmp1,tmp2;
       
   890 		tmp2=h->CalcComp(g);
       
   891 		tmp1=h->Compress();
       
   892 		test(tmp1 == tmp2);
       
   893 		test(h->Top() == orig_top);
       
   894 		test(c.Size() == orig_size);
       
   895 		h->FullCheck();
       
   896 		// shouldn't compress heap as already compressed
       
   897 		test(h->Compress() == 0);
       
   898 		//grow heap by iGrowBy bytes
       
   899 		test(h->TestAlloc(l2) == p2);
       
   900 		//grow heap by iGrowBy bytes
       
   901 		TUint8* p3 = (TUint8*)h->TestAlloc(l2);
       
   902 		test(p3 == p2 + g);
       
   903 		test(h->Top() - orig_top == 2*g);
       
   904 		test(c.Size() - orig_size == 2*g);
       
   905 		// may or may not reduce heap
       
   906 		h->TestFree(p2);
       
   907 		// may or may not reduce heap
       
   908 		h->TestFree(p3);
       
   909 		h->ForceCompress(2*g);
       
   910 		test(h->Top() == orig_top);
       
   911 		test(c.Size() == orig_size);
       
   912 		h->FullCheck();
       
   913 		if (pass)
       
   914 			{
       
   915 			test((TUint8*)h->FreeRef().next == p0 - RHeap::EAllocCellSize);
       
   916 			test((TUint8*)h->FreeRef().next->next == NULL);
       
   917 			}
       
   918 		else
       
   919 			test((TUint8*)h->FreeRef().next == NULL);
       
   920 		//grow heap by iGrowBy bytes
       
   921 		test(h->TestAlloc(l2) == p2);
       
   922 		//grow heap by iGrowBy*2 + page size bytes
       
   923 		test(h->TestAlloc(l2 + g + page_size) == p3);
       
   924 		test(h->Top() - orig_top == 4*g);
       
   925 		test(c.Size() - orig_size == 4*g);
       
   926 		// will compress heap if KHeapShrinkHysRatio <= KHeapShrinkRatioDflt
       
   927 		test(h->TestReAlloc(p3, page_size - RHeap::EAllocCellSize, 0) == p3);
       
   928 		h->ForceCompress(g+page_size);
       
   929 		test(h->Top() - orig_top == g + page_size);
       
   930 		test(c.Size() - orig_size == g + page_size);
       
   931 		h->FullCheck();
       
   932 		// will compress heap if KHeapShrinkHysRatio <= KHeapShrinkRatio1
       
   933 		h->TestFree(p2);
       
   934 		// will compress heap if KHeapShrinkHysRatio <= KHeapShrinkRatio1 && g<=page_size
       
   935 		// or KHeapShrinkHysRatio >= 2.0 and g==page_size
       
   936 		h->TestFree(p3);
       
   937 		// may or may not perform further compression
       
   938 		tmp1=h->CalcComp(g+page_size);
       
   939 		tmp2=h->Compress();
       
   940 		test(tmp1 == tmp2);
       
   941 		test(h->Top() == orig_top);
       
   942 		test(c.Size() == orig_size);
       
   943 		h->FullCheck();
       
   944 		test(h->TestAlloc(l2 - minc) == p2);
       
   945 		test(h->TestAlloc(l2 + g + page_size + minc) == p3 - minc);
       
   946 		test(h->Top() - orig_top == 4*g);
       
   947 		test(c.Size() - orig_size == 4*g);
       
   948 		h->TestFree(p3 - minc);
       
   949 		h->ForceCompress(l2 + g + page_size + minc);
       
   950 		test(h->Top() - orig_top == g);
       
   951 		test(c.Size() - orig_size == g);
       
   952 		h->FullCheck();
       
   953 		if (pass)
       
   954 			{
       
   955 			test((TUint8*)h->FreeRef().next == p0 - RHeap::EAllocCellSize);
       
   956 			test((TUint8*)h->FreeRef().next->next == p3 - minc - RHeap::EAllocCellSize);
       
   957 			}
       
   958 		else
       
   959 			test((TUint8*)h->FreeRef().next == p3 - minc - RHeap::EAllocCellSize);
       
   960 		h->TestFree(p2);
       
   961 		if (l2+RHeap::EAllocCellSize >= shrinkThres)
       
   962 			{
       
   963 			// When KHeapShrinkRatio small enough heap will have been compressed
       
   964 			test(h->Top() == orig_top);
       
   965 			test(c.Size() - orig_size == 0);
       
   966 			}
       
   967 		else
       
   968 			{
       
   969 			test(h->Top() - orig_top == g);
       
   970 			test(c.Size() - orig_size == g);
       
   971 			}
       
   972 		h->FullCheck();
       
   973 		if ( ((TLinAddr)orig_top & (align-1)) == 0)
       
   974 			{
       
   975 			TAny* free;
       
   976 			TEST_ALIGN(p2 - RHeap::EAllocCellSize, page_size);
       
   977 			// will have free space of g-minc
       
   978 			test(h->TestAlloc(l2 + minc) == p2);
       
   979 			test(h->Top() - orig_top == 2*g);
       
   980 			test(c.Size() - orig_size == 2*g);
       
   981 			free = pass ? h->FreeRef().next->next : h->FreeRef().next;
       
   982 			test(free != NULL);
       
   983 			test(h->TestReAlloc(p2, l2 - 4, 0) == p2);
       
   984 			TInt freeSp = g-minc + (l2+minc - (l2-4));
       
   985 			TInt adjust = 0;
       
   986 			if (freeSp >= shrinkThres && freeSp-page_size >= minc)
       
   987 				{
       
   988 				// if page_size is less than growBy (g) then heap will be shrunk
       
   989 				// by less than a whole g.
       
   990 				adjust = g-((page_size<g)?page_size:0);
       
   991 				}
       
   992 			test(h->Top() - orig_top == 2*g - adjust);
       
   993 			test(c.Size() - orig_size == 2*g - adjust);
       
   994 			free = pass ? h->FreeRef().next->next : h->FreeRef().next;
       
   995 			test(free != NULL);
       
   996 			TEST_ALIGN(TLinAddr(free)+4, page_size);
       
   997 			test(h->TestAlloc(l2 + g + page_size + 4) == p3 - 4);
       
   998 			test(h->Top() - orig_top == 4*g - adjust);
       
   999 			test(c.Size() - orig_size == 4*g - adjust);
       
  1000 			h->TestFree(p3 - 4);
       
  1001 			h->ForceCompress(l2 + g + page_size + 4);
       
  1002 			test(h->Top() - orig_top == g + page_size);
       
  1003 			test(c.Size() - orig_size == g + page_size);
       
  1004 			h->FullCheck();
       
  1005 			h->TestFree(p2);
       
  1006 			h->ForceCompress(l2-4);
       
  1007 			test(h->Compress() == 0);
       
  1008 			// check heap is grown, will have free space of g-minc
       
  1009 			test(h->TestAlloc(l2 + minc) == p2);
       
  1010 			test(h->Top() - orig_top == 2*g);
       
  1011 			test(c.Size() - orig_size == 2*g);
       
  1012 			free = pass ? h->FreeRef().next->next : h->FreeRef().next;
       
  1013 			test(free != NULL);
       
  1014 			// may shrink heap as will now have g+minc free bytes
       
  1015 			test(h->TestReAlloc(p2, l2 - minc, 0) == p2);
       
  1016 			if (g+minc >= shrinkThres)
       
  1017 				{
       
  1018 				test(h->Top() - orig_top == g);
       
  1019 				test(c.Size() - orig_size == g);
       
  1020 				}
       
  1021 			else
       
  1022 				{
       
  1023 				test(h->Top() - orig_top == 2*g);
       
  1024 				test(c.Size() - orig_size == 2*g);
       
  1025 				}
       
  1026 			free = pass ? h->FreeRef().next->next : h->FreeRef().next;
       
  1027 			test(free != NULL);
       
  1028 			TEST_ALIGN(TLinAddr(free)+minc, page_size);
       
  1029 			test(h->TestAlloc(l2 + g + page_size + minc) == p3 - minc);
       
  1030 			test(h->Top() - orig_top == 4*g);
       
  1031 			test(c.Size() - orig_size == 4*g);
       
  1032 			h->TestFree(p3 - minc);
       
  1033 			h->ForceCompress(l2 + g + page_size + minc);
       
  1034 			test(h->Top() - orig_top == g);
       
  1035 			test(c.Size() - orig_size == g);
       
  1036 			h->FullCheck();
       
  1037 			h->TestFree(p2);
       
  1038 			}
       
  1039 
       
  1040 		h->TestFree(p1);
       
  1041 		if (pass == 0)
       
  1042 			h->TestFree(p0);
       
  1043 		h->Compress();
       
  1044 		}
       
  1045 	h->FullCheck();
       
  1046 	}
       
  1047 
       
  1048 void Test1()
       
  1049 	{
       
  1050 	RHeap* h;
       
  1051 	h = RTestHeap::FixedHeap(0x1000, 0);
       
  1052 	test(h != NULL);
       
  1053 	DoTest1(h);
       
  1054 	h->Close();
       
  1055 	h = RTestHeap::FixedHeap(0x1000, 0, EFalse);
       
  1056 	test(h != NULL);
       
  1057 	DoTest1(h);
       
  1058 	h->Close();
       
  1059 	h = RTestHeap::FixedHeap(0x10000, 64);
       
  1060 	test(h != NULL);
       
  1061 	DoTest1(h);
       
  1062 	h->Close();
       
  1063 	h = RTestHeap::FixedHeap(0x100000, 4096);
       
  1064 	test(h != NULL);
       
  1065 	DoTest1(h);
       
  1066 	h->Close();
       
  1067 	h = RTestHeap::FixedHeap(0x100000, 8192);
       
  1068 	test(h != NULL);
       
  1069 	DoTest1(h);
       
  1070 	h->Close();
       
  1071 	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x1000, 0x1000, 4);
       
  1072 	test(h != NULL);
       
  1073 	DoTest1(h);
       
  1074 	h->Close();
       
  1075 	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x10000, 0x1000, 4);
       
  1076 	test(h != NULL);
       
  1077 	DoTest1(h);
       
  1078 	h->Close();
       
  1079 	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 4096);
       
  1080 	test(h != NULL);
       
  1081 	DoTest1(h);
       
  1082 	h->Close();
       
  1083 	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 4);
       
  1084 	test(h != NULL);
       
  1085 	DoTest1(h);
       
  1086 	h->Reset();
       
  1087 	DoTest2(h);
       
  1088 	h->Reset();
       
  1089 	DoTest3(h);
       
  1090 	h->Reset();
       
  1091 	DoTest4(h);
       
  1092 	h->Close();
       
  1093 	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 8);
       
  1094 	test(h != NULL);
       
  1095 	DoTest1(h);
       
  1096 	h->Reset();
       
  1097 	DoTest2(h);
       
  1098 	h->Reset();
       
  1099 	DoTest3(h);
       
  1100 	h->Reset();
       
  1101 	DoTest4(h);
       
  1102 	h->Close();
       
  1103 	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 16);
       
  1104 	test(h != NULL);
       
  1105 	DoTest1(h);
       
  1106 	h->Reset();
       
  1107 	DoTest2(h);
       
  1108 	h->Reset();
       
  1109 	DoTest3(h);
       
  1110 	h->Reset();
       
  1111 	DoTest4(h);
       
  1112 	h->Close();
       
  1113 	h = UserHeap::ChunkHeap(&KNullDesC(), 0x1000, 0x100000, 0x1000, 32);
       
  1114 	test(h != NULL);
       
  1115 	DoTest1(h);
       
  1116 	h->Reset();
       
  1117 	DoTest2(h);
       
  1118 	h->Reset();
       
  1119 	DoTest3(h);
       
  1120 	h->Reset();
       
  1121 	DoTest4(h);
       
  1122 	h->Close();
       
  1123 	h = UserHeap::ChunkHeap(&KNullDesC(), 0x3000, 0x100000, 0x3000, 4);
       
  1124 	test(h != NULL);
       
  1125 	DoTest1(h);
       
  1126 	h->Reset();
       
  1127 	DoTest2(h);
       
  1128 	h->Reset();
       
  1129 	DoTest3(h);
       
  1130 	h->Reset();
       
  1131 	DoTest4(h);
       
  1132 	h->Close();
       
  1133 	}
       
  1134 
       
  1135 struct SHeapStress
   242 struct SHeapStress
  1136 	{
   243 	{
  1137 	RThread iThread;
   244 	RThread iThread;
  1138 	volatile TBool iStop;
   245 	volatile TBool iStop;
  1139 	TInt iAllocs;
   246 	TInt iAllocs;
  1275 	}
   382 	}
  1276 
   383 
  1277 void DoStressTest1(RAllocator* aAllocator)
   384 void DoStressTest1(RAllocator* aAllocator)
  1278 	{
   385 	{
  1279 	RTestHeap* h = (RTestHeap*)aAllocator;
   386 	RTestHeap* h = (RTestHeap*)aAllocator;
  1280 	test.Printf(_L("Test Stress 1: min=%x max=%x align=%d growby=%d\n"),
   387 	test.Printf(_L("Test Stress 1: max=%x\n"),	h->MaxLength());
  1281 						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
       
  1282 	SHeapStress hs;
   388 	SHeapStress hs;
  1283 	hs.iSeed = 0xb504f334;
   389 	hs.iSeed = 0xb504f334;
  1284 	hs.iAllocator = aAllocator;
   390 	hs.iAllocator = aAllocator;
  1285 	CreateStressThread(hs);
   391 	CreateStressThread(hs);
  1286 	User::After(10*1000000);
   392 	User::After(10*1000000);
  1290 	}
   396 	}
  1291 
   397 
  1292 void DoStressTest2(RAllocator* aAllocator)
   398 void DoStressTest2(RAllocator* aAllocator)
  1293 	{
   399 	{
  1294 	RTestHeap* h = (RTestHeap*)aAllocator;
   400 	RTestHeap* h = (RTestHeap*)aAllocator;
  1295 	test.Printf(_L("Test Stress 2: min=%x max=%x align=%d growby=%d\n"),
   401 	test.Printf(_L("Test Stress 2: max=%x\n"),	h->MaxLength());	
  1296 						h->MinLength(), h->MaxLength(), h->Align(), h->GrowBy());
       
  1297 	SHeapStress hs1;
   402 	SHeapStress hs1;
  1298 	SHeapStress hs2;
   403 	SHeapStress hs2;
  1299 	hs1.iSeed = 0xb504f334;
   404 	hs1.iSeed = 0xb504f334;
  1300 	hs1.iAllocator = aAllocator;
   405 	hs1.iAllocator = aAllocator;
  1301 	hs2.iSeed = 0xddb3d743;
   406 	hs2.iSeed = 0xddb3d743;
  1328 	}
   433 	}
  1329 		
   434 		
  1330 TInt TestHeapGrowInPlace(TInt aMode)
   435 TInt TestHeapGrowInPlace(TInt aMode)
  1331     {
   436     {
  1332     TBool reAllocs=EFalse;
   437     TBool reAllocs=EFalse;
  1333     TBool heapGrew=EFalse;
       
  1334     
       
  1335     RHeap* myHeap;
   438     RHeap* myHeap;
  1336     
   439 	//
  1337     myHeap = UserHeap::ChunkHeap(NULL,0x1000,0x4000,0x1000);
   440 	// Fixed DL heap used. 
       
   441 	//
       
   442 	myHeap = UserHeap::ChunkHeap(NULL,0x4000,0x4000,0x1000);
  1338     
   443     
  1339     TAny *testBuffer,*testBuffer2;
   444     TAny *testBuffer,*testBuffer2;
  1340     // Start size chosen so that 1st realloc will use up exactly all the heap.
   445     // Start size chosen so that 1st realloc will use up exactly all the heap.
  1341     // Later iterations wont, and there will be a free cell at the end of the heap.
   446     // Later iterations wont, and there will be a free cell at the end of the heap.
  1342     TInt currentSize = ((0x800) - sizeof(RHeap)) - RHeap::EAllocCellSize;
   447     TInt currentSize = ((0x800) - KSizeOfHeap) - KAllocCellSize;
  1343     TInt growBy = 0x800;
   448     TInt growBy = 0x800;
  1344     TInt newSpace, space;
   449 
  1345     
       
  1346     testBuffer2 = myHeap->Alloc(currentSize);
   450     testBuffer2 = myHeap->Alloc(currentSize);
  1347 
   451 
  1348     newSpace = myHeap->Size();
       
  1349     do 
   452     do 
  1350     {
   453     {
  1351     	space = newSpace;
   454     	testBuffer = testBuffer2;
  1352 		testBuffer = testBuffer2;
       
  1353 	    currentSize+=growBy;
   455 	    currentSize+=growBy;
  1354 		testBuffer2 = myHeap->ReAlloc(testBuffer,currentSize,aMode);	
   456 		testBuffer2 = myHeap->ReAlloc(testBuffer,currentSize,aMode);	
  1355 		
       
  1356 		newSpace = myHeap->Size();
       
  1357 		
   457 		
  1358 		if (testBuffer2) 
   458 		if (testBuffer2) 
  1359 			{
   459 			{
  1360 				
   460 				
  1361 			if (testBuffer!=testBuffer2)
   461 			if (testBuffer!=testBuffer2)
  1362 					reAllocs = ETrue;
   462 					reAllocs = ETrue;
  1363 				
       
  1364 			if (newSpace>space)
       
  1365 					heapGrew = ETrue;
       
  1366 			}
   463 			}
  1367 		growBy-=16;
   464 		growBy-=16;
  1368  	} while (testBuffer2);
   465  	} while (testBuffer2);
  1369     currentSize-=growBy;	
   466     currentSize-=growBy;	
  1370     
   467     
  1374     // How did we do?
   471     // How did we do?
  1375     if (reAllocs) 
   472     if (reAllocs) 
  1376     	{
   473     	{
  1377     	test.Printf(_L("Failure - Memory was moved!\n"));
   474     	test.Printf(_L("Failure - Memory was moved!\n"));
  1378     	return -100;
   475     	return -100;
  1379     	}
       
  1380     if (!heapGrew) 
       
  1381     	{
       
  1382     	test.Printf(_L("Failure - Heap Never Grew!\n"));
       
  1383     	return -200;
       
  1384     	}
   476     	}
  1385     if (currentSize<= 0x3000) 
   477     if (currentSize<= 0x3000) 
  1386     	{
   478     	{
  1387     	test.Printf(_L("Failed to grow by a reasonable amount!\n"));
   479     	test.Printf(_L("Failed to grow by a reasonable amount!\n"));
  1388     	return -300;
   480     	return -300;
  1438 
   530 
  1439 	// close the heap that got created earlier
   531 	// close the heap that got created earlier
  1440 	TestDEF078391Heap->Close();
   532 	TestDEF078391Heap->Close();
  1441 	}
   533 	}
  1442 
   534 
       
   535 void PageBitmapGrowTest()
       
   536 	{
       
   537 	// Create a large heap to allocate 4 Mb memory (64 * 68 kb).
       
   538 	test.Next(_L("Allocate 64 * 68 kbytes to cause page bitmap growing"));
       
   539 	RHeap* myHeap;
       
   540 	myHeap = UserHeap::ChunkHeap(NULL,0x1000,0x500000,0x1000);
       
   541 	test(myHeap!=NULL);
       
   542 	TInt OrigSize = myHeap->Size();	
       
   543 	TUint8* cell[64];
       
   544 		// allocate all cells
       
   545 	TInt i;
       
   546 	RTestHeap* h = (RTestHeap*)myHeap;
       
   547 	for (i=0; i<64; ++i)
       
   548 		{
       
   549 		cell[i] = (TUint8*)h->TestAlloc(0x11000);
       
   550 		test(cell[i]!=NULL);
       
   551     	}
       
   552 	h->FullCheck();
       
   553 	
       
   554 	// Release all allocated buffers by reseting heap
       
   555 	TInt Size = myHeap->Size();
       
   556 	test(Size > 0x400000);	
       
   557 	myHeap->Reset();
       
   558 	TInt Count = myHeap->AllocSize(Size);
       
   559  	test(Count==0);
       
   560 	test(Size==0);
       
   561 	Size = myHeap->Size();
       
   562 	test(Size==OrigSize);
       
   563 	
       
   564 	h->Close();
       
   565 	
       
   566 	}
       
   567 	
  1443 TInt E32Main()
   568 TInt E32Main()
  1444 	{
   569 	{
  1445 	test.Title();
   570 	test.Title();
  1446 	__KHEAP_MARK;
   571 	__KHEAP_MARK;
  1447 	test.Start(_L("Testing heaps"));
   572 	test.Start(_L("Testing heaps"));
  1448 	TestDEF078391();
   573 	TestDEF078391();
  1449 	Test1();
       
  1450 	StressTests();
   574 	StressTests();
  1451 	ReAllocTests();
   575 	ReAllocTests();
       
   576 	//
       
   577 	// Some special tests for slab- and paged allocator
       
   578 	//
       
   579 	PageBitmapGrowTest();	
  1452 	test.End();
   580 	test.End();
  1453 	__KHEAP_MARKEND;
   581 	__KHEAP_MARKEND;
  1454 	return 0;
   582 	return 0;
  1455 	}
   583 	}