From dc5e74ac411b1e8d3eb257663e20bc0bb94235f2 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 2 Jan 2023 15:11:32 -0600 Subject: [PATCH] Added range deletion testing --- lfs.c | 8 ++- tests/test_rbyd.toml | 153 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 158 insertions(+), 3 deletions(-) diff --git a/lfs.c b/lfs.c index 784d1d44..35df7010 100644 --- a/lfs.c +++ b/lfs.c @@ -1175,11 +1175,15 @@ static int lfs_rbyd_fetch(lfs_t *lfs, // found a create? increase count of ids if (lfs_rtag_type1(tag) == LFS_TYPE1_CREATE) { - LFS_ASSERT(count < 0xffff); + // TODO put this somewhere? we can't check this here because + // we may be reading invalid tags + //LFS_ASSERT(count < 0xffff); count += 1; // found a delete? decrease count of ids } else if (lfs_rtag_type1(tag) == LFS_TYPE1_DELETE) { - LFS_ASSERT(count > 0); + // TODO put this somewhere? we can't check this here because + // we may be reading invalid tags + //LFS_ASSERT(count > 0); count -= 1; // found an fcrc? save for later } else if (lfs_rtag_type1(tag) == LFS_TYPE1_FCRC) { diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index aa382c93..03e36ec6 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -2718,6 +2718,8 @@ code = ''' assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 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_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; assert(rbyd.count == 1); @@ -2728,6 +2730,8 @@ code = ''' assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 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_ERR_NOENT; // try to delete the other id rbyd = init_rbyd; @@ -2749,6 +2753,8 @@ code = ''' assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 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_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; assert(rbyd.count == 1); @@ -2760,6 +2766,8 @@ code = ''' assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 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_ERR_NOENT; // try to delete the largest of three rbyd = init_rbyd; @@ -2789,6 +2797,8 @@ code = ''' assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 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_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; assert(rbyd.count == 2); @@ -2806,6 +2816,8 @@ code = ''' assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 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_ERR_NOENT; // try to delete the smallest of three rbyd = init_rbyd; @@ -2835,6 +2847,8 @@ code = ''' assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 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_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; assert(rbyd.count == 2); @@ -2852,6 +2866,8 @@ code = ''' assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 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_ERR_NOENT; // try to delete the middle rbyd = init_rbyd; @@ -2881,6 +2897,8 @@ code = ''' assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 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_ERR_NOENT; lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; assert(rbyd.count == 2); @@ -2898,6 +2916,8 @@ code = ''' assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 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_ERR_NOENT; ''' [cases.test_rbyd_delete_permutations] @@ -3021,4 +3041,135 @@ code = ''' } ''' -# [cases.test_rbyd_delete_range_permutations] +[cases.test_rbyd_delete_range_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 + 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], 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++) { + // 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 (unsigned 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(UATTR, 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; + lfs_rbyd_get(&lfs, &rbyd, + LFS_MKRTAG(UATTR, 0, N-1+1), buffer, 4) + => LFS_ERR_NOENT; + } + + // 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; + } + } +'''