Added delete permutation testing (failing as expected) and some minor tweaks

This commit is contained in:
Christopher Haster
2022-12-31 15:17:27 -06:00
parent 22879c1cbb
commit ef7ee6eb7d
3 changed files with 127 additions and 207 deletions

10
lfs.c
View File

@@ -1488,7 +1488,7 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_,
// lt = lfs_rtag_weight_lt(attr->tag & ~0x7fff, count+1);
// gt = lfs_rtag_weight_gt(attr->tag & ~0x7fff, count+1);
// }
lt = lfs_rtag_weight_lt(tag & ~0x7fff, rbyd_->count+1);
lt = lfs_rtag_weight_lt(tag & ~0x7fff, rbyd_->count+1) - 1;
gt = lfs_rtag_weight_gt(tag & ~0x7fff, rbyd_->count+1) + 1;
} else {
lt = lfs_rtag_weight_lt(tag, rbyd_->count+1);
@@ -1917,13 +1917,13 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_,
if (cut && lfs_rtag_isblack(alt)
&& ((lower && lfs_rtag_isgt(alt))
|| (!lower && lfs_rtag_islt(alt)))) {
printf("bcut (%s, %s)\n", lower ? "lower" : "upper", lfs_rtag_isgt(alt) ? "gt" : "lt");
if (p_alts[0] && lfs_rtag_isred(p_alts[0])) {
printf("bcut\n");
p_alts[0] = lfs_rtag_black(p_alts[0]);
if ((lower && lfs_rtag_isgt(alt))
|| (!lower && lfs_rtag_islt(alt))) {
printf("rcut\n");
if ((lower && lfs_rtag_isgt(p_alts[0]))
|| (!lower && lfs_rtag_islt(p_alts[0]))) {
printf("rcut (%s, %s)\n", lower ? "lower" : "upper", lfs_rtag_isgt(p_alts[0]) ? "gt" : "lt");
lfs_rbyd_p_pop(p_alts, p_jumps);
}
}

View File

@@ -371,7 +371,7 @@ def main(disk, block_size, block1, block2=None, *,
and not tag & 0x4 else ''),
'\x1b[m' if color and j_ >= off else '',
' (%s)' % ', '.join(notes) if notes
else ' %s' % ''.join(
else ' %s' % ''.join(
('\x1b[33my\x1b[m' if color else 'y')
if alts[i] & 0x1
and i+1 < len(alts)

View File

@@ -1841,98 +1841,6 @@ code = '''
=> LFS_ERR_NOENT;
'''
[cases.test_rbyd_multi_remove]
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;
lfs_off_t off;
lfs_size_t size;
// add and remove one attribute
rbyd = init_rbyd;
lfs_bd_erase(&lfs, rbyd.block) => 0;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRRMATTR(UATTR, 1, 0, NULL)) => 0;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
=> LFS_ERR_NOENT;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
=> LFS_ERR_NOENT;
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
=> LFS_ERR_NOENT;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
=> LFS_ERR_NOENT;
// commit with two attributes, remove the first one
rbyd = init_rbyd;
lfs_bd_erase(&lfs, rbyd.block) => 0;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)) => 0;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRRMATTR(UATTR, 1, 0, NULL)) => 0;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
=> LFS_MKRTAG(UATTR, 2, 0);
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
=> LFS_MKRTAG(UATTR, 2, 0);
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
=> LFS_ERR_NOENT;
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
=> LFS_MKRTAG(UATTR, 2, 0);
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
=> LFS_MKRTAG(UATTR, 2, 0);
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
=> LFS_ERR_NOENT;
// commit with two attributes, remove the second one
rbyd = init_rbyd;
lfs_bd_erase(&lfs, rbyd.block) => 0;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRATTR(UATTR, 1, 0, &(uint32_t){0xaaaaaaaa}, 4, NULL)) => 0;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRATTR(UATTR, 2, 0, &(uint32_t){0xbbbbbbbb}, 4, NULL)) => 0;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRRMATTR(UATTR, 2, 0, NULL)) => 0;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
=> LFS_MKRTAG(UATTR, 1, 0);
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
=> LFS_ERR_NOENT;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
=> LFS_ERR_NOENT;
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 1, 0), &off, &size)
=> LFS_MKRTAG(UATTR, 1, 0);
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 2, 0), &off, &size)
=> LFS_ERR_NOENT;
lfs_rbyd_lookup(&lfs, &rbyd, LFS_MKRTAG(UATTR, 3, 0), &off, &size)
=> LFS_ERR_NOENT;
'''
[cases.test_rbyd_remove_permutations]
defines.N = 'range(1, 7)'
in = 'lfs.c'
@@ -1961,115 +1869,6 @@ code = '''
stack[i] = 0;
}
uint8_t i = 1;
while (i < N) {
// print permutation to help debugging
printf("--- permutation: [");
for (int j = 0; j < N; j++) {
if (j > 0) {
printf(", ");
}
printf("%d", perm[j]+1);
}
printf("] ---\n");
// build the attribute list for the current permutation
struct lfs_rattr attrs[N];
for (int j = 0; j < N; j++) {
attrs[j] = *LFS_MKRATTR(
UATTR, perm[j]+1, 0,
&(uint32_t){0xaaaaaaaa}, 4,
(j+1 < N) ? &attrs[j+1] : NULL);
}
// create the given permutation
rbyd = init_rbyd;
lfs_bd_erase(&lfs, rbyd.block) => 0;
lfs_rbyd_commit(&lfs, &rbyd, attrs) => 0;
// copy block so we can reset after each remove
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 removing each tag
for (int j = 0; j < N; j++) {
// print what we are removing to help debugging
printf("--- remove: %d ---\n", j+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;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRRMATTR(UATTR, j+1, 0, NULL)) => 0;
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
for (int k = 0; k < N; k++) {
lfs_srtag_t tag = lfs_rbyd_lookup(&lfs, &rbyd,
LFS_MKRTAG(UATTR, k+1, 0), &off, &size);
if (k == j) {
if (j == N-1) {
assert(tag == LFS_ERR_NOENT);
} else {
assert(tag == LFS_MKRTAG(UATTR, j+1+1, 0));
}
} else {
assert(tag == LFS_MKRTAG(UATTR, k+1, 0));
}
}
}
// next permutation using Heap's algorithm
if (stack[i] < i) {
if (i % 2 == 0) {
uint8_t t = perm[0];
perm[0] = perm[i];
perm[i] = t;
} else {
uint8_t t = perm[stack[i]];
perm[stack[i]] = perm[i];
perm[i] = t;
}
stack[i] += 1;
i = 1;
} else {
stack[i] = 0;
i += 1;
}
}
'''
[cases.test_rbyd_multi_remove_permutations]
defines.N = 'range(1, 7)'
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;
lfs_off_t off;
lfs_size_t size;
// test all permutations of a given size
uint8_t perm[N];
uint8_t stack[N];
for (uint8_t i = 0; i < N; i++) {
perm[i] = i;
stack[i] = 0;
}
uint8_t i = 1;
while (i < N) {
// print permutation to help debugging
@@ -3100,3 +2899,124 @@ code = '''
lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4)
=> LFS_ERR_NOENT;
'''
[cases.test_rbyd_delete_permutations]
defines.N = 'range(1, 7)'
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][4] = {
"\xaa\xaa\xaa\xaa",
"\xbb\xbb\xbb\xbb",
"\xcc\xcc\xcc\xcc",
"\xdd\xdd\xdd\xdd",
"\xee\xee\xee\xee",
"\xff\xff\xff\xff",
};
uint8_t buffer[4];
// test all permutations of a given size
uint8_t perm[N];
uint8_t stack[N];
for (uint8_t i = 0; i < N; i++) {
perm[i] = i;
stack[i] = 0;
}
uint8_t i = 1;
while (i < N) {
// print permutation to help debugging
printf("--- permutation: [");
for (int j = 0; j < N; j++) {
if (j > 0) {
printf(", ");
}
printf("%d", perm[j]+1);
}
printf("] ---\n");
// create given permutation with multiple commits
rbyd = init_rbyd;
lfs_bd_erase(&lfs, rbyd.block) => 0;
for (int j = 0; j < N; j++) {
// adjust id based on future insertions
uint16_t id = perm[j];
for (int 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 (int j = 0; j < N; j++) {
// print what we are deleting to help debugging
printf("--- delete: %d ---\n", j+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;
lfs_rbyd_commit(&lfs, &rbyd,
LFS_MKRATTR(DELETE, 0, j+1, NULL, 0, NULL)) => 0;
assert(rbyd.count == N-1);
lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0;
for (int k = 0; k < N-1; k++) {
lfs_rbyd_get(&lfs, &rbyd,
LFS_MKRTAG(CREATEREG, 0, k+1), buffer, 4) => 4;
if (k >= j) {
assert(memcmp(buffer, names[(k+1) % 6], 4) == 0);
} else {
assert(memcmp(buffer, names[k % 6], 4) == 0);
}
}
lfs_rbyd_get(&lfs, &rbyd,
LFS_MKRTAG(CREATEREG, 0, N-1+1), buffer, 4)
=> LFS_ERR_NOENT;
}
// next permutation using Heap's algorithm
if (stack[i] < i) {
if (i % 2 == 0) {
uint8_t t = perm[0];
perm[0] = perm[i];
perm[i] = t;
} else {
uint8_t t = perm[stack[i]];
perm[stack[i]] = perm[i];
perm[i] = t;
}
stack[i] += 1;
i = 1;
} else {
stack[i] = 0;
i += 1;
}
}
'''