diff --git a/source/tests/ftl/write_page_desc.c b/source/tests/ftl/write_page_desc.c new file mode 100644 index 0000000..37520ac --- /dev/null +++ b/source/tests/ftl/write_page_desc.c @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +int write_page_desc(struct ftl_map *map, + struct ftl_page_desc *page_desc); + +static int test_setup(void **state) +{ + struct ftl_map *map; + + if (!(map = test_malloc(sizeof(*map)))) + return -1; + + map->log2_pages_per_group = ilog2(16); + map->log2_groups_per_block = ilog2(1); + map->log2_page_size = ilog2(4 * KIB); + map->nblocks = 4; + map->epoch = 0; + + *state = map; + + return 0; +} + +static int test_teardown(void **state) +{ + struct ftl_map *map = *state; + + test_free(map); + + return 0; +} + +static void test_write_page_desc1(void **state) +{ + struct ftl_map *map = *state; + struct ftl_page_desc page_desc, ret_page_desc; + size_t ret; + + expect_value(__wrap_flash_is_erased, addr, 16 - 1); + expect_value(__wrap_flash_is_erased, len, 1); + will_return(__wrap_flash_is_erased, 0); + + expect_value(__wrap_flash_write, addr, (16 - 1) * 4 * KIB + + sizeof(struct ftl_page_group)); + expect_value(__wrap_flash_write, len, sizeof page_desc); + will_return(__wrap_flash_write, sizeof page_desc); + will_return(__wrap_flash_write, &ret_page_desc); + + map->head = 0; + + ret = write_page_desc(map, &page_desc); + + assert_int_equal(ret, 0); + assert_int_equal(map->root, 0); + assert_int_equal(map->head, 1); + assert_int_equal(map->epoch, 0); + assert_memory_equal(ret_page_desc.magic, "page", 4); +} + +static void test_write_page_desc2(void **state) +{ + struct ftl_map *map = *state; + struct ftl_page_desc page_desc, ret_page_desc; + size_t ret; + + expect_value(__wrap_flash_is_erased, addr, 16 - 1); + expect_value(__wrap_flash_is_erased, len, 1); + will_return(__wrap_flash_is_erased, 0); + + expect_value(__wrap_flash_write, addr, (16 - 1) * 4 * KIB + + sizeof(struct ftl_page_group) + 14 * sizeof(struct ftl_page_desc)); + expect_value(__wrap_flash_write, len, sizeof page_desc); + will_return(__wrap_flash_write, sizeof page_desc); + will_return(__wrap_flash_write, &ret_page_desc); + + map->head = 14; + + ret = write_page_desc(map, &page_desc); + + assert_int_equal(ret, 0); + assert_int_equal(map->root, 14); + assert_int_equal(map->head, 16); + assert_int_equal(map->epoch, 0); + assert_memory_equal(ret_page_desc.magic, "page", 4); +} + +static void test_write_page_desc3(void **state) +{ + struct ftl_map *map = *state; + struct ftl_page_desc page_desc, ret_page_desc; + size_t ret; + + expect_value(__wrap_flash_is_erased, addr, 2 * 16 - 1); + expect_value(__wrap_flash_is_erased, len, 1); + will_return(__wrap_flash_is_erased, 0); + + expect_value(__wrap_flash_write, addr, (2 * 16 - 1) * 4 * KIB + + sizeof(struct ftl_page_group)); + expect_value(__wrap_flash_write, len, sizeof page_desc); + will_return(__wrap_flash_write, sizeof page_desc); + will_return(__wrap_flash_write, &ret_page_desc); + + map->head = 16; + + ret = write_page_desc(map, &page_desc); + + assert_int_equal(ret, 0); + assert_int_equal(map->root, 16); + assert_int_equal(map->head, 17); + assert_int_equal(map->epoch, 0); + assert_memory_equal(ret_page_desc.magic, "page", 4); +} + +static void test_write_page_desc4(void **state) +{ + struct ftl_map *map = *state; + struct ftl_page_desc page_desc, ret_page_desc; + size_t ret; + + expect_value(__wrap_flash_is_erased, addr, 2 * 16 - 1); + expect_value(__wrap_flash_is_erased, len, 1); + will_return(__wrap_flash_is_erased, 0); + + expect_value(__wrap_flash_write, addr, (2 * 16 - 1) * 4 * KIB + + sizeof(struct ftl_page_group) + 14 * sizeof(struct ftl_page_desc)); + expect_value(__wrap_flash_write, len, sizeof page_desc); + will_return(__wrap_flash_write, sizeof page_desc); + will_return(__wrap_flash_write, &ret_page_desc); + + map->head = 30; + + ret = write_page_desc(map, &page_desc); + + assert_int_equal(ret, 0); + assert_int_equal(map->root, 30); + assert_int_equal(map->head, 32); + assert_int_equal(map->epoch, 0); + assert_memory_equal(ret_page_desc.magic, "page", 4); +} + +static void test_write_page_desc5(void **state) +{ + struct ftl_map *map = *state; + struct ftl_page_desc page_desc, ret_page_desc; + size_t ret; + + expect_value(__wrap_flash_is_erased, addr, 3 * 16 - 1); + expect_value(__wrap_flash_is_erased, len, 1); + will_return(__wrap_flash_is_erased, 0); + + expect_value(__wrap_flash_write, addr, (3 * 16 - 1) * 4 * KIB + + sizeof(struct ftl_page_group)); + expect_value(__wrap_flash_write, len, sizeof page_desc); + will_return(__wrap_flash_write, sizeof page_desc); + will_return(__wrap_flash_write, &ret_page_desc); + + map->head = 32; + + ret = write_page_desc(map, &page_desc); + + assert_int_equal(ret, 0); + assert_int_equal(map->root, 32); + assert_int_equal(map->head, 33); + assert_int_equal(map->epoch, 0); + assert_memory_equal(ret_page_desc.magic, "page", 4); +} + +static void test_epoch_wraparound(void **state) +{ + struct ftl_map *map = *state; + struct ftl_page_desc page_desc, ret_page_desc; + size_t ret; + + expect_value(__wrap_flash_is_erased, addr, 4 * 16 - 1); + expect_value(__wrap_flash_is_erased, len, 1); + will_return(__wrap_flash_is_erased, 0); + + expect_value(__wrap_flash_write, addr, (4 * 16 - 1) * 4 * KIB + + sizeof(struct ftl_page_group) + 14 * sizeof(struct ftl_page_desc)); + expect_value(__wrap_flash_write, len, sizeof page_desc); + will_return(__wrap_flash_write, sizeof page_desc); + will_return(__wrap_flash_write, &ret_page_desc); + + map->head = 62; + + ret = write_page_desc(map, &page_desc); + + assert_int_equal(ret, 0); + assert_int_equal(map->root, 62); + assert_int_equal(map->head, 0); + assert_int_equal(map->epoch, 1); + assert_memory_equal(ret_page_desc.magic, "page", 4); +} + +static void test_group_header(void **state) +{ + struct ftl_map *map = *state; + struct ftl_page_group ret_group; + struct ftl_page_desc page_desc, ret_page_desc; + size_t ret; + + expect_value(__wrap_flash_is_erased, addr, 16 - 1); + expect_value(__wrap_flash_is_erased, len, 1); + will_return(__wrap_flash_is_erased, 1); + + expect_value(__wrap_flash_write, addr, (16 - 1) * 4 * KIB); + expect_value(__wrap_flash_write, len, sizeof ret_group); + will_return(__wrap_flash_write, sizeof ret_group); + will_return(__wrap_flash_write, &ret_group); + + expect_value(__wrap_flash_write, addr, (16 - 1) * 4 * KIB + + sizeof(struct ftl_page_group)); + expect_value(__wrap_flash_write, len, sizeof page_desc); + will_return(__wrap_flash_write, sizeof page_desc); + will_return(__wrap_flash_write, &ret_page_desc); + + map->head = 0; + map->epoch = 0; + + ret = write_page_desc(map, &page_desc); + + assert_int_equal(ret, 0); + assert_int_equal(map->root, 0); + assert_int_equal(map->head, 1); + assert_int_equal(map->epoch, 0); + + assert_memory_equal(ret_group.magic, "FTL", 3); + assert_int_equal(ret_group.epoch, map->epoch); + + assert_memory_equal(ret_page_desc.magic, "page", 4); +} + +int test_write_page_desc(void) +{ + const struct CMUnitTest tests[] = { + { "write_page_desc: head=0", test_write_page_desc1, NULL, NULL, NULL }, + { "write_page_desc: head=14", test_write_page_desc2, NULL, NULL, NULL }, + { "write_page_desc: head=16", test_write_page_desc3, NULL, NULL, NULL }, + { "write_page_desc: head=30", test_write_page_desc4, NULL, NULL, NULL }, + { "write_page_desc: head=32", test_write_page_desc5, NULL, NULL, NULL }, + { "write_page_desc: epoch wraparound", test_epoch_wraparound, NULL, NULL, NULL }, + { "write_page_desc: group header", test_group_header, NULL, NULL, NULL }, + }; + + return cmocka_run_group_tests_name("write_page_desc", tests, test_setup, + test_teardown); +}