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 err = pbuf_copy(p3, p1);
92 fail_unless(err == ERR_VAL);
93
94 pbuf_free(p1);
95 pbuf_free(p3);
96 }
97 END_TEST
98
99 /** Call pbuf_copy on pbufs with chains of different sizes */
START_TEST(test_pbuf_copy_unmatched_chains)100 START_TEST(test_pbuf_copy_unmatched_chains)
101 {
102 uint16_t i, j;
103 err_t err;
104 struct pbuf *source, *dest, *p;
105 LWIP_UNUSED_ARG(_i);
106
107 source = NULL;
108 /* Build source pbuf from linked 16 byte parts,
109 * with payload bytes containing their offset */
110 for (i = 0; i < 8; i++) {
111 p = pbuf_alloc(PBUF_RAW, 16, PBUF_RAM);
112 fail_unless(p != NULL);
113 for (j = 0; j < p->len; j++) {
114 ((u8_t*)p->payload)[j] = (u8_t)((i << 4) | j);
115 }
116 if (source) {
117 pbuf_cat(source, p);
118 } else {
119 source = p;
120 }
121 }
122 for (i = 0; i < source->tot_len; i++) {
123 fail_unless(pbuf_get_at(source, i) == i);
124 }
125
126 /* Build dest pbuf from other lengths */
127 dest = pbuf_alloc(PBUF_RAW, 35, PBUF_RAM);
128 fail_unless(dest != NULL);
129 p = pbuf_alloc(PBUF_RAW, 81, PBUF_RAM);
130 fail_unless(p != NULL);
131 pbuf_cat(dest, p);
132 p = pbuf_alloc(PBUF_RAW, 27, PBUF_RAM);
133 fail_unless(p != NULL);
134 pbuf_cat(dest, p);
135
136 /* Copy contents and verify data */
137 err = pbuf_copy(dest, source);
138 fail_unless(err == ERR_OK);
139 for (i = 0; i < source->tot_len; i++) {
140 fail_unless(pbuf_get_at(dest, i) == i);
141 }
142
143 pbuf_free(source);
144 pbuf_free(dest);
145 }
146 END_TEST
147
START_TEST(test_pbuf_copy_partial_pbuf)148 START_TEST(test_pbuf_copy_partial_pbuf)
149 {
150 struct pbuf *a, *b, *dest;
151 char lwip[] = "lwip ";
152 char packet[] = "packet";
153 err_t err;
154 LWIP_UNUSED_ARG(_i);
155
156 a = pbuf_alloc(PBUF_RAW, 5, PBUF_REF);
157 fail_unless(a != NULL);
158 a->payload = lwip;
159 b = pbuf_alloc(PBUF_RAW, 7, PBUF_REF);
160 fail_unless(b != NULL);
161 b->payload = packet;
162 pbuf_cat(a, b);
163 dest = pbuf_alloc(PBUF_RAW, 14, PBUF_RAM);
164 memset(dest->payload, 0, dest->len);
165 fail_unless(dest != NULL);
166
167 /* Don't copy if data will not fit */
168 err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 4);
169 fail_unless(err == ERR_ARG);
170 /* Don't copy if length is longer than source */
171 err = pbuf_copy_partial_pbuf(dest, a, a->tot_len + 1, 0);
172 fail_unless(err == ERR_ARG);
173 /* Normal copy */
174 err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 0);
175 fail_unless(err == ERR_OK);
176 fail_unless(strcmp("lwip packet", (char*)dest->payload) == 0);
177 /* Copy at offset */
178 err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 1);
179 fail_unless(err == ERR_OK);
180 fail_unless(strcmp("llwip packet", (char*)dest->payload) == 0);
181 /* Copy at offset with shorter length */
182 err = pbuf_copy_partial_pbuf(dest, a, 6, 6);
183 fail_unless(err == ERR_OK);
184 fail_unless(strcmp("llwip lwip p", (char*)dest->payload) == 0);
185 /* Copy with shorter length */
186 err = pbuf_copy_partial_pbuf(dest, a, 5, 0);
187 fail_unless(err == ERR_OK);
188 fail_unless(strcmp("lwip lwip p", (char*)dest->payload) == 0);
189
190 pbuf_free(dest);
191 pbuf_free(a);
192 }
193 END_TEST
194
START_TEST(test_pbuf_split_64k_on_small_pbufs)195 START_TEST(test_pbuf_split_64k_on_small_pbufs)
196 {
197 struct pbuf *p, *rest=NULL;
198 LWIP_UNUSED_ARG(_i);
199
200 p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL);
201 pbuf_split_64k(p, &rest);
202 fail_unless(p->tot_len == 1);
203 pbuf_free(p);
204 }
205 END_TEST
206
START_TEST(test_pbuf_queueing_bigger_than_64k)207 START_TEST(test_pbuf_queueing_bigger_than_64k)
208 {
209 int i;
210 err_t err;
211 struct pbuf *p1, *p2, *p3, *rest2=NULL, *rest3=NULL;
212 LWIP_UNUSED_ARG(_i);
213
214 for(i = 0; i < TESTBUFSIZE_1; i++) {
215 testbuf_1[i] = (u8_t)rand();
216 }
217 for(i = 0; i < TESTBUFSIZE_2; i++) {
218 testbuf_2[i] = (u8_t)rand();
219 }
220 for(i = 0; i < TESTBUFSIZE_3; i++) {
221 testbuf_3[i] = (u8_t)rand();
222 }
223
224 p1 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_1, PBUF_POOL);
225 fail_unless(p1 != NULL);
226 p2 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_2, PBUF_POOL);
227 fail_unless(p2 != NULL);
228 p3 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_3, PBUF_POOL);
229 fail_unless(p3 != NULL);
230 err = pbuf_take(p1, testbuf_1, TESTBUFSIZE_1);
231 fail_unless(err == ERR_OK);
232 err = pbuf_take(p2, testbuf_2, TESTBUFSIZE_2);
233 fail_unless(err == ERR_OK);
234 err = pbuf_take(p3, testbuf_3, TESTBUFSIZE_3);
235 fail_unless(err == ERR_OK);
236
237 pbuf_cat(p1, p2);
238 pbuf_cat(p1, p3);
239
240 pbuf_split_64k(p1, &rest2);
241 fail_unless(p1->tot_len == TESTBUFSIZE_1);
242 fail_unless(rest2->tot_len == (u16_t)((TESTBUFSIZE_2+TESTBUFSIZE_3) & 0xFFFF));
243 pbuf_split_64k(rest2, &rest3);
244 fail_unless(rest2->tot_len == TESTBUFSIZE_2);
245 fail_unless(rest3->tot_len == TESTBUFSIZE_3);
246
247 pbuf_copy_partial(p1, testbuf_1a, TESTBUFSIZE_1, 0);
248 pbuf_copy_partial(rest2, testbuf_2a, TESTBUFSIZE_2, 0);
249 pbuf_copy_partial(rest3, testbuf_3a, TESTBUFSIZE_3, 0);
250 fail_if(memcmp(testbuf_1, testbuf_1a, TESTBUFSIZE_1));
251 fail_if(memcmp(testbuf_2, testbuf_2a, TESTBUFSIZE_2));
252 fail_if(memcmp(testbuf_3, testbuf_3a, TESTBUFSIZE_3));
253
254 pbuf_free(p1);
255 pbuf_free(rest2);
256 pbuf_free(rest3);
257 }
258 END_TEST
259
260 /* Test for bug that writing with pbuf_take_at() did nothing
261 * and returned ERR_OK when writing at beginning of a pbuf
262 * in the chain.
263 */
START_TEST(test_pbuf_take_at_edge)264 START_TEST(test_pbuf_take_at_edge)
265 {
266 err_t res;
267 u8_t *out;
268 int i;
269 u8_t testdata[] = { 0x01, 0x08, 0x82, 0x02 };
270 struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
271 struct pbuf *q = p->next;
272 LWIP_UNUSED_ARG(_i);
273 /* alloc big enough to get a chain of pbufs */
274 fail_if(p->tot_len == p->len);
275 memset(p->payload, 0, p->len);
276 memset(q->payload, 0, q->len);
277
278 /* copy data to the beginning of first pbuf */
279 res = pbuf_take_at(p, &testdata, sizeof(testdata), 0);
280 fail_unless(res == ERR_OK);
281
282 out = (u8_t*)p->payload;
283 for (i = 0; i < (int)sizeof(testdata); i++) {
284 fail_unless(out[i] == testdata[i],
285 "Bad data at pos %d, was %02X, expected %02X", i, out[i], testdata[i]);
286 }
287
288 /* copy data to the just before end of first pbuf */
289 res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len - 1);
290 fail_unless(res == ERR_OK);
291
292 out = (u8_t*)p->payload;
293 fail_unless(out[p->len - 1] == testdata[0],
294 "Bad data at pos %d, was %02X, expected %02X", p->len - 1, out[p->len - 1], testdata[0]);
295 out = (u8_t*)q->payload;
296 for (i = 1; i < (int)sizeof(testdata); i++) {
297 fail_unless(out[i-1] == testdata[i],
298 "Bad data at pos %d, was %02X, expected %02X", p->len - 1 + i, out[i-1], testdata[i]);
299 }
300
301 /* copy data to the beginning of second pbuf */
302 res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len);
303 fail_unless(res == ERR_OK);
304
305 out = (u8_t*)p->payload;
306 for (i = 0; i < (int)sizeof(testdata); i++) {
307 fail_unless(out[i] == testdata[i],
308 "Bad data at pos %d, was %02X, expected %02X", p->len+i, out[i], testdata[i]);
309 }
310 pbuf_free(p);
311 }
312 END_TEST
313
314 /* Verify pbuf_put_at()/pbuf_get_at() when using
315 * offsets equal to beginning of new pbuf in chain
316 */
START_TEST(test_pbuf_get_put_at_edge)317 START_TEST(test_pbuf_get_put_at_edge)
318 {
319 u8_t *out;
320 u8_t testdata = 0x01;
321 u8_t getdata;
322 struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
323 struct pbuf *q = p->next;
324 LWIP_UNUSED_ARG(_i);
325 /* alloc big enough to get a chain of pbufs */
326 fail_if(p->tot_len == p->len);
327 memset(p->payload, 0, p->len);
328 memset(q->payload, 0, q->len);
329
330 /* put byte at the beginning of second pbuf */
331 pbuf_put_at(p, p->len, testdata);
332
333 out = (u8_t*)q->payload;
334 fail_unless(*out == testdata,
335 "Bad data at pos %d, was %02X, expected %02X", p->len, *out, testdata);
336
337 getdata = pbuf_get_at(p, p->len);
338 fail_unless(*out == getdata,
339 "pbuf_get_at() returned bad data at pos %d, was %02X, expected %02X", p->len, getdata, *out);
340 pbuf_free(p);
341 }
342 END_TEST
343
344 /** Create the suite including all tests for this module */
345 Suite *
pbuf_suite(void)346 pbuf_suite(void)
347 {
348 testfunc tests[] = {
349 TESTFUNC(test_pbuf_alloc_zero_pbufs),
350 TESTFUNC(test_pbuf_copy_zero_pbuf),
351 TESTFUNC(test_pbuf_copy_unmatched_chains),
352 TESTFUNC(test_pbuf_copy_partial_pbuf),
353 TESTFUNC(test_pbuf_split_64k_on_small_pbufs),
354 TESTFUNC(test_pbuf_queueing_bigger_than_64k),
355 TESTFUNC(test_pbuf_take_at_edge),
356 TESTFUNC(test_pbuf_get_put_at_edge)
357 };
358 return create_suite("PBUF", tests, sizeof(tests)/sizeof(testfunc), pbuf_setup, pbuf_teardown);
359 }
360