From 4bc06d9a4bfab4ed77a5d50f827404ca79a2abab Mon Sep 17 00:00:00 2001 From: chenrun1 Date: Wed, 7 Jun 2023 15:14:53 +0800 Subject: [PATCH] drivertest_block:New test items about cache and memory alignment Signed-off-by: chenrun1 --- testing/drivertest/Makefile | 6 + testing/drivertest/drivertest_block.c | 234 ++++++++++++++++++++++++-- 2 files changed, 223 insertions(+), 17 deletions(-) diff --git a/testing/drivertest/Makefile b/testing/drivertest/Makefile index 439453b1b..3e4aa0a6e 100644 --- a/testing/drivertest/Makefile +++ b/testing/drivertest/Makefile @@ -29,6 +29,12 @@ MAINSRC += drivertest_simple.c PROGNAME += cmocka_driver_simple endif +ifeq ($(CONFIG_BCH),y) +CFLAGS += ${INCDIR_PREFIX}${TOPDIR}/fs +PROGNAME += cmocka_driver_block +MAINSRC += drivertest_block.c +endif + ifneq ($(CONFIG_RTC),) MAINSRC += drivertest_rtc.c PROGNAME += cmocka_driver_rtc diff --git a/testing/drivertest/drivertest_block.c b/testing/drivertest/drivertest_block.c index 355d36393..25152d585 100644 --- a/testing/drivertest/drivertest_block.c +++ b/testing/drivertest/drivertest_block.c @@ -23,6 +23,9 @@ ****************************************************************************/ #include +#include +#include +#include #include #include @@ -39,7 +42,9 @@ #include #include #include -#include + +#include "inode/inode.h" +#include "driver/driver.h" /**************************************************************************** * Private Type @@ -57,7 +62,9 @@ struct pre_build_s { + FAR struct inode *driver; FAR const char *source; + struct mtd_geometry_s geo; struct geometry cfg; int fd; }; @@ -140,24 +147,26 @@ static inline char blktest_randchar(void) * Name: blktest_randcontext ****************************************************************************/ -static void blktest_randcontext(FAR struct pre_build_s *pre, FAR char *input) +static void blktest_randcontext(uint32_t size, FAR void *input) { /* Construct a buffer here and fill it with random characters */ int i; - for (i = 0; i < pre->cfg.geo_sectorsize - 1; i++) + FAR char *tmp; + tmp = input; + for (i = 0; i < size - 1; i++) { - input[i] = blktest_randchar(); + tmp[i] = blktest_randchar(); } - input[i] = '\0'; + tmp[i] = '\0'; } /**************************************************************************** - * Name: setup + * Name: setup_bch ****************************************************************************/ -static int setup(FAR void **state) +static int setup_bch(FAR void **state) { FAR struct pre_build_s *pre = *state; struct stat mode; @@ -180,6 +189,41 @@ static int setup(FAR void **state) return 0; } +/**************************************************************************** + * Name: setup_driver + ****************************************************************************/ + +static int setup_driver(FAR void **state) +{ + FAR struct pre_build_s *pre = *state; + int ret; + + ret = find_mtddriver(pre->source, &pre->driver); + if (ret != 0) + { + struct geometry geometry; + ret = find_blockdriver(pre->source, 0, &pre->driver); + assert_false(ret != 0); + + ret = pre->driver->u.i_bops->geometry(pre->driver, &geometry); + assert_false(ret < 0); + + pre->geo.blocksize = geometry.geo_sectorsize; + pre->geo.erasesize = geometry.geo_sectorsize; + pre->geo.neraseblocks = geometry.geo_nsectors; + } + else + { + ret = MTD_IOCTL(pre->driver->u.i_mtd, MTDIOC_GEOMETRY, + (unsigned long)&pre->geo); + assert_false(ret < 0); + } + + srand((unsigned)time(NULL)); + *state = pre; + return 0; +} + /**************************************************************************** * Name: blktest_stress ****************************************************************************/ @@ -187,11 +231,12 @@ static int setup(FAR void **state) static void blktest_stress(FAR void **state) { FAR struct pre_build_s *pre; - FAR char *input; - FAR char *output; + FAR void *input; + FAR void *output; blkcnt_t nsectors; uint32_t input_crc; uint32_t output_crc; + blkcnt_t i; int ret; pre = *state; @@ -214,12 +259,12 @@ static void blktest_stress(FAR void **state) * system. The general flow is user->bch->ftl->driver */ - for (int i = 0; i < nsectors; i++) + for (i = 0; i < nsectors; i++) { lseek(pre->fd, i * pre->cfg.geo_sectorsize, SEEK_SET); - blktest_randcontext(pre, input); - input_crc = crc32((FAR uint8_t *)input, pre->cfg.geo_sectorsize); + blktest_randcontext(pre->cfg.geo_sectorsize, input); + input_crc = crc32(input, pre->cfg.geo_sectorsize); ret = write(pre->fd, input, pre->cfg.geo_sectorsize); assert_true(ret == pre->cfg.geo_sectorsize); @@ -233,22 +278,171 @@ static void blktest_stress(FAR void **state) ret = read(pre->fd, output, pre->cfg.geo_sectorsize); assert_int_equal(ret, pre->cfg.geo_sectorsize); - output_crc = crc32((FAR uint8_t *)output, pre->cfg.geo_sectorsize); + output_crc = crc32(output, pre->cfg.geo_sectorsize); assert_false(output_crc != input_crc); } free(input); } +/**************************************************************************** + * Name: blktest_multiple_write + ****************************************************************************/ + +static void blktest_cachesize_write(FAR void **state) +{ + FAR struct pre_build_s *pre; + FAR void *input; + FAR void *output; + uint32_t input_crc; + uint32_t output_crc; + uint32_t size; + unsigned int block; + size_t i; + int ret; + + pre = *state; + + /* There is a possibility that the cache size (default 0) is not + * available when the case is not opened, so the case should be checked + * to see if the corresponding cache config is open. + */ + + size = up_get_dcache_size(); + + if (size > pre->geo.blocksize && (size % pre->geo.blocksize) == 0) + { + block = (pre->geo.blocksize + size) / pre->geo.blocksize - 1; + } + else + { + block = (pre->geo.blocksize + size) / pre->geo.blocksize; + } + + /* When we can't get the cachesize, we execute it again as + * blktest_single_write + */ + + size = block * pre->geo.blocksize; + + output = malloc(size); + assert_false(output == NULL); + + for (i = 4; i <= 32; i *= 2) + { + /* This case is designed to simulate the behavior of a + * filesystem write. Simulate the case where the buffer constructed + * at one time may be larger than the cache size for the file system + */ + + input = memalign(i, size); + assert_false(input == NULL); + blktest_randcontext(pre->geo.blocksize, input); + input_crc = crc32(input, size); + if (INODE_IS_MTD(pre->driver)) + { + /* Before writing we need to erase the mtd device */ + + ret = MTD_ERASE(pre->driver->u.i_mtd, 0, 1); + assert_false(ret < 0); + ret = MTD_BWRITE(pre->driver->u.i_mtd, 0, block, input); + assert_false(ret != block); + ret = MTD_BREAD(pre->driver->u.i_mtd, 0, block, output); + assert_false(ret != block); + } + else + { + ret = pre->driver->u.i_bops->write(pre->driver, input, 0, block); + assert_false(ret < 0); + ret = pre->driver->u.i_bops->read(pre->driver, output, 0, block); + assert_false(ret < 0); + } + + output_crc = crc32(output, size); + assert_false(input_crc != output_crc); + + free(input); + } + + free(output); +} + +/**************************************************************************** + * Name: blktest_single_write + ****************************************************************************/ + +static void blktest_single_write(FAR void **state) +{ + FAR struct pre_build_s *pre; + FAR void *input; + FAR void *output; + uint32_t input_crc; + uint32_t output_crc; + size_t i; + int ret; + + pre = *state; + + output = malloc(pre->geo.blocksize); + assert_false(output == NULL); + + /* Obviously, this is just to simulate the case where the file system + * is written one eraseblock at a time + */ + + for (i = 4; i <= 32; i *= 2) + { + input = memalign(i, pre->geo.blocksize); + assert_false(input == NULL); + + blktest_randcontext(pre->geo.blocksize, input); + + input_crc = crc32(input, pre->geo.blocksize); + + if (INODE_IS_MTD(pre->driver)) + { + ret = MTD_ERASE(pre->driver->u.i_mtd, 0, 1); + assert_false(ret < 0); + ret = MTD_BWRITE(pre->driver->u.i_mtd, 0, 1, input); + assert_false(ret != 1); + ret = MTD_BREAD(pre->driver->u.i_mtd, 0, 1, output); + assert_false(ret != 1); + } + else + { + ret = pre->driver->u.i_bops->write(pre->driver, input, 0, 1); + assert_false(ret < 0); + ret = pre->driver->u.i_bops->read(pre->driver, output, 0, 1); + assert_false(ret < 0); + } + + output_crc = crc32(output, pre->geo.blocksize); + assert_false(input_crc != output_crc); + + free(input); + } + + free(output); +} + /**************************************************************************** * Name: teardown ****************************************************************************/ -static int teardown(FAR void **state) +static int teardown_driver(FAR void **state) +{ + return 0; +} + +/**************************************************************************** + * Name: teardown_bch + ****************************************************************************/ + +static int teardown_bch(FAR void **state) { FAR struct pre_build_s *pre; - pre = (FAR struct pre_build_s *)*state; + pre = *state; close(pre->fd); @@ -270,8 +464,14 @@ int main(int argc, FAR char *argv[]) parse_commandline(argc, argv, &pre); const struct CMUnitTest tests[] = { - cmocka_unit_test_prestate_setup_teardown(blktest_stress, setup, - teardown, &pre), + cmocka_unit_test_prestate_setup_teardown(blktest_stress, setup_bch, + teardown_bch, &pre), + cmocka_unit_test_prestate_setup_teardown(blktest_single_write, + setup_driver, teardown_driver, + &pre), + cmocka_unit_test_prestate_setup_teardown(blktest_cachesize_write, + setup_driver, teardown_driver, + &pre), }; return cmocka_run_group_tests(tests, NULL, NULL);