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