Update contrib.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\heap\t_heapdb.cpp
15 // Tests the _DEBUG build dependent aspects of RHeap
17 // Tests debug build dependent aspects of RHeap.
22 // - Allocate a variety of user heap objects and verify the nesting level, allocation count,
23 // allocation level and length are correct. Also check for heap corruption.
25 // - Some assorted indirect calls to alloc, and verify the nesting level, allocation count,
26 // allocation level and length are correct. Also check for heap corruption.
28 // - Allocate a variety of objects and verify that the UHEAP_CHECKALL count is correct.
29 // - Verify the nesting of UHEAP_MARK and UHEAP_MARKEND macros.
30 // - Check the validity of the current thread's default heap.
32 // - Allocate memory for different heaps, check the total number of allocated cells
33 // for different heaps and for the current nested level is as expected.
35 // - Simulate heap allocation failures, allocate the memory from user and
36 // kernel heap and check results are as expected.
37 // Platforms/Drives/Compatibility:
39 // Assumptions/Requirement/Pre-requisites:
40 // Failures and causes:
41 // Base Port information:
47 #include <e32def_private.h>
49 LOCAL_D RTest test(_L("T_HEAPDB"));
53 RHeap::SHeapCellInfo CellInfo[4];
55 class RTestHeap : public RHeap
58 void AttachInfo(SHeapCellInfo* aInfo)
62 void AttachToHeap(RHeap* aHeap, TInt aInfo)
65 aHeap = (RHeap*)&User::Allocator();
66 ((RTestHeap*)aHeap)->AttachInfo(CellInfo + aInfo);
69 void TestCellInfo(TInt aInfo, TInt aNest, TInt aAllocCount, TInt aLevelAlloc, TInt aSize, TAny* aAddr)
71 RHeap::SHeapCellInfo& ci = CellInfo[aInfo];
72 RHeap::SDebugCell& cell = *ci.iStranded;
73 test(cell.nestingLevel == aNest);
74 test(cell.allocCount == aAllocCount);
75 test(ci.iLevelAlloc == aLevelAlloc);
76 test(cell.len == aSize + RHeap::EAllocCellSize);
77 test((&cell+1) == aAddr);
80 const TInt KMaxFailureRate=100;
81 const TInt KThreadMemError=-50;
82 const TInt KCellSize=(sizeof(RHeap::SCell)); // Size of free cell header
83 const TInt KHeadSize=(sizeof(RHeap::SDebugCell)); // Size of allocated cell header with space for heaven info
85 LOCAL_D TInt heapCount=1;
86 LOCAL_D RSemaphore threadSemaphore;
87 LOCAL_D TBool array1[KMaxFailureRate+1];
88 LOCAL_D TBool array2[KMaxFailureRate+1];
90 LOCAL_C TInt ThreadEntryPoint(TAny*)
92 threadSemaphore.Wait();
93 if (User::Alloc(4)==NULL)
94 return(KThreadMemError);
109 LOCAL_C RHeap* allocHeap(TInt aSize)
111 // Allocate a chunk heap with max size aSize
116 n.Format(_L("TESTHEAP%d"),heapCount++);
117 return(User::ChunkHeap(&n,aSize,aSize));
120 void TestRHeapDebug::Test1(void)
125 ///////////////////////
126 // Test heaven cell is found for each method of allocating memory
127 ////////////////////////
139 TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
142 // new(TInt aSize,TInt anExtraSize)
146 TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
149 // new(TInt aSize,TLeave)
153 TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
160 TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
167 TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
170 // ReAlloc with Null parameter
172 p=User::ReAlloc(NULL, 32);
174 TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
177 // ReAllocL with Null parameter
179 p=User::ReAllocL(NULL, 32);
181 TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
184 // ReAlloc with non Null parameter
187 p=User::ReAlloc(p, 4);
189 TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
192 // ReAlloc with non Null parameter such that cell is moved in memory
195 TAny* temp=User::Alloc(128);
196 p=User::ReAlloc(p, 526);
199 TestCellInfo(0, 1, 3, 1, User::AllocLen(p), p);
202 // ReAllocL with non Null parameter
205 p=User::ReAllocL(p, 128);
207 TestCellInfo(0, 1, 1, 1, User::AllocLen(p), p);
212 void TestRHeapDebug::Test2(void)
214 // Some assorted indirect calls to alloc
217 CBufFlat* pBuf=CBufFlat::NewL(10);
219 TestCellInfo(0, 1, 1, 1, User::AllocLen(pBuf), pBuf);
223 HBufC8* pHBufC=HBufC8::New(10);
225 TestCellInfo(0, 1, 1, 1, User::AllocLen(pHBufC), pHBufC);
228 // can also create a HBufC8 from a descriptor by using TDesC::Alloc
232 void TestRHeapDebug::Test3(void)
235 // Check num of cells detected is correct and CHECKTOTALNUM is ok
236 // NOTE: CHECKTOTALNUM counts the TOTAL number of allocations in the heap regardless of
238 // NOTE: the alloc count commences from the FIRST occurrence of a MARKSTART, so if one is nested
239 // in another the alloc count will only start from the second MARKSTART if it applies to a
245 TAny* p2= new(20) TUint;
247 TAny* p3= User::Alloc(15);
251 TAny* p4=User::Alloc(1);
256 TestCellInfo(0, 2, 4, 2, User::AllocLen(p4), p4);
266 // Check some nesting out
275 TestCellInfo(0, 3, 3, 1, User::AllocLen(p4), p4);
277 TestCellInfo(0, 2, 2, 1, User::AllocLen(p3), p3);
279 TestCellInfo(0, 1, 1, 1, User::AllocLen(p2), p2);
287 void TestRHeapDebug::Test4(void)
289 // Test with different heaps
291 __UHEAP_MARK; // Default start
295 RHeap* pHeap1=allocHeap(1000);
296 AttachToHeap(pHeap1,1);
297 __RHEAP_MARK(pHeap1); // Heap1 start
298 __RHEAP_CHECKALL(pHeap1,0);
299 __RHEAP_CHECK(pHeap1,0);
300 TAny* p3=pHeap1->Alloc(4);
301 __RHEAP_CHECKALL(pHeap1,1);
302 __RHEAP_CHECK(pHeap1,1);
303 __RHEAP_CHECKALL(pHeap1,1);
305 RHeap* pHeap2=allocHeap(1000);
306 AttachToHeap(pHeap2,2);
307 RHeap* pHeap3=allocHeap(1000);
308 AttachToHeap(pHeap3,3);
310 __RHEAP_MARK(pHeap2); // Heap2 start
311 __RHEAP_MARK(pHeap3); // Heap3 start
312 TAny* p4=pHeap2->Alloc(8);
313 TAny* p5=pHeap2->Alloc(37);
314 TAny* p6=pHeap3->Alloc(32);
315 TAny* p7=pHeap1->Alloc(43);
317 __RHEAP_CHECKALL(pHeap1,2);
318 __RHEAP_CHECKALL(pHeap2,2);
319 __RHEAP_CHECKALL(pHeap3,1);
320 __RHEAP_MARKEND(pHeap3); // Heap3 end
321 TestCellInfo(3, 1, 1, 1, pHeap3->AllocLen(p6), p6);
322 __RHEAP_MARKEND(pHeap2); // Heap2 end
323 TestCellInfo(2, 1, 1, 2, pHeap2->AllocLen(p4), p4);
325 __RHEAP_MARKEND(pHeap1); // Heap1 end
326 TestCellInfo(1, 1, 2, 1, pHeap1->AllocLen(p7), p7);
341 void TestRHeapDebug::Test5()
342 // Check the alloc failure macros
345 RHeap* pHeap=allocHeap(1000);
347 // DETERMINISTIC FAILURE
350 test(User::Alloc(1)==NULL);
356 __RHEAP_RESET(pHeap);
357 __RHEAP_FAILNEXT(pHeap,1);
358 test(pHeap->Alloc(1)==NULL);
362 __RHEAP_RESET(pHeap);
366 RSemaphore semaphore;
367 test(semaphore.CreateLocal(1)==KErrNoMemory); // allocated from the kernel heap
368 test(semaphore.CreateLocal(1)==KErrNone);
372 __UHEAP_SETFAIL(RHeap::EDeterministic,0);
373 test(User::Alloc(1)==NULL);
376 __RHEAP_SETFAIL(pHeap,RHeap::EDeterministic,0);
377 test(pHeap->Alloc(1)==NULL);
378 __RHEAP_RESET(pHeap);
380 __KHEAP_SETFAIL(RHeap::EDeterministic,0);
381 test(semaphore.CreateLocal(1)==KErrNoMemory);
385 for(determinism=1; determinism<=KMaxFailureRate; determinism++)
387 __UHEAP_SETFAIL(RHeap::EDeterministic,determinism);
388 __RHEAP_SETFAIL(pHeap,RHeap::EDeterministic,determinism);
389 for(TInt ii=1; ii<=determinism; ii++)
393 if(ii%determinism==0)
408 __RHEAP_RESET(pHeap);
410 // Test SetKernelAllocFail
411 // its not possible to test SetKernelAllocFail as above as it is not possible to control the
412 // number of calls to Alloc for the dernel heap - but the following will definitely fail:
413 __KHEAP_SETFAIL(RHeap::EDeterministic,1);
415 test(r.CreateLocal(1)==KErrNoMemory); // allocated from the kernel heap
416 __KHEAP_SETFAIL(RHeap::EDeterministic,50);
417 test(r.CreateLocal(1)==KErrNone);
422 TInt numOccurences1, numOccurences2;
424 __UHEAP_SETFAIL(RHeap::ERandom,1);
425 test(User::Alloc(1)==NULL);
428 __RHEAP_SETFAIL(pHeap,RHeap::ERandom,1);
429 test(pHeap->Alloc(1)==NULL);
430 __RHEAP_RESET(pHeap);
432 // __KHEAP_SETFAIL(RHeap::ERandom,1);
433 // test(semaphore.CreateLocal(1)==KErrNoMemory);
436 __UHEAP_SETFAIL(RHeap::ETrueRandom,1);
437 test(User::Alloc(1)==NULL);
440 __RHEAP_SETFAIL(pHeap,RHeap::ETrueRandom,1);
441 test(pHeap->Alloc(1)==NULL);
442 __RHEAP_RESET(pHeap);
444 // __KHEAP_SETFAIL(RHeap::ETrueRandom,1);
445 // test(semaphore.CreateLocal(1)==KErrNoMemory);
448 for(determinism=1; determinism<=KMaxFailureRate; determinism++)
450 __UHEAP_SETFAIL(RHeap::ERandom,determinism);
451 __RHEAP_SETFAIL(pHeap,RHeap::ERandom,determinism);
453 for(ii=1; ii<=determinism; ii++)
457 array1[ii]=(p==NULL);
458 array2[ii]=(p==NULL);
466 for(ii=1; ii<=determinism; ii++)
473 test(numOccurences1==1);
474 test(numOccurences2==1);
477 __RHEAP_RESET(pHeap);
479 __UHEAP_SETFAIL(RHeap::ERandom,5);
481 for(ii=1; ii<=50; ii++)
484 array1[ii]=(p==NULL);
490 for(ii=1; ii<=50; ii++)
499 test(numOccurences1==1);
503 test(numOccurences2==50/5);
505 // Cannot really test random failure of the kernel heap accurately
508 //client.Disconnect();
510 // Test failing the heap of a child thread
511 // 1st test that it allocates normally
514 test(threadSemaphore.CreateLocal(0)==KErrNone);
515 test(thread.Create(_L("Thread"),ThreadEntryPoint,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
518 threadSemaphore.Signal();
519 User::WaitForRequest(stat);
520 test(thread.ExitReason()==KErrNone);
522 #if defined(CAN_TEST_THREADS)
523 // Now make the thread's heap fail
524 test(thread.Create(_L("Thread"),ThreadEntryPoint,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
527 TH_FAILNEXT(thread.Handle());
528 threadSemaphore.Signal();
529 User::WaitForRequest(stat);
530 test(thread.ExitReason()==KThreadMemError);
532 threadSemaphore.Close();
536 GLDEF_C TInt E32Main(void)
540 AttachToHeap(NULL,0);
541 test.Start(_L("Test1"));
544 test.Next(_L("Test2"));
546 test.Next(_L("Test3"));
548 test.Next(_L("Test4"));
550 test.Next(_L("Test5"));
556 GLDEF_C TInt E32Main()
558 // Test unavailable in release build.
563 test.Start(_L("No tests for release builds"));