1 /* ==========================================
2 * Unity Project - A Test Framework for C
3 * Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
4 * [Released under MIT License. Please refer to license.txt for details]
5 * ========================================== */
6
7 #include "unity.h"
8 #include "unity_memory.h"
9 #include "unity_output_Spy.h"
10 #include <stdlib.h>
11 #include <string.h>
12
13 /* This test module includes the following tests: */
14
15 void test_ForceMallocFail(void);
16 void test_ReallocSmallerIsUnchanged(void);
17 void test_ReallocSameIsUnchanged(void);
18 void test_ReallocLargerNeeded(void);
19 void test_ReallocNullPointerIsLikeMalloc(void);
20 void test_ReallocSizeZeroFreesMemAndReturnsNullPointer(void);
21 void test_CallocFillsWithZero(void);
22 void test_FreeNULLSafety(void);
23 void test_DetectsLeak(void);
24 void test_BufferOverrunFoundDuringFree(void);
25 void test_BufferOverrunFoundDuringRealloc(void);
26 void test_BufferGuardWriteFoundDuringFree(void);
27 void test_BufferGuardWriteFoundDuringRealloc(void);
28 void test_MallocPastBufferFails(void);
29 void test_CallocPastBufferFails(void);
30 void test_MallocThenReallocGrowsMemoryInPlace(void);
31 void test_ReallocFailDoesNotFreeMem(void);
32
33 /* It makes use of the following features */
34 void setUp(void);
35 void tearDown(void);
36
37 /* Let's Go! */
setUp(void)38 void setUp(void)
39 {
40 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
41 UnityOutputCharSpy_Create(200);
42 #else
43 UnityOutputCharSpy_Create(1000);
44 #endif
45 UnityMalloc_StartTest();
46 }
47
tearDown(void)48 void tearDown(void)
49 {
50 UnityMalloc_EndTest();
51 UnityOutputCharSpy_Destroy();
52 }
53
test_ForceMallocFail(void)54 void test_ForceMallocFail(void)
55 {
56 void* m;
57 void* mfails;
58 UnityMalloc_MakeMallocFailAfterCount(1);
59 m = malloc(10);
60 TEST_ASSERT_NOT_NULL(m);
61 mfails = malloc(10);
62 TEST_ASSERT_EQUAL_PTR(0, mfails);
63 free(m);
64 }
65
test_ReallocSmallerIsUnchanged(void)66 void test_ReallocSmallerIsUnchanged(void)
67 {
68 void* m1 = malloc(10);
69 void* m2 = realloc(m1, 5);
70 TEST_ASSERT_NOT_NULL(m1);
71 TEST_ASSERT_EQUAL_PTR(m1, m2);
72 free(m2);
73 }
74
test_ReallocSameIsUnchanged(void)75 void test_ReallocSameIsUnchanged(void)
76 {
77 void* m1 = malloc(10);
78 void* m2 = realloc(m1, 10);
79 TEST_ASSERT_NOT_NULL(m1);
80 TEST_ASSERT_EQUAL_PTR(m1, m2);
81 free(m2);
82 }
83
test_ReallocLargerNeeded(void)84 void test_ReallocLargerNeeded(void)
85 {
86 void* m2;
87 void* m1 = malloc(10);
88 TEST_ASSERT_NOT_NULL(m1);
89 strcpy((char*)m1, "123456789");
90 m2 = realloc(m1, 15);
91 TEST_ASSERT_EQUAL_STRING("123456789", m2);
92 free(m2);
93 }
94
test_ReallocNullPointerIsLikeMalloc(void)95 void test_ReallocNullPointerIsLikeMalloc(void)
96 {
97 void* m = realloc(0, 15);
98 TEST_ASSERT_NOT_NULL(m);
99 free(m);
100 }
101
test_ReallocSizeZeroFreesMemAndReturnsNullPointer(void)102 void test_ReallocSizeZeroFreesMemAndReturnsNullPointer(void)
103 {
104 void* m1 = malloc(10);
105 void* m2 = realloc(m1, 0);
106 TEST_ASSERT_EQUAL_PTR(0, m2);
107 }
108
test_CallocFillsWithZero(void)109 void test_CallocFillsWithZero(void)
110 {
111 void* m = calloc(3, sizeof(char));
112 char* s = (char*)m;
113 TEST_ASSERT_NOT_NULL(m);
114 TEST_ASSERT_EQUAL_HEX8(0, s[0]);
115 TEST_ASSERT_EQUAL_HEX8(0, s[1]);
116 TEST_ASSERT_EQUAL_HEX8(0, s[2]);
117 free(m);
118 }
119
test_FreeNULLSafety(void)120 void test_FreeNULLSafety(void)
121 {
122 free(NULL);
123 }
124
125 /*------------------------------------------------------------ */
126
127 #define EXPECT_ABORT_BEGIN \
128 { \
129 jmp_buf TestAbortFrame; \
130 memcpy(TestAbortFrame, Unity.AbortFrame, sizeof(jmp_buf)); \
131 if (TEST_PROTECT()) \
132 {
133
134 #define EXPECT_ABORT_END \
135 } \
136 memcpy(Unity.AbortFrame, TestAbortFrame, sizeof(jmp_buf)); \
137 }
138
139 /* This tricky set of defines lets us see if we are using the Spy, returns 1 if true */
140 #ifdef __STDC_VERSION__
141
142 #ifdef UNITY_SUPPORT_VARIADIC_MACROS
143 #define USING_SPY_AS(a) EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0)
144 #define ASSIGN_VALUE(a) VAL_##a
145 #define VAL_UnityOutputCharSpy_OutputChar 0, 1
146 #define EXPAND_AND_USE_2ND(a, b) SECOND_PARAM(a, b, throwaway)
147 #define SECOND_PARAM(a, b, ...) b
148 #if USING_SPY_AS(UNITY_OUTPUT_CHAR)
149 #define USING_OUTPUT_SPY /* UNITY_OUTPUT_CHAR = UnityOutputCharSpy_OutputChar */
150 #endif
151 #endif /* UNITY_SUPPORT_VARIADIC_MACROS */
152
153 #else /* __STDC_VERSION__ else */
154
155 #define UnityOutputCharSpy_OutputChar 42
156 #if UNITY_OUTPUT_CHAR == UnityOutputCharSpy_OutputChar /* Works if no -Wundef -Werror */
157 #define USING_OUTPUT_SPY
158 #endif
159 #undef UnityOutputCharSpy_OutputChar
160
161 #endif /* __STDC_VERSION__ */
162
test_DetectsLeak(void)163 void test_DetectsLeak(void)
164 {
165 #ifdef USING_OUTPUT_SPY
166 void* m = malloc(10);
167 TEST_ASSERT_NOT_NULL(m);
168 UnityOutputCharSpy_Enable(1);
169 EXPECT_ABORT_BEGIN
170 UnityMalloc_EndTest();
171 EXPECT_ABORT_END
172 UnityOutputCharSpy_Enable(0);
173 Unity.CurrentTestFailed = 0;
174 TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "This test leaks!"));
175 free(m);
176 #else
177 TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
178 #endif
179 }
180
test_BufferOverrunFoundDuringFree(void)181 void test_BufferOverrunFoundDuringFree(void)
182 {
183 #ifdef USING_OUTPUT_SPY
184 void* m = malloc(10);
185 char* s = (char*)m;
186 TEST_ASSERT_NOT_NULL(m);
187 s[10] = (char)0xFF;
188 UnityOutputCharSpy_Enable(1);
189 EXPECT_ABORT_BEGIN
190 free(m);
191 EXPECT_ABORT_END
192 UnityOutputCharSpy_Enable(0);
193 Unity.CurrentTestFailed = 0;
194 TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
195 #else
196 TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
197 #endif
198 }
199
test_BufferOverrunFoundDuringRealloc(void)200 void test_BufferOverrunFoundDuringRealloc(void)
201 {
202 #ifdef USING_OUTPUT_SPY
203 void* m = malloc(10);
204 char* s = (char*)m;
205 TEST_ASSERT_NOT_NULL(m);
206 s[10] = (char)0xFF;
207 UnityOutputCharSpy_Enable(1);
208 EXPECT_ABORT_BEGIN
209 m = realloc(m, 100);
210 EXPECT_ABORT_END
211 UnityOutputCharSpy_Enable(0);
212 Unity.CurrentTestFailed = 0;
213 TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
214 #else
215 TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
216 #endif
217 }
218
test_BufferGuardWriteFoundDuringFree(void)219 void test_BufferGuardWriteFoundDuringFree(void)
220 {
221 #ifdef USING_OUTPUT_SPY
222 void* m = malloc(10);
223 char* s = (char*)m;
224 TEST_ASSERT_NOT_NULL(m);
225 s[-1] = (char)0x00; /* Will not detect 0 */
226 s[-2] = (char)0x01;
227 UnityOutputCharSpy_Enable(1);
228 EXPECT_ABORT_BEGIN
229 free(m);
230 EXPECT_ABORT_END
231 UnityOutputCharSpy_Enable(0);
232 Unity.CurrentTestFailed = 0;
233 TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
234 #else
235 TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
236 #endif
237 }
238
test_BufferGuardWriteFoundDuringRealloc(void)239 void test_BufferGuardWriteFoundDuringRealloc(void)
240 {
241 #ifdef USING_OUTPUT_SPY
242 void* m = malloc(10);
243 char* s = (char*)m;
244 TEST_ASSERT_NOT_NULL(m);
245 s[-1] = (char)0x0A;
246 UnityOutputCharSpy_Enable(1);
247 EXPECT_ABORT_BEGIN
248 m = realloc(m, 100);
249 EXPECT_ABORT_END
250 UnityOutputCharSpy_Enable(0);
251 Unity.CurrentTestFailed = 0;
252 TEST_ASSERT_NOT_NULL(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
253 #else
254 TEST_IGNORE_MESSAGE("Enable USING_OUTPUT_SPY To Run This Test");
255 #endif
256 }
257
258 /*------------------------------------------------------------ */
259
260 #define TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(first_mem_ptr, ptr) \
261 ptr = malloc(10); free(ptr); \
262 TEST_ASSERT_EQUAL_PTR_MESSAGE(first_mem_ptr, ptr, "Memory was stranded, free in LIFO order");
263
test_MallocPastBufferFails(void)264 void test_MallocPastBufferFails(void)
265 {
266 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
267 void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
268 void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
269 free(m);
270 TEST_ASSERT_NOT_NULL(m);
271 TEST_ASSERT_NULL(n);
272 TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
273 #else
274 TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test");
275 #endif
276 }
277
test_CallocPastBufferFails(void)278 void test_CallocPastBufferFails(void)
279 {
280 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
281 void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
282 void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
283 free(m);
284 TEST_ASSERT_NOT_NULL(m);
285 TEST_ASSERT_NULL(n);
286 TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
287 #else
288 TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test");
289 #endif
290 }
291
test_MallocThenReallocGrowsMemoryInPlace(void)292 void test_MallocThenReallocGrowsMemoryInPlace(void)
293 {
294 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
295 void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
296 void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9);
297 free(n);
298 TEST_ASSERT_NOT_NULL(m);
299 TEST_ASSERT_EQUAL(m, n);
300 TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
301 #else
302 TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test");
303 #endif
304 }
305
test_ReallocFailDoesNotFreeMem(void)306 void test_ReallocFailDoesNotFreeMem(void)
307 {
308 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
309 void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
310 void* n1 = malloc(10);
311 void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
312 void* n2 = malloc(10);
313
314 free(n2);
315 if (out_of_mem == NULL) free(n1);
316 free(m);
317
318 TEST_ASSERT_NOT_NULL(m); /* Got a real memory location */
319 TEST_ASSERT_NULL(out_of_mem); /* The realloc should have failed */
320 TEST_ASSERT_NOT_EQUAL(n2, n1); /* If n1 != n2 then realloc did not free n1 */
321 TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n2);
322 #else
323 TEST_IGNORE_MESSAGE("Enable UNITY_EXCLUDE_STDLIB_MALLOC to Run This Test");
324 #endif
325 }
326