From 0a89d0c2546742a37a4dbad8305129aa8886d8f4 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 13 Mar 2024 03:27:00 -0500 Subject: [PATCH] Fixed recoloring tail-recursion violations during range removals I spoke too soon and made a mistake when reenabling color preservation during range removals. I assumed, that thanks to replacing the diverging alt with a new black alt for stitching together diverging trunks, we would avoid the issue where a deleted diverging alt violates our rbyd's tail-recursive recoloring invariant. Unfortunately, this is not the case. All the stitching alt did was make this violation more difficult to reach, but still reachable. Arguable a worse situation. Now, for this violation to happen, in addition to all of the other requirements, we need the lower-diverging trunk to become empty. This is the only case where we have no stitching alt, because we don't need to stitch an empty trunk. Which means if the upper-diverging trunk has yellow nodes both before and after the diverging alt, our tail-recursive recoloring invariant can break. Here's an example: .-------------r-------------. .-o-. .---+---y----. .-o-. .o. .o. .o. .o. .o. .-y-+-. .o. .o. a a a a a a a a c c c e e e e e e e '--+--' remove Again, this doesn't capture the alt-layout, which _is_ important, so here's the dbgrbyd.py view: .-> aa .-> aa .-b-> a .-b-> a | .-> a | .-> a .-----------b-b-> a .-------b-b-> a | .-> a | .-> a | .---------b-> a | .-b-> a | | .-> a | | .-> a | | .-------b-> a | .-b-b-> a r-b-y-r-b-----b-> cc -. => y-y-r-b-----> ee <- two yellows! | | '-> c + rm | '-----b-> e different dirs! | | .-> c -' | '-> e should not happen! | '-y-r-b-> ee | .-> e | | '---> e | .-b-> e | '-----> e | | .-> e | .-> e '-----b-b-> e | .-b-> e | | .-> e '---------b-b-> e And the steps in our appendattr algorithm that led to this state, which is insightful: read [b => [b] read [b [b [r [b] ^--^------------- yellow-same-dir invariant held read >b => [b >b] diverge => [b] read >r => [b >r] read >r => b >r >r] ^-----------^-- our 4-alt fifo for flips/coloring ysplit => r >b] reorder => r >r |.b.| |.g.| => |.b.| |.e.g.| '|-|-|-|' '|-|' '|-|' '|-|' '|-|-|' | | .-' '-. v v v v .-------. .-------. .---. .---. |.d.e.f.| |.d.e.f.| |.d.| |.f.| '|-|-|-|' '|-|-|-|' '|-|' '|-|' If you lazily split, you aren't guaranteed an open slot in your parent, so you need recursion to solve splits. This is why 2-3 trees, though self-balancing, are not tail-recursive: .-----. .-----. |.a.h.| |.a.h.| '|-|-|' '|-|-|' | | v v .-------. .'''''''''. |.b.c.g.| => >.b.c.e.g.< 5!? '|-|-|-|' '|.|.|.|.|' | .-' '-. v v v .-------. .---. .---. |.d.e.f.| |.d.| |.f.| '|-|-|-|' '|-|' '|-|' But if you are eagerly splitting while also deleting nodes: .-----. .-------. .-------. .'''''''''. |.a.h.| |.a.c.h.| |.a.c.h.| 5!? >.a.c.e.h.< '|-|-|' '|-|-|-|' '|-|-|-|' '|.|.|.|.|' | .-' '-. .-' '---. .---' | '---. v v v v v v v v .-------. .---. .---. .---. .-------. .---. .---. .---. |.b.c.g.| => |.b.| |.g.| => |.b.| |.d.e.f.| => |.b.| |.d.| |.g.| '|-|-|-|' '|-|' '|-|' '|-|' '|-|-|-|' '|-|' '|-|' '|-|' | x | x v v .-------. .-------. |.d.e.f.| |.d.e.f.| '|-|-|-|' '|-|-|-|' Suddenly, recursion. This is a problem. The workaround implemented here is to check during pruning if our parent may risk recursion, and if so, recolor the last alt so nothing will break. This ends up equivalent to the following transformation: .-----. .-------. .-----. .-----. |.a.h.| |.a.c.h.| |.a.c.| |.a.c.| '|-|-|' '|-|-|-|' '|-|-|' '|-|-|' | .-' '-. .-' '-. .-' '--. v v v v v v v .-------. .---. .---. .---. .---. .---. .-----. |.b.c.g.| => |.b.| |.g.| => |.b.| |.h.| => |.b.| |.e.h.| '|-|-|-|' '|-|' '|-|' '|-|' '|-|' '|-|' '|-|-|' | x | x | .-' '-. v v v v v .-------. .-------. .-------. .---. .---. |.d.e.f.| |.d.e.f.| |.d.e.f.| |.d.| |.f.| '|-|-|-|' '|-|-|-|' '|-|-|-|' '|-|' '|-|' You may notice this isn't exactly optimal. The >h branch ends up one level lower, making the balance of the tree off by one. But it at least ends up with a functional tree. I may try to find a better solution... --- The test_rbyd_delete_range_rydy/rydye tests should cover the cases where a diverging alt is deleted. I also tried to write tests for the cases where an alt is pruned, the closest I got is in test_rbyd_delete_range_dryy_backwards, but I couldn't actually come up with a sequence that would break our rbyds. In theory it's possible, but it would need this substructure: .-------> c y-r-b-------> c y-r-b-y-r-b-> c or | | '-y-r-b-> c | | | | | | | | Which, as far as I can tell, can't actually be created with our current algorithm... Note the inverse structure: .---------> c | .-y-r-b-> c y-r- | | Will be pruned before it has a chance to split. So there is no invariant concerns there. We only have issues when it's the tail alts that get pruned, because we decide to split before we know if we are pruning or not. I don't think this can be avoided without additional read-ahead. Also, even if we could create the above substructure, because we are on a diverged trunk, and by definition all alts point the same direction, we would never end up violating our same-dir yellow invariant/assert... Code changes: code stack before: 33880 2880 after: 33912 (+0.1%) 2880 (+0.0%) --- lfs.c | 20 +- tests/test_rbyd.toml | 1901 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 1912 insertions(+), 9 deletions(-) diff --git a/lfs.c b/lfs.c index b3483ede..bfc17865 100644 --- a/lfs.c +++ b/lfs.c @@ -2904,11 +2904,12 @@ again:; // | | LFS_ERR_NOENT; ''' -[cases.test_rbyd_delete_range_ryy] +[cases.test_rbyd_delete_range_rydy] in = 'lfs.c' code = ''' lfs_t lfs; @@ -8312,8 +8312,8 @@ code = ''' // '+' // remove // - // this is a specific nasty case that can happen if you try to - // preserve coloring during range removes + // this is a specific nasty case where tail-recursion can be + // violated if you preserve coloring during range removes // rbyd = init_rbyd; lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; @@ -8633,6 +8633,1901 @@ code = ''' &data) => LFS_ERR_NOENT; ''' +[cases.test_rbyd_delete_range_rydy_backwards] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, CFG) => 0; + + lfsr_rbyd_t init_rbyd = { + .blocks[0] = 0, + .eoff = 0, + .cksum = 0, + .trunk = 0, + .weight = 0, + }; + lfsr_rbyd_t rbyd; + lfsr_data_t data; + uint8_t buffer[4]; + + // delete inner branches + // + // .-------------r-------------. + // .-o-. .---+---y----. .-o-. + // .o. .o. .o. .o. .o. .-y-+-. .o. .o. + // a a a a a a a a a a c e e e e e e e + // '+' + // remove + // + // this is a specific nasty case where tail-recursion can be + // violated if you preserve coloring during range removes + // + rbyd = init_rbyd; + lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xaa\xaa\xaa\xaa", 4)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(9), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), +1, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + // propagate yellow to the root + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)))) => 0; + // this gets a bit messy as we try to make the rbyd take the right shape + lfsr_rbyd_commit(&lfs, &rbyd, 2, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_REG, 0, + LFSR_DATA_BUF("\xee\xee\xee\xee", 4)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(7), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(8), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + // propagate yellow + LFSR_ATTR( + LFSR_TAG_UATTR(8), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)))) => 0; + + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_RM, -1, LFSR_DATA_NULL()))) => 0; + + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + // try to recreate + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)))) => 0; + + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; +''' + +[cases.test_rbyd_delete_range_rydye] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, CFG) => 0; + + lfsr_rbyd_t init_rbyd = { + .blocks[0] = 0, + .eoff = 0, + .cksum = 0, + .trunk = 0, + .weight = 0, + }; + lfsr_rbyd_t rbyd; + lfsr_data_t data; + uint8_t buffer[4]; + + // delete inner branches + // + // .-------------r-------------. + // .-o-. .----y---+---. .-o-. + // .o. .o. .-+-y-. .o. .o. .o. .o. .o. + // a a a a a a a c c c e e e e e e e e + // '--+--' + // remove + // + // this is a specific nasty case where tail-recursion can be + // violated if you preserve coloring during range removes + // + rbyd = init_rbyd; + lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xaa\xaa\xaa\xaa", 4)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), +1, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(7), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + // propagate yellow to the root + LFSR_ATTR( + LFSR_TAG_UATTR(7), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(7), 0, + LFSR_DATA_BUF("\xee\xee", 2)))) => 0; + // this gets a bit messy as we try to make the rbyd take the right shape + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 2, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_REG, 0, + LFSR_DATA_BUF("\xee\xee\xee\xee", 4)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)), + // propagate yellow + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)))) => 0; + + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_RM, -1, LFSR_DATA_NULL()))) => 0; + + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + // try to recreate + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)))) => 0; + + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; +''' + +[cases.test_rbyd_delete_range_rydye_backwards] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, CFG) => 0; + + lfsr_rbyd_t init_rbyd = { + .blocks[0] = 0, + .eoff = 0, + .cksum = 0, + .trunk = 0, + .weight = 0, + }; + lfsr_rbyd_t rbyd; + lfsr_data_t data; + uint8_t buffer[4]; + + // delete inner branches + // + // .-------------r-------------. + // .-o-. .---+---y----. .-o-. + // .o. .o. .o. .o. .o. .-y-+-. .o. .o. + // a a a a a a a a c c c e e e e e e e + // '--+--' + // remove + // + // this is a specific nasty case where tail-recursion can be + // violated if you preserve coloring during range removes + // + rbyd = init_rbyd; + lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xaa\xaa\xaa\xaa", 4)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), +1, + LFSR_DATA_BUF("\xcc\xcc", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), +1, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + // propagate yellow to the root + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)))) => 0; + // this gets a bit messy as we try to make the rbyd take the right shape + lfsr_rbyd_commit(&lfs, &rbyd, 2, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_REG, 0, + LFSR_DATA_BUF("\xee\xee\xee\xee", 4)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(7), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, 0, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)), + // propagate yellow + LFSR_ATTR( + LFSR_TAG_REG, 0, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)))) => 0; + + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_RM, -1, LFSR_DATA_NULL()))) => 0; + + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + // try to recreate + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)))) => 0; + + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; +''' + +[cases.test_rbyd_delete_range_dryy] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, CFG) => 0; + + lfsr_rbyd_t init_rbyd = { + .blocks[0] = 0, + .eoff = 0, + .cksum = 0, + .trunk = 0, + .weight = 0, + }; + lfsr_rbyd_t rbyd; + lfsr_data_t data; + uint8_t buffer[4]; + + // delete inner branches + // + // o---------------------. + // .-------+---------r .---o---. + // .-o-. .-o-. .---y------+----. .-o-. .-o-. + // .o. .o. .o. .o. .o. .o. .-+-y-. .o. .o. .o. .o. .o. + // a a a a a a a a a a a a a a a c c c c e e e e e e e + // '---+---' + // remove + // + // this is an attempt at colliding two splits by pruning after + // diverging, in theory this can lead to tail-recursion violations, + // but no violations have been found to be possible yet + // + rbyd = init_rbyd; + lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xaa\xaa\xaa\xaa", 4)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), +1, + LFSR_DATA_BUF("\xcc\xcc", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)), + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xee\xee\xee\xee", 4)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + // propagate yellow to the root + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xee\xee", 2)))) => 0; + // this gets a bit messy as we try to make the rbyd take the right shape + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(7), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(8), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(11), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)), + // propagate yellow + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(12), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, 0, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)), + // propagate yellow + LFSR_ATTR( + LFSR_TAG_REG, 0, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(13), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(14), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(9), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(10), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + // propagate yellow + LFSR_ATTR( + LFSR_TAG_UATTR(10), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)))) => 0; + + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_RM, -1, LFSR_DATA_NULL()))) => 0; + + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(10), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(11), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(12), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(13), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(14), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(10), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(11), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(12), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(13), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(14), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + // try to recreate + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)))) => 0; + + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(10), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(11), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(12), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(13), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(14), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(10), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(11), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(12), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(13), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(14), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; +''' + +[cases.test_rbyd_delete_range_dryy_backwards] +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, CFG) => 0; + + lfsr_rbyd_t init_rbyd = { + .blocks[0] = 0, + .eoff = 0, + .cksum = 0, + .trunk = 0, + .weight = 0, + }; + lfsr_rbyd_t rbyd; + lfsr_data_t data; + uint8_t buffer[4]; + + // delete inner branches + // + // .---------------------o + // .---o---. r---------+-------. + // .-o-. .-o-. .----+------y---. .-o-. .-o-. + // .o. .o. .o. .o. .o. .-y-+-. .o. .o. .o. .o. .o. .o. + // a a a a a a a c c c c e e e e e e e e e e e e e e e + // '---+---' + // remove + // + // this is an attempt at colliding two splits by pruning after + // diverging, in theory this can lead to tail-recursion violations, + // but no violations have been found to be possible yet + // + rbyd = init_rbyd; + lfsr_bd_erase(&lfs, rbyd.blocks[0]) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 0, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xaa\xaa\xaa\xaa", 4)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), 0, + LFSR_DATA_BUF("\xaa\xaa", 2)), + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)), + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xcc\xcc", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(6), +1, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(7), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(8), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(9), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(10), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + // propagate yellow to the root + LFSR_ATTR( + LFSR_TAG_UATTR(10), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(10), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(10), 0, + LFSR_DATA_BUF("\xee\xee", 2)))) => 0; + // this gets a bit messy as we try to make the rbyd take the right shape + lfsr_rbyd_commit(&lfs, &rbyd, 2, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(11), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(12), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(13), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(14), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + // propagate yellow + LFSR_ATTR( + LFSR_TAG_UATTR(14), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(14), 0, + LFSR_DATA_BUF("\xee\xee", 2)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 2, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(2), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + // propagate yellow + LFSR_ATTR( + LFSR_TAG_UATTR(3), 0, + LFSR_DATA_BUF("\xee\xee", 2)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 2, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(1), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_REG, 0, + LFSR_DATA_BUF("\xee\xee\xee\xee", 4)))) => 0; + lfsr_rbyd_commit(&lfs, &rbyd, 2, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_UATTR(5), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xee\xee", 2)), + // propagate yellow + LFSR_ATTR( + LFSR_TAG_UATTR(4), 0, + LFSR_DATA_BUF("\xee\xee", 2)))) => 0; + + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR(LFSR_TAG_RM, -1, LFSR_DATA_NULL()))) => 0; + + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(10), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(11), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(12), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(13), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(14), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 2); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(10), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(11), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(12), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(13), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_UATTR(14), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + // try to recreate + lfsr_rbyd_commit(&lfs, &rbyd, 1, LFSR_ATTRS( + LFSR_ATTR( + LFSR_TAG_REG, +1, + LFSR_DATA_BUF("\xcc\xcc\xcc\xcc", 4)))) => 0; + + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(10), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(11), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(12), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(13), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(14), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; + + lfsr_rbyd_fetch(&lfs, &rbyd, rbyd.blocks[0], 0) => 0; + assert(rbyd.weight == 3); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 0, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xaa\xaa", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 1, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_REG, &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 4; + assert(memcmp(buffer, "\xee\xee\xee\xee", 4) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(1), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(2), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(3), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(4), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(5), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(6), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(7), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(8), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(9), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(10), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(11), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(12), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(13), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 2, LFSR_TAG_UATTR(14), &data) => 0; + lfsr_data_read(&lfs, &data, buffer, 4) => 2; + assert(memcmp(buffer, "\xee\xee", 2) == 0); + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_REG, + &data) => LFS_ERR_NOENT; + lfsr_rbyd_lookup(&lfs, &rbyd, 3, LFSR_TAG_UATTR(1), + &data) => LFS_ERR_NOENT; +''' + # NOTE if we separate physical/logical block sizes we may be able to # use emubd's copy-on-write copy to speed this up significantly [cases.test_rbyd_delete_permutations]