forked from Imagelibrary/littlefs
Added delete permutation testing (failing as expected) and some minor tweaks
This commit is contained in:
10
lfs.c
10
lfs.c
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
Reference in New Issue
Block a user