1 #include "test_mem.h"
2
3 #include "lwip/mem.h"
4 #include "lwip/stats.h"
5
6 #if !LWIP_STATS || !MEM_STATS
7 #error "This tests needs MEM-statistics enabled"
8 #endif
9
10 /* Setups/teardown functions */
11
12 static void
mem_setup(void)13 mem_setup(void)
14 {
15 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
16 }
17
18 static void
mem_teardown(void)19 mem_teardown(void)
20 {
21 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
22 }
23
24
25 /* Test functions */
26
27 /** Call mem_malloc, mem_free and mem_trim and check stats */
START_TEST(test_mem_one)28 START_TEST(test_mem_one)
29 {
30 #define SIZE1 16
31 #define SIZE1_2 12
32 #define SIZE2 16
33 void *p1, *p2;
34 mem_size_t s1, s2;
35 LWIP_UNUSED_ARG(_i);
36
37 fail_unless(lwip_stats.mem.used == 0);
38
39 p1 = mem_malloc(SIZE1);
40 fail_unless(p1 != NULL);
41 fail_unless(lwip_stats.mem.used >= SIZE1);
42 s1 = lwip_stats.mem.used;
43
44 p2 = mem_malloc(SIZE2);
45 fail_unless(p2 != NULL);
46 fail_unless(lwip_stats.mem.used >= SIZE2 + s1);
47 s2 = lwip_stats.mem.used;
48
49 mem_trim(p1, SIZE1_2);
50
51 mem_free(p2);
52 fail_unless(lwip_stats.mem.used <= s2 - SIZE2);
53
54 mem_free(p1);
55 fail_unless(lwip_stats.mem.used == 0);
56 }
57 END_TEST
58
malloc_keep_x(int x,int num,int size,int freestep)59 static void malloc_keep_x(int x, int num, int size, int freestep)
60 {
61 int i;
62 void* p[16];
63 LWIP_ASSERT("invalid size", size >= 0 && size < (mem_size_t)-1);
64 memset(p, 0, sizeof(p));
65 for(i = 0; i < num && i < 16; i++) {
66 p[i] = mem_malloc((mem_size_t)size);
67 fail_unless(p[i] != NULL);
68 }
69 for(i = 0; i < num && i < 16; i += freestep) {
70 if (i == x) {
71 continue;
72 }
73 mem_free(p[i]);
74 p[i] = NULL;
75 }
76 for(i = 0; i < num && i < 16; i++) {
77 if (i == x) {
78 continue;
79 }
80 if (p[i] != NULL) {
81 mem_free(p[i]);
82 p[i] = NULL;
83 }
84 }
85 fail_unless(p[x] != NULL);
86 mem_free(p[x]);
87 }
88
START_TEST(test_mem_random)89 START_TEST(test_mem_random)
90 {
91 const int num = 16;
92 int x;
93 int size;
94 int freestep;
95 LWIP_UNUSED_ARG(_i);
96
97 fail_unless(lwip_stats.mem.used == 0);
98
99 for (x = 0; x < num; x++) {
100 for (size = 1; size < 32; size++) {
101 for (freestep = 1; freestep <= 3; freestep++) {
102 fail_unless(lwip_stats.mem.used == 0);
103 malloc_keep_x(x, num, size, freestep);
104 fail_unless(lwip_stats.mem.used == 0);
105 }
106 }
107 }
108 }
109 END_TEST
110
START_TEST(test_mem_invalid_free)111 START_TEST(test_mem_invalid_free)
112 {
113 u8_t *ptr, *ptr_low, *ptr_high;
114 LWIP_UNUSED_ARG(_i);
115
116 fail_unless(lwip_stats.mem.used == 0);
117 fail_unless(lwip_stats.mem.illegal == 0);
118
119 ptr = (u8_t *)mem_malloc(1);
120 fail_unless(ptr != NULL);
121 fail_unless(lwip_stats.mem.used != 0);
122
123 ptr_low = ptr - 0x10;
124 mem_free(ptr_low);
125 fail_unless(lwip_stats.mem.illegal == 1);
126 lwip_stats.mem.illegal = 0;
127
128 ptr_high = ptr + (MEM_SIZE * 2);
129 mem_free(ptr_high);
130 fail_unless(lwip_stats.mem.illegal == 1);
131 lwip_stats.mem.illegal = 0;
132
133 mem_free(ptr);
134 fail_unless(lwip_stats.mem.illegal == 0);
135 fail_unless(lwip_stats.mem.used == 0);
136 }
137 END_TEST
138
START_TEST(test_mem_double_free)139 START_TEST(test_mem_double_free)
140 {
141 u8_t *ptr1b, *ptr1, *ptr2, *ptr3;
142 LWIP_UNUSED_ARG(_i);
143
144 fail_unless(lwip_stats.mem.used == 0);
145 fail_unless(lwip_stats.mem.illegal == 0);
146
147 ptr1 = (u8_t *)mem_malloc(1);
148 fail_unless(ptr1 != NULL);
149 fail_unless(lwip_stats.mem.used != 0);
150
151 ptr2 = (u8_t *)mem_malloc(1);
152 fail_unless(ptr2 != NULL);
153 fail_unless(lwip_stats.mem.used != 0);
154
155 ptr3 = (u8_t *)mem_malloc(1);
156 fail_unless(ptr3 != NULL);
157 fail_unless(lwip_stats.mem.used != 0);
158
159 /* free the middle mem */
160 mem_free(ptr2);
161 fail_unless(lwip_stats.mem.illegal == 0);
162
163 /* double-free of middle mem: should fail */
164 mem_free(ptr2);
165 fail_unless(lwip_stats.mem.illegal == 1);
166 lwip_stats.mem.illegal = 0;
167
168 /* free upper memory and try again */
169 mem_free(ptr3);
170 fail_unless(lwip_stats.mem.illegal == 0);
171
172 mem_free(ptr2);
173 fail_unless(lwip_stats.mem.illegal == 1);
174 lwip_stats.mem.illegal = 0;
175
176 /* free lower memory and try again */
177 mem_free(ptr1);
178 fail_unless(lwip_stats.mem.illegal == 0);
179 fail_unless(lwip_stats.mem.used == 0);
180
181 mem_free(ptr2);
182 fail_unless(lwip_stats.mem.illegal == 1);
183 fail_unless(lwip_stats.mem.used == 0);
184 lwip_stats.mem.illegal = 0;
185
186 /* reallocate lowest memory, now overlapping already freed ptr2 */
187 #ifndef MIN_SIZE
188 #define MIN_SIZE 12
189 #endif
190 ptr1b = (u8_t *)mem_malloc(MIN_SIZE * 2);
191 fail_unless(ptr1b != NULL);
192 fail_unless(lwip_stats.mem.used != 0);
193
194 mem_free(ptr2);
195 fail_unless(lwip_stats.mem.illegal == 1);
196 lwip_stats.mem.illegal = 0;
197
198 memset(ptr1b, 1, MIN_SIZE * 2);
199
200 mem_free(ptr2);
201 fail_unless(lwip_stats.mem.illegal == 1);
202 lwip_stats.mem.illegal = 0;
203
204 mem_free(ptr1b);
205 fail_unless(lwip_stats.mem.illegal == 0);
206 fail_unless(lwip_stats.mem.used == 0);
207 }
208 END_TEST
209
210 /** Create the suite including all tests for this module */
211 Suite *
mem_suite(void)212 mem_suite(void)
213 {
214 testfunc tests[] = {
215 TESTFUNC(test_mem_one),
216 TESTFUNC(test_mem_random),
217 TESTFUNC(test_mem_invalid_free),
218 TESTFUNC(test_mem_double_free)
219 };
220 return create_suite("MEM", tests, sizeof(tests)/sizeof(testfunc), mem_setup, mem_teardown);
221 }
222