# Test some low-level block-map operations # # Note these is very much not-exhaustive, but the entire test suite can # be run with the gbmap if you define LFS3_YES_GBMAP: # # LFS3_YES_GBMAP=1 make test -j # after = ['test_btree', 'test_mtree'] ifdef = 'LFS3_GBMAP' # test low-level gbmap operations # test simple set operations [cases.test_gbmap_mark_split] in = 'lfs3.c' code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; lfs3_alloc_ckpoint(&lfs3); // create an initial gbmap lfs3_btree_t gbmap; lfs3_btree_init(&gbmap); lfs3_gbmap_commit(&lfs3, &gbmap, 0, LFS3_RATTRS( LFS3_RATTR(LFS3_TAG_BMFREE, +BLOCK_COUNT))) => 0; // set some blocks as in-use, avoid any weird merges for now lfs3_gbmap_mark(&lfs3, &gbmap, 6, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 8, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 10, LFS3_TAG_BMINUSE) => 0; printf("gbmap: w%d 0x%x.%x\n", gbmap.r.weight, gbmap.r.blocks[0], gbmap.r.trunk); // weight should stay the same assert(gbmap.r.weight == BLOCK_COUNT); // check ranges lfs3_bid_t bid_; lfs3_bid_t weight_; lfs3_gbmap_lookupnext(&lfs3, &gbmap, 0, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 5); assert(weight_ == 6); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 6, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 6); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 7, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 7); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 8, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 8); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 9, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 9); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 10, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 10); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 11, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == BLOCK_COUNT-1); assert(weight_ == BLOCK_COUNT-11); lfs3_unmount(&lfs3) => 0; ''' [cases.test_gbmap_mark_replace] in = 'lfs3.c' code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; lfs3_alloc_ckpoint(&lfs3); // create an initial gbmap lfs3_btree_t gbmap; lfs3_btree_init(&gbmap); lfs3_gbmap_commit(&lfs3, &gbmap, 0, LFS3_RATTRS( LFS3_RATTR(LFS3_TAG_BMFREE, +BLOCK_COUNT))) => 0; // set some blocks as in-use, avoid any weird merges for now lfs3_gbmap_mark(&lfs3, &gbmap, 6, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 8, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 10, LFS3_TAG_BMINUSE) => 0; // replace those blocks as bad, this tests deleting ranges lfs3_gbmap_mark(&lfs3, &gbmap, 6, LFS3_TAG_BMBAD) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 8, LFS3_TAG_BMBAD) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 10, LFS3_TAG_BMBAD) => 0; printf("gbmap: w%d 0x%x.%x\n", gbmap.r.weight, gbmap.r.blocks[0], gbmap.r.trunk); // weight should stay the same assert(gbmap.r.weight == BLOCK_COUNT); // check ranges lfs3_bid_t bid_; lfs3_bid_t weight_; lfs3_gbmap_lookupnext(&lfs3, &gbmap, 0, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 5); assert(weight_ == 6); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 6, &bid_, &weight_) => LFS3_TAG_BMBAD; assert(bid_ == 6); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 7, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 7); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 8, &bid_, &weight_) => LFS3_TAG_BMBAD; assert(bid_ == 8); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 9, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 9); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 10, &bid_, &weight_) => LFS3_TAG_BMBAD; assert(bid_ == 10); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 11, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == BLOCK_COUNT-1); assert(weight_ == BLOCK_COUNT-11); lfs3_unmount(&lfs3) => 0; ''' [cases.test_gbmap_mark_merge] in = 'lfs3.c' code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; lfs3_alloc_ckpoint(&lfs3); // create an initial gbmap lfs3_btree_t gbmap; lfs3_btree_init(&gbmap); lfs3_gbmap_commit(&lfs3, &gbmap, 0, LFS3_RATTRS( LFS3_RATTR(LFS3_TAG_BMFREE, +BLOCK_COUNT))) => 0; // set some blocks as in-use, avoid any weird merges for now lfs3_gbmap_mark(&lfs3, &gbmap, 6, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 8, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 10, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 12, LFS3_TAG_BMINUSE) => 0; // set neighboring blocks as in-use, triggering merges lfs3_gbmap_mark(&lfs3, &gbmap, 5, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 9, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 13, LFS3_TAG_BMINUSE) => 0; printf("gbmap: w%d 0x%x.%x\n", gbmap.r.weight, gbmap.r.blocks[0], gbmap.r.trunk); // weight should stay the same assert(gbmap.r.weight == BLOCK_COUNT); // check ranges lfs3_bid_t bid_; lfs3_bid_t weight_; lfs3_gbmap_lookupnext(&lfs3, &gbmap, 0, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 4); assert(weight_ == 5); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 5, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 6); assert(weight_ == 2); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 7, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 7); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 8, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 10); assert(weight_ == 3); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 11, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 11); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 12, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 13); assert(weight_ == 2); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 14, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == BLOCK_COUNT-1); assert(weight_ == BLOCK_COUNT-14); lfs3_unmount(&lfs3) => 0; ''' [cases.test_gbmap_mark_noop] in = 'lfs3.c' code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; lfs3_alloc_ckpoint(&lfs3); // create an initial gbmap lfs3_btree_t gbmap; lfs3_btree_init(&gbmap); lfs3_gbmap_commit(&lfs3, &gbmap, 0, LFS3_RATTRS( LFS3_RATTR(LFS3_TAG_BMFREE, +BLOCK_COUNT))) => 0; // set some blocks as in-use, avoid any weird merges for now lfs3_gbmap_mark(&lfs3, &gbmap, 6, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 8, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 10, LFS3_TAG_BMINUSE) => 0; // test a bunch of noops lfs3_gbmap_mark(&lfs3, &gbmap, 6, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 7, LFS3_TAG_BMFREE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 8, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 9, LFS3_TAG_BMFREE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, 10, LFS3_TAG_BMINUSE) => 0; printf("gbmap: w%d 0x%x.%x\n", gbmap.r.weight, gbmap.r.blocks[0], gbmap.r.trunk); // weight should stay the same assert(gbmap.r.weight == BLOCK_COUNT); // check ranges lfs3_bid_t bid_; lfs3_bid_t weight_; lfs3_gbmap_lookupnext(&lfs3, &gbmap, 0, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 5); assert(weight_ == 6); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 6, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 6); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 7, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 7); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 8, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 8); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 9, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == 9); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 10, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 10); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 11, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == BLOCK_COUNT-1); assert(weight_ == BLOCK_COUNT-11); lfs3_unmount(&lfs3) => 0; ''' [cases.test_gbmap_mark_bounds] in = 'lfs3.c' code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; lfs3_alloc_ckpoint(&lfs3); // create an initial gbmap lfs3_btree_t gbmap; lfs3_btree_init(&gbmap); lfs3_gbmap_commit(&lfs3, &gbmap, 0, LFS3_RATTRS( LFS3_RATTR(LFS3_TAG_BMFREE, +BLOCK_COUNT))) => 0; // test that setting the first and last blocks don't break anything // // though in theory blocks 0x{0,1} are immutable... lfs3_gbmap_mark(&lfs3, &gbmap, 0, LFS3_TAG_BMINUSE) => 0; lfs3_gbmap_mark(&lfs3, &gbmap, BLOCK_COUNT-1, LFS3_TAG_BMINUSE) => 0; printf("gbmap: w%d 0x%x.%x\n", gbmap.r.weight, gbmap.r.blocks[0], gbmap.r.trunk); // weight should stay the same assert(gbmap.r.weight == BLOCK_COUNT); // check ranges lfs3_bid_t bid_; lfs3_bid_t weight_; lfs3_gbmap_lookupnext(&lfs3, &gbmap, 0, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == 0); assert(weight_ == 1); lfs3_gbmap_lookupnext(&lfs3, &gbmap, 1, &bid_, &weight_) => LFS3_TAG_BMFREE; assert(bid_ == BLOCK_COUNT-2); assert(weight_ == BLOCK_COUNT-2); lfs3_gbmap_lookupnext(&lfs3, &gbmap, BLOCK_COUNT-1, &bid_, &weight_) => LFS3_TAG_BMINUSE; assert(bid_ == BLOCK_COUNT-1); assert(weight_ == 1); lfs3_unmount(&lfs3) => 0; ''' [cases.test_gbmap_mark_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] defines.TYPES = [2, 3, 4] defines.SEED = 'range(20)' fuzz = 'SEED' in = 'lfs3.c' code = ''' lfs3_t lfs3; lfs3_format(&lfs3, LFS3_F_RDWR, CFG) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; lfs3_alloc_ckpoint(&lfs3); // create an initial gbmap lfs3_btree_t gbmap; lfs3_btree_init(&gbmap); lfs3_gbmap_commit(&lfs3, &gbmap, 0, LFS3_RATTRS( LFS3_RATTR(LFS3_TAG_BMFREE, +BLOCK_COUNT))) => 0; // create a simulation to compare against lfs3_tag_t *sim = malloc(BLOCK_COUNT*sizeof(lfs3_tag_t)); for (lfs3_size_t i = 0; i < BLOCK_COUNT; i++) { sim[i] = LFS3_TAG_BMFREE; } uint32_t prng = SEED; for (lfs3_size_t i = 0; i < N; i++) { // choose a pseudo-random block lfs3_block_t block = TEST_PRNG(&prng) % BLOCK_COUNT; // and pseudo-random gbmap type lfs3_tag_t tag = LFS3_TAG_BMRANGE + (TEST_PRNG(&prng) % TYPES); // set in gbmap lfs3_gbmap_mark(&lfs3, &gbmap, block, tag) => 0; // and set in sim sim[block] = tag; } printf("gbmap: w%d 0x%x.%x\n", gbmap.r.weight, gbmap.r.blocks[0], gbmap.r.trunk); // check if gbmap matches sim lfs3_size_t i = 0; while (i < BLOCK_COUNT) { // we need to convert our sim's raw blocks to compressed ranges, // in theory our gbmap is optimal lfs3_tag_t tag = sim[i]; lfs3_size_t d = 1; while (i+d < BLOCK_COUNT && sim[i+d] == tag) { d += 1; } // does our gbmap contain the optimal range? lfs3_bid_t bid_; lfs3_bid_t weight_; lfs3_gbmap_lookupnext(&lfs3, &gbmap, i, &bid_, &weight_) => tag; assert(bid_ == i+(weight_-1)); assert(weight_ == d); i += d; } free(sim); lfs3_unmount(&lfs3) => 0; ''' # test high-level gbmap operations # test that the gbmap generally works [cases.test_gbmap_files] defines.COUNT = [ 'BLOCK_COUNT', 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', '5', '3', ] defines.SIZE = [ 'BLOCK_SIZE', '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] defines.N = ['5', 'BLOCK_COUNT/2'] defines.WRAPAROUND = 3 if = [ 'COUNT >= 3', 'COUNT >= 2*N*SIZE/BLOCK_SIZE', ] code = ''' // test various block counts struct lfs3_cfg cfg = *CFG; cfg.block_count = COUNT; lfs3_t lfs3; // note the gbmap flag lfs3_format(&lfs3, LFS3_F_RDWR | LFS3_F_GBMAP, &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // check that we were formatted with the gbmap struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.flags & LFS3_I_GBMAP); // create n files repeatedly until we're sure we've wrapped around // a few times uint32_t prng = 42; uint32_t prng_ = prng; for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // check that our file writes worked prng_ = prng; for (lfs3_size_t i = 0; i < N; i++) { // check with stat char name[256]; sprintf(name, "file%08d", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_REG); assert(info.size == SIZE); // try reading the file, note we reset prng above uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; uint8_t rbuf[SIZE]; lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0; lfs3_file_read(&lfs3, &file, rbuf, SIZE) => SIZE; assert(memcmp(rbuf, wbuf, SIZE) == 0); lfs3_file_close(&lfs3, &file) => 0; } } lfs3_unmount(&lfs3) => 0; ''' # test that we can remove the gbmap and things still work [cases.test_gbmap_rmgbmap] ifndef = 'LFS3_YES_GBMAP' defines.COUNT = [ 'BLOCK_COUNT', 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', '5', '3', ] defines.SIZE = [ 'BLOCK_SIZE', '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] defines.N = ['5', 'BLOCK_COUNT/2'] defines.WRAPAROUND = 3 # REMOUNT=0 => don't remount # REMOUNT=1 => remount after # REMOUNT=2 => remount before # REMOUNT=3 => remount both after and before defines.REMOUNT = [0, 1, 2, 3] if = [ 'COUNT >= 3', 'COUNT >= 2*N*SIZE/BLOCK_SIZE', ] code = ''' // test various block counts struct lfs3_cfg cfg = *CFG; cfg.block_count = COUNT; lfs3_t lfs3; // note the gbmap flag lfs3_format(&lfs3, LFS3_F_RDWR | LFS3_F_GBMAP, &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // check that we were formatted with the gbmap struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.flags & LFS3_I_GBMAP); // create n files repeatedly until we're sure we've wrapped around // a few times uint32_t prng = 42; uint32_t prng_ = prng; for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } // remount before? if (REMOUNT & 2) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // now remove the gbmap lfs3_fs_rmgbmap(&lfs3) => 0; // remount after? if (REMOUNT & 1) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // we should no longer have a gbmap lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(!(fsinfo.flags & LFS3_I_GBMAP)); // create n files repeatedly until we're sure we've wrapped around // a few times for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // check that our file writes worked prng_ = prng; for (lfs3_size_t i = 0; i < N; i++) { // check with stat char name[256]; sprintf(name, "file%08d", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_REG); assert(info.size == SIZE); // try reading the file, note we reset prng above uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; uint8_t rbuf[SIZE]; lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0; lfs3_file_read(&lfs3, &file, rbuf, SIZE) => SIZE; assert(memcmp(rbuf, wbuf, SIZE) == 0); lfs3_file_close(&lfs3, &file) => 0; } } lfs3_unmount(&lfs3) => 0; ''' # test that we can make the gbmap and things still work [cases.test_gbmap_mkgbmap] ifndef = 'LFS3_YES_GBMAP' defines.COUNT = [ 'BLOCK_COUNT', 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', '5', '3', ] defines.SIZE = [ 'BLOCK_SIZE', '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] defines.N = ['5', 'BLOCK_COUNT/2'] defines.WRAPAROUND = 3 # REMOUNT=0 => don't remount # REMOUNT=1 => remount after # REMOUNT=2 => remount before # REMOUNT=3 => remount both after and before defines.REMOUNT = [0, 1, 2, 3] if = [ 'COUNT >= 3', 'COUNT >= 2*N*SIZE/BLOCK_SIZE', ] code = ''' // test various block counts struct lfs3_cfg cfg = *CFG; cfg.block_count = COUNT; lfs3_t lfs3; // note the lack of gbmap flag lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // check that we were formatted without the gbmap struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(!(fsinfo.flags & LFS3_I_GBMAP)); // create n files repeatedly until we're sure we've wrapped around // a few times uint32_t prng = 42; uint32_t prng_ = prng; for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } // remount before? if (REMOUNT & 2) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // now make the gbmap lfs3_fs_mkgbmap(&lfs3) => 0; // remount after? if (REMOUNT & 1) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // we should now have a gbmap lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.flags & LFS3_I_GBMAP); // create n files repeatedly until we're sure we've wrapped around // a few times for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // check that our file writes worked prng_ = prng; for (lfs3_size_t i = 0; i < N; i++) { // check with stat char name[256]; sprintf(name, "file%08d", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_REG); assert(info.size == SIZE); // try reading the file, note we reset prng above uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; uint8_t rbuf[SIZE]; lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0; lfs3_file_read(&lfs3, &file, rbuf, SIZE) => SIZE; assert(memcmp(rbuf, wbuf, SIZE) == 0); lfs3_file_close(&lfs3, &file) => 0; } } lfs3_unmount(&lfs3) => 0; ''' # test that we can remove and then remake the gbmap and things still # work # # this leaves the disk with garbage gstate that mkgbmap needs to clean # up [cases.test_gbmap_rmmkgbmap] ifndef = 'LFS3_YES_GBMAP' defines.COUNT = [ 'BLOCK_COUNT', 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', '5', '3', ] defines.SIZE = [ 'BLOCK_SIZE', '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] defines.N = ['5', 'BLOCK_COUNT/2'] defines.WRAPAROUND = 3 # REMOUNT=0x1 => remount after # REMOUNT=0x2 => remount before make # REMOUNT=0x4 => remount after remove # REMOUNT=0x8 => remount before defines.REMOUNT = 'range(0x10)' if = [ 'COUNT >= 3', 'COUNT >= 2*N*SIZE/BLOCK_SIZE', ] code = ''' // test various block counts struct lfs3_cfg cfg = *CFG; cfg.block_count = COUNT; lfs3_t lfs3; // note the gbmap flag lfs3_format(&lfs3, LFS3_F_RDWR | LFS3_F_GBMAP, &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // check that we were formatted with the gbmap struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.flags & LFS3_I_GBMAP); // create n files repeatedly until we're sure we've wrapped around // a few times uint32_t prng = 42; uint32_t prng_ = prng; for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } // remount before? if (REMOUNT & 8) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // now remove the gbmap lfs3_fs_rmgbmap(&lfs3) => 0; // remount after remove? if (REMOUNT & 4) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // we should no longer have a gbmap lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(!(fsinfo.flags & LFS3_I_GBMAP)); // create n files repeatedly until we're sure we've wrapped around // a few times for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } // remount before make? if (REMOUNT & 2) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // now remake the gbmap lfs3_fs_mkgbmap(&lfs3) => 0; // remount after? if (REMOUNT & 1) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // we should now have a gbmap lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.flags & LFS3_I_GBMAP); // create n files repeatedly until we're sure we've wrapped around // a few times for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // check that our file writes worked prng_ = prng; for (lfs3_size_t i = 0; i < N; i++) { // check with stat char name[256]; sprintf(name, "file%08d", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_REG); assert(info.size == SIZE); // try reading the file, note we reset prng above uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; uint8_t rbuf[SIZE]; lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0; lfs3_file_read(&lfs3, &file, rbuf, SIZE) => SIZE; assert(memcmp(rbuf, wbuf, SIZE) == 0); lfs3_file_close(&lfs3, &file) => 0; } } lfs3_unmount(&lfs3) => 0; ''' # test that we can make and then remove the gbmap and things still # work # # not exactly sure what this tests, but including for completeness [cases.test_gbmap_mkrmgbmap] ifndef = 'LFS3_YES_GBMAP' defines.COUNT = [ 'BLOCK_COUNT', 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', '5', '3', ] defines.SIZE = [ 'BLOCK_SIZE', '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] defines.N = ['5', 'BLOCK_COUNT/2'] defines.WRAPAROUND = 3 # REMOUNT=0x1 => remount after # REMOUNT=0x2 => remount before remove # REMOUNT=0x4 => remount after make # REMOUNT=0x8 => remount before defines.REMOUNT = 'range(0x10)' if = [ 'COUNT >= 3', 'COUNT >= 2*N*SIZE/BLOCK_SIZE', ] code = ''' // test various block counts struct lfs3_cfg cfg = *CFG; cfg.block_count = COUNT; lfs3_t lfs3; // note the lack of gbmap flag lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // check that we were formatted without the gbmap struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(!(fsinfo.flags & LFS3_I_GBMAP)); // create n files repeatedly until we're sure we've wrapped around // a few times uint32_t prng = 42; uint32_t prng_ = prng; for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } // remount before? if (REMOUNT & 8) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // now make the gbmap lfs3_fs_mkgbmap(&lfs3) => 0; // remount after make? if (REMOUNT & 4) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // we should now have a gbmap lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.flags & LFS3_I_GBMAP); // create n files repeatedly until we're sure we've wrapped around // a few times for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } // remount before remove? if (REMOUNT & 2) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // now remove the gbmap lfs3_fs_rmgbmap(&lfs3) => 0; // remount after? if (REMOUNT & 1) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // we should no longer have a gbmap lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(!(fsinfo.flags & LFS3_I_GBMAP)); // create n files repeatedly until we're sure we've wrapped around // a few times for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // check that our file writes worked prng_ = prng; for (lfs3_size_t i = 0; i < N; i++) { // check with stat char name[256]; sprintf(name, "file%08d", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_REG); assert(info.size == SIZE); // try reading the file, note we reset prng above uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; uint8_t rbuf[SIZE]; lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0; lfs3_file_read(&lfs3, &file, rbuf, SIZE) => SIZE; assert(memcmp(rbuf, wbuf, SIZE) == 0); lfs3_file_close(&lfs3, &file) => 0; } } lfs3_unmount(&lfs3) => 0; ''' # test that removing a non-existant gbmap errors [cases.test_gbmap_rmgbmap_noent] ifndef = 'LFS3_YES_GBMAP' defines.COUNT = [ 'BLOCK_COUNT', 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', '5', '3', ] defines.SIZE = [ 'BLOCK_SIZE', '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] defines.N = ['5', 'BLOCK_COUNT/2'] defines.WRAPAROUND = 3 # REMOUNT=0 => don't remount # REMOUNT=1 => remount after # REMOUNT=2 => remount before # REMOUNT=3 => remount both after and before defines.REMOUNT = [0, 1, 2, 3] if = [ 'COUNT >= 3', 'COUNT >= 2*N*SIZE/BLOCK_SIZE', ] code = ''' // test various block counts struct lfs3_cfg cfg = *CFG; cfg.block_count = COUNT; lfs3_t lfs3; // note the lack of gbmap flag lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // check that we were formatted without the gbmap struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(!(fsinfo.flags & LFS3_I_GBMAP)); // create n files repeatedly until we're sure we've wrapped around // a few times uint32_t prng = 42; uint32_t prng_ = prng; for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } // remount before? if (REMOUNT & 2) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // now try to remove the gbmap lfs3_fs_rmgbmap(&lfs3) => LFS3_ERR_NOENT; // remount after? if (REMOUNT & 1) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // we should no longer have a gbmap lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(!(fsinfo.flags & LFS3_I_GBMAP)); // create n files repeatedly until we're sure we've wrapped around // a few times for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // check that our file writes worked prng_ = prng; for (lfs3_size_t i = 0; i < N; i++) { // check with stat char name[256]; sprintf(name, "file%08d", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_REG); assert(info.size == SIZE); // try reading the file, note we reset prng above uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; uint8_t rbuf[SIZE]; lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0; lfs3_file_read(&lfs3, &file, rbuf, SIZE) => SIZE; assert(memcmp(rbuf, wbuf, SIZE) == 0); lfs3_file_close(&lfs3, &file) => 0; } } lfs3_unmount(&lfs3) => 0; ''' # test that making an existant gbmap errors [cases.test_gbmap_mkgbmap_exist] ifndef = 'LFS3_YES_GBMAP' defines.COUNT = [ 'BLOCK_COUNT', 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', '5', '3', ] defines.SIZE = [ 'BLOCK_SIZE', '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] defines.N = ['5', 'BLOCK_COUNT/2'] defines.WRAPAROUND = 3 # REMOUNT=0 => don't remount # REMOUNT=1 => remount after # REMOUNT=2 => remount before # REMOUNT=3 => remount both after and before defines.REMOUNT = [0, 1, 2, 3] if = [ 'COUNT >= 3', 'COUNT >= 2*N*SIZE/BLOCK_SIZE', ] code = ''' // test various block counts struct lfs3_cfg cfg = *CFG; cfg.block_count = COUNT; lfs3_t lfs3; // note the gbmap flag lfs3_format(&lfs3, LFS3_F_RDWR | LFS3_F_GBMAP, &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // check that we were formatted with the gbmap struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.flags & LFS3_I_GBMAP); // create n files repeatedly until we're sure we've wrapped around // a few times uint32_t prng = 42; uint32_t prng_ = prng; for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } // remount before? if (REMOUNT & 2) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // now make the gbmap lfs3_fs_mkgbmap(&lfs3) => LFS3_ERR_EXIST; // remount after? if (REMOUNT & 1) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // we should now have a gbmap lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.flags & LFS3_I_GBMAP); // create n files repeatedly until we're sure we've wrapped around // a few times for (lfs3_size_t i = 0; i < (WRAPAROUND*COUNT) / (N*(SIZE/BLOCK_SIZE)); i++) { prng = prng_; for (lfs3_size_t n = 0; n < N; n++) { char name[256]; sprintf(name, "file%08d", n); uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; lfs3_file_open(&lfs3, &file, name, LFS3_O_WRONLY | LFS3_O_CREAT | LFS3_O_TRUNC) => 0; lfs3_file_write(&lfs3, &file, wbuf, SIZE) => SIZE; lfs3_file_close(&lfs3, &file) => 0; } } for (int remount = 0; remount < 2; remount++) { // remount? if (remount) { lfs3_unmount(&lfs3) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; } // check that our file writes worked prng_ = prng; for (lfs3_size_t i = 0; i < N; i++) { // check with stat char name[256]; sprintf(name, "file%08d", i); struct lfs3_info info; lfs3_stat(&lfs3, name, &info) => 0; assert(strcmp(info.name, name) == 0); assert(info.type == LFS3_TYPE_REG); assert(info.size == SIZE); // try reading the file, note we reset prng above uint8_t wbuf[SIZE]; for (lfs3_size_t j = 0; j < SIZE; j++) { wbuf[j] = 'a' + (TEST_PRNG(&prng_) % 26); } lfs3_file_t file; uint8_t rbuf[SIZE]; lfs3_file_open(&lfs3, &file, name, LFS3_O_RDONLY) => 0; lfs3_file_read(&lfs3, &file, rbuf, SIZE) => SIZE; assert(memcmp(rbuf, wbuf, SIZE) == 0); lfs3_file_close(&lfs3, &file) => 0; } } lfs3_unmount(&lfs3) => 0; '''