Added fuzzing rbyd tests, mostly to find remove/delete balancing issues
Note that despite being prng based, these are still strictly reproducible. Running the tests multiple times will always give the same result.
This commit is contained in:
+410
-57
@@ -2113,12 +2113,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N;
|
lfs_size_t n = 1 + N;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2212,12 +2212,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N;
|
lfs_size_t n = 1 + N;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -2697,12 +2697,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N + N;
|
lfs_size_t n = 1 + N + N;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -3035,12 +3035,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N + 2;
|
lfs_size_t n = 1 + N + 2;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -3646,12 +3646,186 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N + N + 1;
|
lfs_size_t n = 1 + N + N + 1;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|
||||||
|
# the main purpose of this test is to try to fuzz for failures in the
|
||||||
|
# balancing algorithm
|
||||||
|
[cases.test_rbyd_random_append_removes]
|
||||||
|
defines.N = 'range(1, 33)'
|
||||||
|
defines.ITER = 1000
|
||||||
|
in = 'lfs.c'
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfs_init(&lfs, cfg) => 0;
|
||||||
|
|
||||||
|
lfsr_rbyd_t init_rbyd = {
|
||||||
|
.block = 0,
|
||||||
|
.rev = 1,
|
||||||
|
.off = 0,
|
||||||
|
.crc = 0,
|
||||||
|
.trunk = 0,
|
||||||
|
.weight = 0,
|
||||||
|
.erased = true,
|
||||||
|
};
|
||||||
|
lfsr_rbyd_t rbyd;
|
||||||
|
const char *alpha = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
uint8_t buffer[4];
|
||||||
|
|
||||||
|
// keep track of the worst case size and seed
|
||||||
|
lfs_size_t worst_size = 0;
|
||||||
|
uint32_t worst_seed = 0;
|
||||||
|
|
||||||
|
// iterate through seeds so we can reproduce easily
|
||||||
|
for (uint32_t seed = 1; seed < ITER+1; seed++) {
|
||||||
|
printf("--- seed: %d ---\n", seed);
|
||||||
|
printf("perm: [");
|
||||||
|
uint32_t prng = seed;
|
||||||
|
for (unsigned i = 0; i < N; i++) {
|
||||||
|
// choose an attr
|
||||||
|
uint8_t attr = TEST_PRNG(&prng) % N;
|
||||||
|
// choose append or remove
|
||||||
|
if (TEST_PRNG(&prng) & 1) {
|
||||||
|
printf("a0x%02x=%c", attr, alpha[i % 26]);
|
||||||
|
} else {
|
||||||
|
printf("r0x%02x", attr);
|
||||||
|
}
|
||||||
|
if (i < N-1) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
// set up a simulation to compare against
|
||||||
|
char *sim = malloc(N);
|
||||||
|
memset(sim, 0, N);
|
||||||
|
|
||||||
|
// set up rbyd block
|
||||||
|
rbyd = init_rbyd;
|
||||||
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
||||||
|
|
||||||
|
prng = seed;
|
||||||
|
for (unsigned i = 0; i < N; i++) {
|
||||||
|
// choose an attr
|
||||||
|
uint8_t attr = TEST_PRNG(&prng) % N;
|
||||||
|
// choose append or remove
|
||||||
|
if (TEST_PRNG(&prng) & 1) {
|
||||||
|
// update our sim
|
||||||
|
sim[attr] = alpha[i % 26];
|
||||||
|
// update our rbyd
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd,
|
||||||
|
LFSR_ATTR(UATTR(attr), -1, &alpha[i % 26], 1,
|
||||||
|
NULL)) => 0;
|
||||||
|
} else {
|
||||||
|
// update our sim
|
||||||
|
sim[attr] = '\0';
|
||||||
|
// update our rbyd
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd,
|
||||||
|
LFSR_ATTR(RMUATTR(attr), -1, NULL, 0,
|
||||||
|
NULL)) => 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare rbyd vs simulation
|
||||||
|
printf("expd: [");
|
||||||
|
bool first = true;
|
||||||
|
for (unsigned attr = 0; attr < N; attr++) {
|
||||||
|
if (sim[attr]) {
|
||||||
|
if (!first) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
printf("0x%02x=%c", attr, sim[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
printf("rbyd: [");
|
||||||
|
first = true;
|
||||||
|
for (unsigned attr = 0; attr < N; attr++) {
|
||||||
|
lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd,
|
||||||
|
LFSR_TAG_UATTR(attr), -1, buffer, 4);
|
||||||
|
if (size >= 0) {
|
||||||
|
if (!first) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
printf("0x%02x=%.*s", attr, size, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
for (unsigned attr = 0; attr < N; attr++) {
|
||||||
|
lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd,
|
||||||
|
LFSR_TAG_UATTR(attr), -1, buffer, 4);
|
||||||
|
if (sim[attr]) {
|
||||||
|
assert(size == 1);
|
||||||
|
assert(memcmp(&sim[attr], buffer, 1) == 0);
|
||||||
|
} else {
|
||||||
|
assert(size == LFS_ERR_NOENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep track of the worst permutation
|
||||||
|
if (rbyd.off > worst_size) {
|
||||||
|
worst_size = rbyd.off;
|
||||||
|
worst_seed = seed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the worst seed + size, and rerun it so it's left on the disk
|
||||||
|
// if used with -ddisk
|
||||||
|
printf("--- worst ---\n");
|
||||||
|
printf("worst_seed: %d\n", worst_seed);
|
||||||
|
printf("worst_size: %d\n", worst_size);
|
||||||
|
printf("worst_perm: [");
|
||||||
|
uint32_t prng = worst_seed;
|
||||||
|
for (unsigned i = 0; i < N; i++) {
|
||||||
|
// choose an attr
|
||||||
|
uint8_t attr = TEST_PRNG(&prng) % N;
|
||||||
|
// choose append or remove
|
||||||
|
if (TEST_PRNG(&prng) & 1) {
|
||||||
|
printf("a0x%02x=%c", attr, alpha[i % 26]);
|
||||||
|
} else {
|
||||||
|
printf("r0x%02x", attr);
|
||||||
|
}
|
||||||
|
if (i < N-1) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
// set up rbyd block
|
||||||
|
rbyd = init_rbyd;
|
||||||
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
||||||
|
|
||||||
|
prng = worst_seed;
|
||||||
|
for (unsigned i = 0; i < N; i++) {
|
||||||
|
// choose an attr
|
||||||
|
uint8_t attr = TEST_PRNG(&prng) % N;
|
||||||
|
// choose append or remove
|
||||||
|
if (TEST_PRNG(&prng) & 1) {
|
||||||
|
// update our rbyd
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd,
|
||||||
|
LFSR_ATTR(UATTR(attr), -1, &alpha[i % 26], 1,
|
||||||
|
NULL)) => 0;
|
||||||
|
} else {
|
||||||
|
// update our rbyd
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd,
|
||||||
|
LFSR_ATTR(RMUATTR(attr), -1, NULL, 0,
|
||||||
|
NULL)) => 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// our tree should be strictly <= 2*log(n)+1, assume tags are strictly
|
||||||
|
// <=12 bytes, note this only holds true with byte-level progs
|
||||||
|
if (PROG_SIZE == 1) {
|
||||||
|
assert(worst_size <= N*12*(2*lfs_nlog2(N)+1)+1);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -3796,12 +3970,12 @@ code = '''
|
|||||||
# // by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
# // by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
# lfs_size_t n = 1 + N + 1 + 1;
|
# lfs_size_t n = 1 + N + 1 + 1;
|
||||||
# printf("worst size: %u B (N=%u, estimate=%u)\n",
|
# printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
# worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
# worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
# printf("avg height: %u B (N=%u, estimate=%u)\n",
|
# printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
# worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
# worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
# // note this only holds true with byte-level progs
|
# // note this only holds true with byte-level progs
|
||||||
# if (PROG_SIZE == 1) {
|
# if (PROG_SIZE == 1) {
|
||||||
# assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
# assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
# }
|
# }
|
||||||
#'''
|
#'''
|
||||||
|
|
||||||
@@ -4222,12 +4396,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N;
|
lfs_size_t n = 1 + N;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -4333,12 +4507,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N;
|
lfs_size_t n = 1 + N;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -5471,12 +5645,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N + N*M;
|
lfs_size_t n = 1 + N + N*M;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -5593,12 +5767,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N + N*M;
|
lfs_size_t n = 1 + N + N*M;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -6330,12 +6504,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N + N*M + N*M;
|
lfs_size_t n = 1 + N + N*M + N*M;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -6535,12 +6709,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N+N*M + 2;
|
lfs_size_t n = 1 + N+N*M + 2;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -6670,12 +6844,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N + N*M + N*M;
|
lfs_size_t n = 1 + N + N*M + N*M;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -7301,12 +7475,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N + 2;
|
lfs_size_t n = 1 + N + 2;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -7503,12 +7677,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N+N*M + 1 + 1+M;
|
lfs_size_t n = 1 + N+N*M + 1 + 1+M;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -7900,12 +8074,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + 2*N + 1;
|
lfs_size_t n = 1 + 2*N + 1;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -8073,12 +8247,12 @@ code = '''
|
|||||||
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
// by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
lfs_size_t n = 1 + N+N*M + N + 1+M;
|
lfs_size_t n = 1 + N+N*M + N + 1+M;
|
||||||
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
// note this only holds true with byte-level progs
|
// note this only holds true with byte-level progs
|
||||||
if (PROG_SIZE == 1) {
|
if (PROG_SIZE == 1) {
|
||||||
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@@ -8233,12 +8407,12 @@ code = '''
|
|||||||
# // by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
# // by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
# lfs_size_t n = 1 + N + 1 + 1;
|
# lfs_size_t n = 1 + N + 1 + 1;
|
||||||
# printf("worst size: %u B (N=%u, estimate=%u)\n",
|
# printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
# worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
# worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
# printf("avg height: %u B (N=%u, estimate=%u)\n",
|
# printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
# worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
# worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
# // note this only holds true with byte-level progs
|
# // note this only holds true with byte-level progs
|
||||||
# if (PROG_SIZE == 1) {
|
# if (PROG_SIZE == 1) {
|
||||||
# assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
# assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
# }
|
# }
|
||||||
#'''
|
#'''
|
||||||
#
|
#
|
||||||
@@ -8426,11 +8600,190 @@ code = '''
|
|||||||
# // by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
# // by height <= 2*log(n)+1, assume tags are strictly <=12 bytes
|
||||||
# lfs_size_t n = 1 + N+N*M + 1 + 1+M;
|
# lfs_size_t n = 1 + N+N*M + 1 + 1+M;
|
||||||
# printf("worst size: %u B (N=%u, estimate=%u)\n",
|
# printf("worst size: %u B (N=%u, estimate=%u)\n",
|
||||||
# worst_size, n, 12*n*(2*lfs_nlog2(n)+1));
|
# worst_size, n, 12*n*(2*lfs_nlog2(n)+1)+4);
|
||||||
# printf("avg height: %u B (N=%u, estimate=%u)\n",
|
# printf("avg height: %u B (N=%u, estimate=%u)\n",
|
||||||
# worst_size / n, n, 12*(2*lfs_nlog2(n)+1));
|
# worst_size / n, n, 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
# // note this only holds true with byte-level progs
|
# // note this only holds true with byte-level progs
|
||||||
# if (PROG_SIZE == 1) {
|
# if (PROG_SIZE == 1) {
|
||||||
# assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1));
|
# assert(worst_size / n <= 12*(2*lfs_nlog2(n)+1)+4);
|
||||||
# }
|
# }
|
||||||
#'''
|
#'''
|
||||||
|
|
||||||
|
# the main purpose of this test is to try to fuzz for failures in the
|
||||||
|
# balancing algorithm
|
||||||
|
[cases.test_rbyd_random_create_deletes]
|
||||||
|
defines.N = 'range(1, 33)'
|
||||||
|
defines.ITER = 1000
|
||||||
|
in = 'lfs.c'
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfs_init(&lfs, cfg) => 0;
|
||||||
|
|
||||||
|
lfsr_rbyd_t init_rbyd = {
|
||||||
|
.block = 0,
|
||||||
|
.rev = 1,
|
||||||
|
.off = 0,
|
||||||
|
.crc = 0,
|
||||||
|
.trunk = 0,
|
||||||
|
.weight = 0,
|
||||||
|
.erased = true,
|
||||||
|
};
|
||||||
|
lfsr_rbyd_t rbyd;
|
||||||
|
const char *alpha = "abcdefghijklmnopqrstuvwxyz";
|
||||||
|
uint8_t buffer[4];
|
||||||
|
|
||||||
|
// keep track of the worst case size and seed
|
||||||
|
lfs_size_t worst_size = 0;
|
||||||
|
uint32_t worst_seed = 0;
|
||||||
|
|
||||||
|
// iterate through seeds so we can reproduce easily
|
||||||
|
for (uint32_t seed = 1; seed < ITER+1; seed++) {
|
||||||
|
printf("--- seed: %d ---\n", seed);
|
||||||
|
printf("perm: [");
|
||||||
|
uint32_t prng = seed;
|
||||||
|
lfs_size_t count = 0;
|
||||||
|
for (unsigned i = 0; i < N; i++) {
|
||||||
|
// choose an id
|
||||||
|
lfsr_sid_t id = TEST_PRNG(&prng) % (count+1);
|
||||||
|
// choose create or delete
|
||||||
|
if (id == (lfsr_sid_t)count || (TEST_PRNG(&prng) & 1)) {
|
||||||
|
printf("c%d=%c", id, alpha[i % 26]);
|
||||||
|
count += 1;
|
||||||
|
} else {
|
||||||
|
printf("d%d", id);
|
||||||
|
count -= 1;
|
||||||
|
}
|
||||||
|
if (i < N-1) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
// set up a simulation to compare against, fun fact this performs
|
||||||
|
// worst than our actual rbyd block!
|
||||||
|
char *sim = malloc(N);
|
||||||
|
memset(sim, 0, N);
|
||||||
|
|
||||||
|
// set up rbyd block
|
||||||
|
rbyd = init_rbyd;
|
||||||
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
||||||
|
|
||||||
|
prng = seed;
|
||||||
|
count = 0;
|
||||||
|
for (unsigned i = 0; i < N; i++) {
|
||||||
|
// choose an id
|
||||||
|
lfsr_sid_t id = TEST_PRNG(&prng) % (count+1);
|
||||||
|
// choose create or delete
|
||||||
|
if (id == (lfsr_sid_t)count || (TEST_PRNG(&prng) & 1)) {
|
||||||
|
// update our sim
|
||||||
|
memmove(sim+id+1, sim+id, count-id);
|
||||||
|
sim[id] = alpha[i % 26];
|
||||||
|
count += 1;
|
||||||
|
// update our rbyd
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd,
|
||||||
|
LFSR_ATTR(MKREG, id, &alpha[i % 26], 1,
|
||||||
|
NULL)) => 0;
|
||||||
|
} else {
|
||||||
|
// update our sim
|
||||||
|
memmove(sim+id, sim+id+1, count-id-1);
|
||||||
|
count -= 1;
|
||||||
|
// update our rbyd
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd,
|
||||||
|
LFSR_ATTR(RM, id, NULL, 0,
|
||||||
|
NULL)) => 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare rbyd vs simulation
|
||||||
|
printf("expd: [");
|
||||||
|
for (lfsr_sid_t id = 0; id < (lfsr_sid_t)count; id++) {
|
||||||
|
printf("%c", sim[id]);
|
||||||
|
if (id < (lfsr_sid_t)count-1) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
printf("rbyd: [");
|
||||||
|
for (lfsr_sid_t id = 0; id < (lfsr_sid_t)rbyd.weight; id++) {
|
||||||
|
lfs_ssize_t size = lfsr_rbyd_get(&lfs, &rbyd,
|
||||||
|
LFSR_TAG_MKREG, id, buffer, 4);
|
||||||
|
if (size >= 0) {
|
||||||
|
printf("%.*s", size, buffer);
|
||||||
|
} else {
|
||||||
|
printf("?");
|
||||||
|
}
|
||||||
|
if (id < (lfsr_sid_t)count-1) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
assert(count == rbyd.weight);
|
||||||
|
for (lfsr_sid_t id = 0; id < (lfsr_sid_t)count; id++) {
|
||||||
|
lfsr_rbyd_get(&lfs, &rbyd, LFSR_TAG_MKREG, id, buffer, 4) => 1;
|
||||||
|
assert(memcmp(&sim[id], buffer, 1) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep track of the worst permutation
|
||||||
|
if (rbyd.off > worst_size) {
|
||||||
|
worst_size = rbyd.off;
|
||||||
|
worst_seed = seed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the worst seed + size, and rerun it so it's left on the disk
|
||||||
|
// if used with -ddisk
|
||||||
|
printf("--- worst ---\n");
|
||||||
|
printf("worst_seed: %d\n", worst_seed);
|
||||||
|
printf("worst_size: %d\n", worst_size);
|
||||||
|
printf("worst_perm: [");
|
||||||
|
uint32_t prng = worst_seed;
|
||||||
|
lfs_size_t count = 0;
|
||||||
|
for (unsigned i = 0; i < N; i++) {
|
||||||
|
// choose an id
|
||||||
|
lfsr_sid_t id = TEST_PRNG(&prng) % (count+1);
|
||||||
|
// choose create or delete
|
||||||
|
if (id == (lfsr_sid_t)count || (TEST_PRNG(&prng) & 1)) {
|
||||||
|
printf("c%d=%c", id, alpha[i % 26]);
|
||||||
|
count += 1;
|
||||||
|
} else {
|
||||||
|
printf("d%d", id);
|
||||||
|
count -= 1;
|
||||||
|
}
|
||||||
|
if (i < N-1) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
|
||||||
|
// set up rbyd block
|
||||||
|
rbyd = init_rbyd;
|
||||||
|
lfs_bd_erase(&lfs, rbyd.block) => 0;
|
||||||
|
|
||||||
|
prng = worst_seed;
|
||||||
|
count = 0;
|
||||||
|
for (unsigned i = 0; i < N; i++) {
|
||||||
|
// choose an id
|
||||||
|
lfsr_sid_t id = TEST_PRNG(&prng) % (count+1);
|
||||||
|
// choose create or delete
|
||||||
|
if (id == (lfsr_sid_t)count || (TEST_PRNG(&prng) & 1)) {
|
||||||
|
count += 1;
|
||||||
|
// update our rbyd
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd,
|
||||||
|
LFSR_ATTR(MKREG, id, &alpha[i % 26], 1,
|
||||||
|
NULL)) => 0;
|
||||||
|
} else {
|
||||||
|
count -= 1;
|
||||||
|
// update our rbyd
|
||||||
|
lfsr_rbyd_commit(&lfs, &rbyd,
|
||||||
|
LFSR_ATTR(RM, id, NULL, 0,
|
||||||
|
NULL)) => 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// our tree should be strictly <= 2*log(n)+1, assume tags are strictly
|
||||||
|
// <=12 bytes, note this only holds true with byte-level progs
|
||||||
|
if (PROG_SIZE == 1) {
|
||||||
|
assert(worst_size <= N*12*(2*lfs_nlog2(N)+1)+1);
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
|||||||
Reference in New Issue
Block a user