main.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /*
  2. * lws-api-test-lws_dsh
  3. *
  4. * Written in 2010-2019 by Andy Green <[email protected]>
  5. *
  6. * This file is made available under the Creative Commons CC0 1.0
  7. * Universal Public Domain Dedication.
  8. */
  9. #include <libwebsockets.h>
  10. int
  11. test1(void)
  12. {
  13. struct lws_dsh *dsh;
  14. size_t size;
  15. void *a1;
  16. /*
  17. * test 1: single dsh, alloc 2 kinds and free everything back to a
  18. * single free obj
  19. */
  20. dsh = lws_dsh_create(NULL, 16384, 2);
  21. if (!dsh) {
  22. lwsl_err("%s: Failed to create dsh\n", __func__);
  23. return 1;
  24. }
  25. if (lws_dsh_alloc_tail(dsh, 0, "hello", 5, NULL, 0)) {
  26. lwsl_err("%s: Failed to alloc 1\n", __func__);
  27. goto bail;
  28. }
  29. if (lws_dsh_alloc_tail(dsh, 1, "some other string", 17, NULL, 0)) {
  30. lwsl_err("%s: Failed to alloc 2\n", __func__);
  31. goto bail;
  32. }
  33. if (lws_dsh_alloc_tail(dsh, 0, "hello again", 11, NULL, 0)) {
  34. lwsl_err("%s: Failed to alloc 3\n", __func__);
  35. goto bail;
  36. }
  37. if (lws_dsh_get_head(dsh, 1, &a1, &size)) {
  38. lwsl_err("%s: no head 1\n", __func__);
  39. goto bail;
  40. }
  41. if (size != 17 || memcmp(a1, "some other string", 17)) {
  42. lwsl_err("%s: test 1 mismatch\n", __func__);
  43. goto bail;
  44. }
  45. lws_dsh_free(&a1);
  46. if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
  47. lwsl_err("%s: no head 2\n", __func__);
  48. goto bail;
  49. }
  50. if (size != 5 || memcmp(a1, "hello", 5)) {
  51. lwsl_err("%s: test 2 mismatch\n", __func__);
  52. goto bail;
  53. }
  54. lws_dsh_free(&a1);
  55. if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
  56. lwsl_err("%s: no head 3\n", __func__);
  57. goto bail;
  58. }
  59. if (size != 11 || memcmp(a1, "hello again", 11)) {
  60. lwsl_err("%s: test 3 mismatch\n", __func__);
  61. goto bail;
  62. }
  63. lws_dsh_free(&a1);
  64. lws_dsh_destroy(&dsh);
  65. return 0;
  66. bail:
  67. lws_dsh_destroy(&dsh);
  68. return 1;
  69. }
  70. int
  71. test2(void)
  72. {
  73. struct lws_dsh *dsh, *dsh2;
  74. lws_dll2_owner_t owner;
  75. uint8_t blob[4096];
  76. memset(blob, 0, sizeof(blob));
  77. /*
  78. * test 2: multiple dsh, overflow allocation and dynamic destroy
  79. */
  80. lws_dll2_owner_clear(&owner);
  81. dsh = lws_dsh_create(&owner, 4096, 2);
  82. if (!dsh) {
  83. lwsl_err("%s: Failed to create dsh1\n", __func__);
  84. return 1;
  85. }
  86. dsh2 = lws_dsh_create(&owner, 4096, 2);
  87. if (!dsh2) {
  88. lwsl_err("%s: Failed to create dsh2\n", __func__);
  89. goto bail;
  90. }
  91. if (lws_dsh_alloc_tail(dsh, 0, blob, 4000, NULL, 0)) {
  92. lwsl_err("%s: Failed to alloc 1\n", __func__);
  93. goto bail2;
  94. }
  95. if (lws_dsh_alloc_tail(dsh2, 0, "hello", 5, NULL, 0)) {
  96. lwsl_err("%s: Failed to alloc 2\n", __func__);
  97. goto bail2;
  98. }
  99. /*
  100. * We create this logically on dsh. But there's no room for the body.
  101. * It should figure out it can use space on dsh2.
  102. */
  103. if (lws_dsh_alloc_tail(dsh, 0, blob, 2000, NULL, 0)) {
  104. lwsl_err("%s: Failed to alloc 3\n", __func__);
  105. goto bail2;
  106. }
  107. if (lws_dsh_alloc_tail(dsh2, 0, "hello again", 11, NULL, 0)) {
  108. lwsl_err("%s: Failed to alloc 4\n", __func__);
  109. goto bail2;
  110. }
  111. /*
  112. * When we destroy dsh2 it will try to migrate out the 2000 allocation
  113. * from there but find there is no space in dsh1. It should handle it
  114. * by logicalling dropping the object.
  115. */
  116. lws_dsh_destroy(&dsh2);
  117. lws_dsh_destroy(&dsh);
  118. return 0;
  119. bail2:
  120. lws_dsh_destroy(&dsh2);
  121. bail:
  122. lws_dsh_destroy(&dsh);
  123. return 1;
  124. }
  125. int
  126. test3(void)
  127. {
  128. struct lws_dsh *dsh, *dsh2;
  129. lws_dll2_owner_t owner;
  130. uint8_t blob[4096];
  131. memset(blob, 0, sizeof(blob));
  132. /*
  133. * test 3: multiple dsh, umeetable allocation request
  134. */
  135. lws_dll2_owner_clear(&owner);
  136. dsh = lws_dsh_create(&owner, 4096, 2);
  137. if (!dsh) {
  138. lwsl_err("%s: Failed to create dsh1\n", __func__);
  139. return 1;
  140. }
  141. dsh2 = lws_dsh_create(&owner, 4096, 2);
  142. if (!dsh2) {
  143. lwsl_err("%s: Failed to create dsh2\n", __func__);
  144. goto bail;
  145. }
  146. if (lws_dsh_alloc_tail(dsh, 0, blob, 4000, NULL, 0)) {
  147. lwsl_err("%s: Failed to alloc 1\n", __func__);
  148. goto bail2;
  149. }
  150. if (lws_dsh_alloc_tail(dsh2, 0, "hello", 5, NULL, 0)) {
  151. lwsl_err("%s: Failed to alloc 2\n", __func__);
  152. goto bail2;
  153. }
  154. /*
  155. * There's just no room for this, we expect it to fail
  156. */
  157. if (!lws_dsh_alloc_tail(dsh, 0, blob, 5000, NULL, 0)) {
  158. lwsl_err("%s: Didn't fail to alloc as expected\n", __func__);
  159. goto bail2;
  160. }
  161. if (lws_dsh_alloc_tail(dsh2, 0, "hello again", 11, NULL, 0)) {
  162. lwsl_err("%s: Failed to alloc 4\n", __func__);
  163. goto bail2;
  164. }
  165. lws_dsh_destroy(&dsh2);
  166. lws_dsh_destroy(&dsh);
  167. return 0;
  168. bail2:
  169. lws_dsh_destroy(&dsh2);
  170. bail:
  171. lws_dsh_destroy(&dsh);
  172. return 1;
  173. }
  174. int
  175. test4(void)
  176. {
  177. uint8_t blob[4096];
  178. struct lws_dsh *dsh;
  179. size_t size;
  180. void *a1;
  181. memset(blob, 0, sizeof(blob));
  182. /*
  183. * test 1: use up whole free list, then recover and alloc something
  184. * else
  185. */
  186. dsh = lws_dsh_create(NULL, 4096, 2);
  187. if (!dsh) {
  188. lwsl_err("%s: Failed to create dsh\n", __func__);
  189. return 1;
  190. }
  191. if (lws_dsh_alloc_tail(dsh, 0, blob, 4000, NULL, 0)) {
  192. lwsl_err("%s: Failed to alloc 1\n", __func__);
  193. goto bail;
  194. }
  195. if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
  196. lwsl_err("%s: no head 1\n", __func__);
  197. goto bail;
  198. }
  199. if (size != 4000) {
  200. lwsl_err("%s: test 1 mismatch\n", __func__);
  201. goto bail;
  202. }
  203. lws_dsh_free(&a1);
  204. if (lws_dsh_alloc_tail(dsh, 0, "some other string", 17, NULL, 0)) {
  205. lwsl_err("%s: Failed to alloc 2\n", __func__);
  206. goto bail;
  207. }
  208. if (lws_dsh_alloc_tail(dsh, 0, "hello again", 11, NULL, 0)) {
  209. lwsl_err("%s: Failed to alloc 3\n", __func__);
  210. goto bail;
  211. }
  212. if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
  213. lwsl_err("%s: no head 1\n", __func__);
  214. goto bail;
  215. }
  216. if (size != 17 || memcmp(a1, "some other string", 17)) {
  217. lwsl_err("%s: test 1 mismatch\n", __func__);
  218. goto bail;
  219. }
  220. lws_dsh_free(&a1);
  221. if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
  222. lwsl_err("%s: no head 2\n", __func__);
  223. goto bail;
  224. }
  225. if (size != 11 || memcmp(a1, "hello again", 11)) {
  226. lwsl_err("%s: test 2 mismatch (%zu)\n", __func__, size);
  227. goto bail;
  228. }
  229. lws_dsh_free(&a1);
  230. lws_dsh_destroy(&dsh);
  231. return 0;
  232. bail:
  233. lws_dsh_destroy(&dsh);
  234. return 1;
  235. }
  236. int main(int argc, const char **argv)
  237. {
  238. int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
  239. int ret = 0, n;
  240. const char *p;
  241. if ((p = lws_cmdline_option(argc, argv, "-d")))
  242. logs = atoi(p);
  243. lws_set_log_level(logs, NULL);
  244. lwsl_user("LWS API selftest: lws_dsh\n");
  245. n = test1();
  246. lwsl_user("%s: test1: %d\n", __func__, n);
  247. ret |= n;
  248. n = test2();
  249. lwsl_user("%s: test2: %d\n", __func__, n);
  250. ret |= n;
  251. n = test3();
  252. lwsl_user("%s: test3: %d\n", __func__, n);
  253. ret |= n;
  254. n = test4();
  255. lwsl_user("%s: test4: %d\n", __func__, n);
  256. ret |= n;
  257. lwsl_user("Completed: %s\n", ret ? "FAIL" : "PASS");
  258. return ret;
  259. }