From 788e98a98920e48c4646b3505b102a9c38b044c4 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 3 Jan 2023 22:25:53 -0600 Subject: [PATCH] Made delete remove the path from the tree completely, fixed failing tests --- lfs.c | 225 +++++++++----- tests/test_rbyd.toml | 698 ++++++++++++++++++++++--------------------- 2 files changed, 499 insertions(+), 424 deletions(-) diff --git a/lfs.c b/lfs.c index d88b22c6..916263b4 100644 --- a/lfs.c +++ b/lfs.c @@ -1595,20 +1595,22 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_, // prune? if (lfs_rtag_weight_(alt) >= (upper-lower)) { - printf("prune!\n"); - LFS_ASSERT(p_alts[0]); - //LFS_ASSERT(lfs_rtag_isred(p_alts[0])); - // TODO false when remove all? - // TODO wait is remove all not actually cleaning up all - // zero-weight alt pointers? we can probably fix this with the - // append<->delete merge + if (p_alts[0] && lfs_rtag_isred(p_alts[0])) { + printf("prune red!\n"); - alt = lfs_rtag_black(p_alts[0]); - branch_ = jump; - jump = p_jumps[0]; - lfs_rbyd_p_pop(p_alts, p_jumps); + alt = lfs_rtag_black(p_alts[0]); + branch_ = jump; + jump = p_jumps[0]; + lfs_rbyd_p_pop(p_alts, p_jumps); - lfs_rtag_untrim_(alt, &lower, &upper); + lfs_rtag_untrim_(alt, &lower, &upper); + } else { + printf("prune!\n"); + + graft = branch; // TODO? + branch = jump; + continue; + } } // two reds makes a yellow, split? @@ -1725,17 +1727,20 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_, // split leaf? // TODO we might be able to rearrange this a bit better - if (lfs_rtag_type1(tag) == LFS_TYPE1_CREATE - || tag_ != tag) { + if ((lfs_rtag_type1(tag) == LFS_TYPE1_CREATE + || tag_ != tag) + && !lfs_rtag_isrm(tag_)) { // inserting a new id? if (lfs_rtag_type1(tag) == LFS_TYPE1_CREATE) { // note we bias the weights here so that lfs_rbyd_lookup // always finds the next biggest tag if (lfs_rtag_weight(tag_) < lfs_rtag_weight(tag & ~0x7fff)) { + printf("bsplit lt create\n"); alt = LFS_MKRALT__(B, LT, (lfs_rtag_weight_(tag_)+0x8) - lower); } else { + printf("bsplit gt create\n"); alt = LFS_MKRALT__(B, GT, (upper+0x8000) - (lfs_rtag_weight_(tag)+0x8)); // // TODO hm, can this be done differently? @@ -1746,9 +1751,11 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_, // note we bias the weights here so that lfs_rbyd_lookup // always finds the next biggest tag if (lfs_rtag_weight_(tag_) < lfs_rtag_weight_(tag)) { + printf("bsplit lt\n"); alt = LFS_MKRALT__(B, LT, (lfs_rtag_weight_(tag_)+0x8) - lower); } else { + printf("bsplit gt\n"); alt = LFS_MKRALT__(B, GT, upper - (lfs_rtag_weight_(tag)+0x8)); } @@ -1826,6 +1833,8 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, lfs_rtag_t upper_upper = (rbyd_->count+1) << 15; lfs_rtag_t lower_tag__ = tag & ~0x7fff; lfs_rtag_t upper_tag__ = lower_tag__ + 0x8000; + lfs_rtag_t lower_tag_ = 0; + lfs_rtag_t upper_tag_ = 0; // // weights for pruning // lfs_srtag_t lower_lt = lfs_rtag_weight_lt(tag & ~0x7fff, rbyd_->count+1); @@ -1887,6 +1896,26 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, } } + // prune? + if (lfs_rtag_weight_(alt) >= (upper-lower)) { + if (p_alts[0] && lfs_rtag_isred(p_alts[0])) { + printf("prune red!\n"); + + alt = lfs_rtag_black(p_alts[0]); + branch_ = jump; + jump = p_jumps[0]; + lfs_rbyd_p_pop(p_alts, p_jumps); + + lfs_rtag_untrim_(alt, &lower, &upper); + } else { + printf("prune!\n"); + + graft = branch; // TODO? + branch = jump; + goto next; + } + } + // TODO can this be combined with prune? maybe not? // cut? if (is_cut) { @@ -1944,26 +1973,6 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, } } } - - // prune? - if (lfs_rtag_weight_(alt) >= (upper-lower)) { - if (p_alts[0] && lfs_rtag_isred(p_alts[0])) { - printf("prune red!\n"); - - alt = lfs_rtag_black(p_alts[0]); - branch_ = jump; - jump = p_jumps[0]; - lfs_rbyd_p_pop(p_alts, p_jumps); - - lfs_rtag_untrim_(alt, &lower, &upper); - } else { - printf("prune!\n"); - - graft = branch; // TODO? - branch = jump; - goto next; - } - } // // prune? @@ -2128,6 +2137,13 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, //lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(tag)); lfs_rtag_t tag_ = lfs_rtag_setid(alt, lfs_rtag_id(upper-1)); + if (!is_cut || is_lower) { + lower_tag_ = tag_; + } + if (!is_cut || !is_lower) { + upper_tag_ = tag_; + } + // printf("found %x (%x, %x, lower=%d)\n", tag_, lt, gt, is_lower); // printf("(%x, %x), (%x, %x)\n", lower_lt, lower_gt, upper_lt, upper_gt); @@ -2158,48 +2174,49 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, // } // } - if (tag_ != tag) { - // note we bias the weights here so that lfs_rbyd_lookup - // always finds the next biggest tag - if (lfs_rtag_weight_(tag_) - < lfs_rtag_weight_(tag & ~0x7fff)) { - if (!is_cut || is_lower) { - printf("bsplit lt\n"); - alt = LFS_MKRALT__(B, LT, - (lfs_rtag_weight_(tag_)+0x8) - lower); - - // TODO can we rededuplicate this? - int err = lfs_rbyd_p_push(lfs, rbyd_, - p_alts, p_jumps, - alt, branch); - if (err) { - return err; - } - - // TODO hmmm, red while cutting causes problems? - lfs_rbyd_p_red(p_alts, p_jumps); - } - } else if (lfs_rtag_weight_(tag_) - >= lfs_rtag_weight_(tag & ~0x7fff)+0x8000) { - if (!is_cut || !is_lower) { - printf("bsplit gt\n"); - alt = LFS_MKRALT__(B, GT, - upper - (lfs_rtag_weight_(tag & ~0x7fff) - +0x8000+0x8)); - - // TODO can we rededuplicate this? - int err = lfs_rbyd_p_push(lfs, rbyd_, - p_alts, p_jumps, - alt, branch); - if (err) { - return err; - } - - // TODO hmmm, red while cutting causes problems? - lfs_rbyd_p_red(p_alts, p_jumps); - } - } - } +// if (tag_ != tag) { +// // note we bias the weights here so that lfs_rbyd_lookup +// // always finds the next biggest tag +// if (lfs_rtag_weight_(tag_) +// < lfs_rtag_weight_(tag & ~0x7fff)) { +// if (!is_cut || is_lower) { +// printf("bsplit lt\n"); +// alt = LFS_MKRALT__(B, LT, +// (lfs_rtag_weight_(tag_)+0x8) - lower); +// +// // TODO can we rededuplicate this? +// int err = lfs_rbyd_p_push(lfs, rbyd_, +// p_alts, p_jumps, +// alt, branch); +// if (err) { +// return err; +// } +// +// // TODO hmmm, red while cutting causes problems? +// lfs_rbyd_p_red(p_alts, p_jumps); +// } +// } else if (lfs_rtag_weight_(tag_) +// >= lfs_rtag_weight_(tag & ~0x7fff)+0x8000) { +// if (!is_cut || !is_lower) { +// printf("bsplit gt\n"); +// alt = LFS_MKRALT__(B, GT, +// upper - (lfs_rtag_weight_(tag & ~0x7fff) +// +0x8000+0x8)); +// +// // TODO can we rededuplicate this? +// int err = lfs_rbyd_p_push(lfs, rbyd_, +// p_alts, p_jumps, +// alt, branch); +// if (err) { +// return err; +// } +// +// // TODO hmmm, red while cutting causes problems? +// lfs_rbyd_p_red(p_alts, p_jumps); +// } +// } +// } +// // TODO this should be restructured, it's a bit of mess if (is_cut && !is_other_done) { @@ -2209,6 +2226,62 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, continue; } + LFS_ASSERT(lower_tag_); + LFS_ASSERT(upper_tag_); + +// // make sure to fill out the rest of the weight if we're +// // deleting the last tag in the tree +// if (lfs_rtag_id(tag) == rbyd_->count+1-1) { +// if (p_alts[0]) { +// printf("expand lower\n"); +// LFS_ASSERT(lfs_rtag_islt(p_alts[0])); +// p_alts[0] += upper_upper - lower_lower - 0x8000; +// } else { +// // TODO +// printf("expand empty\n"); +// LFS_ASSERT(false); +// } +// } + + // split leaf nodes? + if (lower_tag_ != tag // TODO need this check? + && lfs_rtag_weight_(lower_tag_) + < lfs_rtag_weight_(tag & ~0x7fff)) { + printf("bsplit lower\n"); + alt = LFS_MKRALT__(B, LT, + (lfs_rtag_weight_(lower_tag_)+0x8) - lower_lower); + + // TODO can we rededuplicate this? + int err = lfs_rbyd_p_push(lfs, rbyd_, + p_alts, p_jumps, + alt, lower_branch); + if (err) { + return err; + } + + lfs_rbyd_p_red(p_alts, p_jumps); + } + + if (upper_tag_ != tag // TODO need this check? + && lfs_rtag_weight_(upper_tag_) + >= lfs_rtag_weight_(tag & ~0x7fff)+0x8000) { + printf("bsplit upper\n"); + alt = LFS_MKRALT__(B, GT, + upper_upper - (lfs_rtag_weight_(lower_tag_)+0x8)); +// upper_upper - (lfs_rtag_weight_(tag & ~0x7fff) +// +0x8000+0x8)); + + // TODO can we rededuplicate this? + int err = lfs_rbyd_p_push(lfs, rbyd_, + p_alts, p_jumps, + alt, upper_branch); + if (err) { + return err; + } + + lfs_rbyd_p_red(p_alts, p_jumps); + } + // flush any pending alts int err = lfs_rbyd_p_flush(lfs, rbyd_, p_alts, p_jumps, 3); diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index c72cead1..bb52a7f7 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -3030,9 +3030,9 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, - LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2, NULL))))) => 0; + LFS_MKRATTR(UATTR, 1, 2, "\xbb\xbb", 2, NULL))))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 2, NULL, 0, NULL)) => 0; @@ -3040,12 +3040,12 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xaa\xaa", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; @@ -3053,12 +3053,12 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xaa\xaa", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => LFS_ERR_NOENT; // try to delete the other id @@ -3066,9 +3066,9 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, - LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2, NULL))))) => 0; + LFS_MKRATTR(UATTR, 1, 2, "\xbb\xbb", 2, NULL))))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL)) => 0; @@ -3076,12 +3076,12 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xbb\xbb", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; @@ -3089,12 +3089,12 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xbb\xbb", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => LFS_ERR_NOENT; // try to delete the largest of three @@ -3102,11 +3102,11 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, - LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2, + LFS_MKRATTR(UATTR, 1, 2, "\xbb\xbb", 2, LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, - LFS_MKRATTR(UATTR, 0, 3, "\xcc\xcc", 2, NULL))))))) => 0; + LFS_MKRATTR(UATTR, 1, 3, "\xcc\xcc", 2, NULL))))))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 3, NULL, 0, NULL)) => 0; @@ -3114,18 +3114,18 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xaa\xaa", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => 2; assert(memcmp(buffer, "\xbb\xbb", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 3), buffer, 4) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; @@ -3133,18 +3133,18 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xaa\xaa", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => 2; assert(memcmp(buffer, "\xbb\xbb", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 3), buffer, 4) => LFS_ERR_NOENT; // try to delete the smallest of three @@ -3152,11 +3152,11 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, - LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2, + LFS_MKRATTR(UATTR, 1, 2, "\xbb\xbb", 2, LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, - LFS_MKRATTR(UATTR, 0, 3, "\xcc\xcc", 2, NULL))))))) => 0; + LFS_MKRATTR(UATTR, 1, 3, "\xcc\xcc", 2, NULL))))))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL)) => 0; @@ -3164,18 +3164,18 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xbb\xbb", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => 2; assert(memcmp(buffer, "\xcc\xcc", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 3), buffer, 4) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; @@ -3183,18 +3183,18 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xbb\xbb", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => 2; assert(memcmp(buffer, "\xcc\xcc", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 3), buffer, 4) => LFS_ERR_NOENT; // try to delete the middle @@ -3202,11 +3202,11 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, - LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb", 2, + LFS_MKRATTR(UATTR, 1, 2, "\xbb\xbb", 2, LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, - LFS_MKRATTR(UATTR, 0, 3, "\xcc\xcc", 2, NULL))))))) => 0; + LFS_MKRATTR(UATTR, 1, 3, "\xcc\xcc", 2, NULL))))))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 2, NULL, 0, NULL)) => 0; @@ -3214,18 +3214,18 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xaa\xaa", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => 2; assert(memcmp(buffer, "\xcc\xcc", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 3), buffer, 4) => LFS_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; @@ -3233,18 +3233,18 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) => 4; assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 1), buffer, 4) => 2; assert(memcmp(buffer, "\xaa\xaa", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 2), buffer, 4) => 2; assert(memcmp(buffer, "\xcc\xcc", 2) == 0); lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => LFS_ERR_NOENT; - lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 3), buffer, 4) + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 3), buffer, 4) => LFS_ERR_NOENT; ''' @@ -3432,7 +3432,7 @@ code = ''' lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4, // note uattrs have a smaller size - LFS_MKRATTR(UATTR, 0, id+1, names[perm[j] % 6], 2, + LFS_MKRATTR(UATTR, 1, id+1, names[perm[j] % 6], 2, NULL))) => 0; } assert(rbyd.count == N); @@ -3468,7 +3468,7 @@ code = ''' } lfs_rbyd_get(&lfs, &rbyd, - LFS_MKRTAG(UATTR, 0, k+1), buffer, 4) => 2; + LFS_MKRTAG(UATTR, 1, k+1), buffer, 4) => 2; if (k >= j) { assert(memcmp(buffer, names[(k+1) % 6], 2) == 0); } else { @@ -3479,7 +3479,7 @@ code = ''' LFS_MKRTAG(CREATEREG, 0, N-1+1), buffer, 4) => LFS_ERR_NOENT; lfs_rbyd_get(&lfs, &rbyd, - LFS_MKRTAG(UATTR, 0, N-1+1), buffer, 4) + LFS_MKRTAG(UATTR, 1, N-1+1), buffer, 4) => LFS_ERR_NOENT; } @@ -3642,7 +3642,7 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, NULL))) => 0; + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, NULL))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL)) => 0; @@ -3660,9 +3660,9 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xbb\xbb", 2, NULL))))) => 0; + LFS_MKRATTR(UATTR, 1, 1, "\xbb\xbb", 2, NULL))))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 1, NULL, 0, LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL))) => 0; @@ -3681,9 +3681,9 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xbb\xbb", 2, NULL))))) => 0; + LFS_MKRATTR(UATTR, 1, 1, "\xbb\xbb", 2, NULL))))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 2, NULL, 0, LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL))) => 0; @@ -3702,11 +3702,11 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xbb\xbb", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xbb\xbb", 2, LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xcc\xcc", 2, NULL))))))) => 0; + LFS_MKRATTR(UATTR, 1, 1, "\xcc\xcc", 2, NULL))))))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 1, NULL, 0, LFS_MKRATTR(DELETE, 0, 1, NULL, 0, @@ -3726,11 +3726,11 @@ code = ''' lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xaa\xaa", 2, LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xbb\xbb", 2, + LFS_MKRATTR(UATTR, 1, 1, "\xbb\xbb", 2, LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, - LFS_MKRATTR(UATTR, 0, 1, "\xcc\xcc", 2, NULL))))))) => 0; + LFS_MKRATTR(UATTR, 1, 1, "\xcc\xcc", 2, NULL))))))) => 0; lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(DELETE, 0, 3, NULL, 0, LFS_MKRATTR(DELETE, 0, 2, NULL, 0, @@ -3893,7 +3893,7 @@ code = ''' for (unsigned j = 0; j < N; j++) { lfs_rbyd_commit(&lfs, &rbyd, LFS_MKRATTR(CREATEREG, 0, j+1, names[j % 6], 4, - LFS_MKRATTR(UATTR, 0, j+1, names[j % 6], 2, + LFS_MKRATTR(UATTR, 1, j+1, names[j % 6], 2, NULL))) => 0; } assert(rbyd.count == N); @@ -3973,298 +3973,300 @@ code = ''' } ''' +# TODO test delete-to-zero with fetches after explicitly? +# TODO also remove-to-zero for removes -# [cases.test_rbyd_delete_create_permutations] -# defines.N = 'range(1, 6)' -# in = 'lfs.c' -# code = ''' -# lfs_t lfs; -# lfs_init(&lfs, cfg) => 0; -# -# lfs_rbyd_t init_rbyd = { -# .block = 0, -# .trunk = 0, -# .off = 0, -# .rev = 1, -# .crc = 0, -# .count = 0, -# .erased = true, -# }; -# lfs_rbyd_t rbyd; -# const uint8_t names[6][6] = { -# "\xaa\xaa\xaa\xaa\xaa\xaa", -# "\xbb\xbb\xbb\xbb\xbb\xbb", -# "\xcc\xcc\xcc\xcc\xcc\xcc", -# "\xdd\xdd\xdd\xdd\xdd\xdd", -# "\xee\xee\xee\xee\xee\xee", -# "\xff\xff\xff\xff\xff\xff", -# }; -# uint8_t buffer[6]; -# -# // test all permutations of a given size -# uint16_t perm[N]; -# unsigned stack[N]; -# for (uint16_t i = 0; i < N; i++) { -# perm[i] = i; -# stack[i] = 0; -# } -# -# unsigned i = 1; -# while (i < N) { -# // print permutation to help debugging -# printf("--- permutation: ["); -# for (unsigned j = 0; j < N; j++) { -# if (j > 0) { -# printf(", "); -# } -# printf("%d", perm[j]+1); -# } -# printf("] ---\n"); -# -# // create given permutation with multiple commits -# rbyd = init_rbyd; -# lfs_bd_erase(&lfs, rbyd.block) => 0; -# -# for (unsigned j = 0; j < N; j++) { -# // adjust id based on future insertions -# uint16_t id = perm[j]; -# for (unsigned k = j+1; k < N; k++) { -# if (perm[j] > perm[k]) { -# id -= 1; -# } -# } -# -# lfs_rbyd_commit(&lfs, &rbyd, -# LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4, -# NULL)) => 0; -# } -# assert(rbyd.count == N); -# -# // copy block so we can reset after each delete -# lfs_rbyd_t backup_rbyd = rbyd; -# uint8_t backup_block[BLOCK_SIZE]; -# lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off, -# rbyd.block, 0, backup_block, rbyd.off) => 0; -# -# // try deleting each id -# for (unsigned j = 0; j < N; j++) { -# for (unsigned l = 0; l < N; l++) { -# // print what we are deleting to help debugging -# printf("--- delete: %d, create: %d ---\n", j+1, l+1); -# -# rbyd = backup_rbyd; -# lfs_bd_erase(&lfs, rbyd.block) => 0; -# lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, -# rbyd.block, 0, backup_block, rbyd.off) => 0; -# -# // delete -# lfs_rbyd_commit(&lfs, &rbyd, -# LFS_MKRATTR(DELETE, 0, j+1, NULL, 0, -# NULL)) => 0; -# assert(rbyd.count == N-1); -# -# // try creating each tag to make sure the rbyd tree -# // is still usable -# lfs_rbyd_commit(&lfs, &rbyd, -# LFS_MKRATTR(CREATEREG, 0, l+1, names[l % 6], 6, -# NULL)) => 0; -# assert(rbyd.count == N); -# -# lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; -# for (unsigned k = 0; k < N; k++) { -# lfs_ssize_t size = lfs_rbyd_get(&lfs, &rbyd, -# LFS_MKRTAG(CREATEREG, 0, k+1), buffer, 6); -# if (k == l) { -# assert(size == 6); -# assert(memcmp(buffer, names[l % 6], 6) == 0); -# } else { -# uint16_t expected = k; -# if (expected > l) { -# expected -= 1; -# } -# if (expected >= j) { -# expected += 1; -# } -# assert(size == 4); -# assert(memcmp(buffer, names[expected % 6], 4) == 0); -# } -# } -# } -# } -# -# // next permutation using Heap's algorithm -# if (stack[i] < i) { -# if (i % 2 == 0) { -# uint16_t t = perm[0]; -# perm[0] = perm[i]; -# perm[i] = t; -# } else { -# uint16_t t = perm[stack[i]]; -# perm[stack[i]] = perm[i]; -# perm[i] = t; -# } -# stack[i] += 1; -# i = 1; -# } else { -# stack[i] = 0; -# i += 1; -# } -# } -# ''' -# -# [cases.test_rbyd_delete_create_range_permutations] -# defines.N = 'range(1, 6)' -# in = 'lfs.c' -# code = ''' -# lfs_t lfs; -# lfs_init(&lfs, cfg) => 0; -# -# lfs_rbyd_t init_rbyd = { -# .block = 0, -# .trunk = 0, -# .off = 0, -# .rev = 1, -# .crc = 0, -# .count = 0, -# .erased = true, -# }; -# lfs_rbyd_t rbyd; -# const uint8_t names[6][6] = { -# "\xaa\xaa\xaa\xaa\xaa\xaa", -# "\xbb\xbb\xbb\xbb\xbb\xbb", -# "\xcc\xcc\xcc\xcc\xcc\xcc", -# "\xdd\xdd\xdd\xdd\xdd\xdd", -# "\xee\xee\xee\xee\xee\xee", -# "\xff\xff\xff\xff\xff\xff", -# }; -# uint8_t buffer[6]; -# -# // test all permutations of a given size -# uint16_t perm[N]; -# unsigned stack[N]; -# for (uint16_t i = 0; i < N; i++) { -# perm[i] = i; -# stack[i] = 0; -# } -# -# unsigned i = 1; -# while (i < N) { -# // print permutation to help debugging -# printf("--- permutation: ["); -# for (unsigned j = 0; j < N; j++) { -# if (j > 0) { -# printf(", "); -# } -# printf("%d", perm[j]+1); -# } -# printf("] ---\n"); -# -# // create given permutation with multiple commits -# rbyd = init_rbyd; -# lfs_bd_erase(&lfs, rbyd.block) => 0; -# -# for (unsigned j = 0; j < N; j++) { -# // adjust id based on future insertions -# uint16_t id = perm[j]; -# for (unsigned k = j+1; k < N; k++) { -# if (perm[j] > perm[k]) { -# id -= 1; -# } -# } -# -# lfs_rbyd_commit(&lfs, &rbyd, -# LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4, -# LFS_MKRATTR(UATTR, 0, id+1, names[perm[j] % 6], 2, -# NULL))) => 0; -# } -# assert(rbyd.count == N); -# -# // copy block so we can reset after each delete -# lfs_rbyd_t backup_rbyd = rbyd; -# uint8_t backup_block[BLOCK_SIZE]; -# lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off, -# rbyd.block, 0, backup_block, rbyd.off) => 0; -# -# // try deleting each id -# for (unsigned j = 0; j < N; j++) { -# for (unsigned l = 0; l < N; l++) { -# // print what we are deleting to help debugging -# printf("--- delete: %d, create: %d ---\n", j+1, l+1); -# -# rbyd = backup_rbyd; -# lfs_bd_erase(&lfs, rbyd.block) => 0; -# lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, -# rbyd.block, 0, backup_block, rbyd.off) => 0; -# -# // delete -# lfs_rbyd_commit(&lfs, &rbyd, -# LFS_MKRATTR(DELETE, 0, j+1, NULL, 0, -# NULL)) => 0; -# assert(rbyd.count == N-1); -# -# // try creating each tag to make sure the rbyd tree -# // is still usable -# lfs_rbyd_commit(&lfs, &rbyd, -# LFS_MKRATTR(CREATEREG, 0, l+1, names[l % 6], 6, -# LFS_MKRATTR(UATTR, 0, l+1, names[l % 6], 3, -# NULL))) => 0; -# assert(rbyd.count == N); -# -# lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; -# for (unsigned k = 0; k < N; k++) { -# lfs_ssize_t size = lfs_rbyd_get(&lfs, &rbyd, -# LFS_MKRTAG(CREATEREG, 0, k+1), buffer, 6); -# if (k == l) { -# assert(size == 6); -# assert(memcmp(buffer, names[l % 6], 6) == 0); -# } else { -# uint16_t expected = k; -# if (expected > l) { -# expected -= 1; -# } -# if (expected >= j) { -# expected += 1; -# } -# assert(size == 4); -# assert(memcmp(buffer, names[expected % 6], 4) == 0); -# } -# -# size = lfs_rbyd_get(&lfs, &rbyd, -# LFS_MKRTAG(UATTR, 0, k+1), buffer, 6); -# if (k == l) { -# assert(size == 3); -# assert(memcmp(buffer, names[l % 6], 3) == 0); -# } else { -# uint16_t expected = k; -# if (expected > l) { -# expected -= 1; -# } -# if (expected >= j) { -# expected += 1; -# } -# assert(size == 2); -# assert(memcmp(buffer, names[expected % 6], 2) == 0); -# } -# } -# } -# } -# -# // next permutation using Heap's algorithm -# if (stack[i] < i) { -# if (i % 2 == 0) { -# uint16_t t = perm[0]; -# perm[0] = perm[i]; -# perm[i] = t; -# } else { -# uint16_t t = perm[stack[i]]; -# perm[stack[i]] = perm[i]; -# perm[i] = t; -# } -# stack[i] += 1; -# i = 1; -# } else { -# stack[i] = 0; -# i += 1; -# } -# } -# ''' +[cases.test_rbyd_delete_create_permutations] +defines.N = 'range(1, 6)' +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + + lfs_rbyd_t init_rbyd = { + .block = 0, + .trunk = 0, + .off = 0, + .rev = 1, + .crc = 0, + .count = 0, + .erased = true, + }; + lfs_rbyd_t rbyd; + const uint8_t names[6][6] = { + "\xaa\xaa\xaa\xaa\xaa\xaa", + "\xbb\xbb\xbb\xbb\xbb\xbb", + "\xcc\xcc\xcc\xcc\xcc\xcc", + "\xdd\xdd\xdd\xdd\xdd\xdd", + "\xee\xee\xee\xee\xee\xee", + "\xff\xff\xff\xff\xff\xff", + }; + uint8_t buffer[6]; + + // test all permutations of a given size + uint16_t perm[N]; + unsigned stack[N]; + for (uint16_t i = 0; i < N; i++) { + perm[i] = i; + stack[i] = 0; + } + + unsigned i = 1; + while (i < N) { + // print permutation to help debugging + printf("--- permutation: ["); + for (unsigned j = 0; j < N; j++) { + if (j > 0) { + printf(", "); + } + printf("%d", perm[j]+1); + } + printf("] ---\n"); + + // create given permutation with multiple commits + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + + for (unsigned j = 0; j < N; j++) { + // adjust id based on future insertions + uint16_t id = perm[j]; + for (unsigned k = j+1; k < N; k++) { + if (perm[j] > perm[k]) { + id -= 1; + } + } + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4, + NULL)) => 0; + } + assert(rbyd.count == N); + + // copy block so we can reset after each delete + lfs_rbyd_t backup_rbyd = rbyd; + uint8_t backup_block[BLOCK_SIZE]; + lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off, + rbyd.block, 0, backup_block, rbyd.off) => 0; + + // try deleting each id + for (unsigned j = 0; j < N; j++) { + for (unsigned l = 0; l < N; l++) { + // print what we are deleting to help debugging + printf("--- delete: %d, create: %d ---\n", j+1, l+1); + + rbyd = backup_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, + rbyd.block, 0, backup_block, rbyd.off) => 0; + + // delete + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(DELETE, 0, j+1, NULL, 0, + NULL)) => 0; + assert(rbyd.count == N-1); + + // try creating each tag to make sure the rbyd tree + // is still usable + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(CREATEREG, 0, l+1, names[l % 6], 6, + NULL)) => 0; + assert(rbyd.count == N); + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + for (unsigned k = 0; k < N; k++) { + lfs_ssize_t size = lfs_rbyd_get(&lfs, &rbyd, + LFS_MKRTAG(CREATEREG, 0, k+1), buffer, 6); + if (k == l) { + assert(size == 6); + assert(memcmp(buffer, names[l % 6], 6) == 0); + } else { + uint16_t expected = k; + if (expected > l) { + expected -= 1; + } + if (expected >= j) { + expected += 1; + } + assert(size == 4); + assert(memcmp(buffer, names[expected % 6], 4) == 0); + } + } + } + } + + // next permutation using Heap's algorithm + if (stack[i] < i) { + if (i % 2 == 0) { + uint16_t t = perm[0]; + perm[0] = perm[i]; + perm[i] = t; + } else { + uint16_t t = perm[stack[i]]; + perm[stack[i]] = perm[i]; + perm[i] = t; + } + stack[i] += 1; + i = 1; + } else { + stack[i] = 0; + i += 1; + } + } +''' + +[cases.test_rbyd_delete_create_range_permutations] +defines.N = 'range(1, 6)' +in = 'lfs.c' +code = ''' + lfs_t lfs; + lfs_init(&lfs, cfg) => 0; + + lfs_rbyd_t init_rbyd = { + .block = 0, + .trunk = 0, + .off = 0, + .rev = 1, + .crc = 0, + .count = 0, + .erased = true, + }; + lfs_rbyd_t rbyd; + const uint8_t names[6][6] = { + "\xaa\xaa\xaa\xaa\xaa\xaa", + "\xbb\xbb\xbb\xbb\xbb\xbb", + "\xcc\xcc\xcc\xcc\xcc\xcc", + "\xdd\xdd\xdd\xdd\xdd\xdd", + "\xee\xee\xee\xee\xee\xee", + "\xff\xff\xff\xff\xff\xff", + }; + uint8_t buffer[6]; + + // test all permutations of a given size + uint16_t perm[N]; + unsigned stack[N]; + for (uint16_t i = 0; i < N; i++) { + perm[i] = i; + stack[i] = 0; + } + + unsigned i = 1; + while (i < N) { + // print permutation to help debugging + printf("--- permutation: ["); + for (unsigned j = 0; j < N; j++) { + if (j > 0) { + printf(", "); + } + printf("%d", perm[j]+1); + } + printf("] ---\n"); + + // create given permutation with multiple commits + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + + for (unsigned j = 0; j < N; j++) { + // adjust id based on future insertions + uint16_t id = perm[j]; + for (unsigned k = j+1; k < N; k++) { + if (perm[j] > perm[k]) { + id -= 1; + } + } + + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(CREATEREG, 0, id+1, names[perm[j] % 6], 4, + LFS_MKRATTR(UATTR, 1, id+1, names[perm[j] % 6], 2, + NULL))) => 0; + } + assert(rbyd.count == N); + + // copy block so we can reset after each delete + lfs_rbyd_t backup_rbyd = rbyd; + uint8_t backup_block[BLOCK_SIZE]; + lfs_bd_read(&lfs, NULL, &lfs.rcache, rbyd.off, + rbyd.block, 0, backup_block, rbyd.off) => 0; + + // try deleting each id + for (unsigned j = 0; j < N; j++) { + for (unsigned l = 0; l < N; l++) { + // print what we are deleting to help debugging + printf("--- delete: %d, create: %d ---\n", j+1, l+1); + + rbyd = backup_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_bd_prog(&lfs, &lfs.pcache, &lfs.rcache, false, + rbyd.block, 0, backup_block, rbyd.off) => 0; + + // delete + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(DELETE, 0, j+1, NULL, 0, + NULL)) => 0; + assert(rbyd.count == N-1); + + // try creating each tag to make sure the rbyd tree + // is still usable + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(CREATEREG, 0, l+1, names[l % 6], 6, + LFS_MKRATTR(UATTR, 1, l+1, names[l % 6], 3, + NULL))) => 0; + assert(rbyd.count == N); + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + for (unsigned k = 0; k < N; k++) { + lfs_ssize_t size = lfs_rbyd_get(&lfs, &rbyd, + LFS_MKRTAG(CREATEREG, 0, k+1), buffer, 6); + if (k == l) { + assert(size == 6); + assert(memcmp(buffer, names[l % 6], 6) == 0); + } else { + uint16_t expected = k; + if (expected > l) { + expected -= 1; + } + if (expected >= j) { + expected += 1; + } + assert(size == 4); + assert(memcmp(buffer, names[expected % 6], 4) == 0); + } + + size = lfs_rbyd_get(&lfs, &rbyd, + LFS_MKRTAG(UATTR, 1, k+1), buffer, 6); + if (k == l) { + assert(size == 3); + assert(memcmp(buffer, names[l % 6], 3) == 0); + } else { + uint16_t expected = k; + if (expected > l) { + expected -= 1; + } + if (expected >= j) { + expected += 1; + } + assert(size == 2); + assert(memcmp(buffer, names[expected % 6], 2) == 0); + } + } + } + } + + // next permutation using Heap's algorithm + if (stack[i] < i) { + if (i % 2 == 0) { + uint16_t t = perm[0]; + perm[0] = perm[i]; + perm[i] = t; + } else { + uint16_t t = perm[stack[i]]; + perm[stack[i]] = perm[i]; + perm[i] = t; + } + stack[i] += 1; + i = 1; + } else { + stack[i] = 0; + i += 1; + } + } +'''