| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- /*
- * lws-api-test-lws_dsh
- *
- * Written in 2010-2019 by Andy Green <[email protected]>
- *
- * This file is made available under the Creative Commons CC0 1.0
- * Universal Public Domain Dedication.
- */
- #include <libwebsockets.h>
- int
- test1(void)
- {
- struct lws_dsh *dsh;
- size_t size;
- void *a1;
- /*
- * test 1: single dsh, alloc 2 kinds and free everything back to a
- * single free obj
- */
- dsh = lws_dsh_create(NULL, 16384, 2);
- if (!dsh) {
- lwsl_err("%s: Failed to create dsh\n", __func__);
- return 1;
- }
- if (lws_dsh_alloc_tail(dsh, 0, "hello", 5, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 1\n", __func__);
- goto bail;
- }
- if (lws_dsh_alloc_tail(dsh, 1, "some other string", 17, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 2\n", __func__);
- goto bail;
- }
- if (lws_dsh_alloc_tail(dsh, 0, "hello again", 11, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 3\n", __func__);
- goto bail;
- }
- if (lws_dsh_get_head(dsh, 1, &a1, &size)) {
- lwsl_err("%s: no head 1\n", __func__);
- goto bail;
- }
- if (size != 17 || memcmp(a1, "some other string", 17)) {
- lwsl_err("%s: test 1 mismatch\n", __func__);
- goto bail;
- }
- lws_dsh_free(&a1);
- if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
- lwsl_err("%s: no head 2\n", __func__);
- goto bail;
- }
- if (size != 5 || memcmp(a1, "hello", 5)) {
- lwsl_err("%s: test 2 mismatch\n", __func__);
- goto bail;
- }
- lws_dsh_free(&a1);
- if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
- lwsl_err("%s: no head 3\n", __func__);
- goto bail;
- }
- if (size != 11 || memcmp(a1, "hello again", 11)) {
- lwsl_err("%s: test 3 mismatch\n", __func__);
- goto bail;
- }
- lws_dsh_free(&a1);
- lws_dsh_destroy(&dsh);
- return 0;
- bail:
- lws_dsh_destroy(&dsh);
- return 1;
- }
- int
- test2(void)
- {
- struct lws_dsh *dsh, *dsh2;
- lws_dll2_owner_t owner;
- uint8_t blob[4096];
- memset(blob, 0, sizeof(blob));
- /*
- * test 2: multiple dsh, overflow allocation and dynamic destroy
- */
- lws_dll2_owner_clear(&owner);
- dsh = lws_dsh_create(&owner, 4096, 2);
- if (!dsh) {
- lwsl_err("%s: Failed to create dsh1\n", __func__);
- return 1;
- }
- dsh2 = lws_dsh_create(&owner, 4096, 2);
- if (!dsh2) {
- lwsl_err("%s: Failed to create dsh2\n", __func__);
- goto bail;
- }
- if (lws_dsh_alloc_tail(dsh, 0, blob, 4000, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 1\n", __func__);
- goto bail2;
- }
- if (lws_dsh_alloc_tail(dsh2, 0, "hello", 5, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 2\n", __func__);
- goto bail2;
- }
- /*
- * We create this logically on dsh. But there's no room for the body.
- * It should figure out it can use space on dsh2.
- */
- if (lws_dsh_alloc_tail(dsh, 0, blob, 2000, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 3\n", __func__);
- goto bail2;
- }
- if (lws_dsh_alloc_tail(dsh2, 0, "hello again", 11, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 4\n", __func__);
- goto bail2;
- }
- /*
- * When we destroy dsh2 it will try to migrate out the 2000 allocation
- * from there but find there is no space in dsh1. It should handle it
- * by logicalling dropping the object.
- */
- lws_dsh_destroy(&dsh2);
- lws_dsh_destroy(&dsh);
- return 0;
- bail2:
- lws_dsh_destroy(&dsh2);
- bail:
- lws_dsh_destroy(&dsh);
- return 1;
- }
- int
- test3(void)
- {
- struct lws_dsh *dsh, *dsh2;
- lws_dll2_owner_t owner;
- uint8_t blob[4096];
- memset(blob, 0, sizeof(blob));
- /*
- * test 3: multiple dsh, umeetable allocation request
- */
- lws_dll2_owner_clear(&owner);
- dsh = lws_dsh_create(&owner, 4096, 2);
- if (!dsh) {
- lwsl_err("%s: Failed to create dsh1\n", __func__);
- return 1;
- }
- dsh2 = lws_dsh_create(&owner, 4096, 2);
- if (!dsh2) {
- lwsl_err("%s: Failed to create dsh2\n", __func__);
- goto bail;
- }
- if (lws_dsh_alloc_tail(dsh, 0, blob, 4000, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 1\n", __func__);
- goto bail2;
- }
- if (lws_dsh_alloc_tail(dsh2, 0, "hello", 5, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 2\n", __func__);
- goto bail2;
- }
- /*
- * There's just no room for this, we expect it to fail
- */
- if (!lws_dsh_alloc_tail(dsh, 0, blob, 5000, NULL, 0)) {
- lwsl_err("%s: Didn't fail to alloc as expected\n", __func__);
- goto bail2;
- }
- if (lws_dsh_alloc_tail(dsh2, 0, "hello again", 11, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 4\n", __func__);
- goto bail2;
- }
- lws_dsh_destroy(&dsh2);
- lws_dsh_destroy(&dsh);
- return 0;
- bail2:
- lws_dsh_destroy(&dsh2);
- bail:
- lws_dsh_destroy(&dsh);
- return 1;
- }
- int
- test4(void)
- {
- uint8_t blob[4096];
- struct lws_dsh *dsh;
- size_t size;
- void *a1;
- memset(blob, 0, sizeof(blob));
- /*
- * test 1: use up whole free list, then recover and alloc something
- * else
- */
- dsh = lws_dsh_create(NULL, 4096, 2);
- if (!dsh) {
- lwsl_err("%s: Failed to create dsh\n", __func__);
- return 1;
- }
- if (lws_dsh_alloc_tail(dsh, 0, blob, 4000, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 1\n", __func__);
- goto bail;
- }
- if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
- lwsl_err("%s: no head 1\n", __func__);
- goto bail;
- }
- if (size != 4000) {
- lwsl_err("%s: test 1 mismatch\n", __func__);
- goto bail;
- }
- lws_dsh_free(&a1);
- if (lws_dsh_alloc_tail(dsh, 0, "some other string", 17, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 2\n", __func__);
- goto bail;
- }
- if (lws_dsh_alloc_tail(dsh, 0, "hello again", 11, NULL, 0)) {
- lwsl_err("%s: Failed to alloc 3\n", __func__);
- goto bail;
- }
- if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
- lwsl_err("%s: no head 1\n", __func__);
- goto bail;
- }
- if (size != 17 || memcmp(a1, "some other string", 17)) {
- lwsl_err("%s: test 1 mismatch\n", __func__);
- goto bail;
- }
- lws_dsh_free(&a1);
- if (lws_dsh_get_head(dsh, 0, &a1, &size)) {
- lwsl_err("%s: no head 2\n", __func__);
- goto bail;
- }
- if (size != 11 || memcmp(a1, "hello again", 11)) {
- lwsl_err("%s: test 2 mismatch (%zu)\n", __func__, size);
- goto bail;
- }
- lws_dsh_free(&a1);
- lws_dsh_destroy(&dsh);
- return 0;
- bail:
- lws_dsh_destroy(&dsh);
- return 1;
- }
- int main(int argc, const char **argv)
- {
- int logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE;
- int ret = 0, n;
- const char *p;
- if ((p = lws_cmdline_option(argc, argv, "-d")))
- logs = atoi(p);
- lws_set_log_level(logs, NULL);
- lwsl_user("LWS API selftest: lws_dsh\n");
- n = test1();
- lwsl_user("%s: test1: %d\n", __func__, n);
- ret |= n;
- n = test2();
- lwsl_user("%s: test2: %d\n", __func__, n);
- ret |= n;
- n = test3();
- lwsl_user("%s: test3: %d\n", __func__, n);
- ret |= n;
- n = test4();
- lwsl_user("%s: test4: %d\n", __func__, n);
- ret |= n;
- lwsl_user("Completed: %s\n", ret ? "FAIL" : "PASS");
- return ret;
- }
|