1 #include "test_pbuf.h"
2
3 #include "lwip/pbuf.h"
4 #include "lwip/stats.h"
5
6 #if !LWIP_STATS || !MEM_STATS ||!MEMP_STATS
7 #error "This tests needs MEM- and MEMP-statistics enabled"
8 #endif
9 #if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !LWIP_WND_SCALE
10 #error "This test needs TCP OOSEQ queueing and window scaling enabled"
11 #endif
12
13 /* Setups/teardown functions */
14
15 static void
pbuf_setup(void)16 pbuf_setup(void)
17 {
18 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
19 }
20
21 static void
pbuf_teardown(void)22 pbuf_teardown(void)
23 {
24 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
25 }
26
27
28 #define TESTBUFSIZE_1 65535
29 #define TESTBUFSIZE_2 65530
30 #define TESTBUFSIZE_3 50050
31 static u8_t testbuf_1[TESTBUFSIZE_1];
32 static u8_t testbuf_1a[TESTBUFSIZE_1];
33 static u8_t testbuf_2[TESTBUFSIZE_2];
34 static u8_t testbuf_2a[TESTBUFSIZE_2];
35 static u8_t testbuf_3[TESTBUFSIZE_3];
36 static u8_t testbuf_3a[TESTBUFSIZE_3];
37
38 /* Test functions */
START_TEST(test_pbuf_alloc_zero_pbufs)39 START_TEST(test_pbuf_alloc_zero_pbufs)
40 {
41 struct pbuf *p;
42 LWIP_UNUSED_ARG(_i);
43
44 p = pbuf_alloc(PBUF_RAW, 0, PBUF_ROM);
45 fail_unless(p != NULL);
46 if (p != NULL) {
47 pbuf_free(p);
48 }
49
50 p = pbuf_alloc(PBUF_RAW, 0, PBUF_RAM);
51 fail_unless(p != NULL);
52 if (p != NULL) {
53 pbuf_free(p);
54 }
55
56 p = pbuf_alloc(PBUF_RAW, 0, PBUF_REF);
57 fail_unless(p != NULL);
58 if (p != NULL) {
59 pbuf_free(p);
60 }
61
62 p = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
63 fail_unless(p != NULL);
64 if (p != NULL) {
65 pbuf_free(p);
66 }
67 }
68 END_TEST
69
70 /** Call pbuf_copy on a pbuf with zero length */
START_TEST(test_pbuf_copy_zero_pbuf)71 START_TEST(test_pbuf_copy_zero_pbuf)
72 {
73 struct pbuf *p1, *p2, *p3;
74 err_t err;
75 LWIP_UNUSED_ARG(_i);
76
77 p1 = pbuf_alloc(PBUF_RAW, 1024, PBUF_RAM);
78 fail_unless(p1 != NULL);
79 fail_unless(p1->ref == 1);
80
81 p2 = pbuf_alloc(PBUF_RAW, 2, PBUF_POOL);
82 fail_unless(p2 != NULL);
83 fail_unless(p2->ref == 1);
84 p2->len = p2->tot_len = 0;
85
86 pbuf_cat(p1, p2);
87 fail_unless(p1->ref == 1);
88 fail_unless(p2->ref == 1);
89
90 p3 = pbuf_alloc(PBUF_RAW, p1->tot_len, PBUF_POOL);
91 fail_unless(p3 != NULL);
92 err = pbuf_copy(p3, p1);
93 fail_unless(err == ERR_VAL);
94
95 pbuf_free(p1);
96 pbuf_free(p3);
97 }
98 END_TEST
99
100 /** Call pbuf_copy on pbufs with chains of different sizes */
START_TEST(test_pbuf_copy_unmatched_chains)101 START_TEST(test_pbuf_copy_unmatched_chains)
102 {
103 uint16_t i, j;
104 err_t err;
105 struct pbuf *source, *dest, *p;
106 LWIP_UNUSED_ARG(_i);
107
108 source = NULL;
109 /* Build source pbuf from linked 16 byte parts,
110 * with payload bytes containing their offset */
111 for (i = 0; i < 8; i++) {
112 p = pbuf_alloc(PBUF_RAW, 16, PBUF_RAM);
113 fail_unless(p != NULL);
114 for (j = 0; j < p->len; j++) {
115 ((u8_t*)p->payload)[j] = (u8_t)((i << 4) | j);
116 }
117 if (source) {
118 pbuf_cat(source, p);
119 } else {
120 source = p;
121 }
122 }
123 for (i = 0; i < source->tot_len; i++) {
124 fail_unless(pbuf_get_at(source, i) == i);
125 }
126
127 /* Build dest pbuf from other lengths */
128 dest = pbuf_alloc(PBUF_RAW, 35, PBUF_RAM);
129 fail_unless(dest != NULL);
130 p = pbuf_alloc(PBUF_RAW, 81, PBUF_RAM);
131 fail_unless(p != NULL);
132 pbuf_cat(dest, p);
133 p = pbuf_alloc(PBUF_RAW, 27, PBUF_RAM);
134 fail_unless(p != NULL);
135 pbuf_cat(dest, p);
136
137 /* Copy contents and verify data */
138 err = pbuf_copy(dest, source);
139 fail_unless(err == ERR_OK);
140 for (i = 0; i < source->tot_len; i++) {
141 fail_unless(pbuf_get_at(dest, i) == i);
142 }
143
144 pbuf_free(source);
145 pbuf_free(dest);
146 }
147 END_TEST
148
START_TEST(test_pbuf_copy_partial_pbuf)149 START_TEST(test_pbuf_copy_partial_pbuf)
150 {
151 struct pbuf *a, *b, *dest;
152 char lwip[] = "lwip ";
153 char packet[] = "packet";
154 err_t err;
155 LWIP_UNUSED_ARG(_i);
156
157 a = pbuf_alloc(PBUF_RAW, 5, PBUF_REF);
158 fail_unless(a != NULL);
159 a->payload = lwip;
160 b = pbuf_alloc(PBUF_RAW, 7, PBUF_REF);
161 fail_unless(b != NULL);
162 b->payload = packet;
163 pbuf_cat(a, b);
164 dest = pbuf_alloc(PBUF_RAW, 14, PBUF_RAM);
165 fail_unless(dest != NULL);
166 memset(dest->payload, 0, dest->len);
167
168 /* Don't copy if data will not fit */
169 err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 4);
170 fail_unless(err == ERR_ARG);
171 /* Don't copy if length is longer than source */
172 err = pbuf_copy_partial_pbuf(dest, a, a->tot_len + 1, 0);
173 fail_unless(err == ERR_ARG);
174 /* Normal copy */
175 err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 0);
176 fail_unless(err == ERR_OK);
177 fail_unless(strcmp("lwip packet", (char*)dest->payload) == 0);
178 /* Copy at offset */
179 err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 1);
180 fail_unless(err == ERR_OK);
181 fail_unless(strcmp("llwip packet", (char*)dest->payload) == 0);
182 /* Copy at offset with shorter length */
183 err = pbuf_copy_partial_pbuf(dest, a, 6, 6);
184 fail_unless(err == ERR_OK);
185 fail_unless(strcmp("llwip lwip p", (char*)dest->payload) == 0);
186 /* Copy with shorter length */
187 err = pbuf_copy_partial_pbuf(dest, a, 5, 0);
188 fail_unless(err == ERR_OK);
189 fail_unless(strcmp("lwip lwip p", (char*)dest->payload) == 0);
190
191 pbuf_free(dest);
192 pbuf_free(a);
193 }
194 END_TEST
195
START_TEST(test_pbuf_split_64k_on_small_pbufs)196 START_TEST(test_pbuf_split_64k_on_small_pbufs)
197 {
198 struct pbuf *p, *rest=NULL;
199 LWIP_UNUSED_ARG(_i);
200
201 p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL);
202 fail_unless(p != NULL);
203 pbuf_split_64k(p, &rest);
204 fail_unless(p->tot_len == 1);
205 pbuf_free(p);
206 }
207 END_TEST
208
START_TEST(test_pbuf_queueing_bigger_than_64k)209 START_TEST(test_pbuf_queueing_bigger_than_64k)
210 {
211 int i;
212 err_t err;
213 struct pbuf *p1, *p2, *p3, *rest2=NULL, *rest3=NULL;
214 LWIP_UNUSED_ARG(_i);
215
216 for(i = 0; i < TESTBUFSIZE_1; i++) {
217 testbuf_1[i] = (u8_t)rand();
218 }
219 for(i = 0; i < TESTBUFSIZE_2; i++) {
220 testbuf_2[i] = (u8_t)rand();
221 }
222 for(i = 0; i < TESTBUFSIZE_3; i++) {
223 testbuf_3[i] = (u8_t)rand();
224 }
225
226 p1 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_1, PBUF_POOL);
227 fail_unless(p1 != NULL);
228 p2 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_2, PBUF_POOL);
229 fail_unless(p2 != NULL);
230 p3 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_3, PBUF_POOL);
231 fail_unless(p3 != NULL);
232 err = pbuf_take(p1, testbuf_1, TESTBUFSIZE_1);
233 fail_unless(err == ERR_OK);
234 err = pbuf_take(p2, testbuf_2, TESTBUFSIZE_2);
235 fail_unless(err == ERR_OK);
236 err = pbuf_take(p3, testbuf_3, TESTBUFSIZE_3);
237 fail_unless(err == ERR_OK);
238
239 pbuf_cat(p1, p2);
240 pbuf_cat(p1, p3);
241
242 pbuf_split_64k(p1, &rest2);
243 fail_unless(p1->tot_len == TESTBUFSIZE_1);
244 fail_unless(rest2->tot_len == (u16_t)((TESTBUFSIZE_2+TESTBUFSIZE_3) & 0xFFFF));
245 pbuf_split_64k(rest2, &rest3);
246 fail_unless(rest2->tot_len == TESTBUFSIZE_2);
247 fail_unless(rest3->tot_len == TESTBUFSIZE_3);
248
249 pbuf_copy_partial(p1, testbuf_1a, TESTBUFSIZE_1, 0);
250 pbuf_copy_partial(rest2, testbuf_2a, TESTBUFSIZE_2, 0);
251 pbuf_copy_partial(rest3, testbuf_3a, TESTBUFSIZE_3, 0);
252 fail_if(memcmp(testbuf_1, testbuf_1a, TESTBUFSIZE_1));
253 fail_if(memcmp(testbuf_2, testbuf_2a, TESTBUFSIZE_2));
254 fail_if(memcmp(testbuf_3, testbuf_3a, TESTBUFSIZE_3));
255
256 pbuf_free(p1);
257 pbuf_free(rest2);
258 pbuf_free(rest3);
259 }
260 END_TEST
261
262 /* Test for bug that writing with pbuf_take_at() did nothing
263 * and returned ERR_OK when writing at beginning of a pbuf
264 * in the chain.
265 */
START_TEST(test_pbuf_take_at_edge)266 START_TEST(test_pbuf_take_at_edge)
267 {
268 err_t res;
269 u8_t *out;
270 int i;
271 u8_t testdata[] = { 0x01, 0x08, 0x82, 0x02 };
272 struct pbuf *p;
273 struct pbuf *q;
274 LWIP_UNUSED_ARG(_i);
275
276 p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
277 fail_unless(p != NULL);
278 q = p->next;
279
280 /* alloc big enough to get a chain of pbufs */
281 fail_if(p->tot_len == p->len);
282 memset(p->payload, 0, p->len);
283 memset(q->payload, 0, q->len);
284
285 /* copy data to the beginning of first pbuf */
286 res = pbuf_take_at(p, &testdata, sizeof(testdata), 0);
287 fail_unless(res == ERR_OK);
288
289 out = (u8_t*)p->payload;
290 for (i = 0; i < (int)sizeof(testdata); i++) {
291 fail_unless(out[i] == testdata[i],
292 "Bad data at pos %d, was %02X, expected %02X", i, out[i], testdata[i]);
293 }
294
295 /* copy data to the just before end of first pbuf */
296 res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len - 1);
297 fail_unless(res == ERR_OK);
298
299 out = (u8_t*)p->payload;
300 fail_unless(out[p->len - 1] == testdata[0],
301 "Bad data at pos %d, was %02X, expected %02X", p->len - 1, out[p->len - 1], testdata[0]);
302 out = (u8_t*)q->payload;
303 for (i = 1; i < (int)sizeof(testdata); i++) {
304 fail_unless(out[i-1] == testdata[i],
305 "Bad data at pos %d, was %02X, expected %02X", p->len - 1 + i, out[i-1], testdata[i]);
306 }
307
308 /* copy data to the beginning of second pbuf */
309 res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len);
310 fail_unless(res == ERR_OK);
311
312 out = (u8_t*)p->payload;
313 for (i = 0; i < (int)sizeof(testdata); i++) {
314 fail_unless(out[i] == testdata[i],
315 "Bad data at pos %d, was %02X, expected %02X", p->len+i, out[i], testdata[i]);
316 }
317 pbuf_free(p);
318 }
319 END_TEST
320
321 /* Verify pbuf_put_at()/pbuf_get_at() when using
322 * offsets equal to beginning of new pbuf in chain
323 */
START_TEST(test_pbuf_get_put_at_edge)324 START_TEST(test_pbuf_get_put_at_edge)
325 {
326 u8_t *out;
327 u8_t testdata = 0x01;
328 u8_t getdata;
329 struct pbuf *p;
330 struct pbuf *q;
331 LWIP_UNUSED_ARG(_i);
332
333 p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
334 fail_unless(p != NULL);
335 q = p->next;
336
337 /* alloc big enough to get a chain of pbufs */
338 fail_if(p->tot_len == p->len);
339 memset(p->payload, 0, p->len);
340 memset(q->payload, 0, q->len);
341
342 /* put byte at the beginning of second pbuf */
343 pbuf_put_at(p, p->len, testdata);
344
345 out = (u8_t*)q->payload;
346 fail_unless(*out == testdata,
347 "Bad data at pos %d, was %02X, expected %02X", p->len, *out, testdata);
348
349 getdata = pbuf_get_at(p, p->len);
350 fail_unless(*out == getdata,
351 "pbuf_get_at() returned bad data at pos %d, was %02X, expected %02X", p->len, getdata, *out);
352 pbuf_free(p);
353 }
354 END_TEST
355
356 /** Create the suite including all tests for this module */
357 Suite *
pbuf_suite(void)358 pbuf_suite(void)
359 {
360 testfunc tests[] = {
361 TESTFUNC(test_pbuf_alloc_zero_pbufs),
362 TESTFUNC(test_pbuf_copy_zero_pbuf),
363 TESTFUNC(test_pbuf_copy_unmatched_chains),
364 TESTFUNC(test_pbuf_copy_partial_pbuf),
365 TESTFUNC(test_pbuf_split_64k_on_small_pbufs),
366 TESTFUNC(test_pbuf_queueing_bigger_than_64k),
367 TESTFUNC(test_pbuf_take_at_edge),
368 TESTFUNC(test_pbuf_get_put_at_edge)
369 };
370 return create_suite("PBUF", tests, sizeof(tests)/sizeof(testfunc), pbuf_setup, pbuf_teardown);
371 }
372