1 #include <hawktracer/alloc_hooks.h>
2
3 #include <gtest/gtest.h>
4
5 #ifdef VALGRIND_CHECK_ENABLED
6 #include <valgrind/valgrind.h>
7 # define CHECK_VALGRIND() do {\
8 if (RUNNING_ON_VALGRIND) { \
9 printf("[ INFO ] Test run under valgrind!.The test is actually not executed!\n"); \
10 return; \
11 } \
12 } while (false)
13 #else /* VALGRIND_CHECK_ENABLED */
14 # define CHECK_VALGRIND();
15 #endif /* VALGRIND_CHECK_ENABLED */
16
17 #define VALGRIND_CHECK_ASSERT_EQ(val1, val2) ASSERT_EQ(val1, val2) << "The test can't be run under valgrind. Please disable valgrind and re-run the test.";
18
19 struct AllocHooksInfo
20 {
21 void* ret_ptr = NULL;
22 void* ptr = NULL;
23 size_t size = 0u;
24 size_t num = 0u;
25 size_t count = 0u;
26 };
27
test_malloc_hook(void * ret,size_t size,void * ud)28 void test_malloc_hook(void* ret, size_t size, void* ud)
29 {
30 AllocHooksInfo* info = static_cast<AllocHooksInfo*>(ud);
31 info->ret_ptr = ret;
32 info->size = size;
33 info->count++;
34 }
35
test_calloc_hook(void * ret,size_t num,size_t size,void * ud)36 void test_calloc_hook(void* ret, size_t num, size_t size, void* ud)
37 {
38 AllocHooksInfo* info = static_cast<AllocHooksInfo*>(ud);
39 info->ret_ptr = ret;
40 info->num = num;
41 info->size = size;
42 info->count++;
43 }
44
test_realloc_hook(void * ret,void * ptr,size_t size,void * ud)45 void test_realloc_hook(void* ret, void* ptr, size_t size, void* ud)
46 {
47 AllocHooksInfo* info = static_cast<AllocHooksInfo*>(ud);
48 info->ret_ptr = ret;
49 info->ptr = ptr;
50 info->size = size;
51 info->count++;
52 }
53
test_free_hook(void * ptr,void * ud)54 void test_free_hook(void* ptr, void* ud)
55 {
56 AllocHooksInfo* info = static_cast<AllocHooksInfo*>(ud);
57 info->ptr = ptr;
58 info->count++;
59 }
60
61 class TestAllocHooks : public ::testing::Test
62 {
63 protected:
_register_pre_hooks()64 void _register_pre_hooks()
65 {
66 ht_alloc_hooks_register_hooks(test_malloc_hook, NULL, test_calloc_hook, NULL, test_realloc_hook, NULL, test_free_hook, NULL, &_user_data);
67 }
68
_register_post_hooks()69 void _register_post_hooks()
70 {
71 ht_alloc_hooks_register_hooks(NULL, test_malloc_hook, NULL, test_calloc_hook, NULL, test_realloc_hook, NULL, test_free_hook, &_user_data);
72 }
73
TearDown()74 void TearDown() override
75 {
76 ht_alloc_hooks_register_hooks(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
77 }
78
79 AllocHooksInfo _user_data;
80 };
81
TEST_F(TestAllocHooks,TestMallocPreHook)82 TEST_F(TestAllocHooks, TestMallocPreHook)
83 {
84 // Arrange
85 CHECK_VALGRIND();
86 _register_pre_hooks();
87
88 // Act
89 void* volatile malloc_ptr = malloc(24);
90
91 // Assert
92 VALGRIND_CHECK_ASSERT_EQ(NULL, _user_data.ret_ptr);
93 VALGRIND_CHECK_ASSERT_EQ(24u, _user_data.size);
94 VALGRIND_CHECK_ASSERT_EQ(1u, _user_data.count);
95
96 (void)malloc_ptr; // avoid static code analysis tools warnings
97 free(malloc_ptr);
98 }
99
TEST_F(TestAllocHooks,TestMallocPostHook)100 TEST_F(TestAllocHooks, TestMallocPostHook)
101 {
102 // Arrange
103 CHECK_VALGRIND();
104 _register_post_hooks();
105
106 // Act
107 void* malloc_ptr = malloc(24);
108
109 // Assert
110 VALGRIND_CHECK_ASSERT_EQ(malloc_ptr, _user_data.ret_ptr);
111 VALGRIND_CHECK_ASSERT_EQ(24u, _user_data.size);
112 VALGRIND_CHECK_ASSERT_EQ(1u, _user_data.count);
113
114 free(malloc_ptr);
115 }
116
TEST_F(TestAllocHooks,TestCallocPreHook)117 TEST_F(TestAllocHooks, TestCallocPreHook)
118 {
119 // Arrange
120 CHECK_VALGRIND();
121 _register_pre_hooks();
122
123 // Act
124 void* volatile calloc_ptr = calloc(16u, 32u);
125
126 // Assert
127 VALGRIND_CHECK_ASSERT_EQ(NULL, _user_data.ret_ptr);
128 VALGRIND_CHECK_ASSERT_EQ(16u, _user_data.num);
129 VALGRIND_CHECK_ASSERT_EQ(32u, _user_data.size);
130 VALGRIND_CHECK_ASSERT_EQ(1u, _user_data.count);
131
132 (void)calloc_ptr; // avoid static code analysis tools warnings
133 free(calloc_ptr);
134 }
135
TEST_F(TestAllocHooks,TestCallocPostHook)136 TEST_F(TestAllocHooks, TestCallocPostHook)
137 {
138 // Arrange
139 CHECK_VALGRIND();
140 _register_post_hooks();
141
142 // Act
143 void* calloc_ptr = calloc(16u, 32u);
144
145 // Assert
146 VALGRIND_CHECK_ASSERT_EQ(calloc_ptr, _user_data.ret_ptr);
147 VALGRIND_CHECK_ASSERT_EQ(16u, _user_data.num);
148 VALGRIND_CHECK_ASSERT_EQ(32u, _user_data.size);
149 VALGRIND_CHECK_ASSERT_EQ(1u, _user_data.count);
150
151 free(calloc_ptr);
152 }
153
TEST_F(TestAllocHooks,TestReallocPreHook)154 TEST_F(TestAllocHooks, TestReallocPreHook)
155 {
156 // Arrange
157 CHECK_VALGRIND();
158 _register_pre_hooks();
159 void* malloc_ptr = malloc(24);
160
161 // Act
162 void* realloc_ptr = realloc(malloc_ptr, 64);
163
164 // Assert
165 VALGRIND_CHECK_ASSERT_EQ(NULL, _user_data.ret_ptr);
166 VALGRIND_CHECK_ASSERT_EQ(malloc_ptr, _user_data.ptr);
167 VALGRIND_CHECK_ASSERT_EQ(64u, _user_data.size);
168 VALGRIND_CHECK_ASSERT_EQ(2u, _user_data.count);
169
170 free(realloc_ptr);
171 }
172
TEST_F(TestAllocHooks,TestReallocPostHook)173 TEST_F(TestAllocHooks, TestReallocPostHook)
174 {
175 // Arrange
176 CHECK_VALGRIND();
177 _register_post_hooks();
178 void* malloc_ptr = malloc(24);
179
180 // Act
181 void* realloc_ptr = realloc(malloc_ptr, 64);
182
183 // Assert
184 VALGRIND_CHECK_ASSERT_EQ(realloc_ptr, _user_data.ret_ptr);
185 VALGRIND_CHECK_ASSERT_EQ(malloc_ptr, _user_data.ptr);
186 VALGRIND_CHECK_ASSERT_EQ(64u, _user_data.size);
187 VALGRIND_CHECK_ASSERT_EQ(2u, _user_data.count);
188
189 free(realloc_ptr);
190 }
191
TEST_F(TestAllocHooks,TestFreePreHook)192 TEST_F(TestAllocHooks, TestFreePreHook)
193 {
194 // Arrange
195 CHECK_VALGRIND();
196 _register_pre_hooks();
197 void* malloc_ptr = malloc(24);
198
199 // Act
200 free(malloc_ptr);
201
202 // Assert
203 VALGRIND_CHECK_ASSERT_EQ(malloc_ptr, _user_data.ptr);
204 VALGRIND_CHECK_ASSERT_EQ(2u, _user_data.count);
205 }
206
TEST_F(TestAllocHooks,TestFreePostHook)207 TEST_F(TestAllocHooks, TestFreePostHook)
208 {
209 // Arrange
210 CHECK_VALGRIND();
211 _register_post_hooks();
212 void* malloc_ptr = malloc(24);
213
214 // Act
215 free(malloc_ptr);
216
217 // Assert
218 VALGRIND_CHECK_ASSERT_EQ(malloc_ptr, _user_data.ptr);
219 VALGRIND_CHECK_ASSERT_EQ(2u, _user_data.count);
220 }
221
TEST_F(TestAllocHooks,SkipHookFunctionsShouldAllocateMemoryButNotCallCallback)222 TEST_F(TestAllocHooks, SkipHookFunctionsShouldAllocateMemoryButNotCallCallback)
223 {
224 // Arrange
225 CHECK_VALGRIND();
226 ht_alloc_hooks_register_hooks(test_malloc_hook, test_malloc_hook,
227 test_calloc_hook, test_calloc_hook,
228 test_realloc_hook, test_realloc_hook,
229 test_free_hook, test_free_hook, &_user_data);
230
231 // Act
232 void* volatile malloc_ptr = ht_alloc_hooks_malloc_skip_hook(10);
233 void* volatile realloc_ptr = ht_alloc_hooks_realloc_skip_hook(malloc_ptr, 32);
234 void* volatile calloc_ptr = ht_alloc_hooks_calloc_skip_hook(2, 4);
235
236 ht_alloc_hooks_free_skip_hook(realloc_ptr);
237 ht_alloc_hooks_free_skip_hook(calloc_ptr);
238
239 // Assert
240 ASSERT_EQ(0u, _user_data.count);
241 ASSERT_NE(nullptr, (void*)malloc_ptr);
242 ASSERT_NE(nullptr, (void*)calloc_ptr);
243 ASSERT_NE(nullptr, (void*)realloc_ptr);
244 }
245