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
pbuf_setup(void)19 pbuf_setup(void)
20 {
21 }
22
23 static void
pbuf_teardown(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 */
START_TEST(test_pbuf_copy_zero_pbuf)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
START_TEST(test_pbuf_split_64k_on_small_pbufs)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
START_TEST(test_pbuf_queueing_bigger_than_64k)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 */
START_TEST(test_pbuf_take_at_edge)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 */
START_TEST(test_pbuf_get_put_at_edge)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 *
pbuf_suite(void)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