1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "util_allocator.h"
30
31 void *cx_malloc_testing(
void *d,
size_t n) {
32 auto data = reinterpret_cast<CxTestingAllocator *>(d);
33 void *ptr = malloc(n);
34 data->alloc_total++;
35 if (ptr == nullptr) {
36 data->alloc_failed++;
37 }
else {
38 data->tracked.insert(ptr);
39 }
40 return ptr;
41 }
42
43 void *cx_realloc_testing(
void *d,
void *mem,
size_t n) {
44 auto data = reinterpret_cast<CxTestingAllocator *>(d);
45 void *ptr = realloc(mem, n);
46 if (ptr == mem) {
47 return ptr;
48 }
else {
49 data->alloc_total++;
50 if (ptr == nullptr) {
51 data->alloc_failed++;
52 }
else {
53 data->free_total++;
54 if (data->tracked.erase(mem) ==
0) {
55 data->free_failed++;
56 }
57 data->tracked.insert(ptr);
58 }
59 return ptr;
60 }
61 }
62
63 void *cx_calloc_testing(
void *d,
size_t nelem,
size_t n) {
64 auto data = reinterpret_cast<CxTestingAllocator *>(d);
65 void *ptr = calloc(nelem, n);
66 data->alloc_total++;
67 if (ptr == nullptr) {
68 data->alloc_failed++;
69 }
else {
70 data->tracked.insert(ptr);
71 }
72 return ptr;
73 }
74
75 void cx_free_testing(
void *d,
void *mem) {
76 auto data = reinterpret_cast<CxTestingAllocator *>(d);
77 data->free_total++;
78 if (data->tracked.erase(mem) ==
0) {
79 data->free_failed++;
80
81 }
else {
82 free(mem);
83 }
84 }
85
86 cx_allocator_class cx_testing_allocator_class = {
87 cx_malloc_testing,
88 cx_realloc_testing,
89 cx_calloc_testing,
90 cx_free_testing
91 };
92
93 CxTestingAllocator::CxTestingAllocator() : CxAllocator() {
94 cl = &cx_testing_allocator_class;
95 data = this;
96 }
97
98 bool CxTestingAllocator::used()
const {
99 return alloc_total >
0;
100 }
101
102 bool CxTestingAllocator::verify()
const {
103 return tracked.empty() && alloc_failed ==
0 && free_failed ==
0 && alloc_total == free_total;
104 }
105
106
107
108 #include <gtest/gtest.h>
109
110 TEST(TestingAllocator, ExpectFree) {
111 CxTestingAllocator allocator;
112
113 ASSERT_TRUE(allocator.verify());
114 EXPECT_FALSE(allocator.used());
115 auto ptr = cxMalloc(&allocator,
16);
116 EXPECT_TRUE(allocator.used());
117 ASSERT_NE(ptr, nullptr);
118 EXPECT_FALSE(allocator.verify());
119
120 cxFree(&allocator, ptr);
121 EXPECT_TRUE(allocator.verify());
122 }
123
124 TEST(TestingAllocator, DetectDoubleFree) {
125 CxTestingAllocator allocator;
126
127 ASSERT_TRUE(allocator.verify());
128 auto ptr = cxMalloc(&allocator,
16);
129 ASSERT_NE(ptr, nullptr);
130
131 cxFree(&allocator, ptr);
132 EXPECT_TRUE(allocator.verify());
133 ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr));
134 EXPECT_FALSE(allocator.verify());
135 }
136
137 TEST(TestingAllocator, FreeUntracked) {
138 CxTestingAllocator allocator;
139
140 auto ptr = malloc(
16);
141 ASSERT_TRUE(allocator.verify());
142 ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr));
143 EXPECT_FALSE(allocator.verify());
144 ASSERT_NO_FATAL_FAILURE(free(ptr));
145 }
146
147 TEST(TestingAllocator, FullLifecycleWithRealloc) {
148 CxTestingAllocator allocator;
149 ASSERT_TRUE(allocator.verify());
150 auto ptr = cxMalloc(&allocator,
16);
151 ASSERT_NE(ptr, nullptr);
152 EXPECT_EQ(allocator.tracked.size(),
1);
153 ptr = cxRealloc(&allocator, ptr,
256);
154 ASSERT_NE(ptr, nullptr);
155 EXPECT_EQ(allocator.tracked.size(),
1);
156 cxFree(&allocator, ptr);
157 EXPECT_TRUE(allocator.verify());
158 }
159
160 TEST(TestingAllocator, CallocInitializes) {
161 CxTestingAllocator allocator;
162 const char zeros[
16] = {
0};
163 auto ptr = cxCalloc(&allocator,
16,
1);
164 EXPECT_EQ(memcmp(ptr, zeros,
16),
0);
165 cxFree(&allocator, ptr);
166 EXPECT_TRUE(allocator.verify());
167 }
168