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/mufs/Makefile |
||||
-include source/platform/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 |
||||
|
@ -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