1 /*
2  * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the <organization> nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "CppUTest/TestHarness.h"
29 #include "CppUTest/TestMemoryAllocator.h"
30 #include "CppUTest/PlatformSpecificFunctions.h"
31 #include "CppUTest/TestTestingFixture.h"
32 #include "CppUTest/MemoryLeakDetector.h"
33 
TEST_GROUP(TestMemoryAllocatorTest)34 TEST_GROUP(TestMemoryAllocatorTest)
35 {
36     TestMemoryAllocator* allocator;
37     GlobalMemoryAllocatorStash memoryAllocatorStash;
38 
39     void setup()
40     {
41         allocator = NULLPTR;
42         memoryAllocatorStash.save();
43     }
44 
45     void teardown()
46     {
47         memoryAllocatorStash.restore();
48         delete allocator;
49     }
50 };
51 
TEST(TestMemoryAllocatorTest,SetCurrentNewAllocator)52 TEST(TestMemoryAllocatorTest, SetCurrentNewAllocator)
53 {
54     allocator = new TestMemoryAllocator("new allocator for test");
55     setCurrentNewAllocator(allocator);
56     POINTERS_EQUAL(allocator, getCurrentNewAllocator());
57 }
58 
TEST(TestMemoryAllocatorTest,SetCurrentNewAllocatorToDefault)59 TEST(TestMemoryAllocatorTest, SetCurrentNewAllocatorToDefault)
60 {
61     TestMemoryAllocator* originalAllocator = getCurrentNewAllocator();
62 
63     setCurrentNewAllocatorToDefault();
64     POINTERS_EQUAL(defaultNewAllocator(), getCurrentNewAllocator());
65 
66     setCurrentNewAllocator(originalAllocator);
67 }
68 
TEST(TestMemoryAllocatorTest,SetCurrentNewArrayAllocator)69 TEST(TestMemoryAllocatorTest, SetCurrentNewArrayAllocator)
70 {
71     allocator = new TestMemoryAllocator("new array allocator for test");
72     setCurrentNewArrayAllocator(allocator);
73     POINTERS_EQUAL(allocator, getCurrentNewArrayAllocator());
74     setCurrentNewArrayAllocatorToDefault();
75     POINTERS_EQUAL(defaultNewArrayAllocator(), getCurrentNewArrayAllocator());
76 }
77 
TEST(TestMemoryAllocatorTest,SetCurrentMallocAllocator)78 TEST(TestMemoryAllocatorTest, SetCurrentMallocAllocator)
79 {
80     allocator = new TestMemoryAllocator("malloc_allocator");
81     setCurrentMallocAllocator(allocator);
82     POINTERS_EQUAL(allocator, getCurrentMallocAllocator());
83     setCurrentMallocAllocatorToDefault();
84     POINTERS_EQUAL(defaultMallocAllocator(), getCurrentMallocAllocator());
85 }
86 
TEST(TestMemoryAllocatorTest,MemoryAllocation)87 TEST(TestMemoryAllocatorTest, MemoryAllocation)
88 {
89     allocator = new TestMemoryAllocator();
90     allocator->free_memory(allocator->alloc_memory(100, "file", 1), 100, "file", 1);
91 }
92 
TEST(TestMemoryAllocatorTest,MallocNames)93 TEST(TestMemoryAllocatorTest, MallocNames)
94 {
95     STRCMP_EQUAL("Standard Malloc Allocator", defaultMallocAllocator()->name());
96     STRCMP_EQUAL("malloc", defaultMallocAllocator()->alloc_name());
97     STRCMP_EQUAL("free", defaultMallocAllocator()->free_name());
98 }
99 
TEST(TestMemoryAllocatorTest,NewNames)100 TEST(TestMemoryAllocatorTest, NewNames)
101 {
102     STRCMP_EQUAL("Standard New Allocator", defaultNewAllocator()->name());
103     STRCMP_EQUAL("new", defaultNewAllocator()->alloc_name());
104     STRCMP_EQUAL("delete", defaultNewAllocator()->free_name());
105 }
106 
TEST(TestMemoryAllocatorTest,NewArrayNames)107 TEST(TestMemoryAllocatorTest, NewArrayNames)
108 {
109     STRCMP_EQUAL("Standard New [] Allocator", defaultNewArrayAllocator()->name());
110     STRCMP_EQUAL("new []", defaultNewArrayAllocator()->alloc_name());
111     STRCMP_EQUAL("delete []", defaultNewArrayAllocator()->free_name());
112 }
113 
TEST(TestMemoryAllocatorTest,NullUnknownAllocation)114 TEST(TestMemoryAllocatorTest, NullUnknownAllocation)
115 {
116     allocator = new NullUnknownAllocator;
117     allocator->free_memory(allocator->alloc_memory(100, "file", 1), 100, "file", 1);
118 }
119 
TEST(TestMemoryAllocatorTest,NullUnknownNames)120 TEST(TestMemoryAllocatorTest, NullUnknownNames)
121 {
122     allocator = new NullUnknownAllocator;
123     STRCMP_EQUAL("Null Allocator", allocator->name());
124     STRCMP_EQUAL("unknown", allocator->alloc_name());
125     STRCMP_EQUAL("unknown", allocator->free_name());
126 }
127 
128 #if (! CPPUTEST_SANITIZE_ADDRESS)
129 
130 #define MAX_SIZE_FOR_ALLOC ((size_t) -1 > (unsigned short)-1) ? (size_t) -97 : (size_t) -1
131 
failTryingToAllocateTooMuchMemory(void)132 static void failTryingToAllocateTooMuchMemory(void)
133 {
134     TestMemoryAllocator allocator;
135     allocator.alloc_memory(MAX_SIZE_FOR_ALLOC, "file", 1);
136 } // LCOV_EXCL_LINE
137 
TEST(TestMemoryAllocatorTest,TryingToAllocateTooMuchFailsTest)138 TEST(TestMemoryAllocatorTest, TryingToAllocateTooMuchFailsTest)
139 {
140     TestTestingFixture fixture;
141     fixture.setTestFunction(&failTryingToAllocateTooMuchMemory);
142     fixture.runAllTests();
143     fixture.assertPrintContains("malloc returned null pointer");
144 }
145 
146 #endif
147 
TEST_GROUP(MemoryLeakAllocator)148 TEST_GROUP(MemoryLeakAllocator)
149 {
150     MemoryLeakAllocator* allocator;
151 
152     void setup()
153     {
154         allocator = new MemoryLeakAllocator(defaultMallocAllocator());
155     }
156 
157     void teardown()
158     {
159         delete allocator;
160     }
161 };
162 
TEST(MemoryLeakAllocator,allocMemory)163 TEST(MemoryLeakAllocator, allocMemory)
164 {
165     char* memory = allocator->alloc_memory(10, __FILE__, __LINE__);
166     memory[0] = 'B';
167     MemoryLeakWarningPlugin::getGlobalDetector()->deallocMemory(allocator->actualAllocator(), memory);
168 
169     /* No leaks or crashes */
170 }
171 
TEST(MemoryLeakAllocator,freeMemory)172 TEST(MemoryLeakAllocator, freeMemory)
173 {
174     char* memory = MemoryLeakWarningPlugin::getGlobalDetector()->allocMemory(allocator->actualAllocator(), 10);
175     allocator->free_memory(memory, 10, __FILE__, __LINE__);
176 
177     /* No leaks or crashes */
178 }
179 
TEST(MemoryLeakAllocator,originalAllocator)180 TEST(MemoryLeakAllocator, originalAllocator)
181 {
182     POINTERS_EQUAL(defaultMallocAllocator(), allocator->actualAllocator());
183     STRCMP_EQUAL(defaultMallocAllocator()->alloc_name(), allocator->alloc_name());
184     STRCMP_EQUAL(defaultMallocAllocator()->free_name(), allocator->free_name());
185 }
186 
TEST(MemoryLeakAllocator,name)187 TEST(MemoryLeakAllocator, name)
188 {
189     STRCMP_EQUAL("MemoryLeakAllocator", allocator->name());
190 }
191 
192 #if CPPUTEST_USE_MEM_LEAK_DETECTION
193 #if CPPUTEST_USE_MALLOC_MACROS
194 
195 class FailableMemoryAllocatorExecFunction : public ExecFunction
196 {
197 public:
198     FailableMemoryAllocator* allocator_;
199     void (*testFunction_)(FailableMemoryAllocator*);
200 
exec()201     void exec() _override
202     {
203         testFunction_(allocator_);
204     }
205 
FailableMemoryAllocatorExecFunction()206     FailableMemoryAllocatorExecFunction() : allocator_(NULLPTR), testFunction_(NULLPTR) {}
~FailableMemoryAllocatorExecFunction()207     virtual ~FailableMemoryAllocatorExecFunction() _destructor_override {}
208 };
209 
TEST_GROUP(FailableMemoryAllocator)210 TEST_GROUP(FailableMemoryAllocator)
211 {
212     FailableMemoryAllocator *failableMallocAllocator;
213     FailableMemoryAllocatorExecFunction testFunction;
214     TestTestingFixture fixture;
215     GlobalMemoryAllocatorStash stash;
216 
217     void setup()
218     {
219         stash.save();
220         testFunction.allocator_ = failableMallocAllocator = new FailableMemoryAllocator("Failable Malloc Allocator", "malloc", "free");
221         fixture.setTestFunction(&testFunction);
222         setCurrentMallocAllocator(failableMallocAllocator);
223     }
224     void teardown()
225     {
226         failableMallocAllocator->checkAllFailedAllocsWereDone();
227         failableMallocAllocator->clearFailedAllocs();
228         delete failableMallocAllocator;
229         stash.restore();
230     }
231 };
232 
TEST(FailableMemoryAllocator,MallocWorksNormallyIfNotAskedToFail)233 TEST(FailableMemoryAllocator, MallocWorksNormallyIfNotAskedToFail)
234 {
235     int *memory = (int*)malloc(sizeof(int));
236     CHECK(memory != NULLPTR);
237     free(memory);
238 }
239 
TEST(FailableMemoryAllocator,FailFirstMalloc)240 TEST(FailableMemoryAllocator, FailFirstMalloc)
241 {
242     failableMallocAllocator->failAllocNumber(1);
243     POINTERS_EQUAL(NULLPTR, (int*)malloc(sizeof(int)));
244 }
245 
TEST(FailableMemoryAllocator,FailSecondAndFourthMalloc)246 TEST(FailableMemoryAllocator, FailSecondAndFourthMalloc)
247 {
248     failableMallocAllocator->failAllocNumber(2);
249     failableMallocAllocator->failAllocNumber(4);
250     int *memory1 = (int*)malloc(sizeof(int));
251     int *memory2 = (int*)malloc(sizeof(int));
252     int *memory3 = (int*)malloc(sizeof(int));
253     int *memory4 = (int*)malloc(sizeof(int));
254 
255     CHECK(NULLPTR != memory1);
256     POINTERS_EQUAL(NULLPTR, memory2);
257     CHECK(NULLPTR != memory3);
258     POINTERS_EQUAL(NULLPTR, memory4);
259 
260     free(memory1);
261     free(memory3);
262 }
263 
_failingAllocIsNeverDone(FailableMemoryAllocator * failableMallocAllocator)264 static void _failingAllocIsNeverDone(FailableMemoryAllocator* failableMallocAllocator)
265 {
266     failableMallocAllocator->failAllocNumber(1);
267     failableMallocAllocator->failAllocNumber(2);
268     failableMallocAllocator->failAllocNumber(3);
269     malloc(sizeof(int));
270     malloc(sizeof(int));
271     failableMallocAllocator->checkAllFailedAllocsWereDone();
272 }
273 
TEST(FailableMemoryAllocator,CheckAllFailingAllocsWereDone)274 TEST(FailableMemoryAllocator, CheckAllFailingAllocsWereDone)
275 {
276     testFunction.testFunction_ = _failingAllocIsNeverDone;
277 
278     fixture.runAllTests();
279 
280     LONGS_EQUAL(1, fixture.getFailureCount());
281     fixture.assertPrintContains("Expected allocation number 3 was never done");
282     failableMallocAllocator->clearFailedAllocs();
283 }
284 
TEST(FailableMemoryAllocator,FailFirstAllocationAtGivenLine)285 TEST(FailableMemoryAllocator, FailFirstAllocationAtGivenLine)
286 {
287     failableMallocAllocator->failNthAllocAt(1, __FILE__, __LINE__ + 2);
288 
289     POINTERS_EQUAL(NULLPTR, malloc(sizeof(int)));
290 }
291 
TEST(FailableMemoryAllocator,FailThirdAllocationAtGivenLine)292 TEST(FailableMemoryAllocator, FailThirdAllocationAtGivenLine)
293 {
294     int *memory[10] = { NULLPTR };
295     int allocation;
296     failableMallocAllocator->failNthAllocAt(3, __FILE__, __LINE__ + 4);
297 
298     for (allocation = 1; allocation <= 10; allocation++)
299     {
300         memory[allocation - 1] = (int *)malloc(sizeof(int));
301         if (memory[allocation - 1] == NULLPTR)
302             break;
303         free(memory[allocation -1]);
304     }
305 
306     LONGS_EQUAL(3, allocation);
307 }
308 
_failingLocationAllocIsNeverDone(FailableMemoryAllocator * failableMallocAllocator)309 static void _failingLocationAllocIsNeverDone(FailableMemoryAllocator* failableMallocAllocator)
310 {
311     failableMallocAllocator->failNthAllocAt(1, "TestMemoryAllocatorTest.cpp", __LINE__);
312     failableMallocAllocator->checkAllFailedAllocsWereDone();
313 }
314 
TEST(FailableMemoryAllocator,CheckAllFailingLocationAllocsWereDone)315 TEST(FailableMemoryAllocator, CheckAllFailingLocationAllocsWereDone)
316 {
317     testFunction.testFunction_ = _failingLocationAllocIsNeverDone;
318 
319     fixture.runAllTests();
320 
321     LONGS_EQUAL(1, fixture.getFailureCount());
322     fixture.assertPrintContains("Expected failing alloc at TestMemoryAllocatorTest.cpp:");
323     fixture.assertPrintContains("was never done");
324 
325     failableMallocAllocator->clearFailedAllocs();
326 }
327 
328 #endif
329 #endif
330 
331 class MemoryAccountantExecFunction
332     : public ExecFunction
333 {
334 public:
~MemoryAccountantExecFunction()335     virtual ~MemoryAccountantExecFunction() _destructor_override
336     {
337     }
338 
339     void (*testFunction_)(MemoryAccountant*);
340     MemoryAccountant* parameter_;
341 
exec()342     virtual void exec() _override
343     {
344         testFunction_(parameter_);
345     }
346 };
347 
TEST_GROUP(TestMemoryAccountant)348 TEST_GROUP(TestMemoryAccountant)
349 {
350     MemoryAccountant accountant;
351     TestTestingFixture fixture;
352     MemoryAccountantExecFunction testFunction;
353 
354     void setup()
355     {
356         testFunction.parameter_ = &accountant;
357         fixture.setTestFunction(&testFunction);
358     }
359 
360     void teardown()
361     {
362         accountant.clear();
363     }
364 };
365 
TEST(TestMemoryAccountant,totalAllocsIsZero)366 TEST(TestMemoryAccountant, totalAllocsIsZero)
367 {
368     LONGS_EQUAL(0, accountant.totalAllocations());
369     LONGS_EQUAL(0, accountant.totalDeallocations());
370 }
371 
TEST(TestMemoryAccountant,countAllocationsPerSize)372 TEST(TestMemoryAccountant, countAllocationsPerSize)
373 {
374     accountant.alloc(4);
375     LONGS_EQUAL(1, accountant.totalAllocationsOfSize(4));
376     LONGS_EQUAL(0, accountant.totalAllocationsOfSize(10));
377     LONGS_EQUAL(1, accountant.totalAllocations());
378     LONGS_EQUAL(0, accountant.maximumAllocationAtATimeOfSize(10));
379 }
380 
TEST(TestMemoryAccountant,countAllocationsPerSizeMultipleAllocations)381 TEST(TestMemoryAccountant, countAllocationsPerSizeMultipleAllocations)
382 {
383     accountant.alloc(4);
384     accountant.alloc(4);
385     accountant.alloc(8);
386     LONGS_EQUAL(2, accountant.totalAllocationsOfSize(4));
387     LONGS_EQUAL(1, accountant.totalAllocationsOfSize(8));
388     LONGS_EQUAL(0, accountant.totalAllocationsOfSize(10));
389     LONGS_EQUAL(3, accountant.totalAllocations());
390 }
391 
TEST(TestMemoryAccountant,countAllocationsPerSizeMultipleAllocationsOutOfOrder)392 TEST(TestMemoryAccountant, countAllocationsPerSizeMultipleAllocationsOutOfOrder)
393 {
394     accountant.alloc(4);
395     accountant.alloc(8);
396     accountant.alloc(4);
397     accountant.alloc(5);
398     accountant.alloc(2);
399     accountant.alloc(4);
400     accountant.alloc(10);
401 
402     LONGS_EQUAL(3, accountant.totalAllocationsOfSize(4));
403     LONGS_EQUAL(1, accountant.totalAllocationsOfSize(8));
404     LONGS_EQUAL(1, accountant.totalAllocationsOfSize(10));
405     LONGS_EQUAL(7, accountant.totalAllocations());
406 }
407 
TEST(TestMemoryAccountant,countDeallocationsPerSizeMultipleAllocations)408 TEST(TestMemoryAccountant, countDeallocationsPerSizeMultipleAllocations)
409 {
410     accountant.dealloc(8);
411     accountant.dealloc(4);
412     accountant.dealloc(8);
413     LONGS_EQUAL(1, accountant.totalDeallocationsOfSize(4));
414     LONGS_EQUAL(2, accountant.totalDeallocationsOfSize(8));
415     LONGS_EQUAL(0, accountant.totalDeallocationsOfSize(20));
416     LONGS_EQUAL(3, accountant.totalDeallocations());
417 }
418 
TEST(TestMemoryAccountant,countMaximumAllocationsAtATime)419 TEST(TestMemoryAccountant, countMaximumAllocationsAtATime)
420 {
421     accountant.alloc(4);
422     accountant.alloc(4);
423     accountant.dealloc(4);
424     accountant.dealloc(4);
425     accountant.alloc(4);
426     LONGS_EQUAL(2, accountant.maximumAllocationAtATimeOfSize(4));
427 }
428 
TEST(TestMemoryAccountant,reportNoAllocations)429 TEST(TestMemoryAccountant, reportNoAllocations)
430 {
431     STRCMP_EQUAL("CppUTest Memory Accountant has not noticed any allocations or deallocations. Sorry\n", accountant.report().asCharString());
432 }
433 
TEST(TestMemoryAccountant,reportAllocations)434 TEST(TestMemoryAccountant, reportAllocations)
435 {
436     accountant.dealloc(8);
437     accountant.dealloc(8);
438     accountant.dealloc(8);
439 
440     accountant.alloc(4);
441     accountant.dealloc(4);
442     accountant.alloc(4);
443     STRCMP_EQUAL("CppUTest Memory Accountant report:\n"
444                  "Allocation size     # allocations    # deallocations   max # allocations at one time\n"
445                  "    4                   2                1                 1\n"
446                  "    8                   0                3                 0\n"
447                  "   Thank you for your business\n"
448                  , accountant.report().asCharString());
449 }
450 
TEST(TestMemoryAccountant,reportAllocationsWithSizeZero)451 TEST(TestMemoryAccountant, reportAllocationsWithSizeZero)
452 {
453     accountant.dealloc(0);
454 
455     accountant.dealloc(4);
456     accountant.dealloc(4);
457     accountant.alloc(4);
458 
459     STRCMP_EQUAL("CppUTest Memory Accountant report:\n"
460                  "Allocation size     # allocations    # deallocations   max # allocations at one time\n"
461                  "other                   0                1                 0\n"
462                  "    4                   1                2                 1\n"
463                  "   Thank you for your business\n"
464                  , accountant.report().asCharString());
465 }
466 
467 
_failUseCacheSizesAfterAllocation(MemoryAccountant * accountant)468 static void _failUseCacheSizesAfterAllocation(MemoryAccountant* accountant)
469 {
470     size_t cacheSizes[] = {0};
471 
472     accountant->alloc(4);
473     accountant->useCacheSizes(cacheSizes, 1);
474 }
475 
TEST(TestMemoryAccountant,withCacheSizesFailsWhenAlreadyAllocatedMemory)476 TEST(TestMemoryAccountant, withCacheSizesFailsWhenAlreadyAllocatedMemory)
477 {
478     testFunction.testFunction_ = _failUseCacheSizesAfterAllocation;
479 
480     fixture.runAllTests();
481 
482     fixture.assertPrintContains("MemoryAccountant: Cannot set cache sizes as allocations already occured!");
483 }
484 
TEST(TestMemoryAccountant,reportWithCacheSizesEmpty)485 TEST(TestMemoryAccountant, reportWithCacheSizesEmpty)
486 {
487     size_t cacheSizes[] = {0};
488 
489     accountant.useCacheSizes(cacheSizes, 0);
490     accountant.alloc(4);
491 
492     STRCMP_EQUAL("CppUTest Memory Accountant report (with cache sizes):\n"
493                  "Cache size          # allocations    # deallocations   max # allocations at one time\n"
494                  "other                   1                0                 1\n"
495                  "   Thank you for your business\n"
496                  , accountant.report().asCharString());
497 }
498 
499 
TEST(TestMemoryAccountant,reportWithCacheSizes)500 TEST(TestMemoryAccountant, reportWithCacheSizes)
501 {
502     size_t cacheSizes[] = {4};
503 
504     accountant.useCacheSizes(cacheSizes, 1);
505     accountant.dealloc(8);
506     accountant.dealloc(12);
507     accountant.dealloc(20);
508 
509     accountant.alloc(4);
510     accountant.dealloc(4);
511     accountant.alloc(4);
512     STRCMP_EQUAL("CppUTest Memory Accountant report (with cache sizes):\n"
513                  "Cache size          # allocations    # deallocations   max # allocations at one time\n"
514                  "    4                   2                1                 1\n"
515                  "other                   0                3                 0\n"
516                  "   Thank you for your business\n"
517                  , accountant.report().asCharString());
518 }
519 
TEST(TestMemoryAccountant,reportWithCacheSizesMultipleCaches)520 TEST(TestMemoryAccountant, reportWithCacheSizesMultipleCaches)
521 {
522     size_t cacheSizes[] = {4, 10, 20};
523 
524     accountant.useCacheSizes(cacheSizes, 3);
525     accountant.alloc(8);
526     accountant.alloc(12);
527     accountant.alloc(20);
528 
529     accountant.alloc(4);
530     accountant.dealloc(4);
531     accountant.alloc(4);
532     STRCMP_EQUAL("CppUTest Memory Accountant report (with cache sizes):\n"
533                  "Cache size          # allocations    # deallocations   max # allocations at one time\n"
534                  "    4                   2                1                 1\n"
535                  "   10                   1                0                 1\n"
536                  "   20                   2                0                 2\n"
537                  "other                   0                0                 0\n"
538                  "   Thank you for your business\n"
539                  , accountant.report().asCharString());
540 }
541 
542 
TEST_GROUP(AccountingTestMemoryAllocator)543 TEST_GROUP(AccountingTestMemoryAllocator)
544 {
545     MemoryAccountant accountant;
546     AccountingTestMemoryAllocator *allocator;
547 
548     void setup()
549     {
550         allocator = new AccountingTestMemoryAllocator(accountant, getCurrentMallocAllocator());
551     }
552 
553     void teardown()
554     {
555         accountant.clear();
556         delete allocator;
557     }
558 };
559 
TEST(AccountingTestMemoryAllocator,canAllocateAndAccountMemory)560 TEST(AccountingTestMemoryAllocator, canAllocateAndAccountMemory)
561 {
562     char* memory = allocator->alloc_memory(10, __FILE__, __LINE__);
563     allocator->free_memory(memory, 10, __FILE__, __LINE__);
564 
565     LONGS_EQUAL(1, accountant.totalAllocationsOfSize(10));
566     LONGS_EQUAL(1, accountant.totalDeallocationsOfSize(10));
567 }
568 
TEST(AccountingTestMemoryAllocator,canAllocateAndAccountMemoryMultipleAllocations)569 TEST(AccountingTestMemoryAllocator, canAllocateAndAccountMemoryMultipleAllocations)
570 {
571     char* memory1 = allocator->alloc_memory(10, __FILE__, __LINE__);
572     char* memory2 = allocator->alloc_memory(8, __FILE__, __LINE__);
573     char* memory3 = allocator->alloc_memory(12, __FILE__, __LINE__);
574 
575     allocator->free_memory(memory1, 10,  __FILE__, __LINE__);
576     allocator->free_memory(memory3, 12,  __FILE__, __LINE__);
577 
578     char* memory4 = allocator->alloc_memory(15, __FILE__, __LINE__);
579     char* memory5 = allocator->alloc_memory(20, __FILE__, __LINE__);
580 
581     allocator->free_memory(memory2, 8, __FILE__, __LINE__);
582     allocator->free_memory(memory4, 15, __FILE__, __LINE__);
583     allocator->free_memory(memory5, 20, __FILE__, __LINE__);
584 
585     char* memory6 = allocator->alloc_memory(1, __FILE__, __LINE__);
586     char* memory7 = allocator->alloc_memory(100, __FILE__, __LINE__);
587 
588     allocator->free_memory(memory6, 1, __FILE__, __LINE__);
589     allocator->free_memory(memory7, 100, __FILE__, __LINE__);
590 
591     LONGS_EQUAL(7, accountant.totalAllocations());
592     LONGS_EQUAL(7, accountant.totalDeallocations());
593 }
594 
TEST(AccountingTestMemoryAllocator,useOriginalAllocatorWhenDeallocatingMemoryNotAllocatedByAllocator)595 TEST(AccountingTestMemoryAllocator, useOriginalAllocatorWhenDeallocatingMemoryNotAllocatedByAllocator)
596 {
597     char* memory = getCurrentMallocAllocator()->alloc_memory(10, __FILE__, __LINE__);
598     allocator->free_memory(memory, 10, __FILE__, __LINE__);
599 
600     LONGS_EQUAL(0, accountant.totalAllocations());
601     LONGS_EQUAL(1, accountant.totalDeallocations());
602 }
603 
TEST(AccountingTestMemoryAllocator,allocatorForwardsAllocAndFreeName)604 TEST(AccountingTestMemoryAllocator, allocatorForwardsAllocAndFreeName)
605 {
606     STRCMP_EQUAL("malloc", allocator->alloc_name());
607     STRCMP_EQUAL("free", allocator->free_name());
608 }
609 
610 
611 class GlobalMemoryAccountantExecFunction
612     : public ExecFunction
613 {
614 public:
615     void (*testFunction_)(GlobalMemoryAccountant*);
616     GlobalMemoryAccountant* parameter_;
617 
exec()618     virtual void exec() _override
619     {
620         testFunction_(parameter_);
621     }
622 };
623 
TEST_GROUP(GlobalMemoryAccountant)624 TEST_GROUP(GlobalMemoryAccountant)
625 {
626     GlobalMemoryAccountant accountant;
627     TestTestingFixture fixture;
628     GlobalMemoryAccountantExecFunction testFunction;
629     GlobalMemoryAllocatorStash stash;
630 
631     void setup()
632     {
633         testFunction.parameter_ = &accountant;
634         fixture.setTestFunction(&testFunction);
635         stash.save();
636     }
637 
638     void teardown()
639     {
640         stash.restore();
641     }
642 };
643 
TEST(GlobalMemoryAccountant,start)644 TEST(GlobalMemoryAccountant, start)
645 {
646     accountant.start();
647 
648     POINTERS_EQUAL(accountant.getMallocAllocator(), getCurrentMallocAllocator());
649     POINTERS_EQUAL(accountant.getNewAllocator(), getCurrentNewAllocator());
650     POINTERS_EQUAL(accountant.getNewArrayAllocator(), getCurrentNewArrayAllocator());
651 
652     accountant.stop();
653 }
654 
TEST(GlobalMemoryAccountant,stop)655 TEST(GlobalMemoryAccountant, stop)
656 {
657     TestMemoryAllocator* originalMallocAllocator = getCurrentMallocAllocator();
658     TestMemoryAllocator* originalNewAllocator = getCurrentNewAllocator();
659     TestMemoryAllocator* originalNewArrayAllocator = getCurrentNewArrayAllocator();
660 
661     accountant.start();
662     accountant.stop();
663 
664     POINTERS_EQUAL(originalMallocAllocator, getCurrentMallocAllocator());
665     POINTERS_EQUAL(originalNewAllocator, getCurrentNewAllocator());
666     POINTERS_EQUAL(originalNewArrayAllocator, getCurrentNewArrayAllocator());
667 }
668 
669 #if CPPUTEST_USE_MEM_LEAK_DETECTION
670 
TEST(GlobalMemoryAccountant,report)671 TEST(GlobalMemoryAccountant, report)
672 {
673     accountant.start();
674     char* memory = new char[185];
675     delete [] memory;
676     accountant.stop();
677 
678     /* Allocation includes memory leak info */
679     STRCMP_CONTAINS("1                1                 1", accountant.report().asCharString());
680 }
681 
TEST(GlobalMemoryAccountant,reportWithCacheSizes)682 TEST(GlobalMemoryAccountant, reportWithCacheSizes)
683 {
684     size_t cacheSizes[] = {512};
685     accountant.useCacheSizes(cacheSizes, 1);
686     accountant.start();
687     char* memory = new char[185];
688     delete [] memory;
689     accountant.stop();
690 
691     /* Allocation includes memory leak info */
692     STRCMP_CONTAINS("512                   1                1                 1", accountant.report().asCharString());
693 }
694 
695 
696 #endif
697 
_failStopWithoutStartingWillFail(GlobalMemoryAccountant * accountant)698 static void _failStopWithoutStartingWillFail(GlobalMemoryAccountant* accountant)
699 {
700     accountant->stop();
701 }
702 
TEST(GlobalMemoryAccountant,StopCantBeCalledWithoutStarting)703 TEST(GlobalMemoryAccountant, StopCantBeCalledWithoutStarting)
704 {
705     testFunction.testFunction_ = _failStopWithoutStartingWillFail;
706     fixture.runAllTests();
707     fixture.assertPrintContains("GlobalMemoryAccount: Stop called without starting");
708 }
709 
_failStartingTwiceWillFail(GlobalMemoryAccountant * accountant)710 static void _failStartingTwiceWillFail(GlobalMemoryAccountant* accountant)
711 {
712     accountant->start();
713     accountant->start();
714 }
715 
TEST(GlobalMemoryAccountant,startTwiceWillFail)716 TEST(GlobalMemoryAccountant, startTwiceWillFail)
717 {
718     testFunction.testFunction_ = _failStartingTwiceWillFail;
719     fixture.runAllTests();
720     accountant.stop();
721 
722     fixture.assertPrintContains("Global allocator start called twice!");
723 }
724 
_failChangeMallocMemoryAllocator(GlobalMemoryAccountant * accountant)725 static void _failChangeMallocMemoryAllocator(GlobalMemoryAccountant* accountant)
726 {
727     accountant->start();
728     setCurrentMallocAllocator(defaultMallocAllocator());
729     accountant->stop();
730 }
731 
TEST(GlobalMemoryAccountant,checkWhetherMallocAllocatorIsNotChanged)732 TEST(GlobalMemoryAccountant, checkWhetherMallocAllocatorIsNotChanged)
733 {
734     testFunction.testFunction_ = _failChangeMallocMemoryAllocator;
735     fixture.runAllTests();
736     fixture.assertPrintContains("GlobalMemoryAccountant: Malloc memory allocator has been changed while accounting for memory");
737 }
738 
_failChangeNewMemoryAllocator(GlobalMemoryAccountant * accountant)739 static void _failChangeNewMemoryAllocator(GlobalMemoryAccountant* accountant)
740 {
741     accountant->start();
742     setCurrentNewAllocator(defaultNewAllocator());
743     accountant->stop();
744 }
745 
TEST(GlobalMemoryAccountant,checkWhetherNewAllocatorIsNotChanged)746 TEST(GlobalMemoryAccountant, checkWhetherNewAllocatorIsNotChanged)
747 {
748     testFunction.testFunction_ = _failChangeNewMemoryAllocator;
749     fixture.runAllTests();
750     fixture.assertPrintContains("GlobalMemoryAccountant: New memory allocator has been changed while accounting for memory");
751 }
752 
_failChangeNewArrayMemoryAllocator(GlobalMemoryAccountant * accountant)753 static void _failChangeNewArrayMemoryAllocator(GlobalMemoryAccountant* accountant)
754 {
755     accountant->start();
756     setCurrentNewArrayAllocator(defaultNewArrayAllocator());
757     accountant->stop();
758 }
759 
TEST(GlobalMemoryAccountant,checkWhetherNewArrayAllocatorIsNotChanged)760 TEST(GlobalMemoryAccountant, checkWhetherNewArrayAllocatorIsNotChanged)
761 {
762     testFunction.testFunction_ = _failChangeNewArrayMemoryAllocator;
763     fixture.runAllTests();
764     fixture.assertPrintContains("GlobalMemoryAccountant: New Array memory allocator has been changed while accounting for memory");
765 }
766 
767