| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * Copyright 2021 Google LLC |
| * Written by Simon Glass <sjg@chromium.org> |
| */ |
| |
| #include <common.h> |
| #include <abuf.h> |
| #include <mapmem.h> |
| #include <test/lib.h> |
| #include <test/test.h> |
| #include <test/ut.h> |
| |
| static char test_data[] = "1234"; |
| #define TEST_DATA_LEN sizeof(test_data) |
| |
| /* Test abuf_set() */ |
| static int lib_test_abuf_set(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| ulong start; |
| |
| start = ut_check_free(); |
| |
| abuf_init(&buf); |
| abuf_set(&buf, test_data, TEST_DATA_LEN); |
| ut_asserteq_ptr(test_data, buf.data); |
| ut_asserteq(TEST_DATA_LEN, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| /* Force it to allocate */ |
| ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN + 1)); |
| ut_assertnonnull(buf.data); |
| ut_asserteq(TEST_DATA_LEN + 1, buf.size); |
| ut_asserteq(true, buf.alloced); |
| |
| /* Now set it again, to force it to free */ |
| abuf_set(&buf, test_data, TEST_DATA_LEN); |
| ut_asserteq_ptr(test_data, buf.data); |
| ut_asserteq(TEST_DATA_LEN, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| /* Check for memory leaks */ |
| ut_assertok(ut_check_delta(start)); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_set, 0); |
| |
| /* Test abuf_map_sysmem() */ |
| static int lib_test_abuf_map_sysmem(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| ulong addr; |
| |
| abuf_init(&buf); |
| addr = 0x100; |
| abuf_map_sysmem(&buf, addr, TEST_DATA_LEN); |
| |
| ut_asserteq_ptr(map_sysmem(0x100, 0), buf.data); |
| ut_asserteq(TEST_DATA_LEN, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_map_sysmem, 0); |
| |
| /* Test abuf_realloc() */ |
| static int lib_test_abuf_realloc(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| ulong start; |
| void *ptr; |
| |
| /* |
| * TODO: crashes on sandbox sometimes due to an apparent bug in |
| * realloc(). |
| */ |
| return 0; |
| |
| start = ut_check_free(); |
| |
| abuf_init(&buf); |
| |
| /* Allocate an empty buffer */ |
| ut_asserteq(true, abuf_realloc(&buf, 0)); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| /* Allocate a non-empty abuf */ |
| ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN)); |
| ut_assertnonnull(buf.data); |
| ut_asserteq(TEST_DATA_LEN, buf.size); |
| ut_asserteq(true, buf.alloced); |
| ptr = buf.data; |
| |
| /* |
| * Make it smaller; the pointer should remain the same. Note this relies |
| * on knowledge of how U-Boot's realloc() works |
| */ |
| ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN - 1)); |
| ut_asserteq(TEST_DATA_LEN - 1, buf.size); |
| ut_asserteq(true, buf.alloced); |
| ut_asserteq_ptr(ptr, buf.data); |
| |
| /* |
| * Make it larger, forcing reallocation. Note this relies on knowledge |
| * of how U-Boot's realloc() works |
| */ |
| ut_asserteq(true, abuf_realloc(&buf, 0x1000)); |
| ut_assert(buf.data != ptr); |
| ut_asserteq(0x1000, buf.size); |
| ut_asserteq(true, buf.alloced); |
| |
| /* Free it */ |
| ut_asserteq(true, abuf_realloc(&buf, 0)); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| /* Check for memory leaks */ |
| ut_assertok(ut_check_delta(start)); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_realloc, 0); |
| |
| /* Test abuf_realloc() on an non-allocated buffer of zero size */ |
| static int lib_test_abuf_realloc_size(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| ulong start; |
| |
| start = ut_check_free(); |
| |
| abuf_init(&buf); |
| |
| /* Allocate some space */ |
| ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN)); |
| ut_assertnonnull(buf.data); |
| ut_asserteq(TEST_DATA_LEN, buf.size); |
| ut_asserteq(true, buf.alloced); |
| |
| /* Free it */ |
| ut_asserteq(true, abuf_realloc(&buf, 0)); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| /* Check for memory leaks */ |
| ut_assertok(ut_check_delta(start)); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_realloc_size, 0); |
| |
| /* Test abuf_realloc_inc() */ |
| static int lib_test_abuf_realloc_inc(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| ulong start; |
| |
| start = ut_check_free(); |
| |
| abuf_init(&buf); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| abuf_realloc_inc(&buf, 20); |
| ut_asserteq(20, buf.size); |
| ut_asserteq(true, buf.alloced); |
| |
| abuf_uninit(&buf); |
| |
| /* Check for memory leaks */ |
| ut_assertok(ut_check_delta(start)); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_realloc_inc, 0); |
| |
| /* Test handling of buffers that are too large */ |
| static int lib_test_abuf_large(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| ulong start; |
| size_t size; |
| int delta; |
| void *ptr; |
| |
| /* |
| * This crashes at present due to trying to allocate more memory than |
| * available, which breaks something on sandbox. |
| */ |
| return 0; |
| |
| start = ut_check_free(); |
| |
| /* Try an impossible size */ |
| abuf_init(&buf); |
| ut_asserteq(false, abuf_realloc(&buf, CONFIG_SYS_MALLOC_LEN)); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| abuf_uninit(&buf); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| /* Start with a normal size then try to increase it, to check realloc */ |
| ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN)); |
| ut_assertnonnull(buf.data); |
| ut_asserteq(TEST_DATA_LEN, buf.size); |
| ut_asserteq(true, buf.alloced); |
| ptr = buf.data; |
| delta = ut_check_delta(start); |
| ut_assert(delta > 0); |
| |
| /* try to increase it */ |
| ut_asserteq(false, abuf_realloc(&buf, CONFIG_SYS_MALLOC_LEN)); |
| ut_asserteq_ptr(ptr, buf.data); |
| ut_asserteq(TEST_DATA_LEN, buf.size); |
| ut_asserteq(true, buf.alloced); |
| ut_asserteq(delta, ut_check_delta(start)); |
| |
| /* Check for memory leaks */ |
| abuf_uninit(&buf); |
| ut_assertok(ut_check_delta(start)); |
| |
| /* Start with a huge unallocated buf and try to move it */ |
| abuf_init(&buf); |
| abuf_map_sysmem(&buf, 0, CONFIG_SYS_MALLOC_LEN); |
| ut_asserteq(CONFIG_SYS_MALLOC_LEN, buf.size); |
| ut_asserteq(false, buf.alloced); |
| ut_assertnull(abuf_uninit_move(&buf, &size)); |
| |
| /* Check for memory leaks */ |
| abuf_uninit(&buf); |
| ut_assertok(ut_check_delta(start)); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_large, 0); |
| |
| /* Test abuf_uninit_move() */ |
| static int lib_test_abuf_uninit_move(struct unit_test_state *uts) |
| { |
| void *ptr, *orig_ptr; |
| struct abuf buf; |
| size_t size; |
| ulong start; |
| int delta; |
| |
| start = ut_check_free(); |
| |
| /* |
| * TODO: crashes on sandbox sometimes due to an apparent bug in |
| * realloc(). |
| */ |
| return 0; |
| |
| /* Move an empty buffer */ |
| abuf_init(&buf); |
| ut_assertnull(abuf_uninit_move(&buf, &size)); |
| ut_asserteq(0, size); |
| ut_assertnull(abuf_uninit_move(&buf, NULL)); |
| |
| /* Move an unallocated buffer */ |
| abuf_set(&buf, test_data, TEST_DATA_LEN); |
| ut_assertok(ut_check_delta(start)); |
| ptr = abuf_uninit_move(&buf, &size); |
| ut_asserteq(TEST_DATA_LEN, size); |
| ut_asserteq_str(ptr, test_data); |
| ut_assertnonnull(ptr); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| /* Check that freeing it frees the only allocation */ |
| delta = ut_check_delta(start); |
| ut_assert(delta > 0); |
| free(ptr); |
| ut_assertok(ut_check_delta(start)); |
| |
| /* Move an allocated buffer */ |
| ut_asserteq(true, abuf_realloc(&buf, TEST_DATA_LEN)); |
| orig_ptr = buf.data; |
| strcpy(orig_ptr, test_data); |
| |
| delta = ut_check_delta(start); |
| ut_assert(delta > 0); |
| ptr = abuf_uninit_move(&buf, &size); |
| ut_asserteq(TEST_DATA_LEN, size); |
| ut_assertnonnull(ptr); |
| ut_asserteq_ptr(ptr, orig_ptr); |
| ut_asserteq_str(ptr, test_data); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| /* Check there was no new allocation */ |
| ut_asserteq(delta, ut_check_delta(start)); |
| |
| /* Check that freeing it frees the only allocation */ |
| free(ptr); |
| ut_assertok(ut_check_delta(start)); |
| |
| /* Move an unallocated buffer, without the size */ |
| abuf_set(&buf, test_data, TEST_DATA_LEN); |
| ut_assertok(ut_check_delta(start)); |
| ptr = abuf_uninit_move(&buf, NULL); |
| ut_asserteq_str(ptr, test_data); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_uninit_move, 0); |
| |
| /* Test abuf_uninit() */ |
| static int lib_test_abuf_uninit(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| |
| /* Nothing in the buffer */ |
| abuf_init(&buf); |
| abuf_uninit(&buf); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| /* Not allocated */ |
| abuf_set(&buf, test_data, TEST_DATA_LEN); |
| abuf_uninit(&buf); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_uninit, 0); |
| |
| /* Test abuf_init_set() */ |
| static int lib_test_abuf_init_set(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| |
| abuf_init_set(&buf, test_data, TEST_DATA_LEN); |
| ut_asserteq_ptr(test_data, buf.data); |
| ut_asserteq(TEST_DATA_LEN, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_init_set, 0); |
| |
| /* Test abuf_init_move() */ |
| static int lib_test_abuf_init_move(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| void *ptr; |
| |
| /* |
| * TODO: crashes on sandbox sometimes due to an apparent bug in |
| * realloc(). |
| */ |
| return 0; |
| |
| ptr = strdup(test_data); |
| ut_assertnonnull(ptr); |
| |
| free(ptr); |
| |
| abuf_init_move(&buf, ptr, TEST_DATA_LEN); |
| ut_asserteq_ptr(ptr, abuf_data(&buf)); |
| ut_asserteq(TEST_DATA_LEN, abuf_size(&buf)); |
| ut_asserteq(true, buf.alloced); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_init_move, 0); |
| |
| /* Test abuf_init() */ |
| static int lib_test_abuf_init(struct unit_test_state *uts) |
| { |
| struct abuf buf; |
| |
| buf.data = &buf; |
| buf.size = 123; |
| buf.alloced = true; |
| abuf_init(&buf); |
| ut_assertnull(buf.data); |
| ut_asserteq(0, buf.size); |
| ut_asserteq(false, buf.alloced); |
| |
| return 0; |
| } |
| LIB_TEST(lib_test_abuf_init, 0); |