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