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_DNS
10 #error "This test needs DNS turned off (as it mallocs on init)"
11 #endif
12 #if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !LWIP_WND_SCALE
13 #error "This test needs TCP OOSEQ queueing and window scaling enabled"
14 #endif
15 
16 /* Setups/teardown functions */
17 
18 static void
19 pbuf_setup(void)
20 {
21 }
22 
23 static void
24 pbuf_teardown(void)
25 {
26 }
27 
28 
29 #define TESTBUFSIZE_1 65535
30 #define TESTBUFSIZE_2 65530
31 #define TESTBUFSIZE_3 50050
32 static u8_t testbuf_1[TESTBUFSIZE_1];
33 static u8_t testbuf_1a[TESTBUFSIZE_1];
34 static u8_t testbuf_2[TESTBUFSIZE_2];
35 static u8_t testbuf_2a[TESTBUFSIZE_2];
36 static u8_t testbuf_3[TESTBUFSIZE_3];
37 static u8_t testbuf_3a[TESTBUFSIZE_3];
38 
39 /* Test functions */
40 
41 /** Call pbuf_copy on a pbuf with zero length */
42 START_TEST(test_pbuf_copy_zero_pbuf)
43 {
44   struct pbuf *p1, *p2, *p3;
45   err_t err;
46   LWIP_UNUSED_ARG(_i);
47 
48   fail_unless(lwip_stats.mem.used == 0);
49   fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0);
50 
51   p1 = pbuf_alloc(PBUF_RAW, 1024, PBUF_RAM);
52   fail_unless(p1 != NULL);
53   fail_unless(p1->ref == 1);
54 
55   p2 = pbuf_alloc(PBUF_RAW, 2, PBUF_POOL);
56   fail_unless(p2 != NULL);
57   fail_unless(p2->ref == 1);
58   p2->len = p2->tot_len = 0;
59 
60   pbuf_cat(p1, p2);
61   fail_unless(p1->ref == 1);
62   fail_unless(p2->ref == 1);
63 
64   p3 = pbuf_alloc(PBUF_RAW, p1->tot_len, PBUF_POOL);
65   err = pbuf_copy(p3, p1);
66   fail_unless(err == ERR_VAL);
67 
68   pbuf_free(p1);
69   pbuf_free(p3);
70   fail_unless(lwip_stats.mem.used == 0);
71 
72   fail_unless(lwip_stats.mem.used == 0);
73   fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0);
74 }
75 END_TEST
76 
77 START_TEST(test_pbuf_split_64k_on_small_pbufs)
78 {
79   struct pbuf *p, *rest=NULL;
80   LWIP_UNUSED_ARG(_i);
81 
82   p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL);
83   pbuf_split_64k(p, &rest);
84   fail_unless(p->tot_len == 1);
85   pbuf_free(p);
86 }
87 END_TEST
88 
89 START_TEST(test_pbuf_queueing_bigger_than_64k)
90 {
91   int i;
92   err_t err;
93   struct pbuf *p1, *p2, *p3, *rest2=NULL, *rest3=NULL;
94   LWIP_UNUSED_ARG(_i);
95 
96   for(i = 0; i < TESTBUFSIZE_1; i++) {
97     testbuf_1[i] = (u8_t)rand();
98   }
99   for(i = 0; i < TESTBUFSIZE_2; i++) {
100     testbuf_2[i] = (u8_t)rand();
101   }
102   for(i = 0; i < TESTBUFSIZE_3; i++) {
103     testbuf_3[i] = (u8_t)rand();
104   }
105 
106   p1 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_1, PBUF_POOL);
107   fail_unless(p1 != NULL);
108   p2 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_2, PBUF_POOL);
109   fail_unless(p2 != NULL);
110   p3 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_3, PBUF_POOL);
111   fail_unless(p3 != NULL);
112   err = pbuf_take(p1, testbuf_1, TESTBUFSIZE_1);
113   fail_unless(err == ERR_OK);
114   err = pbuf_take(p2, testbuf_2, TESTBUFSIZE_2);
115   fail_unless(err == ERR_OK);
116   err = pbuf_take(p3, testbuf_3, TESTBUFSIZE_3);
117   fail_unless(err == ERR_OK);
118 
119   pbuf_cat(p1, p2);
120   pbuf_cat(p1, p3);
121 
122   pbuf_split_64k(p1, &rest2);
123   fail_unless(p1->tot_len == TESTBUFSIZE_1);
124   fail_unless(rest2->tot_len == (u16_t)((TESTBUFSIZE_2+TESTBUFSIZE_3) & 0xFFFF));
125   pbuf_split_64k(rest2, &rest3);
126   fail_unless(rest2->tot_len == TESTBUFSIZE_2);
127   fail_unless(rest3->tot_len == TESTBUFSIZE_3);
128 
129   pbuf_copy_partial(p1, testbuf_1a, TESTBUFSIZE_1, 0);
130   pbuf_copy_partial(rest2, testbuf_2a, TESTBUFSIZE_2, 0);
131   pbuf_copy_partial(rest3, testbuf_3a, TESTBUFSIZE_3, 0);
132   for(i = 0; i < TESTBUFSIZE_1; i++)
133     fail_unless(testbuf_1[i] == testbuf_1a[i]);
134   for(i = 0; i < TESTBUFSIZE_2; i++)
135     fail_unless(testbuf_2[i] == testbuf_2a[i]);
136   for(i = 0; i < TESTBUFSIZE_3; i++)
137     fail_unless(testbuf_3[i] == testbuf_3a[i]);
138 
139   pbuf_free(p1);
140   pbuf_free(rest2);
141   pbuf_free(rest3);
142 }
143 END_TEST
144 
145 /* Test for bug that writing with pbuf_take_at() did nothing
146  * and returned ERR_OK when writing at beginning of a pbuf
147  * in the chain.
148  */
149 START_TEST(test_pbuf_take_at_edge)
150 {
151   err_t res;
152   u8_t *out;
153   int i;
154   u8_t testdata[] = { 0x01, 0x08, 0x82, 0x02 };
155   struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
156   struct pbuf *q = p->next;
157   LWIP_UNUSED_ARG(_i);
158   /* alloc big enough to get a chain of pbufs */
159   fail_if(p->tot_len == p->len);
160   memset(p->payload, 0, p->len);
161   memset(q->payload, 0, q->len);
162 
163   /* copy data to the beginning of first pbuf */
164   res = pbuf_take_at(p, &testdata, sizeof(testdata), 0);
165   fail_unless(res == ERR_OK);
166 
167   out = (u8_t*)p->payload;
168   for (i = 0; i < (int)sizeof(testdata); i++) {
169     fail_unless(out[i] == testdata[i],
170       "Bad data at pos %d, was %02X, expected %02X", i, out[i], testdata[i]);
171   }
172 
173   /* copy data to the just before end of first pbuf */
174   res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len - 1);
175   fail_unless(res == ERR_OK);
176 
177   out = (u8_t*)p->payload;
178   fail_unless(out[p->len - 1] == testdata[0],
179     "Bad data at pos %d, was %02X, expected %02X", p->len - 1, out[p->len - 1], testdata[0]);
180   out = (u8_t*)q->payload;
181   for (i = 1; i < (int)sizeof(testdata); i++) {
182     fail_unless(out[i-1] == testdata[i],
183       "Bad data at pos %d, was %02X, expected %02X", p->len - 1 + i, out[i-1], testdata[i]);
184   }
185 
186   /* copy data to the beginning of second pbuf */
187   res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len);
188   fail_unless(res == ERR_OK);
189 
190   out = (u8_t*)p->payload;
191   for (i = 0; i < (int)sizeof(testdata); i++) {
192     fail_unless(out[i] == testdata[i],
193       "Bad data at pos %d, was %02X, expected %02X", p->len+i, out[i], testdata[i]);
194   }
195 }
196 END_TEST
197 
198 /* Verify pbuf_put_at()/pbuf_get_at() when using
199  * offsets equal to beginning of new pbuf in chain
200  */
201 START_TEST(test_pbuf_get_put_at_edge)
202 {
203   u8_t *out;
204   u8_t testdata = 0x01;
205   u8_t getdata;
206   struct pbuf *p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
207   struct pbuf *q = p->next;
208   LWIP_UNUSED_ARG(_i);
209   /* alloc big enough to get a chain of pbufs */
210   fail_if(p->tot_len == p->len);
211   memset(p->payload, 0, p->len);
212   memset(q->payload, 0, q->len);
213 
214   /* put byte at the beginning of second pbuf */
215   pbuf_put_at(p, p->len, testdata);
216 
217   out = (u8_t*)q->payload;
218   fail_unless(*out == testdata,
219     "Bad data at pos %d, was %02X, expected %02X", p->len, *out, testdata);
220 
221   getdata = pbuf_get_at(p, p->len);
222   fail_unless(*out == getdata,
223     "pbuf_get_at() returned bad data at pos %d, was %02X, expected %02X", p->len, getdata, *out);
224 }
225 END_TEST
226 
227 /** Create the suite including all tests for this module */
228 Suite *
229 pbuf_suite(void)
230 {
231   testfunc tests[] = {
232     TESTFUNC(test_pbuf_copy_zero_pbuf),
233     TESTFUNC(test_pbuf_split_64k_on_small_pbufs),
234     TESTFUNC(test_pbuf_queueing_bigger_than_64k),
235     TESTFUNC(test_pbuf_take_at_edge),
236     TESTFUNC(test_pbuf_get_put_at_edge)
237   };
238   return create_suite("PBUF", tests, sizeof(tests)/sizeof(testfunc), pbuf_setup, pbuf_teardown);
239 }
240