You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/07/17 15:15:37 UTC

[nuttx-apps] branch master updated (5d3738345 -> 4bc06d9a4)

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


    from 5d3738345 examples: Build both native app and wasm app for hello to pass CI test
     new 3cb5d475a drivertest_block:Test the availability of each sector of the block.
     new 9768cfab7 drivertest_block:Give redundant space for bad blocks in nand flash
     new 4bc06d9a4 drivertest_block:New test items about cache and memory alignment

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 testing/drivertest/Makefile           |   6 +
 testing/drivertest/drivertest_block.c | 363 ++++++++++++++++++++++++++--------
 2 files changed, 285 insertions(+), 84 deletions(-)


[nuttx-apps] 01/03: drivertest_block:Test the availability of each sector of the block.

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 3cb5d475ae734d37c55a752be099ec846d9182d2
Author: chenrun1 <ch...@xiaomi.com>
AuthorDate: Mon May 15 20:21:37 2023 +0800

    drivertest_block:Test the availability of each sector of the block.
    
    Signed-off-by: chenrun1 <ch...@xiaomi.com>
---
 testing/drivertest/drivertest_block.c | 157 ++++++++++++++--------------------
 1 file changed, 64 insertions(+), 93 deletions(-)

diff --git a/testing/drivertest/drivertest_block.c b/testing/drivertest/drivertest_block.c
index 790b813d0..9a81521e5 100644
--- a/testing/drivertest/drivertest_block.c
+++ b/testing/drivertest/drivertest_block.c
@@ -26,6 +26,7 @@
 
 #include <sys/mount.h>
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 
 #include <stdarg.h>
 #include <stddef.h>
@@ -43,27 +44,14 @@
  * Private Type
  ****************************************************************************/
 
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-#define BLKTEST_MAXLEN  255
-#define BLKTEST_LOOPS   100
-
 /****************************************************************************
  * Private Types
  ****************************************************************************/
 
-struct pre_build
+struct pre_build_s
 {
-  FAR const char *mountpt;
-};
-
-struct test_state_s
-{
-  FAR char *context[BLKTEST_MAXLEN];
-  size_t len[BLKTEST_LOOPS];
-  uint32_t crc[BLKTEST_LOOPS];
+  FAR const char *source;
+  struct geometry cfg;
   int fd;
 };
 
@@ -77,10 +65,10 @@ struct test_state_s
 
 static void show_usage(FAR const char *progname, int exitcode)
 {
-  printf("Usage: %s -m <mountpt>\n", progname);
+  printf("Usage: %s -m <source>\n", progname);
   printf("Where:\n");
-  printf("  -m <mountpt> Block device or mtd device"
-         " mount location[default location: dev/ram10].\n");
+  printf("  -m <source> Block device or mtd device"
+         " mount location.\n");
   exit(exitcode);
 }
 
@@ -89,16 +77,18 @@ static void show_usage(FAR const char *progname, int exitcode)
  ****************************************************************************/
 
 static void parse_commandline(int argc, FAR char **argv,
-                              FAR struct pre_build *pre_build)
+                              FAR struct pre_build_s *pre)
 {
   int option;
 
+  pre->source = NULL;
+
   while ((option = getopt(argc, argv, "m:")) != ERROR)
     {
       switch (option)
         {
           case 'm':
-            pre_build->mountpt = optarg;
+            pre->source = optarg;
             break;
           case '?':
             printf("Unknown option: %c\n", optopt);
@@ -106,6 +96,12 @@ static void parse_commandline(int argc, FAR char **argv,
             break;
         }
     }
+
+  if (pre->source == NULL)
+    {
+      printf("Missing <source>\n");
+      show_usage(argv[0], EXIT_FAILURE);
+    }
 }
 
 /****************************************************************************
@@ -137,27 +133,15 @@ static inline char blktest_randchar(void)
  * Name: blktest_randcontext
  ****************************************************************************/
 
-static void blktest_randcontext(FAR struct test_state_s *test_state)
+static void blktest_randcontext(FAR struct pre_build_s *pre, char *input)
 {
   int i;
-  int j;
-  int rnd;
-
-  for (i = 0; i < BLKTEST_LOOPS; i++)
+  for (i = 0; i < pre->cfg.geo_sectorsize - 1; i++)
     {
-      rnd = (rand() % BLKTEST_MAXLEN) + 1;
-      test_state->context[i] = malloc(rnd + 1);
-      assert_true(test_state->context[i] != NULL);
-      for (j = 0; j < rnd; j++)
-        {
-          test_state->context[i][j] = blktest_randchar();
-        }
-
-      test_state->context[i][rnd] = '\0';
-      size_t len = strlen(test_state->context[i]);
-      test_state->len[i] = len;
-      test_state->crc[i] = crc32((FAR uint8_t *)test_state->context[i], len);
+      input[i] = blktest_randchar();
     }
+
+  input[i] = '\0';
 }
 
 /****************************************************************************
@@ -166,27 +150,24 @@ static void blktest_randcontext(FAR struct test_state_s *test_state)
 
 static int setup(FAR void **state)
 {
-  FAR struct test_state_s *test_state;
-  FAR struct pre_build    *pre_build;
+  FAR struct pre_build_s *pre = (FAR struct pre_build_s *)*state;
+  struct stat mode;
   time_t t;
+  int ret;
 
-  pre_build = (FAR struct pre_build *)*state;
-
-  /* Allocate memory space and initialize */
+  pre->fd = open(pre->source, O_RDWR | O_DIRECT);
+  assert_false(pre->fd < 0);
 
-  test_state = zalloc(sizeof(struct test_state_s));
-  assert_false(test_state == NULL);
+  ret = fstat(pre->fd, &mode);
+  assert_int_equal(ret, 0);
+  ret = (mode.st_mode & S_IFBLK) | (mode.st_mode & S_IFMTD);
+  assert_true(ret != 0);
 
-  /* Seed the random number generated */
+  ret = ioctl(pre->fd, BIOC_GEOMETRY, (unsigned long)((uintptr_t)&pre->cfg));
+  assert_false(ret < 0);
 
   srand((unsigned)time(&t));
-
-  /* Open */
-
-  test_state->fd = open(pre_build->mountpt, O_RDWR | O_DIRECT);
-  assert_false(test_state->fd < 0);
-  *state = test_state;
-
+  *state = pre;
   return 0;
 }
 
@@ -196,49 +177,42 @@ static int setup(FAR void **state)
 
 static void blktest_stress(FAR void **state)
 {
-  FAR struct test_state_s *test_state;
-  int i;
-  int ret;
-  char *output;
+  FAR struct pre_build_s *pre;
+  FAR char *input;
+  FAR char *output;
+  uint32_t input_crc;
   uint32_t output_crc;
+  int ret;
 
-  test_state = (FAR struct test_state_s *)*state;
-
-  /* Create some random context */
-
-  blktest_randcontext(test_state);
+  pre = (FAR struct pre_build_s *)*state;
 
-  /* Writes all text to the block device bypassing the buffer cache,
-   * ensuring that reads are read from the block device.
-   * Get the value of crc32 after reading and compare it with the crc32
-   * of the previously written text.
-   */
+  input = malloc(pre->cfg.geo_sectorsize);
+  assert_true(input != NULL);
+  output = malloc(pre->cfg.geo_sectorsize);
+  assert_true(output != NULL);
 
-  for (i = 0; i < BLKTEST_LOOPS; i++)
+  for (int i = 0; i < pre->cfg.geo_nsectors; i++)
     {
-      ret = write(test_state->fd, test_state->context[i],
-                  test_state->len[i]);
-      assert_true(ret == test_state->len[i]);
-      fsync(test_state->fd);
-    }
+      input_crc = 0;
+      output_crc = 0;
 
-  /* Reset read and write position */
+      blktest_randcontext(pre, input);
+      input_crc = crc32((FAR uint8_t *)input, pre->cfg.geo_sectorsize);
+      ret = write(pre->fd, input, pre->cfg.geo_sectorsize);
+      assert_true(ret == pre->cfg.geo_sectorsize);
+      fsync(pre->fd);
 
-  lseek(test_state->fd, 0, SEEK_SET);
+      lseek(pre->fd, i * pre->cfg.geo_sectorsize, SEEK_SET);
 
-  output = malloc (BLKTEST_MAXLEN);
-  assert_true(output != NULL);
+      ret = read(pre->fd, output, pre->cfg.geo_sectorsize);
+      assert_int_equal(ret, pre->cfg.geo_sectorsize);
 
-  for (i = 0; i < BLKTEST_LOOPS; i++)
-    {
-      memset(output, 0, BLKTEST_MAXLEN);
-      ret = read(test_state->fd, output, test_state->len[i]);
-      assert_int_equal(ret, test_state->len[i]);
+      output_crc = crc32((FAR uint8_t *)output, pre->cfg.geo_sectorsize);
 
-      output_crc = crc32((FAR uint8_t *)output, test_state->len[i]);
-      assert_false(output_crc != test_state->crc[i]);
+      assert_false(output_crc != input_crc);
     }
 
+  free(input);
   free(output);
 }
 
@@ -248,12 +222,11 @@ static void blktest_stress(FAR void **state)
 
 static int teardown(FAR void **state)
 {
-  FAR struct test_state_s *test_state;
+  FAR struct pre_build_s *pre;
 
-  test_state = (FAR struct test_state_s *)*state;
+  pre = (FAR struct pre_build_s *)*state;
 
-  close(test_state->fd);
-  free(test_state);
+  close(pre->fd);
 
   return 0;
 }
@@ -268,15 +241,13 @@ static int teardown(FAR void **state)
 
 int main(int argc, FAR char *argv[])
 {
-  FAR struct pre_build pre_build = {
-    .mountpt = "dev/ram10"
-  };
+  struct pre_build_s pre;
 
-  parse_commandline(argc, argv, &pre_build);
+  parse_commandline(argc, argv, &pre);
   const struct CMUnitTest tests[] =
     {
       cmocka_unit_test_prestate_setup_teardown(blktest_stress, setup,
-                                               teardown, &pre_build),
+                                               teardown, &pre),
     };
 
   return cmocka_run_group_tests(tests, NULL, NULL);


[nuttx-apps] 03/03: drivertest_block:New test items about cache and memory alignment

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 4bc06d9a4bfab4ed77a5d50f827404ca79a2abab
Author: chenrun1 <ch...@xiaomi.com>
AuthorDate: Wed Jun 7 15:14:53 2023 +0800

    drivertest_block:New test items about cache and memory alignment
    
    Signed-off-by: chenrun1 <ch...@xiaomi.com>
---
 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 <nuttx/config.h>
+#include <nuttx/cache.h>
+#include <nuttx/crc32.h>
+#include <nuttx/mtd/mtd.h>
 
 #include <sys/mount.h>
 #include <sys/ioctl.h>
@@ -39,7 +42,9 @@
 #include <string.h>
 #include <fcntl.h>
 #include <cmocka.h>
-#include <nuttx/crc32.h>
+
+#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);


[nuttx-apps] 02/03: drivertest_block:Give redundant space for bad blocks in nand flash

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 9768cfab79afaa0fd35950543b05756c91356fb1
Author: chenrun1 <ch...@xiaomi.com>
AuthorDate: Mon Jun 5 14:07:04 2023 +0800

    drivertest_block:Give redundant space for bad blocks in nand flash
    
    Signed-off-by: chenrun1 <ch...@xiaomi.com>
---
 testing/drivertest/drivertest_block.c | 48 ++++++++++++++++++++++++++---------
 1 file changed, 36 insertions(+), 12 deletions(-)

diff --git a/testing/drivertest/drivertest_block.c b/testing/drivertest/drivertest_block.c
index 9a81521e5..355d36393 100644
--- a/testing/drivertest/drivertest_block.c
+++ b/testing/drivertest/drivertest_block.c
@@ -27,6 +27,7 @@
 #include <sys/mount.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 
 #include <stdarg.h>
 #include <stddef.h>
@@ -44,6 +45,12 @@
  * Private Type
  ****************************************************************************/
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define SECTORS_RANGE 0.95
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -133,8 +140,10 @@ static inline char blktest_randchar(void)
  * Name: blktest_randcontext
  ****************************************************************************/
 
-static void blktest_randcontext(FAR struct pre_build_s *pre, char *input)
+static void blktest_randcontext(FAR struct pre_build_s *pre, FAR char *input)
 {
+  /* Construct a buffer here and fill it with random characters */
+
   int i;
   for (i = 0; i < pre->cfg.geo_sectorsize - 1; i++)
     {
@@ -150,7 +159,7 @@ static void blktest_randcontext(FAR struct pre_build_s *pre, char *input)
 
 static int setup(FAR void **state)
 {
-  FAR struct pre_build_s *pre = (FAR struct pre_build_s *)*state;
+  FAR struct pre_build_s *pre = *state;
   struct stat mode;
   time_t t;
   int ret;
@@ -180,40 +189,55 @@ static void blktest_stress(FAR void **state)
   FAR struct pre_build_s *pre;
   FAR char *input;
   FAR char *output;
+  blkcnt_t nsectors;
   uint32_t input_crc;
   uint32_t output_crc;
   int ret;
 
-  pre = (FAR struct pre_build_s *)*state;
+  pre = *state;
 
-  input = malloc(pre->cfg.geo_sectorsize);
+  input = malloc(pre->cfg.geo_sectorsize * 2);
   assert_true(input != NULL);
-  output = malloc(pre->cfg.geo_sectorsize);
-  assert_true(output != NULL);
+  output = input + pre->cfg.geo_sectorsize;
+
+  /* We expect the physical bad block rate on nand flash to be no more
+   * than 5%, we give the redundancy space at the end.
+   */
 
-  for (int i = 0; i < pre->cfg.geo_nsectors; i++)
+  nsectors =  pre->cfg.geo_nsectors * SECTORS_RANGE;
+
+  /* Test process: convert the device information of the storage device into
+   * 'sectors' by bch, and fill each 'sector' with random characters, then
+   * read it out and compare whether the writing and The difference between
+   * write and store is verified by crc32.
+   * This behavior simulates the behavior of commands such as 'dd' in the
+   * system. The general flow is user->bch->ftl->driver
+   */
+
+  for (int i = 0; i < nsectors; i++)
     {
-      input_crc = 0;
-      output_crc = 0;
+      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);
       ret = write(pre->fd, input, pre->cfg.geo_sectorsize);
       assert_true(ret == pre->cfg.geo_sectorsize);
+
       fsync(pre->fd);
 
+      /* Let's write each time we need to move the pointer back to the
+       * beginning
+       */
+
       lseek(pre->fd, i * pre->cfg.geo_sectorsize, SEEK_SET);
 
       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);
-
       assert_false(output_crc != input_crc);
     }
 
   free(input);
-  free(output);
 }
 
 /****************************************************************************