Compare commits
45 Commits
e089e2ba4e
...
adbd045af5
@ -0,0 +1,3 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
void draw_progress(FILE *fp, unsigned long pos, unsigned max); |
@ -1,4 +1,10 @@ |
|||||||
|
-include source/core/Makefile |
||||||
-include source/ftl/Makefile |
-include source/ftl/Makefile |
||||||
-include source/mufs/Makefile |
-include source/mufs/Makefile |
||||||
-include source/platform/Makefile |
-include source/platform/Makefile |
||||||
-include source/shell/Makefile |
-include source/shell/Makefile |
||||||
|
-include source/tests/Makefile |
||||||
|
|
||||||
|
obj-y += source/bitops.o
|
||||||
|
|
||||||
|
tbm-obj-y += source/main.o
|
||||||
|
@ -0,0 +1 @@ |
|||||||
|
tbm-obj-y += source/core/flash.o
|
@ -1,7 +1 @@ |
|||||||
ifeq ($(TARGET),host) |
|
||||||
else |
|
||||||
obj-y += source/platform/spi_flash.o
|
|
||||||
obj-y += source/platform/usart.o
|
|
||||||
endif |
|
||||||
|
|
||||||
-include source/platform/$(TARGET)/Makefile |
-include source/platform/$(TARGET)/Makefile |
||||||
|
@ -0,0 +1,26 @@ |
|||||||
|
#include <stdio.h> |
||||||
|
|
||||||
|
#define TERM_WIDTH 80 |
||||||
|
|
||||||
|
void draw_progress(FILE *fp, unsigned long pos, unsigned long max) |
||||||
|
{ |
||||||
|
unsigned long head, i; |
||||||
|
|
||||||
|
if (pos > max) |
||||||
|
pos = max; |
||||||
|
|
||||||
|
head = (TERM_WIDTH - 2) * pos / max; |
||||||
|
|
||||||
|
fputc('[', fp); |
||||||
|
|
||||||
|
for (i = 0; i < head; ++i) |
||||||
|
fputc('#', fp); |
||||||
|
|
||||||
|
for (; i < (TERM_WIDTH - 2); ++i) |
||||||
|
fputc(' ', fp); |
||||||
|
|
||||||
|
fputc(']', fp); |
||||||
|
|
||||||
|
for (i = 0; i < TERM_WIDTH; ++i) |
||||||
|
fputc('\b', fp); |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
test-obj-y += source/tests/main.o
|
||||||
|
|
||||||
|
test-obj-y += source/tests/flash/mock.o
|
||||||
|
|
||||||
|
test-obj-y += source/tests/ftl/main.o
|
||||||
|
test-obj-y += source/tests/ftl/mock.o
|
||||||
|
test-obj-y += source/tests/ftl/find_block.o
|
||||||
|
test-obj-y += source/tests/ftl/find_block_div.o
|
||||||
|
test-obj-y += source/tests/ftl/find_last_block.o
|
||||||
|
test-obj-y += source/tests/ftl/find_last_group.o
|
||||||
|
test-obj-y += source/tests/ftl/find_head.o
|
||||||
|
test-obj-y += source/tests/ftl/find_root.o
|
||||||
|
test-obj-y += source/tests/ftl/next_upage.o
|
||||||
|
test-obj-y += source/tests/ftl/read_page_group.o
|
||||||
|
test-obj-y += source/tests/ftl/read_page_desc.o
|
||||||
|
test-obj-y += source/tests/ftl/write_page_desc.o
|
||||||
|
test-obj-y += source/tests/ftl/write_upage.o
|
||||||
|
test-obj-y += source/tests/ftl/trace_path.o
|
||||||
|
|
||||||
|
test-obj-y += source/tests/ftl/ftl_is_mapped.o
|
||||||
|
test-obj-y += source/tests/ftl/ftl_read.o
|
||||||
|
|
||||||
|
TEST_CFLAGS += -Dflash_read=__wrap_flash_read
|
||||||
|
TEST_CFLAGS += -Dflash_write=__wrap_flash_write
|
||||||
|
TEST_CFLAGS += -Dflash_write0=__wrap_flash_write0
|
||||||
|
TEST_CFLAGS += -Dflash_copy=__wrap_flash_copy
|
||||||
|
TEST_CFLAGS += -Dflash_is_erased=__wrap_flash_is_erased
|
||||||
|
|
||||||
|
TEST_CFLAGS += -Dis_group_erased=__wrap_is_group_erased
|
||||||
|
TEST_CFLAGS += -Dfind_block=__wrap_find_block
|
||||||
|
TEST_CFLAGS += -Dprepare_head=__wrap_prepare_head
|
||||||
|
TEST_CFLAGS += -Dread_page_desc=__wrap_read_page_desc
|
||||||
|
TEST_CFLAGS += -Dwrite_page_desc=__wrap_write_page_desc
|
||||||
|
TEST_CFLAGS += -Dtrace_path=__wrap_trace_path
|
@ -0,0 +1,89 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
size_t __wrap_flash_read(struct flash_dev *dev, uint32_t addr, |
||||||
|
void *data, size_t len) |
||||||
|
{ |
||||||
|
const void *ret_data; |
||||||
|
size_t ret_len; |
||||||
|
|
||||||
|
(void)dev; |
||||||
|
|
||||||
|
check_expected(addr); |
||||||
|
check_expected(len); |
||||||
|
|
||||||
|
ret_len = mock_type(size_t); |
||||||
|
ret_data = mock_type(const void *); |
||||||
|
|
||||||
|
if (len > ret_len) |
||||||
|
len = ret_len; |
||||||
|
|
||||||
|
if (len && ret_data) |
||||||
|
memcpy(data, ret_data, len); |
||||||
|
|
||||||
|
return len; |
||||||
|
} |
||||||
|
|
||||||
|
size_t __wrap_flash_write(struct flash_dev *dev, uint32_t addr, |
||||||
|
const void *data, size_t len) |
||||||
|
{ |
||||||
|
void *ret_data; |
||||||
|
size_t ret_len; |
||||||
|
|
||||||
|
(void)dev; |
||||||
|
|
||||||
|
check_expected(addr); |
||||||
|
check_expected(len); |
||||||
|
|
||||||
|
ret_len = mock_type(size_t); |
||||||
|
ret_data = mock_type(void *); |
||||||
|
|
||||||
|
if (len > ret_len) |
||||||
|
len = ret_len; |
||||||
|
|
||||||
|
if (len) |
||||||
|
memcpy(ret_data, data, len); |
||||||
|
|
||||||
|
return len; |
||||||
|
} |
||||||
|
|
||||||
|
size_t __wrap_flash_write0(struct flash_dev *dev, uint32_t addr, size_t len) |
||||||
|
{ |
||||||
|
(void)dev; |
||||||
|
|
||||||
|
check_expected(addr); |
||||||
|
check_expected(len); |
||||||
|
|
||||||
|
return mock_type(int); |
||||||
|
} |
||||||
|
|
||||||
|
size_t __wrap_flash_copy(struct flash_dev *dev, uint32_t dst, uint32_t src, size_t len) |
||||||
|
{ |
||||||
|
(void)dev; |
||||||
|
|
||||||
|
check_expected(dst); |
||||||
|
check_expected(src); |
||||||
|
check_expected(len); |
||||||
|
|
||||||
|
return mock_type(int); |
||||||
|
} |
||||||
|
|
||||||
|
int __wrap_flash_is_erased(struct flash_dev *dev, uint32_t addr, size_t len) |
||||||
|
{ |
||||||
|
(void)dev; |
||||||
|
|
||||||
|
check_expected(addr); |
||||||
|
check_expected(len); |
||||||
|
|
||||||
|
return mock_type(int); |
||||||
|
} |
@ -0,0 +1,170 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int __real_find_block(struct ftl_map *map, struct ftl_page_group *group, |
||||||
|
uint32_t *where, uint32_t block); |
||||||
|
|
||||||
|
static void test_block0(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group, ret_group; |
||||||
|
int ret; |
||||||
|
uint32_t where; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(group.magic, "FTL", 3); |
||||||
|
|
||||||
|
map.log2_block_size = ilog2(64 * KIB); |
||||||
|
map.log2_page_size = ilog2(1 * KIB); |
||||||
|
map.log2_pages_per_group = ilog2(8); |
||||||
|
map.nblocks = 64; |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, sizeof group); |
||||||
|
will_return(__wrap_flash_read, &group); |
||||||
|
|
||||||
|
ret = __real_find_block(&map, &ret_group, &where, 0); |
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_int_equal(where, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_block3(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group, ret_group; |
||||||
|
int ret; |
||||||
|
uint32_t where; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(group.magic, "FTL", 3); |
||||||
|
|
||||||
|
map.log2_block_size = ilog2(64 * KIB); |
||||||
|
map.log2_page_size = ilog2(1 * KIB); |
||||||
|
map.log2_pages_per_group = ilog2(8); |
||||||
|
map.nblocks = 64; |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, 0); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (1 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, 0); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (2 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, 0); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (3 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, sizeof group); |
||||||
|
will_return(__wrap_flash_read, &group); |
||||||
|
|
||||||
|
ret = __real_find_block(&map, &ret_group, &where, 0); |
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_int_equal(where, 3); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_block8_offset5(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group, ret_group; |
||||||
|
int ret; |
||||||
|
uint32_t where; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(group.magic, "FTL", 3); |
||||||
|
|
||||||
|
map.log2_block_size = ilog2(64 * KIB); |
||||||
|
map.log2_page_size = ilog2(1 * KIB); |
||||||
|
map.log2_pages_per_group = ilog2(8); |
||||||
|
map.nblocks = 64; |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (5 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, 0); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (6 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, 0); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (7 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, 0); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (8 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, sizeof group); |
||||||
|
will_return(__wrap_flash_read, &group); |
||||||
|
|
||||||
|
ret = __real_find_block(&map, &ret_group, &where, 5); |
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_int_equal(where, 8); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_no_block(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group, ret_group; |
||||||
|
int ret; |
||||||
|
uint32_t where; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(group.magic, "FTL", 3); |
||||||
|
|
||||||
|
map.log2_block_size = ilog2(64 * KIB); |
||||||
|
map.log2_page_size = ilog2(1 * KIB); |
||||||
|
map.log2_pages_per_group = ilog2(8); |
||||||
|
map.nblocks = 64; |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (61 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, 0); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (62 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, 0); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (63 * 64 + 8 - 1) * 1 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, 0); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
ret = __real_find_block(&map, &ret_group, &where, 61); |
||||||
|
assert_int_equal(ret, -1); |
||||||
|
} |
||||||
|
|
||||||
|
int test_find_block(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "find_block: block=0, offset=0", test_block0, NULL, NULL, NULL }, |
||||||
|
{ "find_block: block=3, offset=0", test_block3, NULL, NULL, NULL }, |
||||||
|
{ "find_block: block=8, offset=5", test_block8_offset5, NULL, NULL, NULL }, |
||||||
|
{ "find_block: no block, offset=61", test_no_block, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("find_block", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,70 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int find_block_div(struct ftl_map *map); |
||||||
|
|
||||||
|
static void test_4k_page_64k_block(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_block_size = ilog2(64 * KIB); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
find_block_div(&map); |
||||||
|
|
||||||
|
assert_int_equal(1 << map.log2_pages_per_group, 16); |
||||||
|
assert_int_equal(1 << map.log2_groups_per_block, 1); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_4k_page_16k_block(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_block_size = ilog2(16 * KIB); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
find_block_div(&map); |
||||||
|
|
||||||
|
assert_int_equal(1 << map.log2_pages_per_group, 4); |
||||||
|
assert_int_equal(1 << map.log2_groups_per_block, 1); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_1k_page_64k_block(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_block_size = ilog2(64 * KIB); |
||||||
|
map.log2_page_size = ilog2(1 * KIB); |
||||||
|
|
||||||
|
find_block_div(&map); |
||||||
|
|
||||||
|
assert_int_equal(1 << map.log2_pages_per_group, 8); |
||||||
|
assert_int_equal(1 << map.log2_groups_per_block, 8); |
||||||
|
} |
||||||
|
|
||||||
|
int test_find_block_div(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "find_block_div: 4K page, 64K block", test_4k_page_64k_block, NULL, NULL, NULL }, |
||||||
|
{ "find_block_div: 4K page, 16K block", test_4k_page_16k_block, NULL, NULL, NULL }, |
||||||
|
{ "find_block_div: 1K page, 64K block", test_1k_page_64k_block, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("find_block_div", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int find_head(struct ftl_map *map); |
||||||
|
|
||||||
|
static void test_erased(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
map.root = 4; |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 5); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 1); |
||||||
|
|
||||||
|
ret = find_head(&map); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_int_equal(map.head, 5); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_end_of_block(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
map.root = 4; |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 5); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 6); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 7); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 8); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 9); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 10); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 11); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 12); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 13); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_is_erased, addr, 14); |
||||||
|
expect_value(__wrap_flash_is_erased, len, 1); |
||||||
|
will_return(__wrap_flash_is_erased, 0); |
||||||
|
|
||||||
|
ret = find_head(&map); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_int_equal(map.head, 16); |
||||||
|
} |
||||||
|
|
||||||
|
int test_find_head(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "find_head: erased", test_erased, NULL, NULL, NULL }, |
||||||
|
{ "find_head: end of block", test_end_of_block, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("find_head", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,291 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
uint32_t find_last_block(struct ftl_map *map, uint32_t first); |
||||||
|
|
||||||
|
static void test_middle(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(group.magic, "FTL", 3); |
||||||
|
group.epoch = 0; |
||||||
|
|
||||||
|
map.nblocks = 64; |
||||||
|
map.epoch = 0; |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 31); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 31); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 32); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
ret = find_last_block(&map, 0); |
||||||
|
assert_int_equal(ret, 31); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_first(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(group.magic, "FTL", 3); |
||||||
|
group.epoch = 0; |
||||||
|
|
||||||
|
map.nblocks = 64; |
||||||
|
map.epoch = 0; |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 31); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 15); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 7); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 3); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 1); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
ret = find_last_block(&map, 0); |
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_last(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(group.magic, "FTL", 3); |
||||||
|
group.epoch = 0; |
||||||
|
|
||||||
|
map.nblocks = 64; |
||||||
|
map.epoch = 0; |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 31); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 31); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 32); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 32); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 47); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 47); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 48); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 48); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 55); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 55); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 56); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 56); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 59); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 59); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 60); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 60); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 61); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 61); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 62); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 62); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 62); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 62); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 63); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 63); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
ret = find_last_block(&map, 0); |
||||||
|
assert_int_equal(ret, 63); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_left_right(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(group.magic, "FTL", 3); |
||||||
|
group.epoch = 0; |
||||||
|
|
||||||
|
map.nblocks = 64; |
||||||
|
map.epoch = 0; |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 31); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 31); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 15); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 15); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 16); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 16); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 23); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 23); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 24); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 24); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
ret = find_last_block(&map, 0); |
||||||
|
assert_int_equal(ret, 23); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_right_left(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(group.magic, "FTL", 3); |
||||||
|
group.epoch = 0; |
||||||
|
|
||||||
|
map.nblocks = 64; |
||||||
|
map.epoch = 0; |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 31); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 31); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 32); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 32); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 47); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 47); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 39); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 39); |
||||||
|
will_return(__wrap_find_block, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_find_block, map, &map); |
||||||
|
expect_value(__wrap_find_block, block, 40); |
||||||
|
will_return(__wrap_find_block, &group); |
||||||
|
will_return(__wrap_find_block, 40); |
||||||
|
will_return(__wrap_find_block, -1); |
||||||
|
|
||||||
|
ret = find_last_block(&map, 0); |
||||||
|
assert_int_equal(ret, 39); |
||||||
|
} |
||||||
|
|
||||||
|
int test_find_last_block(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "find_last_block: middle", test_middle, NULL, NULL, NULL }, |
||||||
|
{ "find_last_block: first", test_first, NULL, NULL, NULL }, |
||||||
|
{ "find_last_block: last", test_last, NULL, NULL, NULL }, |
||||||
|
{ "find_last_block: left right", test_left_right, NULL, NULL, NULL }, |
||||||
|
{ "find_last_block: right left", test_right_left, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("find_last_block", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,156 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
uint32_t find_last_group(struct ftl_map *map, uint32_t block); |
||||||
|
|
||||||
|
static void test_middle(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_groups_per_block = ilog2(8); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 3); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 4); |
||||||
|
will_return(__wrap_is_group_erased, 1); |
||||||
|
|
||||||
|
ret = find_last_group(&map, 4); |
||||||
|
assert_int_equal(ret, 32 + 3); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_first(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_groups_per_block = ilog2(8); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 3); |
||||||
|
will_return(__wrap_is_group_erased, 1); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 1); |
||||||
|
will_return(__wrap_is_group_erased, 1); |
||||||
|
|
||||||
|
ret = find_last_group(&map, 4); |
||||||
|
assert_int_equal(ret, 32); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_last(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_groups_per_block = ilog2(8); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 3); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 4); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 5); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 6); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 6); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 7); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
ret = find_last_group(&map, 4); |
||||||
|
assert_int_equal(ret, 32 + 7); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_left_right(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_groups_per_block = ilog2(8); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 3); |
||||||
|
will_return(__wrap_is_group_erased, 1); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 1); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 2); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
ret = find_last_group(&map, 4); |
||||||
|
assert_int_equal(ret, 32 + 2); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_right_left(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_groups_per_block = ilog2(8); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 3); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 4); |
||||||
|
will_return(__wrap_is_group_erased, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_is_group_erased, map, &map); |
||||||
|
expect_value(__wrap_is_group_erased, group, 32 + 5); |
||||||
|
will_return(__wrap_is_group_erased, 1); |
||||||
|
|
||||||
|
ret = find_last_group(&map, 4); |
||||||
|
assert_int_equal(ret, 32 + 4); |
||||||
|
} |
||||||
|
|
||||||
|
int test_find_last_group(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "find_last_group: middle", test_middle, NULL, NULL, NULL }, |
||||||
|
{ "find_last_group: first", test_first, NULL, NULL, NULL }, |
||||||
|
{ "find_last_group: last", test_last, NULL, NULL, NULL }, |
||||||
|
{ "find_last_group: left right", test_left_right, NULL, NULL, NULL }, |
||||||
|
{ "find_last_group: right left", test_right_left, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("find_last_group", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,153 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int find_root(struct ftl_map *map, uint32_t group); |
||||||
|
|
||||||
|
static void test_group0_upage0(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 0); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, -1); |
||||||
|
|
||||||
|
ret = find_root(&map, 0); |
||||||
|
|
||||||
|
assert_int_equal(ret, -1); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_group0_upage5(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 0); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 1); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 2); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 3); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 4); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 5); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 6); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, -1); |
||||||
|
|
||||||
|
ret = find_root(&map, 0); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_int_equal(map.root, 5); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_group1_upage5(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 16); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 16 + 1); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 16 + 2); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 16 + 3); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 16 + 4); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 16 + 5); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 16 + 6); |
||||||
|
will_return(__wrap_read_page_desc, &page_desc); |
||||||
|
will_return(__wrap_read_page_desc, -1); |
||||||
|
|
||||||
|
ret = find_root(&map, 1); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_int_equal(map.root, 16 + 5); |
||||||
|
} |
||||||
|
|
||||||
|
int test_find_root(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "find_root: group=0, upage=0 (no root)", test_group0_upage0, NULL, NULL, NULL }, |
||||||
|
{ "find_root: group=0, upage=5", test_group0_upage5, NULL, NULL, NULL }, |
||||||
|
{ "find_root: group=1, upage=5", test_group1_upage5, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("find_root", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
static void test_unmapped(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
expect_value(__wrap_trace_path, map, &map); |
||||||
|
expect_value(__wrap_trace_path, new_page_desc, NULL); |
||||||
|
expect_value(__wrap_trace_path, page, NULL); |
||||||
|
expect_value(__wrap_trace_path, va, 42); |
||||||
|
will_return(__wrap_trace_path, NULL); |
||||||
|
will_return(__wrap_trace_path, 0); |
||||||
|
will_return(__wrap_trace_path, -1); |
||||||
|
|
||||||
|
ret = ftl_is_mapped(&map, 42); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_mapped(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
expect_value(__wrap_trace_path, map, &map); |
||||||
|
expect_value(__wrap_trace_path, new_page_desc, NULL); |
||||||
|
expect_value(__wrap_trace_path, page, NULL); |
||||||
|
expect_value(__wrap_trace_path, va, 42); |
||||||
|
will_return(__wrap_trace_path, NULL); |
||||||
|
will_return(__wrap_trace_path, 0); |
||||||
|
will_return(__wrap_trace_path, 0); |
||||||
|
|
||||||
|
ret = ftl_is_mapped(&map, 42); |
||||||
|
|
||||||
|
assert_int_equal(ret, 1); |
||||||
|
} |
||||||
|
|
||||||
|
int test_ftl_is_mapped(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "ftl_is_mapped: unmapped", test_unmapped, NULL, NULL, NULL }, |
||||||
|
{ "ftl_is_mapped: mapped", test_mapped, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("ftl_is_unmapped", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
static void test_basic_read(void **state) |
||||||
|
{ |
||||||
|
char data[24]; |
||||||
|
struct ftl_map map; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
map.outstanding.flags = 0; |
||||||
|
|
||||||
|
expect_value(__wrap_trace_path, map, &map); |
||||||
|
expect_value(__wrap_trace_path, new_page_desc, NULL); |
||||||
|
expect_not_value(__wrap_trace_path, page, NULL); |
||||||
|
expect_value(__wrap_trace_path, va, 4); |
||||||
|
will_return(__wrap_trace_path, NULL); |
||||||
|
will_return(__wrap_trace_path, 42); |
||||||
|
will_return(__wrap_trace_path, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, 42 << 12 | 0x321); |
||||||
|
expect_value(__wrap_flash_read, len, 24); |
||||||
|
will_return(__wrap_flash_read, 24); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
ret = ftl_read(&map, data, 24, 0x4321); |
||||||
|
|
||||||
|
assert_int_equal(ret, 24); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_boundary(void **state) |
||||||
|
{ |
||||||
|
char data[32]; |
||||||
|
struct ftl_map map; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
map.outstanding.flags = 0; |
||||||
|
|
||||||
|
expect_value(__wrap_trace_path, map, &map); |
||||||
|
expect_value(__wrap_trace_path, new_page_desc, NULL); |
||||||
|
expect_not_value(__wrap_trace_path, page, NULL); |
||||||
|
expect_value(__wrap_trace_path, va, 4); |
||||||
|
will_return(__wrap_trace_path, NULL); |
||||||
|
will_return(__wrap_trace_path, 42); |
||||||
|
will_return(__wrap_trace_path, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, 42 << 12 | 0xff0); |
||||||
|
expect_value(__wrap_flash_read, len, 16); |
||||||
|
will_return(__wrap_flash_read, 16); |
||||||
|
will_return(__wrap_flash_read, NULL); |
||||||
|
|
||||||
|
ret = ftl_read(&map, data, 32, 0x4ff0); |
||||||
|
|
||||||
|
assert_int_equal(ret, 16); |
||||||
|
} |
||||||
|
|
||||||
|
int test_ftl_read(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "ftl_read: basic read", test_basic_read, NULL, NULL, NULL }, |
||||||
|
{ "ftl_read: boundary", test_boundary, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("ftl_read", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int test_find_block(void); |
||||||
|
int test_find_block_div(void); |
||||||
|
int test_find_last_block(void); |
||||||
|
int test_find_last_group(void); |
||||||
|
int test_find_head(void); |
||||||
|
int test_find_root(void); |
||||||
|
int test_next_upage(void); |
||||||
|
int test_read_page_group(void); |
||||||
|
int test_read_page_desc(void); |
||||||
|
int test_write_page_desc(void); |
||||||
|
int test_write_upage(void); |
||||||
|
int test_trace_path(void); |
||||||
|
|
||||||
|
int test_ftl_is_mapped(void); |
||||||
|
int test_ftl_read(void); |
||||||
|
|
||||||
|
int test_ftl(void) |
||||||
|
{ |
||||||
|
int count = 0; |
||||||
|
|
||||||
|
count += test_find_block(); |
||||||
|
count += test_find_block_div(); |
||||||
|
count += test_find_last_block(); |
||||||
|
count += test_find_last_group(); |
||||||
|
count += test_find_head(); |
||||||
|
count += test_find_root(); |
||||||
|
count += test_next_upage(); |
||||||
|
count += test_read_page_group(); |
||||||
|
count += test_read_page_desc(); |
||||||
|
count += test_write_page_desc(); |
||||||
|
count += test_write_upage(); |
||||||
|
count += test_trace_path(); |
||||||
|
|
||||||
|
count += test_ftl_is_mapped(); |
||||||
|
count += test_ftl_read(); |
||||||
|
|
||||||
|
return count; |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <ftl.h> |
||||||
|
|
||||||
|
int __wrap_is_group_erased(struct ftl_map *map, uint32_t group) |
||||||
|
{ |
||||||
|
check_expected_ptr(map); |
||||||
|
check_expected(group); |
||||||
|
|
||||||
|
return mock_type(int); |
||||||
|
} |
||||||
|
|
||||||
|
int __wrap_find_block(struct ftl_map *map, struct ftl_page_group *group, |
||||||
|
uint32_t *where, uint32_t block) |
||||||
|
{ |
||||||
|
struct ftl_page_group *ret_group; |
||||||
|
|
||||||
|
check_expected_ptr(map); |
||||||
|
check_expected(block); |
||||||
|
|
||||||
|
ret_group = mock_type(struct ftl_page_group *); |
||||||
|
|
||||||
|
if (ret_group) |
||||||
|
memcpy(group, ret_group, sizeof *group); |
||||||
|
|
||||||
|
*where = mock_type(uint32_t); |
||||||
|
|
||||||
|
return mock_type(int); |
||||||
|
} |
||||||
|
|
||||||
|
int __wrap_prepare_head(struct ftl_map *map) |
||||||
|
{ |
||||||
|
(void)map; |
||||||
|
|
||||||
|
return mock_type(int); |
||||||
|
} |
||||||
|
|
||||||
|
int __wrap_read_page_desc(struct ftl_map *map, |
||||||
|
struct ftl_page_desc *page_desc, uint32_t upage) |
||||||
|
{ |
||||||
|
check_expected_ptr(map); |
||||||
|
check_expected(upage); |
||||||
|
|
||||||
|
memcpy(page_desc, mock_type(struct ftl_page_desc *), sizeof *page_desc); |
||||||
|
|
||||||
|
return mock_type(int); |
||||||
|
} |
||||||
|
|
||||||
|
int __wrap_write_page_desc(struct ftl_map *map, |
||||||
|
struct ftl_page_desc *page_desc) |
||||||
|
{ |
||||||
|
check_expected_ptr(map); |
||||||
|
check_expected_ptr(page_desc); |
||||||
|
|
||||||
|
return mock_type(int); |
||||||
|
} |
||||||
|
|
||||||
|
int __wrap_trace_path(struct ftl_map *map, struct ftl_page_desc *new_page_desc, |
||||||
|
uint32_t *page, uint32_t va) |
||||||
|
{ |
||||||
|
struct ftl_page_desc *ret_page_desc; |
||||||
|
uint32_t ret_page; |
||||||
|
|
||||||
|
check_expected_ptr(map); |
||||||
|
check_expected_ptr(new_page_desc); |
||||||
|
check_expected_ptr(page); |
||||||
|
check_expected(va); |
||||||
|
|
||||||
|
ret_page_desc = mock_type(struct ftl_page_desc *); |
||||||
|
|
||||||
|
if (new_page_desc) |
||||||
|
memcpy(new_page_desc, ret_page_desc, sizeof *new_page_desc); |
||||||
|
|
||||||
|
ret_page = mock_type(uint32_t); |
||||||
|
|
||||||
|
if (page) |
||||||
|
*page = ret_page; |
||||||
|
|
||||||
|
return mock_type(int); |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
int __wrap_prepare_head(struct ftl_map *map); |
@ -0,0 +1,124 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int next_upage(struct ftl_map *map, uint32_t p); |
||||||
|
|
||||||
|
static void test_upage0(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
|
||||||
|
ret = next_upage(&map, 0); |
||||||
|
|
||||||
|
assert_int_equal(ret, 1); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage14(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
|
||||||
|
ret = next_upage(&map, 14); |
||||||
|
|
||||||
|
assert_int_equal(ret, 16); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage15(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
|
||||||
|
ret = next_upage(&map, 15); |
||||||
|
|
||||||
|
assert_int_equal(ret, 16); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage16(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
|
||||||
|
ret = next_upage(&map, 16); |
||||||
|
|
||||||
|
assert_int_equal(ret, 17); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage62(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
|
||||||
|
ret = next_upage(&map, 62); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage63(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_groups_per_block = ilog2(1); |
||||||
|
map.nblocks = 4; |
||||||
|
|
||||||
|
ret = next_upage(&map, 63); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
int test_next_upage(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "next_upage: upage=0", test_upage0, NULL, NULL, NULL }, |
||||||
|
{ "next_upage: upage=14", test_upage14, NULL, NULL, NULL }, |
||||||
|
{ "next_upage: upage=15", test_upage15, NULL, NULL, NULL }, |
||||||
|
{ "next_upage: upage=16", test_upage16, NULL, NULL, NULL }, |
||||||
|
{ "next_upage: upage=62 (wraparound)", test_upage62, NULL, NULL, NULL }, |
||||||
|
{ "next_upage: upage=63 (wraparound)", test_upage63, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("next_upage", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,182 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int __real_read_page_desc(struct ftl_map *map, |
||||||
|
struct ftl_page_desc *page_desc, uint32_t upage); |
||||||
|
|
||||||
|
static void test_upage0(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc, ret_page_desc; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(&page_desc.magic, "page", 4); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (16 - 1) * 4 * KIB + |
||||||
|
sizeof(struct ftl_page_group)); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, &page_desc); |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = __real_read_page_desc(&map, &ret_page_desc, 0); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage14(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc, ret_page_desc; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(&page_desc.magic, "page", 4); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (16 - 1) * 4 * KIB + |
||||||
|
sizeof(struct ftl_page_group) + 14 * sizeof(struct ftl_page_desc)); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, &page_desc); |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = __real_read_page_desc(&map, &ret_page_desc, 14); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage15(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc ret_page_desc; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = __real_read_page_desc(&map, &ret_page_desc, 15); |
||||||
|
|
||||||
|
assert_int_equal(ret, -1); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage16(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc, ret_page_desc; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(&page_desc.magic, "page", 4); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (32 - 1) * 4 * KIB + |
||||||
|
sizeof(struct ftl_page_group)); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, &page_desc); |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = __real_read_page_desc(&map, &ret_page_desc, 16); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage30(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc, ret_page_desc; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(&page_desc.magic, "page", 4); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (32 - 1) * 4 * KIB + |
||||||
|
sizeof(struct ftl_page_group) + 14 * sizeof(struct ftl_page_desc)); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, &page_desc); |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = __real_read_page_desc(&map, &ret_page_desc, 30); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage31(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc ret_page_desc; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = __real_read_page_desc(&map, &ret_page_desc, 31); |
||||||
|
|
||||||
|
assert_int_equal(ret, -1); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_upage32(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc, ret_page_desc; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(&page_desc.magic, "page", 4); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (48 - 1) * 4 * KIB + |
||||||
|
sizeof(struct ftl_page_group)); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, sizeof page_desc); |
||||||
|
will_return(__wrap_flash_read, &page_desc); |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = __real_read_page_desc(&map, &ret_page_desc, 32); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
int test_read_page_desc(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "read_page_desc: upage=0", test_upage0, NULL, NULL, NULL }, |
||||||
|
{ "read_page_desc: upage=14", test_upage14, NULL, NULL, NULL }, |
||||||
|
{ "read_page_desc: upage=15 (invalid)", test_upage15, NULL, NULL, NULL }, |
||||||
|
{ "read_page_desc: upage=16", test_upage16, NULL, NULL, NULL }, |
||||||
|
{ "read_page_desc: upage=30", test_upage30, NULL, NULL, NULL }, |
||||||
|
{ "read_page_desc: upage=31 (invalid)", test_upage31, NULL, NULL, NULL }, |
||||||
|
{ "read_page_desc: upage=32", test_upage32, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("read_page_desc", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,95 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int read_page_group(struct ftl_map *map, |
||||||
|
struct ftl_page_group *group, uint32_t upage); |
||||||
|
|
||||||
|
static void test_magic(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group, ret_group; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(&group.magic, "FtL", 3); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (16 - 1) * 4 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, sizeof group); |
||||||
|
will_return(__wrap_flash_read, &group); |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = read_page_group(&map, &ret_group, 0); |
||||||
|
|
||||||
|
assert_int_equal(ret, -1); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_group0(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group, ret_group; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(&group.magic, "FTL", 3); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (16 - 1) * 4 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, sizeof group); |
||||||
|
will_return(__wrap_flash_read, &group); |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = read_page_group(&map, &ret_group, 0); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_group1(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_group group, ret_group; |
||||||
|
size_t ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memcpy(&group.magic, "FTL", 3); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_read, addr, (2 * 16 - 1) * 4 * KIB); |
||||||
|
expect_value(__wrap_flash_read, len, sizeof group); |
||||||
|
will_return(__wrap_flash_read, sizeof group); |
||||||
|
will_return(__wrap_flash_read, &group); |
||||||
|
|
||||||
|
map.log2_pages_per_group = ilog2(16); |
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
|
||||||
|
ret = read_page_group(&map, &ret_group, 1); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
int test_read_page_group(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "read_page_group: invalid magic", test_magic, NULL, NULL, NULL }, |
||||||
|
{ "read_page_group: group=0", test_group0, NULL, NULL, NULL }, |
||||||
|
{ "read_page_group: group=1", test_group1, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("read_page_group", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,197 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int __real_trace_path(struct ftl_map *map, struct ftl_page_desc *new_page_desc, |
||||||
|
uint32_t *page, uint32_t va); |
||||||
|
|
||||||
|
static void test_empty_root(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t page; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
map.root = UINT32_MAX; |
||||||
|
|
||||||
|
ret = __real_trace_path(&map, NULL, &page, 0); |
||||||
|
|
||||||
|
assert_int_equal(ret, -2); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_exact_match(void **state) |
||||||
|
{ |
||||||
|
struct ftl_page_desc descs[] = { |
||||||
|
{ |
||||||
|
.va = 0xdeadbeef, |
||||||
|
.subtrees = { |
||||||
|
[0] = 19, |
||||||
|
[1] = 21, |
||||||
|
[2] = 38, |
||||||
|
[3] = 81, |
||||||
|
[4] = 24, |
||||||
|
[5] = 64, |
||||||
|
[6] = 25, |
||||||
|
[7] = 15, |
||||||
|
[8] = 0, |
||||||
|
[9] = 73, |
||||||
|
[10] = 49, |
||||||
|
[11] = 22, |
||||||
|
[12] = 85, |
||||||
|
[13] = 45, |
||||||
|
[14] = 98, |
||||||
|
[15] = 7, |
||||||
|
[16] = 72, |
||||||
|
[17] = 26, |
||||||
|
[18] = 92, |
||||||
|
[19] = 16, |
||||||
|
[20] = 12, |
||||||
|
[21] = 57, |
||||||
|
[22] = 52, |
||||||
|
[23] = 39, |
||||||
|
[24] = 28, |
||||||
|
[25] = 42, |
||||||
|
[26] = 37, |
||||||
|
[27] = 87, |
||||||
|
[28] = 5, |
||||||
|
[29] = 27, |
||||||
|
[30] = 30, |
||||||
|
[31] = 47, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
struct ftl_page_desc ret_page_desc; |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t page; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
map.root = 75; |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 75); |
||||||
|
will_return(__wrap_read_page_desc, descs); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
ret = __real_trace_path(&map, &ret_page_desc, &page, 0xdeadbeef); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_int_equal(page, 75); |
||||||
|
|
||||||
|
assert_memory_equal(&ret_page_desc, descs, sizeof ret_page_desc); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_walk(void **state) |
||||||
|
{ |
||||||
|
struct ftl_page_desc descs[] = { |
||||||
|
{ |
||||||
|
.va = 0x7, |
||||||
|
.subtrees = { |
||||||
|
[0] = UINT32_MAX, |
||||||
|
[28] = 43, |
||||||
|
[29] = UINT32_MAX, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.va = 0xb, |
||||||
|
.subtrees = { |
||||||
|
[0] = UINT32_MAX, |
||||||
|
[28] = 42, |
||||||
|
[29] = 44, |
||||||
|
[30] = UINT32_MAX, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.va = 0xd, |
||||||
|
.subtrees = { |
||||||
|
[0] = UINT32_MAX, |
||||||
|
[29] = 43, |
||||||
|
[30] = 45, |
||||||
|
[31] = UINT32_MAX, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.va = 0xe, |
||||||
|
.subtrees = { |
||||||
|
[0] = UINT32_MAX, |
||||||
|
[30] = 44, |
||||||
|
[31] = 46, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
.va = 0xf, |
||||||
|
.subtrees = { |
||||||
|
UINT32_MAX, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
struct ftl_page_desc ret_page_desc; |
||||||
|
struct ftl_map map; |
||||||
|
uint32_t page; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
map.root = 42; |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 42); |
||||||
|
will_return(__wrap_read_page_desc, descs); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 43); |
||||||
|
will_return(__wrap_read_page_desc, descs + 1); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 44); |
||||||
|
will_return(__wrap_read_page_desc, descs + 2); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 45); |
||||||
|
will_return(__wrap_read_page_desc, descs + 3); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_read_page_desc, map, &map); |
||||||
|
expect_value(__wrap_read_page_desc, upage, 46); |
||||||
|
will_return(__wrap_read_page_desc, descs + 3); |
||||||
|
will_return(__wrap_read_page_desc, 0); |
||||||
|
|
||||||
|
ret = __real_trace_path(&map, &ret_page_desc, &page, 0xf); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_int_equal(page, 46); |
||||||
|
|
||||||
|
assert_int_equal(ret_page_desc.va, 0xf); |
||||||
|
assert_int_equal(ret_page_desc.subtrees[28], 42); |
||||||
|
assert_int_equal(ret_page_desc.subtrees[29], 43); |
||||||
|
assert_int_equal(ret_page_desc.subtrees[30], 44); |
||||||
|
assert_int_equal(ret_page_desc.subtrees[31], 45); |
||||||
|
} |
||||||
|
|
||||||
|
int test_trace_path(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "trace_path: empty root", test_empty_root, NULL, NULL, NULL }, |
||||||
|
{ "trace_path: exact match", test_exact_match, NULL, NULL, NULL }, |
||||||
|
{ "trace_path: page descriptor walk", test_walk, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("trace_path", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,258 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int __real_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_head0(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 = __real_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_head14(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 = __real_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_head16(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 = __real_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_head30(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 = __real_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_head32(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 = __real_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 = __real_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 = __real_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_head0, NULL, NULL, NULL }, |
||||||
|
{ "write_page_desc: head=14", test_head14, NULL, NULL, NULL }, |
||||||
|
{ "write_page_desc: head=16", test_head16, NULL, NULL, NULL }, |
||||||
|
{ "write_page_desc: head=30", test_head30, NULL, NULL, NULL }, |
||||||
|
{ "write_page_desc: head=32", test_head32, 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); |
||||||
|
} |
@ -0,0 +1,131 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int write_upage(struct ftl_map *map, const void *page, |
||||||
|
struct ftl_page_desc *page_desc); |
||||||
|
|
||||||
|
static void test_prepare_head(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
map.head = 0; |
||||||
|
|
||||||
|
will_return(__wrap_prepare_head, -1); |
||||||
|
|
||||||
|
ret = write_upage(&map, NULL, &page_desc); |
||||||
|
|
||||||
|
assert_int_equal(ret, -1); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_null_page(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
struct ftl_page_desc page_desc; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
map.head = 0; |
||||||
|
|
||||||
|
will_return(__wrap_prepare_head, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_write_page_desc, map, &map); |
||||||
|
expect_value(__wrap_write_page_desc, page_desc, &page_desc); |
||||||
|
will_return(__wrap_write_page_desc, 0); |
||||||
|
|
||||||
|
ret = write_upage(&map, NULL, &page_desc); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_page0(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
char page[4 * KIB], ret_page[4 * KIB]; |
||||||
|
struct ftl_page_desc page_desc; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memset(page, 0x5a, sizeof page); |
||||||
|
memset(ret_page, 0, sizeof ret_page); |
||||||
|
|
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
map.head = 0; |
||||||
|
|
||||||
|
will_return(__wrap_prepare_head, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_write, addr, 0); |
||||||
|
expect_value(__wrap_flash_write, len, 4 * KIB); |
||||||
|
will_return(__wrap_flash_write, 4 * KIB); |
||||||
|
will_return(__wrap_flash_write, &ret_page); |
||||||
|
|
||||||
|
expect_value(__wrap_write_page_desc, map, &map); |
||||||
|
expect_value(__wrap_write_page_desc, page_desc, &page_desc); |
||||||
|
will_return(__wrap_write_page_desc, 0); |
||||||
|
|
||||||
|
ret = write_upage(&map, &page, &page_desc); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_memory_equal(page, ret_page, sizeof page); |
||||||
|
} |
||||||
|
|
||||||
|
static void test_page42(void **state) |
||||||
|
{ |
||||||
|
struct ftl_map map; |
||||||
|
char page[4 * KIB], ret_page[4 * KIB]; |
||||||
|
struct ftl_page_desc page_desc; |
||||||
|
int ret; |
||||||
|
|
||||||
|
(void)state; |
||||||
|
|
||||||
|
memset(page, 0x5a, sizeof page); |
||||||
|
memset(ret_page, 0, sizeof ret_page); |
||||||
|
|
||||||
|
map.log2_page_size = ilog2(4 * KIB); |
||||||
|
map.head = 42; |
||||||
|
|
||||||
|
will_return(__wrap_prepare_head, 0); |
||||||
|
|
||||||
|
expect_value(__wrap_flash_write, addr, 42 * 4 * KIB); |
||||||
|
expect_value(__wrap_flash_write, len, 4 * KIB); |
||||||
|
will_return(__wrap_flash_write, 4 * KIB); |
||||||
|
will_return(__wrap_flash_write, &ret_page); |
||||||
|
|
||||||
|
expect_value(__wrap_write_page_desc, map, &map); |
||||||
|
expect_value(__wrap_write_page_desc, page_desc, &page_desc); |
||||||
|
will_return(__wrap_write_page_desc, 0); |
||||||
|
|
||||||
|
ret = write_upage(&map, &page, &page_desc); |
||||||
|
|
||||||
|
assert_int_equal(ret, 0); |
||||||
|
assert_memory_equal(page, ret_page, sizeof page); |
||||||
|
} |
||||||
|
|
||||||
|
int test_write_upage(void) |
||||||
|
{ |
||||||
|
const struct CMUnitTest tests[] = { |
||||||
|
{ "write_upage: prepare_head() = -1", test_prepare_head, NULL, NULL, NULL }, |
||||||
|
{ "write_upage: null page", test_null_page, NULL, NULL, NULL }, |
||||||
|
{ "write_upage: head=0", test_page0, NULL, NULL, NULL }, |
||||||
|
{ "write_upage: head=42", test_page42, NULL, NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
return cmocka_run_group_tests_name("write_upage", tests, NULL, NULL); |
||||||
|
} |
@ -0,0 +1,23 @@ |
|||||||
|
#include <stdarg.h> |
||||||
|
#include <stddef.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <setjmp.h> |
||||||
|
|
||||||
|
#include <cmocka.h> |
||||||
|
|
||||||
|
#include <bitops.h> |
||||||
|
#include <flash.h> |
||||||
|
#include <ftl.h> |
||||||
|
#include <macros.h> |
||||||
|
|
||||||
|
int test_ftl(void); |
||||||
|
|
||||||
|
int main(void) |
||||||
|
{ |
||||||
|
int count = 0; |
||||||
|
|
||||||
|
count += test_ftl(); |
||||||
|
|
||||||
|
return count; |
||||||
|
} |
Loading…
Reference in new issue