# Test this inner rbyd data-structure # test with a number of different erase values defines.ERASE_VALUE = [0xff, 0x00, 0x1b, -1] [cases.test_rbyd_fetch] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; // try an empty commit rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; // commit with one attribute rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; // commit with two attributes rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; ''' [cases.test_rbyd_multi_fetch] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; // try an empty commit rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; // commit with one attribute rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; // commit with two attributes rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; ''' # [cases.test_rbyd_fetchmatch] # [cases.test_rbyd_multi_fetchmatch] [cases.test_rbyd_lookup] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // try an empty commit rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; // TODO test in-between lookups for consistently finding the next >= tag? lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_ERR_NOENT; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_ERR_NOENT; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_ERR_NOENT; // commit with one attribute rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_ERR_NOENT; // commit with two attributes rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_ERR_NOENT; ''' [cases.test_rbyd_multi_lookup] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // try an empty commit rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_ERR_NOENT; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; // TODO move these extra checks (for 0, in-between, enoent) to other tests lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_ERR_NOENT; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_ERR_NOENT; // commit with one attribute rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_ERR_NOENT; // commit with two attributes rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_ERR_NOENT; ''' [cases.test_rbyd_traverse] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; lfs_srtag_t tag; // traverse requires correct biasing of the weights in the rbyd tree // so that lookups return strictly the tag greater than or equal to // the tag requested rbyd = rbyd_init; rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))) => 0; tag = lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size); assert(tag == LFS_MKRTAG(UATTR, 1, 0)); tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size); assert(tag == LFS_MKRTAG(UATTR, 2, 0)); tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size); assert(tag == LFS_ERR_NOENT); lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; tag = lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size); assert(tag == LFS_MKRTAG(UATTR, 1, 0)); tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size); assert(tag == LFS_MKRTAG(UATTR, 2, 0)); tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size); assert(tag == LFS_ERR_NOENT); ''' [cases.test_rbyd_multi_traverse] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; lfs_srtag_t tag; // traverse requires correct biasing of the weights in the rbyd tree // so that lookups return strictly the tag greater than or equal to // the tag requested rbyd = rbyd_init; rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)) => 0; tag = lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size); assert(tag == LFS_MKRTAG(UATTR, 1, 0)); tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size); assert(tag == LFS_MKRTAG(UATTR, 2, 0)); tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size); assert(tag == LFS_ERR_NOENT); lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; tag = lfs_rbyd_lookup(&lfs, &rbyd, 0, &off, &size); assert(tag == LFS_MKRTAG(UATTR, 1, 0)); tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size); assert(tag == LFS_MKRTAG(UATTR, 2, 0)); tag = lfs_rbyd_lookup(&lfs, &rbyd, lfs_rtag_inc(tag), &off, &size); assert(tag == LFS_ERR_NOENT); ''' [cases.test_rbyd_bifoliate] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // create a split in the leaves // .-'| // 1 1 2 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); // split the other direction // >b // => .-'| // 2 2 1 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); ''' [cases.test_rbyd_bflips] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // ignore a black edge // .----'| // 1 2 1 2 2 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); // flip a black edge // b // .-'| => .-'| // 1 2 1 2 1 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); ''' [cases.test_rbyd_trifoliate] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // ignore a black edge // | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, NULL)))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); // flip a black edge // >r // .-'| // | >b // .-'| .--|-'| // 2 3 2 3 1 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); ''' [cases.test_rbyd_rflips] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // ignore a red edge and black edge // | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); // ignore a red edge, flip a black edge // | >b // | .-'| | .-'| // 1 2 3 1 2 3 2 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); // flip a red edge and black edge // r // .----'| .-'| // | | >b // | .-'| .--|-'| // 1 2 3 1 2 3 1 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); // flip a red edge, ignore a black edge // r // .-'| .-------'| // | >b => | >b // .--|-'| | .-'| // 3 1 2 3 1 2 1 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); ''' [cases.test_rbyd_quadrifoliate] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // ignore a red edge and black edge // | .----'| // | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); // ignore a red edge, flip a black edge // y // .-------'| .-'| // r | >r // .----'| => | .-'| => .--|-'| // | b | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); // flip a red edge and black edge // >y // .-'| // b // .----'| => .--|-'| // | b // | .-'| .--|--|-'| // 2 3 4 2 3 4 1 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); // flip a red edge, ignore a black edge // >y // .-------'| // r // .-'| => | .-'| // | >b | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); ''' [cases.test_rbyd_rotations] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // all three the same // | .----'| // | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); // yellow and red alt the same // | .----'| // | b // | .-'| | | .-'| // 1 2 4 1 2 4 3 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); // yellow and black alt the same // r | | .----'| => | .-'| // | >b | | b // | .-'| | | .-'| | .--|-'| // 1 4 2 1 4 2 3 1 4 2 3 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); // red and black alt the same // >y r | | .----'| => | .-'| // | b // | .-'| | | .-'| .--|--|-'| // 4 1 2 4 1 2 3 4 1 2 3 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, NULL))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); ''' [cases.test_rbyd_ysplits] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // split a yellow triple, not taking any alt // | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, NULL)))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); // split a yellow triple, taking the black alt // | b // | | .-'| | | .-'| // 1 2 3 4 1 2 3 4 3 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, NULL)))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); // split a yellow triple, taking the red alt // b // .-------'| .-'| // | .--------|-'| // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); // split a yellow triple, taking the yellow alt // b // .-------'| .-'| // | b // | .----'| => .-----|-'| // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); ''' [cases.test_rbyd_quintifoliate] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // split a yellow triple, not taking any alt // | .----' | // | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, NULL)))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); // split a yellow triple, taking the black alt // | .----' | // | r // | .----'| | | .-'| // | | b // | | .-'| | | .--|-'| // 1 2 4 5 1 2 4 5 3 rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, NULL)))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); // split a yellow triple, taking the red alt // >b // .-'| // b // | .----'| => | .-----|-'| // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); // split a yellow triple, taking the yellow alt // >b // .-'| // r // .-------'| .-----|-'| // | b // | .----'| => .--|-----|-'| // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); ''' [cases.test_rbyd_prunes] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // don't prune // | .----' | // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, NULL))))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); // prune by taking a red alt // b // .-------'| | .-'| // | .-----------|-'| // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); // prune by taking a yellow alt (this needs to prune during the rflip) // b // .-------'| | .-'| // | b // | .----' | => .--------|-'| // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL))))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); ''' [cases.test_rbyd_sextifoliate] in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // don't prune // | | .-------'| // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, LFS_MKRATTR(UATTR, 6, 0, &(uint32_t){0xffffffff}, 4, NULL))))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 6, 0), &off, &size) => LFS_MKRTAG(UATTR, 6, 0); // prune by taking a red alt // b // .-'| .-'| // b // | .----' | => | .--------|-'| // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, LFS_MKRATTR(UATTR, 6, 0, &(uint32_t){0xffffffff}, 4, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL))))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 6, 0), &off, &size) => LFS_MKRTAG(UATTR, 6, 0); // prune by taking a yellow alt (this needs to prune during the rflip) // b // .-'| .-'| // r // .-------'| | .--------|-'| // | b // | .----' | => .--|--------|-'| // | | 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, LFS_MKRATTR(UATTR, 3, 0, &(uint32_t){0xcccccccc}, 4, LFS_MKRATTR(UATTR, 4, 0, &(uint32_t){0xdddddddd}, 4, LFS_MKRATTR(UATTR, 5, 0, &(uint32_t){0xeeeeeeee}, 4, LFS_MKRATTR(UATTR, 6, 0, &(uint32_t){0xffffffff}, 4, LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL))))))) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size) => LFS_MKRTAG(UATTR, 1, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size) => LFS_MKRTAG(UATTR, 2, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size) => LFS_MKRTAG(UATTR, 3, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 4, 0), &off, &size) => LFS_MKRTAG(UATTR, 4, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 5, 0), &off, &size) => LFS_MKRTAG(UATTR, 5, 0); lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 6, 0), &off, &size) => LFS_MKRTAG(UATTR, 6, 0); ''' [cases.test_rbyd_permutations] defines.N = 'range(1, 8)' in = 'lfs.c' code = ''' lfs_t lfs; lfs_init(&lfs, cfg) => 0; lfs_rbyd_t rbyd_init = { .block = 0, .trunk = 0, .noff = 0, .rev = 1, .crc = 0, .count = 0, .erased = true, }; lfs_rbyd_t rbyd; lfs_off_t off; lfs_size_t size; // test all permutations of a given size uint8_t perm[N]; uint8_t stack[N]; for (uint8_t i = 0; i < N; i++) { perm[i] = i; stack[i] = 0; } uint8_t i = 1; while (i < N) { // print permutation to help debugging printf("--- permutation: ["); for (int j = 0; j < N; j++) { if (j > 0) { printf(", "); } printf("%d", perm[j]+1); } printf("] ---\n"); // build the attribute list for the current permutation struct lfs_rattr attrs[N]; for (int j = 0; j < N; j++) { attrs[j] = *LFS_MKRATTR( UATTR, perm[j]+1, 0, &(uint32_t){0xaaaaaaaa}, 4, (j+1 < N) ? &attrs[j+1] : NULL); } // test the given permutation rbyd = rbyd_init; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, attrs) => 0; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; for (int j = 0; j < N; j++) { lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, j+1, 0), &off, &size) => LFS_MKRTAG(UATTR, j+1, 0); } // next permutation using Heap's algorithm if (stack[i] < i) { if (i % 2 == 0) { uint8_t t = perm[0]; perm[0] = perm[i]; perm[i] = t; } else { uint8_t t = perm[stack[i]]; perm[stack[i]] = perm[i]; perm[i] = t; } stack[i] += 1; i = 1; } else { stack[i] = 0; i += 1; } } '''