test_pbuf.c 9.6 KB

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