| # simple formatting test |
| [cases.test_superblocks_format] |
| code = ''' |
| lfs_t lfs; |
| lfs_format(&lfs, cfg) => 0; |
| ''' |
| |
| # mount/unmount |
| [cases.test_superblocks_mount] |
| code = ''' |
| lfs_t lfs; |
| lfs_format(&lfs, cfg) => 0; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| # reentrant format |
| [cases.test_superblocks_reentrant_format] |
| reentrant = true |
| code = ''' |
| lfs_t lfs; |
| int err = lfs_mount(&lfs, cfg); |
| if (err) { |
| lfs_format(&lfs, cfg) => 0; |
| lfs_mount(&lfs, cfg) => 0; |
| } |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| # invalid mount |
| [cases.test_superblocks_invalid_mount] |
| code = ''' |
| lfs_t lfs; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| ''' |
| |
| # expanding superblock |
| [cases.test_superblocks_expand] |
| defines.BLOCK_CYCLES = [32, 33, 1] |
| defines.N = [10, 100, 1000] |
| code = ''' |
| lfs_t lfs; |
| lfs_format(&lfs, cfg) => 0; |
| lfs_mount(&lfs, cfg) => 0; |
| for (int i = 0; i < N; i++) { |
| lfs_file_t file; |
| lfs_file_open(&lfs, &file, "dummy", |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| struct lfs_info info; |
| lfs_stat(&lfs, "dummy", &info) => 0; |
| assert(strcmp(info.name, "dummy") == 0); |
| assert(info.type == LFS_TYPE_REG); |
| lfs_remove(&lfs, "dummy") => 0; |
| } |
| lfs_unmount(&lfs) => 0; |
| |
| // one last check after power-cycle |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_file_t file; |
| lfs_file_open(&lfs, &file, "dummy", |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| struct lfs_info info; |
| lfs_stat(&lfs, "dummy", &info) => 0; |
| assert(strcmp(info.name, "dummy") == 0); |
| assert(info.type == LFS_TYPE_REG); |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| # expanding superblock with power cycle |
| [cases.test_superblocks_expand_power_cycle] |
| defines.BLOCK_CYCLES = [32, 33, 1] |
| defines.N = [10, 100, 1000] |
| code = ''' |
| lfs_t lfs; |
| lfs_format(&lfs, cfg) => 0; |
| for (int i = 0; i < N; i++) { |
| lfs_mount(&lfs, cfg) => 0; |
| // remove lingering dummy? |
| struct lfs_info info; |
| int err = lfs_stat(&lfs, "dummy", &info); |
| assert(err == 0 || (err == LFS_ERR_NOENT && i == 0)); |
| if (!err) { |
| assert(strcmp(info.name, "dummy") == 0); |
| assert(info.type == LFS_TYPE_REG); |
| lfs_remove(&lfs, "dummy") => 0; |
| } |
| |
| lfs_file_t file; |
| lfs_file_open(&lfs, &file, "dummy", |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_stat(&lfs, "dummy", &info) => 0; |
| assert(strcmp(info.name, "dummy") == 0); |
| assert(info.type == LFS_TYPE_REG); |
| lfs_unmount(&lfs) => 0; |
| } |
| |
| // one last check after power-cycle |
| lfs_mount(&lfs, cfg) => 0; |
| struct lfs_info info; |
| lfs_stat(&lfs, "dummy", &info) => 0; |
| assert(strcmp(info.name, "dummy") == 0); |
| assert(info.type == LFS_TYPE_REG); |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| # reentrant expanding superblock |
| [cases.test_superblocks_reentrant_expand] |
| defines.BLOCK_CYCLES = [2, 1] |
| defines.N = 24 |
| reentrant = true |
| code = ''' |
| lfs_t lfs; |
| int err = lfs_mount(&lfs, cfg); |
| if (err) { |
| lfs_format(&lfs, cfg) => 0; |
| lfs_mount(&lfs, cfg) => 0; |
| } |
| |
| for (int i = 0; i < N; i++) { |
| // remove lingering dummy? |
| struct lfs_info info; |
| err = lfs_stat(&lfs, "dummy", &info); |
| assert(err == 0 || (err == LFS_ERR_NOENT && i == 0)); |
| if (!err) { |
| assert(strcmp(info.name, "dummy") == 0); |
| assert(info.type == LFS_TYPE_REG); |
| lfs_remove(&lfs, "dummy") => 0; |
| } |
| |
| lfs_file_t file; |
| lfs_file_open(&lfs, &file, "dummy", |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_stat(&lfs, "dummy", &info) => 0; |
| assert(strcmp(info.name, "dummy") == 0); |
| assert(info.type == LFS_TYPE_REG); |
| } |
| |
| lfs_unmount(&lfs) => 0; |
| |
| // one last check after power-cycle |
| lfs_mount(&lfs, cfg) => 0; |
| struct lfs_info info; |
| lfs_stat(&lfs, "dummy", &info) => 0; |
| assert(strcmp(info.name, "dummy") == 0); |
| assert(info.type == LFS_TYPE_REG); |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| # mount with unknown block_size/block_count |
| [cases.test_superblocks_unknowns] |
| code = ''' |
| lfs_t lfs; |
| lfs_format(&lfs, cfg) => 0; |
| |
| // known block_size/block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = BLOCK_COUNT; |
| lfs_mount(&lfs, cfg) => 0; |
| struct lfs_fsinfo fsinfo; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_size |
| cfg->block_size = 0; |
| cfg->block_count = ERASE_COUNT; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_count/block_size |
| cfg->block_size = 0; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // do some work |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_file_t file; |
| lfs_file_open(&lfs, &file, "test", |
| LFS_O_CREAT | LFS_O_EXCL | LFS_O_WRONLY) => 0; |
| lfs_file_write(&lfs, &file, "hello!", 6) => 6; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0; |
| uint8_t buffer[256]; |
| lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => 6; |
| lfs_file_close(&lfs, &file) => 0; |
| assert(memcmp(buffer, "hello!", 6) == 0); |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| # mount with blocks larger than the erase_size |
| [cases.test_superblocks_larger_blocks] |
| defines.BLOCK_SIZE = [ |
| '2*ERASE_SIZE', |
| '4*ERASE_SIZE', |
| '(ERASE_COUNT/2)*ERASE_SIZE'] |
| code = ''' |
| lfs_t lfs; |
| lfs_format(&lfs, cfg) => 0; |
| |
| // known block_size/block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = BLOCK_COUNT; |
| lfs_mount(&lfs, cfg) => 0; |
| struct lfs_fsinfo fsinfo; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // incorrect block_size |
| cfg->block_size = ERASE_SIZE; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| |
| // unknown block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_size |
| cfg->block_size = 0; |
| cfg->block_count = ERASE_COUNT; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_count/block_size |
| cfg->block_size = 0; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // do some work |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_file_t file; |
| lfs_file_open(&lfs, &file, "test", |
| LFS_O_CREAT | LFS_O_EXCL | LFS_O_WRONLY) => 0; |
| lfs_file_write(&lfs, &file, "hello!", 6) => 6; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0; |
| uint8_t buffer[256]; |
| lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => 6; |
| lfs_file_close(&lfs, &file) => 0; |
| assert(memcmp(buffer, "hello!", 6) == 0); |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| # mount with blocks smaller than the erase_size |
| [cases.test_superblocks_smaller_blocks] |
| defines.FORMAT_BLOCK_SIZE = 'ERASE_SIZE/2' |
| defines.FORMAT_BLOCK_COUNT = 'BLOCK_COUNT * (BLOCK_SIZE/FORMAT_BLOCK_SIZE)' |
| in = 'lfs.c' |
| code = ''' |
| lfs_t lfs; |
| lfs_init(&lfs, cfg) => 0; |
| lfs.block_size = BLOCK_SIZE; |
| lfs.block_count = BLOCK_COUNT; |
| |
| lfs_mdir_t root = { |
| .pair = {0, 0}, // make sure this goes into block 0 |
| .rev = 0, |
| .off = sizeof(uint32_t), |
| .etag = 0xffffffff, |
| .count = 0, |
| .tail = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}, |
| .erased = false, |
| .split = false, |
| }; |
| |
| lfs_superblock_t superblock = { |
| .version = LFS_DISK_VERSION, |
| .block_size = FORMAT_BLOCK_SIZE, |
| .block_count = FORMAT_BLOCK_COUNT, |
| .name_max = LFS_NAME_MAX, |
| .file_max = LFS_FILE_MAX, |
| .attr_max = LFS_ATTR_MAX, |
| }; |
| |
| lfs_superblock_tole32(&superblock); |
| lfs_dir_commit(&lfs, &root, LFS_MKATTRS( |
| {LFS_MKTAG(LFS_TYPE_CREATE, 0, 0), NULL}, |
| {LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8), "littlefs"}, |
| {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)), |
| &superblock})) => 0; |
| lfs_deinit(&lfs) => 0; |
| |
| // known block_size/block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = BLOCK_COUNT; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| |
| // unknown block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| |
| // unknown block_size |
| cfg->block_size = 0; |
| cfg->block_count = ERASE_COUNT; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| |
| // unknown block_count/block_size |
| cfg->block_size = 0; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| ''' |
| |
| # mount with blocks fewer than the erase_count |
| [cases.test_superblocks_fewer_blocks] |
| defines.BLOCK_COUNT = ['ERASE_COUNT/2', 'ERASE_COUNT/4', '2'] |
| code = ''' |
| lfs_t lfs; |
| lfs_format(&lfs, cfg) => 0; |
| |
| // known block_size/block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = BLOCK_COUNT; |
| lfs_mount(&lfs, cfg) => 0; |
| struct lfs_fsinfo fsinfo; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // incorrect block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = ERASE_COUNT; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| |
| // unknown block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_size |
| cfg->block_size = 0; |
| cfg->block_count = BLOCK_COUNT; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_count/block_size |
| cfg->block_size = 0; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // do some work |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_file_t file; |
| lfs_file_open(&lfs, &file, "test", |
| LFS_O_CREAT | LFS_O_EXCL | LFS_O_WRONLY) => 0; |
| lfs_file_write(&lfs, &file, "hello!", 6) => 6; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0; |
| uint8_t buffer[256]; |
| lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => 6; |
| lfs_file_close(&lfs, &file) => 0; |
| assert(memcmp(buffer, "hello!", 6) == 0); |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| # mount with more blocks than the erase_count |
| [cases.test_superblocks_more_blocks] |
| defines.FORMAT_BLOCK_COUNT = '2*ERASE_COUNT' |
| in = 'lfs.c' |
| code = ''' |
| lfs_t lfs; |
| lfs_init(&lfs, cfg) => 0; |
| lfs.block_size = BLOCK_SIZE; |
| lfs.block_count = BLOCK_COUNT; |
| |
| lfs_mdir_t root = { |
| .pair = {0, 0}, // make sure this goes into block 0 |
| .rev = 0, |
| .off = sizeof(uint32_t), |
| .etag = 0xffffffff, |
| .count = 0, |
| .tail = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}, |
| .erased = false, |
| .split = false, |
| }; |
| |
| lfs_superblock_t superblock = { |
| .version = LFS_DISK_VERSION, |
| .block_size = BLOCK_SIZE, |
| .block_count = FORMAT_BLOCK_COUNT, |
| .name_max = LFS_NAME_MAX, |
| .file_max = LFS_FILE_MAX, |
| .attr_max = LFS_ATTR_MAX, |
| }; |
| |
| lfs_superblock_tole32(&superblock); |
| lfs_dir_commit(&lfs, &root, LFS_MKATTRS( |
| {LFS_MKTAG(LFS_TYPE_CREATE, 0, 0), NULL}, |
| {LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8), "littlefs"}, |
| {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)), |
| &superblock})) => 0; |
| lfs_deinit(&lfs) => 0; |
| |
| // known block_size/block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = BLOCK_COUNT; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| |
| // unknown block_size |
| cfg->block_size = 0; |
| cfg->block_count = ERASE_COUNT; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| ''' |
| |
| # the real challenge is finding superblock 1 when block_size is unknown, |
| # test for this explicitly |
| [cases.test_superblocks_unknown_superblock1] |
| in = 'lfs.c' |
| defines.BLOCK_SIZE = [ |
| 'ERASE_SIZE', |
| '2*ERASE_SIZE', |
| '4*ERASE_SIZE', |
| '(ERASE_COUNT/2)*ERASE_SIZE'] |
| code = ''' |
| lfs_t lfs; |
| lfs_init(&lfs, cfg) => 0; |
| lfs.block_size = BLOCK_SIZE; |
| lfs.block_count = BLOCK_COUNT; |
| |
| uint8_t buffer[lfs_max(READ_SIZE, sizeof(uint32_t))]; |
| memset(buffer, 0, lfs_max(READ_SIZE, sizeof(uint32_t))); |
| cfg->read(cfg, 0, 0, buffer, lfs_max(READ_SIZE, sizeof(uint32_t))) => 0; |
| uint32_t rev; |
| memcpy(&rev, buffer, sizeof(uint32_t)); |
| rev = lfs_fromle32(rev); |
| |
| lfs_mdir_t root = { |
| .pair = {1, 1}, // make sure this goes into block 1 |
| .rev = rev, |
| .off = sizeof(uint32_t), |
| .etag = 0xffffffff, |
| .count = 0, |
| .tail = {LFS_BLOCK_NULL, LFS_BLOCK_NULL}, |
| .erased = false, |
| .split = false, |
| }; |
| |
| lfs_superblock_t superblock = { |
| .version = LFS_DISK_VERSION, |
| .block_size = BLOCK_SIZE, |
| .block_count = BLOCK_COUNT, |
| .name_max = LFS_NAME_MAX, |
| .file_max = LFS_FILE_MAX, |
| .attr_max = LFS_ATTR_MAX, |
| }; |
| |
| lfs_superblock_tole32(&superblock); |
| lfs_dir_commit(&lfs, &root, LFS_MKATTRS( |
| {LFS_MKTAG(LFS_TYPE_CREATE, 0, 0), NULL}, |
| {LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8), "littlefs"}, |
| {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)), |
| &superblock})) => 0; |
| lfs_deinit(&lfs) => 0; |
| |
| // known block_size/block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = BLOCK_COUNT; |
| lfs_mount(&lfs, cfg) => 0; |
| struct lfs_fsinfo fsinfo; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_count |
| cfg->block_size = BLOCK_SIZE; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_size |
| cfg->block_size = 0; |
| cfg->block_count = ERASE_COUNT; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // unknown block_count/block_size |
| cfg->block_size = 0; |
| cfg->block_count = 0; |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| # mount and grow the filesystem |
| [cases.test_superblocks_grow] |
| defines.BLOCK_COUNT = ['ERASE_COUNT/2', 'ERASE_COUNT/4', '2'] |
| defines.BLOCK_COUNT_2 = 'ERASE_COUNT' |
| defines.KNOWN_BLOCK_COUNT = [true, false] |
| code = ''' |
| lfs_t lfs; |
| lfs_format(&lfs, cfg) => 0; |
| |
| if (KNOWN_BLOCK_COUNT) { |
| cfg->block_count = BLOCK_COUNT; |
| } else { |
| cfg->block_count = 0; |
| } |
| |
| // mount with block_size < erase_size |
| lfs_mount(&lfs, cfg) => 0; |
| struct lfs_fsinfo fsinfo; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // same size is a noop |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_grow(&lfs, BLOCK_COUNT) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT); |
| lfs_unmount(&lfs) => 0; |
| |
| // grow to new size |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_grow(&lfs, BLOCK_COUNT_2) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT_2); |
| lfs_unmount(&lfs) => 0; |
| |
| if (KNOWN_BLOCK_COUNT) { |
| cfg->block_count = BLOCK_COUNT_2; |
| } else { |
| cfg->block_count = 0; |
| } |
| |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT_2); |
| lfs_unmount(&lfs) => 0; |
| |
| // mounting with the previous size should fail |
| cfg->block_count = BLOCK_COUNT; |
| lfs_mount(&lfs, cfg) => LFS_ERR_INVAL; |
| |
| if (KNOWN_BLOCK_COUNT) { |
| cfg->block_count = BLOCK_COUNT_2; |
| } else { |
| cfg->block_count = 0; |
| } |
| |
| // same size is a noop |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_grow(&lfs, BLOCK_COUNT_2) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT_2); |
| lfs_unmount(&lfs) => 0; |
| |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT_2); |
| lfs_unmount(&lfs) => 0; |
| |
| // do some work |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT_2); |
| lfs_file_t file; |
| lfs_file_open(&lfs, &file, "test", |
| LFS_O_CREAT | LFS_O_EXCL | LFS_O_WRONLY) => 0; |
| lfs_file_write(&lfs, &file, "hello!", 6) => 6; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| lfs_mount(&lfs, cfg) => 0; |
| lfs_fs_stat(&lfs, &fsinfo) => 0; |
| assert(fsinfo.block_size == BLOCK_SIZE); |
| assert(fsinfo.block_count == BLOCK_COUNT_2); |
| lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0; |
| uint8_t buffer[256]; |
| lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => 6; |
| lfs_file_close(&lfs, &file) => 0; |
| assert(memcmp(buffer, "hello!", 6) == 0); |
| lfs_unmount(&lfs) => 0; |
| ''' |