diff options
Diffstat (limited to 'test/lib')
-rw-r--r-- | test/lib/Makefile | 1 | ||||
-rw-r--r-- | test/lib/kconfig.c | 8 | ||||
-rw-r--r-- | test/lib/lmb.c | 114 | ||||
-rw-r--r-- | test/lib/longjmp.c | 2 | ||||
-rw-r--r-- | test/lib/membuf.c | 239 |
5 files changed, 355 insertions, 9 deletions
diff --git a/test/lib/Makefile b/test/lib/Makefile index 0e4cb8e3dfd..aa89923f786 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -14,6 +14,7 @@ obj-y += hexdump.o obj-$(CONFIG_SANDBOX) += kconfig.o obj-y += lmb.o obj-$(CONFIG_HAVE_SETJMP) += longjmp.o +obj-$(CONFIG_SANDBOX) += membuf.o obj-$(CONFIG_CONSOLE_RECORD) += test_print.o obj-$(CONFIG_SSCANF) += sscanf.o obj-$(CONFIG_$(PHASE_)STRTO) += str.o diff --git a/test/lib/kconfig.c b/test/lib/kconfig.c index a3645abf946..2f47af9acf1 100644 --- a/test/lib/kconfig.c +++ b/test/lib/kconfig.c @@ -22,10 +22,10 @@ static int lib_test_is_enabled(struct unit_test_state *uts) ut_asserteq(0, CONFIG_IS_ENABLED(_UNDEFINED)); if (IS_ENABLED(CONFIG_BLOBLIST)) { - ut_asserteq(0xb000, IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, - CONFIG_BLOBLIST_ADDR)); - ut_asserteq(0xb000, CONFIG_IF_ENABLED_INT(BLOBLIST_FIXED, - BLOBLIST_ADDR)); + ut_asserteq(0x100, IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, + CONFIG_BLOBLIST_ADDR)); + ut_asserteq(0x100, CONFIG_IF_ENABLED_INT(BLOBLIST_FIXED, + BLOBLIST_ADDR)); } /* diff --git a/test/lib/lmb.c b/test/lib/lmb.c index 01b1c7fdedd..3bf558f7f4f 100644 --- a/test/lib/lmb.c +++ b/test/lib/lmb.c @@ -471,17 +471,17 @@ static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts) ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, 0x40010000, 0x10000, 0, 0, 0, 0); - /* allocate overlapping region should return the coalesced count */ + /* allocate overlapping region */ ret = lmb_reserve(0x40011000, 0x10000, LMB_NONE); ut_asserteq(ret, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, 0x40010000, 0x11000, 0, 0, 0, 0); - /* allocate 3nd region */ + /* allocate 2nd region */ ret = lmb_reserve(0x40030000, 0x10000, LMB_NONE); ut_asserteq(ret, 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, 0x40010000, 0x11000, 0x40030000, 0x10000, 0, 0); - /* allocate 2nd region , This should coalesced all region into one */ + /* allocate 3rd region , This should coalesce all regions into one */ ret = lmb_reserve(0x40020000, 0x10000, LMB_NONE); ut_assert(ret >= 0); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, 0x40010000, 0x30000, @@ -499,6 +499,41 @@ static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts) ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, 0x40000000, 0x40000, 0, 0, 0, 0); + /* try to allocate overlapping region with a different flag, should fail */ + ret = lmb_reserve(0x40008000, 0x1000, LMB_NOOVERWRITE); + ut_asserteq(ret, -EEXIST); + + /* allocate another region at 0x40050000 with a different flag */ + ret = lmb_reserve(0x40050000, 0x10000, LMB_NOOVERWRITE); + ut_asserteq(ret, 0); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, 0x40000000, 0x40000, + 0x40050000, 0x10000, 0, 0); + + /* + * try to reserve a region adjacent to region 1 overlapping the 2nd region, + * should fail + */ + ret = lmb_reserve(0x40040000, 0x20000, LMB_NONE); + ut_asserteq(ret, -EEXIST); + + /* + * try to reserve a region between the two regions, but without an overlap, + * should succeed. this added region coalesces with the region 1 + */ + ret = lmb_reserve(0x40040000, 0x10000, LMB_NONE); + ut_asserteq(ret, 0); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, 0x40000000, 0x50000, + 0x40050000, 0x10000, 0, 0); + + /* + * try to reserve a region which overlaps with both the regions, + * should fail as the flags do not match + */ + ret = lmb_reserve(0x40020000, 0x80000, LMB_NONE); + ut_asserteq(ret, -EEXIST); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, 0x40000000, 0x50000, + 0x40050000, 0x10000, 0, 0); + lmb_pop(&store); return 0; @@ -549,6 +584,77 @@ static int test_alloc_addr(struct unit_test_state *uts, const phys_addr_t ram) ret = lmb_free(alloc_addr_a, 0x1000); ut_asserteq(ret, 0); + /* + * Add two regions with different flags, region1 and region2 with + * a gap between them. + * Try adding another region, adjacent to region 1 and overlapping + * region 2. Should fail. + */ + a = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NONE); + ut_asserteq(a, 0); + + b = lmb_alloc_addr(alloc_addr_a + 0x4000, 0x1000, LMB_NOOVERWRITE); + ut_asserteq(b, 0); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, alloc_addr_a, 0x1000, + alloc_addr_a + 0x4000, 0x1000, 0, 0); + + c = lmb_alloc_addr(alloc_addr_a + 0x1000, 0x5000, LMB_NONE); + ut_asserteq(c, -1); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, alloc_addr_a, 0x1000, + alloc_addr_a + 0x4000, 0x1000, 0, 0); + + ret = lmb_free(alloc_addr_a, 0x1000); + ut_asserteq(ret, 0); + ret = lmb_free(alloc_addr_a + 0x4000, 0x1000); + ut_asserteq(ret, 0); + + /* + * Add two regions with same flags(LMB_NONE), region1 and region2 + * with a gap between them. + * Try adding another region, adjacent to region 1 and overlapping + * region 2. Should succeed. All regions should coalesce into a + * single region. + */ + a = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NONE); + ut_asserteq(a, 0); + + b = lmb_alloc_addr(alloc_addr_a + 0x4000, 0x1000, LMB_NONE); + ut_asserteq(b, 0); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, alloc_addr_a, 0x1000, + alloc_addr_a + 0x4000, 0x1000, 0, 0); + + c = lmb_alloc_addr(alloc_addr_a + 0x1000, 0x5000, LMB_NONE); + ut_asserteq(c, 0); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, alloc_addr_a, 0x6000, + 0, 0, 0, 0); + + ret = lmb_free(alloc_addr_a, 0x6000); + ut_asserteq(ret, 0); + + /* + * Add two regions with same flags(LMB_NOOVERWRITE), region1 and + * region2 with a gap between them. + * Try adding another region, adjacent to region 1 and overlapping + * region 2. Should fail. + */ + a = lmb_alloc_addr(alloc_addr_a, 0x1000, LMB_NOOVERWRITE); + ut_asserteq(a, 0); + + b = lmb_alloc_addr(alloc_addr_a + 0x4000, 0x1000, LMB_NOOVERWRITE); + ut_asserteq(b, 0); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, alloc_addr_a, 0x1000, + alloc_addr_a + 0x4000, 0x1000, 0, 0); + + c = lmb_alloc_addr(alloc_addr_a + 0x1000, 0x5000, LMB_NOOVERWRITE); + ut_asserteq(c, -1); + ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 2, alloc_addr_a, 0x1000, + alloc_addr_a + 0x4000, 0x1000, 0, 0); + + ret = lmb_free(alloc_addr_a, 0x1000); + ut_asserteq(ret, 0); + ret = lmb_free(alloc_addr_a + 0x4000, 0x1000); + ut_asserteq(ret, 0); + /* reserve 3 blocks */ ret = lmb_reserve(alloc_addr_a, 0x10000, LMB_NONE); ut_asserteq(ret, 0); @@ -761,7 +867,7 @@ static int lib_test_lmb_flags(struct unit_test_state *uts) /* reserve again, new flag */ ret = lmb_reserve(0x40010000, 0x10000, LMB_NONE); - ut_asserteq(ret, -1); + ut_asserteq(ret, -EEXIST); ASSERT_LMB(mem_lst, used_lst, ram, ram_size, 1, 0x40010000, 0x10000, 0, 0, 0, 0); diff --git a/test/lib/longjmp.c b/test/lib/longjmp.c index 79d889bdd5f..74c3465b8c2 100644 --- a/test/lib/longjmp.c +++ b/test/lib/longjmp.c @@ -5,10 +5,10 @@ * Copyright (c) 2021, Heinrich Schuchardt <xypron.glpk@gmx.de> */ +#include <setjmp.h> #include <test/lib.h> #include <test/test.h> #include <test/ut.h> -#include <asm/setjmp.h> struct test_jmp_buf { jmp_buf env; diff --git a/test/lib/membuf.c b/test/lib/membuf.c new file mode 100644 index 00000000000..3f268a422d5 --- /dev/null +++ b/test/lib/membuf.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <membuf.h> +#include <os.h> +#include <rand.h> +#include <string.h> +#include <test/lib.h> +#include <test/test.h> +#include <test/ut.h> + +#define TEST_SIZE 16 +#define TEST_COUNT 10000 + +static void membuf_zero(struct membuf *mb) +{ + memset(mb->start, '\0', mb->end - mb->start); +} + +static int membuf_check(struct unit_test_state *uts, struct membuf *mb, + int value) +{ + /* head is out of range */ + ut_assert(!(mb->head < mb->start || mb->head >= mb->end)); + + /* tail is out of range */ + ut_assert(!(mb->tail < mb->start || mb->tail >= mb->end)); + + return 0; +} + +/* write from 1 to test_size bytes, and check they come back OK */ +static int lib_test_membuf_one(struct unit_test_state *uts) +{ + char in[TEST_SIZE * 2], out[TEST_SIZE * 2]; + struct membuf mb; + int size, ret, test_size, i; + + ut_assertok(membuf_new(&mb, TEST_SIZE)); + + /* setup in test */ + for (i = 0; i < TEST_SIZE; i++) { + in[i] = (i & 63) + '0'; + in[i + TEST_SIZE] = in[i]; + } + + test_size = TEST_SIZE; + + for (i = 1; i < TEST_COUNT; i++) { + membuf_zero(&mb); + size = rand() % test_size; + + // now write patterns and check they come back OK + ret = membuf_put(&mb, in, 0); + ret = membuf_put(&mb, in, size); + ut_asserteq(size, ret); + + ret = membuf_put(&mb, in, 0); + ut_assertok(membuf_check(uts, &mb, i)); + + ret = membuf_get(&mb, out, 0); + ret = membuf_get(&mb, out, size); + ut_asserteq(size, ret); + + ret = membuf_get(&mb, out, 0); + ut_assertok(membuf_check(uts, &mb, i)); + + ut_asserteq_mem(in, out, size); + } + + return 0; +} +LIB_TEST(lib_test_membuf_one, 0); + +/* write random number of bytes, and check they come back OK */ +static int lib_test_membuf_random(struct unit_test_state *uts) +{ + char in[TEST_SIZE * 2]; + char buf[TEST_SIZE * 2]; + struct membuf mb; + int size, ret, test_size, i; + char *inptr, *outptr; + int max_avail, min_free; + + ut_assertok(membuf_new(&mb, TEST_SIZE)); + + for (i = 0; i < TEST_SIZE; i++) { + in[i] = (i & 63) + '0'; + in[i + TEST_SIZE] = in[i]; + } + + test_size = TEST_SIZE; + + inptr = in; + outptr = in; + min_free = TEST_COUNT; + max_avail = 0; + membuf_zero(&mb); + for (i = 0; i < TEST_COUNT; i++) { + size = rand() % test_size; + + if (membuf_free(&mb) < min_free) + min_free = membuf_free(&mb); + + ret = membuf_put(&mb, inptr, size); + ut_assertok(membuf_check(uts, &mb, i)); + inptr += ret; + if (inptr >= in + TEST_SIZE) + inptr -= TEST_SIZE; + + size = rand() % (test_size - 1); + + if (membuf_avail(&mb) > max_avail) + max_avail = membuf_avail(&mb); + + ret = membuf_get(&mb, buf, size); + ut_assertok(membuf_check(uts, &mb, i)); + ut_asserteq_mem(buf, outptr, ret); + + outptr += ret; + if (outptr >= in + TEST_SIZE) + outptr -= TEST_SIZE; + } + + return 0; +} +LIB_TEST(lib_test_membuf_random, 0); + +/* test membuf_extend() with split segments */ +static int lib_test_membuf_extend(struct unit_test_state *uts) +{ + char in[TEST_SIZE * 2]; + char buf[TEST_SIZE * 2]; + struct membuf mb; + int ret, test_size, i, cur; + char *data; + + ut_assertok(membuf_new(&mb, TEST_SIZE)); + + for (i = 0; i < TEST_SIZE; i++) { + in[i] = (i & 63) + '0'; + in[i + TEST_SIZE] = in[i]; + } + + test_size = TEST_SIZE - 1; + + for (cur = 0; cur <= test_size; cur++) { + ut_assertok(membuf_new(&mb, TEST_SIZE)); + + membuf_zero(&mb); + + /* + * add some bytes, then remove them - this will force the membuf + * to have data split into two segments when we fill it + */ + ret = membuf_putraw(&mb, TEST_SIZE / 2, true, &data); + membuf_getraw(&mb, ret, true, &data); + ut_asserteq(TEST_SIZE / 2, ret); + + /* fill it */ + ret = membuf_put(&mb, in, cur); + ut_assertok(membuf_check(uts, &mb, cur)); + ut_asserteq(cur, ret); + + /* extend the buffer */ + ut_assertok(membuf_extend_by(&mb, TEST_SIZE, -1)); + ut_assertok(membuf_check(uts, &mb, cur)); + + /* check our data is still there */ + ret = membuf_get(&mb, buf, TEST_SIZE * 2); + ut_assertok(membuf_check(uts, &mb, cur)); + ut_asserteq(cur, ret); + ut_asserteq_mem(in, buf, cur); + membuf_uninit(&mb); + } + + return 0; +} +LIB_TEST(lib_test_membuf_extend, 0); + +/* test membuf_readline() with generated data */ +static int lib_test_membuf_readline(struct unit_test_state *uts) +{ + char *buf; + int size, cur, i, ret, readptr, cmpptr; + struct membuf mb; + char *data; + char str[256]; + char *s; + + ut_assertok(membuf_new(&mb, 1024)); + membuf_zero(&mb); + + /* Use the README as test data */ + ut_assertok(os_read_file("README", (void **)&buf, &size)); + + cur = 0; + readptr = 0; + cmpptr = 0; + for (i = 0; i < 100000; i++, cur += 1) { + /* fill the buffer with up to 'cur' bytes */ + ret = membuf_putraw(&mb, cur, false, &data); + + if (ret > 0) { + int can_read = min(ret, size - readptr); + + memcpy(data, &buf[readptr], can_read); + readptr += can_read; + + membuf_putraw(&mb, can_read, true, &data); + ut_assertok(membuf_check(uts, &mb, i)); + } + + /* read a line and compare */ + ret = membuf_readline(&mb, str, 256, 0, true); + ut_assertok(membuf_check(uts, &mb, i)); + if (ret) { + char *ptr; + + s = &buf[cmpptr]; + ptr = strchr(s, '\n'); + *ptr = '\0'; + + ut_asserteq_str(s, str); + cmpptr += strlen(s) + 1; + *ptr = '\n'; + } else { + ut_assert(membuf_free(&mb)); + } + } + membuf_dispose(&mb); + os_free(buf); + + return 0; +} +LIB_TEST(lib_test_membuf_readline, 0); |