• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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