119ea8026Sopenharmony_ci# simple formatting test
219ea8026Sopenharmony_ci[cases.test_superblocks_format]
319ea8026Sopenharmony_cicode = '''
419ea8026Sopenharmony_ci    lfs_t lfs;
519ea8026Sopenharmony_ci    lfs_format(&lfs, cfg) => 0;
619ea8026Sopenharmony_ci'''
719ea8026Sopenharmony_ci
819ea8026Sopenharmony_ci# mount/unmount
919ea8026Sopenharmony_ci[cases.test_superblocks_mount]
1019ea8026Sopenharmony_cicode = '''
1119ea8026Sopenharmony_ci    lfs_t lfs;
1219ea8026Sopenharmony_ci    lfs_format(&lfs, cfg) => 0;
1319ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
1419ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
1519ea8026Sopenharmony_ci'''
1619ea8026Sopenharmony_ci
1719ea8026Sopenharmony_ci# mount/unmount from interpretting a previous superblock block_count
1819ea8026Sopenharmony_ci[cases.test_superblocks_mount_unknown_block_count]
1919ea8026Sopenharmony_cicode = '''
2019ea8026Sopenharmony_ci    lfs_t lfs;
2119ea8026Sopenharmony_ci    lfs_format(&lfs, cfg) => 0;
2219ea8026Sopenharmony_ci
2319ea8026Sopenharmony_ci    memset(&lfs, 0, sizeof(lfs));
2419ea8026Sopenharmony_ci    struct lfs_config tweaked_cfg = *cfg;
2519ea8026Sopenharmony_ci    tweaked_cfg.block_count = 0;
2619ea8026Sopenharmony_ci    lfs_mount(&lfs, &tweaked_cfg) => 0;
2719ea8026Sopenharmony_ci    assert(lfs.block_count == cfg->block_count);
2819ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
2919ea8026Sopenharmony_ci'''
3019ea8026Sopenharmony_ci
3119ea8026Sopenharmony_ci
3219ea8026Sopenharmony_ci# reentrant format
3319ea8026Sopenharmony_ci[cases.test_superblocks_reentrant_format]
3419ea8026Sopenharmony_cireentrant = true
3519ea8026Sopenharmony_cicode = '''
3619ea8026Sopenharmony_ci    lfs_t lfs;
3719ea8026Sopenharmony_ci    int err = lfs_mount(&lfs, cfg);
3819ea8026Sopenharmony_ci    if (err) {
3919ea8026Sopenharmony_ci        lfs_format(&lfs, cfg) => 0;
4019ea8026Sopenharmony_ci        lfs_mount(&lfs, cfg) => 0;
4119ea8026Sopenharmony_ci    }
4219ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
4319ea8026Sopenharmony_ci'''
4419ea8026Sopenharmony_ci
4519ea8026Sopenharmony_ci# invalid mount
4619ea8026Sopenharmony_ci[cases.test_superblocks_invalid_mount]
4719ea8026Sopenharmony_cicode = '''
4819ea8026Sopenharmony_ci    lfs_t lfs;
4919ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => LFS_ERR_CORRUPT;
5019ea8026Sopenharmony_ci'''
5119ea8026Sopenharmony_ci
5219ea8026Sopenharmony_ci# test we can read superblock info through lfs_fs_stat
5319ea8026Sopenharmony_ci[cases.test_superblocks_stat]
5419ea8026Sopenharmony_ciif = 'DISK_VERSION == 0'
5519ea8026Sopenharmony_cicode = '''
5619ea8026Sopenharmony_ci    lfs_t lfs;
5719ea8026Sopenharmony_ci    lfs_format(&lfs, cfg) => 0;
5819ea8026Sopenharmony_ci
5919ea8026Sopenharmony_ci    // test we can mount and read fsinfo
6019ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
6119ea8026Sopenharmony_ci
6219ea8026Sopenharmony_ci    struct lfs_fsinfo fsinfo;
6319ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
6419ea8026Sopenharmony_ci    assert(fsinfo.disk_version == LFS_DISK_VERSION);
6519ea8026Sopenharmony_ci    assert(fsinfo.name_max == LFS_NAME_MAX);
6619ea8026Sopenharmony_ci    assert(fsinfo.file_max == LFS_FILE_MAX);
6719ea8026Sopenharmony_ci    assert(fsinfo.attr_max == LFS_ATTR_MAX);
6819ea8026Sopenharmony_ci
6919ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
7019ea8026Sopenharmony_ci'''
7119ea8026Sopenharmony_ci
7219ea8026Sopenharmony_ci[cases.test_superblocks_stat_tweaked]
7319ea8026Sopenharmony_ciif = 'DISK_VERSION == 0'
7419ea8026Sopenharmony_cidefines.TWEAKED_NAME_MAX = 63
7519ea8026Sopenharmony_cidefines.TWEAKED_FILE_MAX = '(1 << 16)-1'
7619ea8026Sopenharmony_cidefines.TWEAKED_ATTR_MAX = 512
7719ea8026Sopenharmony_cicode = '''
7819ea8026Sopenharmony_ci    // create filesystem with tweaked params
7919ea8026Sopenharmony_ci    struct lfs_config tweaked_cfg = *cfg;
8019ea8026Sopenharmony_ci    tweaked_cfg.name_max = TWEAKED_NAME_MAX;
8119ea8026Sopenharmony_ci    tweaked_cfg.file_max = TWEAKED_FILE_MAX;
8219ea8026Sopenharmony_ci    tweaked_cfg.attr_max = TWEAKED_ATTR_MAX;
8319ea8026Sopenharmony_ci
8419ea8026Sopenharmony_ci    lfs_t lfs;
8519ea8026Sopenharmony_ci    lfs_format(&lfs, &tweaked_cfg) => 0;
8619ea8026Sopenharmony_ci
8719ea8026Sopenharmony_ci    // test we can mount and read these params with the original config
8819ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
8919ea8026Sopenharmony_ci
9019ea8026Sopenharmony_ci    struct lfs_fsinfo fsinfo;
9119ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
9219ea8026Sopenharmony_ci    assert(fsinfo.disk_version == LFS_DISK_VERSION);
9319ea8026Sopenharmony_ci    assert(fsinfo.name_max == TWEAKED_NAME_MAX);
9419ea8026Sopenharmony_ci    assert(fsinfo.file_max == TWEAKED_FILE_MAX);
9519ea8026Sopenharmony_ci    assert(fsinfo.attr_max == TWEAKED_ATTR_MAX);
9619ea8026Sopenharmony_ci
9719ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
9819ea8026Sopenharmony_ci'''
9919ea8026Sopenharmony_ci
10019ea8026Sopenharmony_ci# expanding superblock
10119ea8026Sopenharmony_ci[cases.test_superblocks_expand]
10219ea8026Sopenharmony_cidefines.BLOCK_CYCLES = [32, 33, 1]
10319ea8026Sopenharmony_cidefines.N = [10, 100, 1000]
10419ea8026Sopenharmony_cicode = '''
10519ea8026Sopenharmony_ci    lfs_t lfs;
10619ea8026Sopenharmony_ci    lfs_format(&lfs, cfg) => 0;
10719ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
10819ea8026Sopenharmony_ci    for (int i = 0; i < N; i++) {
10919ea8026Sopenharmony_ci        lfs_file_t file;
11019ea8026Sopenharmony_ci        lfs_file_open(&lfs, &file, "dummy",
11119ea8026Sopenharmony_ci                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
11219ea8026Sopenharmony_ci        lfs_file_close(&lfs, &file) => 0;
11319ea8026Sopenharmony_ci        struct lfs_info info;
11419ea8026Sopenharmony_ci        lfs_stat(&lfs, "dummy", &info) => 0;
11519ea8026Sopenharmony_ci        assert(strcmp(info.name, "dummy") == 0);
11619ea8026Sopenharmony_ci        assert(info.type == LFS_TYPE_REG);
11719ea8026Sopenharmony_ci        lfs_remove(&lfs, "dummy") => 0;
11819ea8026Sopenharmony_ci    }
11919ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
12019ea8026Sopenharmony_ci
12119ea8026Sopenharmony_ci    // one last check after power-cycle
12219ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
12319ea8026Sopenharmony_ci    lfs_file_t file;
12419ea8026Sopenharmony_ci    lfs_file_open(&lfs, &file, "dummy",
12519ea8026Sopenharmony_ci            LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
12619ea8026Sopenharmony_ci    lfs_file_close(&lfs, &file) => 0;
12719ea8026Sopenharmony_ci    struct lfs_info info;
12819ea8026Sopenharmony_ci    lfs_stat(&lfs, "dummy", &info) => 0;
12919ea8026Sopenharmony_ci    assert(strcmp(info.name, "dummy") == 0);
13019ea8026Sopenharmony_ci    assert(info.type == LFS_TYPE_REG);
13119ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
13219ea8026Sopenharmony_ci'''
13319ea8026Sopenharmony_ci
13419ea8026Sopenharmony_ci# expanding superblock with power cycle
13519ea8026Sopenharmony_ci[cases.test_superblocks_expand_power_cycle]
13619ea8026Sopenharmony_cidefines.BLOCK_CYCLES = [32, 33, 1]
13719ea8026Sopenharmony_cidefines.N = [10, 100, 1000]
13819ea8026Sopenharmony_cicode = '''
13919ea8026Sopenharmony_ci    lfs_t lfs;
14019ea8026Sopenharmony_ci    lfs_format(&lfs, cfg) => 0;
14119ea8026Sopenharmony_ci    for (int i = 0; i < N; i++) {
14219ea8026Sopenharmony_ci        lfs_mount(&lfs, cfg) => 0;
14319ea8026Sopenharmony_ci        // remove lingering dummy?
14419ea8026Sopenharmony_ci        struct lfs_info info;
14519ea8026Sopenharmony_ci        int err = lfs_stat(&lfs, "dummy", &info);
14619ea8026Sopenharmony_ci        assert(err == 0 || (err == LFS_ERR_NOENT && i == 0));
14719ea8026Sopenharmony_ci        if (!err) {
14819ea8026Sopenharmony_ci            assert(strcmp(info.name, "dummy") == 0);
14919ea8026Sopenharmony_ci            assert(info.type == LFS_TYPE_REG);
15019ea8026Sopenharmony_ci            lfs_remove(&lfs, "dummy") => 0;
15119ea8026Sopenharmony_ci        }
15219ea8026Sopenharmony_ci
15319ea8026Sopenharmony_ci        lfs_file_t file;
15419ea8026Sopenharmony_ci        lfs_file_open(&lfs, &file, "dummy",
15519ea8026Sopenharmony_ci                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
15619ea8026Sopenharmony_ci        lfs_file_close(&lfs, &file) => 0;
15719ea8026Sopenharmony_ci        lfs_stat(&lfs, "dummy", &info) => 0;
15819ea8026Sopenharmony_ci        assert(strcmp(info.name, "dummy") == 0);
15919ea8026Sopenharmony_ci        assert(info.type == LFS_TYPE_REG);
16019ea8026Sopenharmony_ci        lfs_unmount(&lfs) => 0;
16119ea8026Sopenharmony_ci    }
16219ea8026Sopenharmony_ci
16319ea8026Sopenharmony_ci    // one last check after power-cycle
16419ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
16519ea8026Sopenharmony_ci    struct lfs_info info;
16619ea8026Sopenharmony_ci    lfs_stat(&lfs, "dummy", &info) => 0;
16719ea8026Sopenharmony_ci    assert(strcmp(info.name, "dummy") == 0);
16819ea8026Sopenharmony_ci    assert(info.type == LFS_TYPE_REG);
16919ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
17019ea8026Sopenharmony_ci'''
17119ea8026Sopenharmony_ci
17219ea8026Sopenharmony_ci# reentrant expanding superblock
17319ea8026Sopenharmony_ci[cases.test_superblocks_reentrant_expand]
17419ea8026Sopenharmony_cidefines.BLOCK_CYCLES = [2, 1]
17519ea8026Sopenharmony_cidefines.N = 24
17619ea8026Sopenharmony_cireentrant = true
17719ea8026Sopenharmony_cicode = '''
17819ea8026Sopenharmony_ci    lfs_t lfs;
17919ea8026Sopenharmony_ci    int err = lfs_mount(&lfs, cfg);
18019ea8026Sopenharmony_ci    if (err) {
18119ea8026Sopenharmony_ci        lfs_format(&lfs, cfg) => 0;
18219ea8026Sopenharmony_ci        lfs_mount(&lfs, cfg) => 0;
18319ea8026Sopenharmony_ci    }
18419ea8026Sopenharmony_ci
18519ea8026Sopenharmony_ci    for (int i = 0; i < N; i++) {
18619ea8026Sopenharmony_ci        // remove lingering dummy?
18719ea8026Sopenharmony_ci        struct lfs_info info;
18819ea8026Sopenharmony_ci        err = lfs_stat(&lfs, "dummy", &info);
18919ea8026Sopenharmony_ci        assert(err == 0 || (err == LFS_ERR_NOENT && i == 0));
19019ea8026Sopenharmony_ci        if (!err) {
19119ea8026Sopenharmony_ci            assert(strcmp(info.name, "dummy") == 0);
19219ea8026Sopenharmony_ci            assert(info.type == LFS_TYPE_REG);
19319ea8026Sopenharmony_ci            lfs_remove(&lfs, "dummy") => 0;
19419ea8026Sopenharmony_ci        }
19519ea8026Sopenharmony_ci
19619ea8026Sopenharmony_ci        lfs_file_t file;
19719ea8026Sopenharmony_ci        lfs_file_open(&lfs, &file, "dummy",
19819ea8026Sopenharmony_ci                LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
19919ea8026Sopenharmony_ci        lfs_file_close(&lfs, &file) => 0;
20019ea8026Sopenharmony_ci        lfs_stat(&lfs, "dummy", &info) => 0;
20119ea8026Sopenharmony_ci        assert(strcmp(info.name, "dummy") == 0);
20219ea8026Sopenharmony_ci        assert(info.type == LFS_TYPE_REG);
20319ea8026Sopenharmony_ci    }
20419ea8026Sopenharmony_ci
20519ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
20619ea8026Sopenharmony_ci
20719ea8026Sopenharmony_ci    // one last check after power-cycle
20819ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
20919ea8026Sopenharmony_ci    struct lfs_info info;
21019ea8026Sopenharmony_ci    lfs_stat(&lfs, "dummy", &info) => 0;
21119ea8026Sopenharmony_ci    assert(strcmp(info.name, "dummy") == 0);
21219ea8026Sopenharmony_ci    assert(info.type == LFS_TYPE_REG);
21319ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
21419ea8026Sopenharmony_ci'''
21519ea8026Sopenharmony_ci
21619ea8026Sopenharmony_ci# mount with unknown block_count
21719ea8026Sopenharmony_ci[cases.test_superblocks_unknown_blocks]
21819ea8026Sopenharmony_cicode = '''
21919ea8026Sopenharmony_ci    lfs_t lfs;
22019ea8026Sopenharmony_ci    lfs_format(&lfs, cfg) => 0;
22119ea8026Sopenharmony_ci
22219ea8026Sopenharmony_ci    // known block_size/block_count
22319ea8026Sopenharmony_ci    cfg->block_size = BLOCK_SIZE;
22419ea8026Sopenharmony_ci    cfg->block_count = BLOCK_COUNT;
22519ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
22619ea8026Sopenharmony_ci    struct lfs_fsinfo fsinfo;
22719ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
22819ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
22919ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
23019ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
23119ea8026Sopenharmony_ci
23219ea8026Sopenharmony_ci    // unknown block_count
23319ea8026Sopenharmony_ci    cfg->block_size = BLOCK_SIZE;
23419ea8026Sopenharmony_ci    cfg->block_count = 0;
23519ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
23619ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
23719ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
23819ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
23919ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
24019ea8026Sopenharmony_ci
24119ea8026Sopenharmony_ci    // do some work
24219ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
24319ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
24419ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
24519ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
24619ea8026Sopenharmony_ci    lfs_file_t file;
24719ea8026Sopenharmony_ci    lfs_file_open(&lfs, &file, "test",
24819ea8026Sopenharmony_ci            LFS_O_CREAT | LFS_O_EXCL | LFS_O_WRONLY) => 0;
24919ea8026Sopenharmony_ci    lfs_file_write(&lfs, &file, "hello!", 6) => 6;
25019ea8026Sopenharmony_ci    lfs_file_close(&lfs, &file) => 0;
25119ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
25219ea8026Sopenharmony_ci
25319ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
25419ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
25519ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
25619ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
25719ea8026Sopenharmony_ci    lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0;
25819ea8026Sopenharmony_ci    uint8_t buffer[256];
25919ea8026Sopenharmony_ci    lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => 6;
26019ea8026Sopenharmony_ci    lfs_file_close(&lfs, &file) => 0;
26119ea8026Sopenharmony_ci    assert(memcmp(buffer, "hello!", 6) == 0);
26219ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
26319ea8026Sopenharmony_ci'''
26419ea8026Sopenharmony_ci
26519ea8026Sopenharmony_ci# mount with blocks fewer than the erase_count
26619ea8026Sopenharmony_ci[cases.test_superblocks_fewer_blocks]
26719ea8026Sopenharmony_cidefines.BLOCK_COUNT = ['ERASE_COUNT/2', 'ERASE_COUNT/4', '2']
26819ea8026Sopenharmony_cicode = '''
26919ea8026Sopenharmony_ci    lfs_t lfs;
27019ea8026Sopenharmony_ci    lfs_format(&lfs, cfg) => 0;
27119ea8026Sopenharmony_ci
27219ea8026Sopenharmony_ci    // known block_size/block_count
27319ea8026Sopenharmony_ci    cfg->block_size = BLOCK_SIZE;
27419ea8026Sopenharmony_ci    cfg->block_count = BLOCK_COUNT;
27519ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
27619ea8026Sopenharmony_ci    struct lfs_fsinfo fsinfo;
27719ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
27819ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
27919ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
28019ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
28119ea8026Sopenharmony_ci
28219ea8026Sopenharmony_ci    // incorrect block_count
28319ea8026Sopenharmony_ci    cfg->block_size = BLOCK_SIZE;
28419ea8026Sopenharmony_ci    cfg->block_count = ERASE_COUNT;
28519ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => LFS_ERR_INVAL;
28619ea8026Sopenharmony_ci
28719ea8026Sopenharmony_ci    // unknown block_count
28819ea8026Sopenharmony_ci    cfg->block_size = BLOCK_SIZE;
28919ea8026Sopenharmony_ci    cfg->block_count = 0;
29019ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
29119ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
29219ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
29319ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
29419ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
29519ea8026Sopenharmony_ci
29619ea8026Sopenharmony_ci    // do some work
29719ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
29819ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
29919ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
30019ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
30119ea8026Sopenharmony_ci    lfs_file_t file;
30219ea8026Sopenharmony_ci    lfs_file_open(&lfs, &file, "test",
30319ea8026Sopenharmony_ci            LFS_O_CREAT | LFS_O_EXCL | LFS_O_WRONLY) => 0;
30419ea8026Sopenharmony_ci    lfs_file_write(&lfs, &file, "hello!", 6) => 6;
30519ea8026Sopenharmony_ci    lfs_file_close(&lfs, &file) => 0;
30619ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
30719ea8026Sopenharmony_ci
30819ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
30919ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
31019ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
31119ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
31219ea8026Sopenharmony_ci    lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0;
31319ea8026Sopenharmony_ci    uint8_t buffer[256];
31419ea8026Sopenharmony_ci    lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => 6;
31519ea8026Sopenharmony_ci    lfs_file_close(&lfs, &file) => 0;
31619ea8026Sopenharmony_ci    assert(memcmp(buffer, "hello!", 6) == 0);
31719ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
31819ea8026Sopenharmony_ci'''
31919ea8026Sopenharmony_ci
32019ea8026Sopenharmony_ci# mount with more blocks than the erase_count
32119ea8026Sopenharmony_ci[cases.test_superblocks_more_blocks]
32219ea8026Sopenharmony_cidefines.FORMAT_BLOCK_COUNT = '2*ERASE_COUNT'
32319ea8026Sopenharmony_ciin = 'lfs.c'
32419ea8026Sopenharmony_cicode = '''
32519ea8026Sopenharmony_ci    lfs_t lfs;
32619ea8026Sopenharmony_ci    lfs_init(&lfs, cfg) => 0;
32719ea8026Sopenharmony_ci    lfs.block_count = BLOCK_COUNT;
32819ea8026Sopenharmony_ci
32919ea8026Sopenharmony_ci    lfs_mdir_t root = {
33019ea8026Sopenharmony_ci        .pair = {0, 0}, // make sure this goes into block 0
33119ea8026Sopenharmony_ci        .rev = 0,
33219ea8026Sopenharmony_ci        .off = sizeof(uint32_t),
33319ea8026Sopenharmony_ci        .etag = 0xffffffff,
33419ea8026Sopenharmony_ci        .count = 0,
33519ea8026Sopenharmony_ci        .tail = {LFS_BLOCK_NULL, LFS_BLOCK_NULL},
33619ea8026Sopenharmony_ci        .erased = false,
33719ea8026Sopenharmony_ci        .split = false,
33819ea8026Sopenharmony_ci    };
33919ea8026Sopenharmony_ci
34019ea8026Sopenharmony_ci    lfs_superblock_t superblock = {
34119ea8026Sopenharmony_ci        .version     = LFS_DISK_VERSION,
34219ea8026Sopenharmony_ci        .block_size  = BLOCK_SIZE,
34319ea8026Sopenharmony_ci        .block_count = FORMAT_BLOCK_COUNT,
34419ea8026Sopenharmony_ci        .name_max    = LFS_NAME_MAX,
34519ea8026Sopenharmony_ci        .file_max    = LFS_FILE_MAX,
34619ea8026Sopenharmony_ci        .attr_max    = LFS_ATTR_MAX,
34719ea8026Sopenharmony_ci    };
34819ea8026Sopenharmony_ci
34919ea8026Sopenharmony_ci    lfs_superblock_tole32(&superblock);
35019ea8026Sopenharmony_ci    lfs_dir_commit(&lfs, &root, LFS_MKATTRS(
35119ea8026Sopenharmony_ci            {LFS_MKTAG(LFS_TYPE_CREATE, 0, 0), NULL},
35219ea8026Sopenharmony_ci            {LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, 8), "littlefs"},
35319ea8026Sopenharmony_ci            {LFS_MKTAG(LFS_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
35419ea8026Sopenharmony_ci                &superblock})) => 0;
35519ea8026Sopenharmony_ci    lfs_deinit(&lfs) => 0;
35619ea8026Sopenharmony_ci
35719ea8026Sopenharmony_ci    // known block_size/block_count
35819ea8026Sopenharmony_ci    cfg->block_size = BLOCK_SIZE;
35919ea8026Sopenharmony_ci    cfg->block_count = BLOCK_COUNT;
36019ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => LFS_ERR_INVAL;
36119ea8026Sopenharmony_ci'''
36219ea8026Sopenharmony_ci
36319ea8026Sopenharmony_ci# mount and grow the filesystem
36419ea8026Sopenharmony_ci[cases.test_superblocks_grow]
36519ea8026Sopenharmony_cidefines.BLOCK_COUNT = ['ERASE_COUNT/2', 'ERASE_COUNT/4', '2']
36619ea8026Sopenharmony_cidefines.BLOCK_COUNT_2 = 'ERASE_COUNT'
36719ea8026Sopenharmony_cidefines.KNOWN_BLOCK_COUNT = [true, false]
36819ea8026Sopenharmony_cicode = '''
36919ea8026Sopenharmony_ci    lfs_t lfs;
37019ea8026Sopenharmony_ci    lfs_format(&lfs, cfg) => 0;
37119ea8026Sopenharmony_ci
37219ea8026Sopenharmony_ci    if (KNOWN_BLOCK_COUNT) {
37319ea8026Sopenharmony_ci        cfg->block_count = BLOCK_COUNT;
37419ea8026Sopenharmony_ci    } else {
37519ea8026Sopenharmony_ci        cfg->block_count = 0;
37619ea8026Sopenharmony_ci    }
37719ea8026Sopenharmony_ci
37819ea8026Sopenharmony_ci    // mount with block_size < erase_size
37919ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
38019ea8026Sopenharmony_ci    struct lfs_fsinfo fsinfo;
38119ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
38219ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
38319ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
38419ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
38519ea8026Sopenharmony_ci
38619ea8026Sopenharmony_ci    // same size is a noop
38719ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
38819ea8026Sopenharmony_ci    lfs_fs_grow(&lfs, BLOCK_COUNT) => 0;
38919ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
39019ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
39119ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
39219ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
39319ea8026Sopenharmony_ci
39419ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
39519ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
39619ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
39719ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT);
39819ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
39919ea8026Sopenharmony_ci
40019ea8026Sopenharmony_ci    // grow to new size
40119ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
40219ea8026Sopenharmony_ci    lfs_fs_grow(&lfs, BLOCK_COUNT_2) => 0;
40319ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
40419ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
40519ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT_2);
40619ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
40719ea8026Sopenharmony_ci
40819ea8026Sopenharmony_ci    if (KNOWN_BLOCK_COUNT) {
40919ea8026Sopenharmony_ci        cfg->block_count = BLOCK_COUNT_2;
41019ea8026Sopenharmony_ci    } else {
41119ea8026Sopenharmony_ci        cfg->block_count = 0;
41219ea8026Sopenharmony_ci    }
41319ea8026Sopenharmony_ci
41419ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
41519ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
41619ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
41719ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT_2);
41819ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
41919ea8026Sopenharmony_ci
42019ea8026Sopenharmony_ci    // mounting with the previous size should fail
42119ea8026Sopenharmony_ci    cfg->block_count = BLOCK_COUNT;
42219ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => LFS_ERR_INVAL;
42319ea8026Sopenharmony_ci
42419ea8026Sopenharmony_ci    if (KNOWN_BLOCK_COUNT) {
42519ea8026Sopenharmony_ci        cfg->block_count = BLOCK_COUNT_2;
42619ea8026Sopenharmony_ci    } else {
42719ea8026Sopenharmony_ci        cfg->block_count = 0;
42819ea8026Sopenharmony_ci    }
42919ea8026Sopenharmony_ci
43019ea8026Sopenharmony_ci    // same size is a noop
43119ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
43219ea8026Sopenharmony_ci    lfs_fs_grow(&lfs, BLOCK_COUNT_2) => 0;
43319ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
43419ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
43519ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT_2);
43619ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
43719ea8026Sopenharmony_ci
43819ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
43919ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
44019ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
44119ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT_2);
44219ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
44319ea8026Sopenharmony_ci
44419ea8026Sopenharmony_ci    // do some work
44519ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
44619ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
44719ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
44819ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT_2);
44919ea8026Sopenharmony_ci    lfs_file_t file;
45019ea8026Sopenharmony_ci    lfs_file_open(&lfs, &file, "test",
45119ea8026Sopenharmony_ci            LFS_O_CREAT | LFS_O_EXCL | LFS_O_WRONLY) => 0;
45219ea8026Sopenharmony_ci    lfs_file_write(&lfs, &file, "hello!", 6) => 6;
45319ea8026Sopenharmony_ci    lfs_file_close(&lfs, &file) => 0;
45419ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
45519ea8026Sopenharmony_ci
45619ea8026Sopenharmony_ci    lfs_mount(&lfs, cfg) => 0;
45719ea8026Sopenharmony_ci    lfs_fs_stat(&lfs, &fsinfo) => 0;
45819ea8026Sopenharmony_ci    assert(fsinfo.block_size == BLOCK_SIZE);
45919ea8026Sopenharmony_ci    assert(fsinfo.block_count == BLOCK_COUNT_2);
46019ea8026Sopenharmony_ci    lfs_file_open(&lfs, &file, "test", LFS_O_RDONLY) => 0;
46119ea8026Sopenharmony_ci    uint8_t buffer[256];
46219ea8026Sopenharmony_ci    lfs_file_read(&lfs, &file, buffer, sizeof(buffer)) => 6;
46319ea8026Sopenharmony_ci    lfs_file_close(&lfs, &file) => 0;
46419ea8026Sopenharmony_ci    assert(memcmp(buffer, "hello!", 6) == 0);
46519ea8026Sopenharmony_ci    lfs_unmount(&lfs) => 0;
46619ea8026Sopenharmony_ci'''
467