kerneltest/e32test/heap/t_heapdl.cpp
changeset 109 b3a1d9898418
child 252 0a40b8675b23
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/heap/t_heapdl.cpp	Fri May 14 17:13:29 2010 +0300
@@ -0,0 +1,495 @@
+// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\heap\t_heapdl.cpp
+// Overview:
+// Tests RHybridHeap class.
+// API Information:
+// RHybridHeap
+// Details:
+// 
+//
+
+#include <e32test.h>
+#include <e32math.h>
+#include <e32def_private.h>
+#include "dla.h"
+#include "slab.h"
+#include "page_alloc.h"
+#include "heap_hybrid.h"
+
+const TInt KHeadSize = (TInt)RHeap::EAllocCellSize;
+
+class TestHybridHeap
+  {
+public:
+  static void TopSize(TInt& aTopSize, const RHybridHeap * aHybridHeap);
+  static void DvSize(TInt& aDvSize, const RHybridHeap * aHybridHeap);
+  static void SmallMap(TUint& aSmallMap, const RHybridHeap * aHybridHeap);
+  static void TreeMap(TUint& aTreeMap, const RHybridHeap * aHybridHeap);
+  static void TrimCheck(TInt& aTrimCheck, const RHybridHeap * aHybridHeap);
+  static void GrowBy(TInt& aGrowBy, const RHybridHeap * aHybridHeap);
+  static void PageSize(TInt& aPageSize, const RHybridHeap * aHybridHeap);
+  };
+
+
+void TestHybridHeap::TopSize(TInt& aTopSize, const RHybridHeap * aHybridHeap)
+  {
+  aTopSize = aHybridHeap->iGlobalMallocState.iTopSize;
+  }
+
+
+void TestHybridHeap::DvSize(TInt& aDvSize, const RHybridHeap * aHybridHeap)
+  {
+  aDvSize = aHybridHeap->iGlobalMallocState.iDvSize;
+  }
+
+
+void TestHybridHeap::SmallMap(TUint& aSmallMap, const RHybridHeap * aHybridHeap)
+  {
+  aSmallMap = aHybridHeap->iGlobalMallocState.iSmallMap;
+  }
+
+
+void TestHybridHeap::TreeMap(TUint& aTreeMap, const RHybridHeap * aHybridHeap)
+  {
+  aTreeMap = aHybridHeap->iGlobalMallocState.iTreeMap;
+  }
+
+
+void TestHybridHeap::TrimCheck(TInt& aTrimCheck, const RHybridHeap * aHybridHeap)
+  {
+  aTrimCheck = aHybridHeap->iGlobalMallocState.iTrimCheck;
+  }
+
+
+void TestHybridHeap::GrowBy(TInt& aGrowBy, const RHybridHeap * aHybridHeap)
+  {
+  aGrowBy = aHybridHeap->iGrowBy;
+  }
+
+void TestHybridHeap::PageSize(TInt& aPageSize, const RHybridHeap * aHybridHeap)
+  {
+  aPageSize = aHybridHeap->iPageSize;
+  }
+
+
+LOCAL_D RTest test(_L("T_HEAPDL"));
+
+
+class TestRHeap
+  {
+public:
+  void InitTests();
+  void Test1(void);
+  void Test2(void);
+  void Test3(void);
+  void Test4(void);
+  void CloseTests();
+private:
+  RHybridHeap* iHybridHeap;
+  RHeap *iHeap;
+  };
+
+
+void TestRHeap::InitTests()
+  {
+  // Allocate a chunk heap
+  TPtrC testHeap=_L("TESTHEAP");
+  iHeap=User::ChunkHeap(&testHeap,0x1800,0x16000);
+        
+  RHybridHeap::STestCommand cmd;
+  cmd.iCommand = RHybridHeap::EHeapMetaData;
+  iHeap->DebugFunction(RHeap::EHybridHeap, (TAny*)&cmd );
+  iHybridHeap = (RHybridHeap*) cmd.iData;
+  }
+
+
+void TestRHeap::Test1(void)
+  {
+  //
+  //  Splitting a new cell off 'top' chunk
+  //  Growing and shrinking 'top' chunk
+  //  Coalesceing of adjacent free cells
+  //
+    
+  TInt topSizeBefore, topSizeAfter, allocSize;
+  TInt growBy, pageSize;
+  TestHybridHeap::GrowBy(growBy,iHybridHeap);
+  TestHybridHeap::PageSize(pageSize,iHybridHeap);
+        
+  //Splitting a new cell off 'top' chunk
+  TestHybridHeap::TopSize(topSizeBefore,iHybridHeap);
+  TAny* p1=iHeap->Alloc(0x256);
+  TestHybridHeap::TopSize(topSizeAfter,iHybridHeap);
+  test(topSizeBefore > topSizeAfter);
+  iHeap->Check();
+  iHeap->Free(p1);
+  iHeap->Check();
+    
+  //Growing 'top' chunk
+  test(iHeap!=NULL);
+  TestHybridHeap::TopSize(topSizeBefore,iHybridHeap);
+  p1=iHeap->Alloc(pageSize*2); 
+  test(p1!=NULL);
+  allocSize=iHeap->AllocLen(p1);
+  TestHybridHeap::TopSize(topSizeAfter,iHybridHeap);
+  test(topSizeBefore + growBy == topSizeAfter+allocSize+KHeadSize);
+    
+  //Splitting a new cell off 'top' chunk
+  TAny *p2=iHeap->Alloc(pageSize/8); 
+  test(p2!=NULL);
+  //Splitting a new cell off 'top' chunk
+  TAny *p3=iHeap->Alloc(pageSize/2); 
+  test(p3!=NULL);
+  //Growing 'top' chunk
+  TAny *p4=iHeap->Alloc(pageSize*2); 
+  test(p4!=NULL);
+  //Take allocSize of p4
+  allocSize=iHeap->AllocLen(p4);
+    
+  //Shrinking 'top' chunk
+  TInt trimCheck;
+  TestHybridHeap::TopSize(topSizeBefore,iHybridHeap);
+  iHeap->Free(p4);
+  TestHybridHeap::TopSize(topSizeAfter,iHybridHeap);
+  TestHybridHeap::TrimCheck(trimCheck,iHybridHeap);
+  test(topSizeAfter + trimCheck == topSizeBefore+allocSize+KHeadSize);
+  iHeap->Check();
+  
+  //Insert chunk into treebin
+  TUint treeMap,treeMap2;
+  TestHybridHeap::TreeMap(treeMap,iHybridHeap);
+  test(treeMap==0);
+  iHeap->Free(p2);
+  TestHybridHeap::TreeMap(treeMap,iHybridHeap);
+  test(treeMap>0);
+  iHeap->Check();
+    
+  //Coalesce adjacent free cells and insert chunk into treebin
+  TestHybridHeap::TreeMap(treeMap,iHybridHeap);
+  iHeap->Free(p1);
+  TestHybridHeap::TreeMap(treeMap2,iHybridHeap);
+  test(treeMap < treeMap2);
+  iHeap->Check();
+    
+  //free last allocation
+  iHeap->Free(p3);
+  iHeap->Check();
+  }
+
+
+void TestRHeap::Test2(void)
+  {
+  //
+  // Allocation of exact sized cells from 'small cell' lists (smallbin)
+  // Freeing of exact sized cells back to 'small cell' lists (smallbin)
+  //
+  TInt ArraySize=32;
+  TInt cellSize=0;
+  TInt topSizeBefore, topSizeAfter;
+     
+  TAny** ArrayOfCells;
+  ArrayOfCells= new TAny*[ArraySize];
+  TInt ArrayIndex;
+  // Allocate exact sized small cells 8,16,32,40--->
+  // and put them to the array. They are allocated from TOP chunk
+  for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++)
+    {
+    TestHybridHeap::TopSize(topSizeBefore,iHybridHeap);
+    cellSize=cellSize+8;
+    ArrayOfCells[ArrayIndex]=iHeap->Alloc(cellSize);
+    TestHybridHeap::TopSize(topSizeAfter,iHybridHeap);
+    test(topSizeBefore > topSizeAfter);
+    }
+  iHeap->Check();
+  
+  TUint smallMap, smallMap2;
+  TInt dvSize, dvSize2;
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  test(smallMap == 0);
+  // Free some of small cells from the array. So they are inserted
+  // to the smallbin
+  for(ArrayIndex=2; ArrayIndex<ArraySize-1; ArrayIndex+=5)
+    {
+    TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+    iHeap->Free(ArrayOfCells[ArrayIndex]);
+    TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+    test(smallMap<smallMap2);
+    }
+  iHeap->Check();
+    
+  // Allocate exact sized cells from smallbin (or Designated Victim)   
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  TAny* p1=iHeap->Alloc(32);
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  test(smallMap>smallMap2);
+    
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize,iHybridHeap);
+  TAny* p2=iHeap->Alloc(32);
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize2,iHybridHeap);
+  if(dvSize <= dvSize2)
+    test(smallMap>smallMap2);
+    
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize,iHybridHeap);
+  TAny* p3=iHeap->Alloc(32);
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize2,iHybridHeap);
+  if(dvSize <= dvSize2)
+  	test(smallMap>smallMap2);
+   
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize,iHybridHeap);
+  TAny* p4=iHeap->Alloc(32);
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize2,iHybridHeap);
+  if(dvSize <= dvSize2)
+    test(smallMap>smallMap2);
+   
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize,iHybridHeap);
+  TAny* p5=iHeap->Alloc(48);
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize2,iHybridHeap);
+  if(dvSize <= dvSize2)
+    test(smallMap>smallMap2);
+    
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize,iHybridHeap);
+  TAny* p6=iHeap->Alloc(64);
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize2,iHybridHeap);
+  if(dvSize <= dvSize2)
+    test(smallMap>smallMap2);
+   
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize,iHybridHeap);
+  TAny* p7=iHeap->Alloc(80);
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize2,iHybridHeap);
+  if(dvSize <= dvSize2)
+    test(smallMap>smallMap2);
+   
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize,iHybridHeap);
+  TAny* p8=iHeap->Alloc(96);
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  TestHybridHeap::DvSize(dvSize2,iHybridHeap);
+  if(dvSize <= dvSize2)
+    test(smallMap>smallMap2);
+  iHeap->Check();
+  
+  // Freeing of exact sized cells back to smallbin
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  iHeap->Free(p1);
+  iHeap->Free(p2);
+  iHeap->Free(p3);
+  iHeap->Free(p4);
+  iHeap->Free(p5);
+  iHeap->Free(p6);
+  iHeap->Free(p7);
+  iHeap->Free(p8);
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  test(smallMap < smallMap2);
+  iHeap->Check();
+  
+  // Now free rest of the array with Reset
+  iHeap->Reset();
+  iHeap->Check();
+  
+  delete [] ArrayOfCells;
+  }
+
+
+void TestRHeap::Test3(void)
+  {
+  //
+  // Allocation of approximate sized cells from 'small cell' lists (smallbin)
+  //
+  TInt ArraySize=32;
+  TInt cellSize=0;
+  TAny** ArrayOfCells;
+  ArrayOfCells= new TAny*[ArraySize];
+  TInt ArrayIndex;
+  TInt topSizeBefore, topSizeAfter;
+    
+  // Allocate small approximate sized cells and put
+  //them to the array. They are allocated from TOP chunk
+  TUint8 randomSize;
+  for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++)
+    {
+    TestHybridHeap::TopSize(topSizeBefore,iHybridHeap);
+    do
+      {
+      randomSize= (TUint8)Math::Random();
+      }
+    while (randomSize>240);
+       
+  	cellSize=randomSize;
+  	ArrayOfCells[ArrayIndex]=iHeap->Alloc(cellSize);
+  	TestHybridHeap::TopSize(topSizeAfter,iHybridHeap);
+  	test(topSizeBefore > topSizeAfter);
+  	}
+  iHeap->Check();
+  
+  TUint smallMap, smallMap2;
+  // Free some of allocated cells from the array. So they are inserted
+  // to the smallbin
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  for(ArrayIndex=2; ArrayIndex<ArraySize-1; ArrayIndex+=5)
+    {
+    iHeap->Free(ArrayOfCells[ArrayIndex]);
+    }
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  test(smallMap<=smallMap2);
+  iHeap->Check();
+  
+  // Allocate approximate sized cells from smallbin
+  TInt ArraySize2=6;
+  TInt cellSize2=0;    
+  TAny** ArrayOfCells2;
+  ArrayOfCells2= new TAny*[ArraySize2];
+  TInt ArrayIndex2;
+  TestHybridHeap::SmallMap(smallMap,iHybridHeap);
+  for(ArrayIndex2=0; ArrayIndex2<ArraySize2;ArrayIndex2++)
+    {
+    TUint8 randomSize2 = (TUint8)Math::Random();
+    cellSize2=(randomSize2);
+    ArrayOfCells2[ArrayIndex2]=iHeap->Alloc(cellSize2);
+    }
+  TestHybridHeap::SmallMap(smallMap2,iHybridHeap);
+  test(smallMap>=smallMap2);              
+  iHeap->Check();
+  
+  // Freeing of approximate sized cells back to smallbin
+  for(ArrayIndex2=0; ArrayIndex2<ArraySize2-1; ArrayIndex2+=1)
+    {
+    iHeap->Free(ArrayOfCells2[ArrayIndex2]);
+    }
+  iHeap->Check();
+  
+  // Now free rest of the array with Reset
+  iHeap->Reset();
+  iHeap->Check();
+  
+  delete [] ArrayOfCells;
+  delete [] ArrayOfCells2; 
+  }
+
+
+void TestRHeap::Test4(void)
+  {
+  //
+  // Allocation of approximate sized cells from digital trees (treebin) and splitting
+  // Freeing of approximate sized cells back to digital trees (treebin)
+  //
+  TInt ArraySize=32;
+  TInt cellSize=0;
+  TAny** ArrayOfCells;
+  ArrayOfCells= new TAny*[ArraySize];
+  TInt ArrayIndex;
+        
+  // Allocate approximate sized cells bigger than 256
+  // and put them to the array. They are allocated from TOP chunk
+  for(ArrayIndex=0; ArrayIndex<ArraySize;ArrayIndex++)
+    {
+    TUint8 randomSize = (TUint8)Math::Random();
+    cellSize=(randomSize+256);
+    ArrayOfCells[ArrayIndex]=iHeap->Alloc(cellSize);
+    }
+  iHeap->Check();
+  
+  TUint treeMap,treeMap2;    
+  // Free some of allocated cells from the array. So they are inserted
+  // to the treebin
+  for(ArrayIndex=2; ArrayIndex<ArraySize-1; ArrayIndex+=5)
+    {
+    TestHybridHeap::TreeMap(treeMap,iHybridHeap);
+    iHeap->Free(ArrayOfCells[ArrayIndex]);
+    TestHybridHeap::TreeMap(treeMap2,iHybridHeap);
+    test(treeMap <= treeMap2);
+    }
+  iHeap->Check();
+  
+  // Allocate approximate sized cells from treebin
+  TInt ArraySize2=16;
+  TInt cellSize2=0;    
+  TAny** ArrayOfCells2;
+  ArrayOfCells2= new TAny*[ArraySize2];
+  TInt ArrayIndex2;
+  for(ArrayIndex2=0; ArrayIndex2<ArraySize2;ArrayIndex2++)
+    {
+    TestHybridHeap::TreeMap(treeMap,iHybridHeap);
+    TUint8 randomSize2 = (TUint8)Math::Random();
+    cellSize2=(randomSize2+256);
+    ArrayOfCells2[ArrayIndex2]=iHeap->Alloc(cellSize2);
+    TestHybridHeap::TreeMap(treeMap2,iHybridHeap);
+    test(treeMap >= treeMap2);
+    }
+  iHeap->Check();
+  
+  // Freeing of approximate sized cells back to treebin
+  TestHybridHeap::TreeMap(treeMap,iHybridHeap);
+  for(ArrayIndex2=0; ArrayIndex2<ArraySize2-1; ArrayIndex2+=1)
+    {
+    iHeap->Free(ArrayOfCells2[ArrayIndex2]);
+    }
+  TestHybridHeap::TreeMap(treeMap2,iHybridHeap);
+  test(treeMap <= treeMap2);
+  iHeap->Check();
+    
+  // Now free rest of the array with Reset
+  iHeap->Reset();
+  iHeap->Check();
+    
+  delete [] ArrayOfCells;
+  delete [] ArrayOfCells2; 
+  }
+
+
+void TestRHeap::CloseTests()
+  {
+  // close heap so we don't exceed chunk limit
+  iHeap->Close();  
+  }
+
+
+GLDEF_C TInt E32Main(void)
+  {
+  test.Title();
+
+  __KHEAP_MARK;
+
+  TestRHeap T;
+  test.Start(_L("Init DL allocator tests"));
+  T.InitTests();
+  test.Next(_L("Test DL allocator 1"));
+  T.Test1();
+  test.Next(_L("Test DL allocator 2"));
+  T.Test2();
+  test.Next(_L("Test DL allocator 3"));
+  T.Test3();
+  test.Next(_L("Test DL allocator 4"));
+  T.Test4();
+  test.Next(_L("Close DL allocator tests"));
+  T.CloseTests();
+	
+  __KHEAP_CHECK(0);
+  __KHEAP_MARKEND;
+
+  test.End();
+  return(0);
+  }