[cases.test_files_simple] defines.INLINE_MAX = [0, -1, 8] code = ''' lfs2_t lfs2; lfs2_format(&lfs2, cfg) => 0; lfs2_mount(&lfs2, cfg) => 0; lfs2_file_t file; lfs2_file_open(&lfs2, &file, "hello", LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_EXCL) => 0; lfs2_size_t size = strlen("Hello World!")+1; uint8_t buffer[1024]; strcpy((char*)buffer, "Hello World!"); lfs2_file_write(&lfs2, &file, buffer, size) => size; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "hello", LFS2_O_RDONLY) => 0; lfs2_file_read(&lfs2, &file, buffer, size) => size; assert(strcmp((char*)buffer, "Hello World!") == 0); lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; ''' [cases.test_files_large] defines.SIZE = [32, 8192, 262144, 0, 7, 8193] defines.CHUNKSIZE = [31, 16, 33, 1, 1023] defines.INLINE_MAX = [0, -1, 8] code = ''' lfs2_t lfs2; lfs2_format(&lfs2, cfg) => 0; // write lfs2_mount(&lfs2, cfg) => 0; lfs2_file_t file; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_EXCL) => 0; uint32_t prng = 1; uint8_t buffer[1024]; for (lfs2_size_t i = 0; i < SIZE; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE-i); for (lfs2_size_t b = 0; b < chunk; b++) { buffer[b] = TEST_PRNG(&prng) & 0xff; } lfs2_file_write(&lfs2, &file, buffer, chunk) => chunk; } lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // read lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY) => 0; lfs2_file_size(&lfs2, &file) => SIZE; prng = 1; for (lfs2_size_t i = 0; i < SIZE; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } lfs2_file_read(&lfs2, &file, buffer, CHUNKSIZE) => 0; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; ''' [cases.test_files_rewrite] defines.SIZE1 = [32, 8192, 131072, 0, 7, 8193] defines.SIZE2 = [32, 8192, 131072, 0, 7, 8193] defines.CHUNKSIZE = [31, 16, 1] defines.INLINE_MAX = [0, -1, 8] code = ''' lfs2_t lfs2; lfs2_format(&lfs2, cfg) => 0; // write lfs2_mount(&lfs2, cfg) => 0; lfs2_file_t file; uint8_t buffer[1024]; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_EXCL) => 0; uint32_t prng = 1; for (lfs2_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE1-i); for (lfs2_size_t b = 0; b < chunk; b++) { buffer[b] = TEST_PRNG(&prng) & 0xff; } lfs2_file_write(&lfs2, &file, buffer, chunk) => chunk; } lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // read lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY) => 0; lfs2_file_size(&lfs2, &file) => SIZE1; prng = 1; for (lfs2_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE1-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } lfs2_file_read(&lfs2, &file, buffer, CHUNKSIZE) => 0; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // rewrite lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_WRONLY) => 0; prng = 2; for (lfs2_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE2-i); for (lfs2_size_t b = 0; b < chunk; b++) { buffer[b] = TEST_PRNG(&prng) & 0xff; } lfs2_file_write(&lfs2, &file, buffer, chunk) => chunk; } lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // read lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY) => 0; lfs2_file_size(&lfs2, &file) => lfs2_max(SIZE1, SIZE2); prng = 2; for (lfs2_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE2-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } if (SIZE1 > SIZE2) { prng = 1; for (lfs2_size_t b = 0; b < SIZE2; b++) { TEST_PRNG(&prng); } for (lfs2_size_t i = SIZE2; i < SIZE1; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE1-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } } lfs2_file_read(&lfs2, &file, buffer, CHUNKSIZE) => 0; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; ''' [cases.test_files_append] defines.SIZE1 = [32, 8192, 131072, 0, 7, 8193] defines.SIZE2 = [32, 8192, 131072, 0, 7, 8193] defines.CHUNKSIZE = [31, 16, 1] defines.INLINE_MAX = [0, -1, 8] code = ''' lfs2_t lfs2; lfs2_format(&lfs2, cfg) => 0; // write lfs2_mount(&lfs2, cfg) => 0; lfs2_file_t file; uint8_t buffer[1024]; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_EXCL) => 0; uint32_t prng = 1; for (lfs2_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE1-i); for (lfs2_size_t b = 0; b < chunk; b++) { buffer[b] = TEST_PRNG(&prng) & 0xff; } lfs2_file_write(&lfs2, &file, buffer, chunk) => chunk; } lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // read lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY) => 0; lfs2_file_size(&lfs2, &file) => SIZE1; prng = 1; for (lfs2_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE1-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } lfs2_file_read(&lfs2, &file, buffer, CHUNKSIZE) => 0; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // append lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_WRONLY | LFS2_O_APPEND) => 0; prng = 2; for (lfs2_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE2-i); for (lfs2_size_t b = 0; b < chunk; b++) { buffer[b] = TEST_PRNG(&prng) & 0xff; } lfs2_file_write(&lfs2, &file, buffer, chunk) => chunk; } lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // read lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY) => 0; lfs2_file_size(&lfs2, &file) => SIZE1 + SIZE2; prng = 1; for (lfs2_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE1-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } prng = 2; for (lfs2_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE2-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } lfs2_file_read(&lfs2, &file, buffer, CHUNKSIZE) => 0; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; ''' [cases.test_files_truncate] defines.SIZE1 = [32, 8192, 131072, 0, 7, 8193] defines.SIZE2 = [32, 8192, 131072, 0, 7, 8193] defines.CHUNKSIZE = [31, 16, 1] defines.INLINE_MAX = [0, -1, 8] code = ''' lfs2_t lfs2; lfs2_format(&lfs2, cfg) => 0; // write lfs2_mount(&lfs2, cfg) => 0; lfs2_file_t file; uint8_t buffer[1024]; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_EXCL) => 0; uint32_t prng = 1; for (lfs2_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE1-i); for (lfs2_size_t b = 0; b < chunk; b++) { buffer[b] = TEST_PRNG(&prng) & 0xff; } lfs2_file_write(&lfs2, &file, buffer, chunk) => chunk; } lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // read lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY) => 0; lfs2_file_size(&lfs2, &file) => SIZE1; prng = 1; for (lfs2_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE1-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } lfs2_file_read(&lfs2, &file, buffer, CHUNKSIZE) => 0; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // truncate lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_WRONLY | LFS2_O_TRUNC) => 0; prng = 2; for (lfs2_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE2-i); for (lfs2_size_t b = 0; b < chunk; b++) { buffer[b] = TEST_PRNG(&prng) & 0xff; } lfs2_file_write(&lfs2, &file, buffer, chunk) => chunk; } lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; // read lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY) => 0; lfs2_file_size(&lfs2, &file) => SIZE2; prng = 2; for (lfs2_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE2-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } lfs2_file_read(&lfs2, &file, buffer, CHUNKSIZE) => 0; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; ''' [cases.test_files_reentrant_write] defines.SIZE = [32, 0, 7, 2049] defines.CHUNKSIZE = [31, 16, 65] defines.INLINE_MAX = [0, -1, 8] reentrant = true defines.POWERLOSS_BEHAVIOR = [ 'LFS2_EMUBD_POWERLOSS_NOOP', 'LFS2_EMUBD_POWERLOSS_OOO', ] code = ''' lfs2_t lfs2; int err = lfs2_mount(&lfs2, cfg); if (err) { lfs2_format(&lfs2, cfg) => 0; lfs2_mount(&lfs2, cfg) => 0; } lfs2_file_t file; uint8_t buffer[1024]; err = lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY); assert(err == LFS2_ERR_NOENT || err == 0); if (err == 0) { // can only be 0 (new file) or full size lfs2_size_t size = lfs2_file_size(&lfs2, &file); assert(size == 0 || size == SIZE); lfs2_file_close(&lfs2, &file) => 0; } // write lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_WRONLY | LFS2_O_CREAT) => 0; uint32_t prng = 1; for (lfs2_size_t i = 0; i < SIZE; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE-i); for (lfs2_size_t b = 0; b < chunk; b++) { buffer[b] = TEST_PRNG(&prng) & 0xff; } lfs2_file_write(&lfs2, &file, buffer, chunk) => chunk; } lfs2_file_close(&lfs2, &file) => 0; // read lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY) => 0; lfs2_file_size(&lfs2, &file) => SIZE; prng = 1; for (lfs2_size_t i = 0; i < SIZE; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } lfs2_file_read(&lfs2, &file, buffer, CHUNKSIZE) => 0; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; ''' [cases.test_files_reentrant_write_sync] defines = [ # append (O(n)) {MODE='LFS2_O_APPEND', SIZE=[32, 0, 7, 2049], CHUNKSIZE=[31, 16, 65], INLINE_MAX=[0, -1, 8]}, # truncate (O(n^2)) {MODE='LFS2_O_TRUNC', SIZE=[32, 0, 7, 200], CHUNKSIZE=[31, 16, 65], INLINE_MAX=[0, -1, 8]}, # rewrite (O(n^2)) {MODE=0, SIZE=[32, 0, 7, 200], CHUNKSIZE=[31, 16, 65], INLINE_MAX=[0, -1, 8]}, ] reentrant = true code = ''' lfs2_t lfs2; int err = lfs2_mount(&lfs2, cfg); if (err) { lfs2_format(&lfs2, cfg) => 0; lfs2_mount(&lfs2, cfg) => 0; } lfs2_file_t file; uint8_t buffer[1024]; err = lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY); assert(err == LFS2_ERR_NOENT || err == 0); if (err == 0) { // with syncs we could be any size, but it at least must be valid data lfs2_size_t size = lfs2_file_size(&lfs2, &file); assert(size <= SIZE); uint32_t prng = 1; for (lfs2_size_t i = 0; i < size; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, size-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } lfs2_file_close(&lfs2, &file) => 0; } // write lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_WRONLY | LFS2_O_CREAT | MODE) => 0; lfs2_size_t size = lfs2_file_size(&lfs2, &file); assert(size <= SIZE); uint32_t prng = 1; lfs2_size_t skip = (MODE == LFS2_O_APPEND) ? size : 0; for (lfs2_size_t b = 0; b < skip; b++) { TEST_PRNG(&prng); } for (lfs2_size_t i = skip; i < SIZE; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE-i); for (lfs2_size_t b = 0; b < chunk; b++) { buffer[b] = TEST_PRNG(&prng) & 0xff; } lfs2_file_write(&lfs2, &file, buffer, chunk) => chunk; lfs2_file_sync(&lfs2, &file) => 0; } lfs2_file_close(&lfs2, &file) => 0; // read lfs2_file_open(&lfs2, &file, "avacado", LFS2_O_RDONLY) => 0; lfs2_file_size(&lfs2, &file) => SIZE; prng = 1; for (lfs2_size_t i = 0; i < SIZE; i += CHUNKSIZE) { lfs2_size_t chunk = lfs2_min(CHUNKSIZE, SIZE-i); lfs2_file_read(&lfs2, &file, buffer, chunk) => chunk; for (lfs2_size_t b = 0; b < chunk; b++) { assert(buffer[b] == (TEST_PRNG(&prng) & 0xff)); } } lfs2_file_read(&lfs2, &file, buffer, CHUNKSIZE) => 0; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; ''' [cases.test_files_many] defines.N = 300 code = ''' lfs2_t lfs2; lfs2_format(&lfs2, cfg) => 0; // create N files of 7 bytes lfs2_mount(&lfs2, cfg) => 0; for (int i = 0; i < N; i++) { lfs2_file_t file; char path[1024]; sprintf(path, "file_%03d", i); lfs2_file_open(&lfs2, &file, path, LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_EXCL) => 0; char wbuffer[1024]; lfs2_size_t size = 7; sprintf(wbuffer, "Hi %03d", i); lfs2_file_write(&lfs2, &file, wbuffer, size) => size; lfs2_file_close(&lfs2, &file) => 0; char rbuffer[1024]; lfs2_file_open(&lfs2, &file, path, LFS2_O_RDONLY) => 0; lfs2_file_read(&lfs2, &file, rbuffer, size) => size; assert(strcmp(rbuffer, wbuffer) == 0); lfs2_file_close(&lfs2, &file) => 0; } lfs2_unmount(&lfs2) => 0; ''' [cases.test_files_many_power_cycle] defines.N = 300 code = ''' lfs2_t lfs2; lfs2_format(&lfs2, cfg) => 0; // create N files of 7 bytes lfs2_mount(&lfs2, cfg) => 0; for (int i = 0; i < N; i++) { lfs2_file_t file; char path[1024]; sprintf(path, "file_%03d", i); lfs2_file_open(&lfs2, &file, path, LFS2_O_WRONLY | LFS2_O_CREAT | LFS2_O_EXCL) => 0; char wbuffer[1024]; lfs2_size_t size = 7; sprintf(wbuffer, "Hi %03d", i); lfs2_file_write(&lfs2, &file, wbuffer, size) => size; lfs2_file_close(&lfs2, &file) => 0; lfs2_unmount(&lfs2) => 0; char rbuffer[1024]; lfs2_mount(&lfs2, cfg) => 0; lfs2_file_open(&lfs2, &file, path, LFS2_O_RDONLY) => 0; lfs2_file_read(&lfs2, &file, rbuffer, size) => size; assert(strcmp(rbuffer, wbuffer) == 0); lfs2_file_close(&lfs2, &file) => 0; } lfs2_unmount(&lfs2) => 0; ''' [cases.test_files_many_power_loss] defines.N = 300 reentrant = true defines.POWERLOSS_BEHAVIOR = [ 'LFS2_EMUBD_POWERLOSS_NOOP', 'LFS2_EMUBD_POWERLOSS_OOO', ] code = ''' lfs2_t lfs2; int err = lfs2_mount(&lfs2, cfg); if (err) { lfs2_format(&lfs2, cfg) => 0; lfs2_mount(&lfs2, cfg) => 0; } // create N files of 7 bytes for (int i = 0; i < N; i++) { lfs2_file_t file; char path[1024]; sprintf(path, "file_%03d", i); err = lfs2_file_open(&lfs2, &file, path, LFS2_O_WRONLY | LFS2_O_CREAT); char wbuffer[1024]; lfs2_size_t size = 7; sprintf(wbuffer, "Hi %03d", i); if ((lfs2_size_t)lfs2_file_size(&lfs2, &file) != size) { lfs2_file_write(&lfs2, &file, wbuffer, size) => size; } lfs2_file_close(&lfs2, &file) => 0; char rbuffer[1024]; lfs2_file_open(&lfs2, &file, path, LFS2_O_RDONLY) => 0; lfs2_file_read(&lfs2, &file, rbuffer, size) => size; assert(strcmp(rbuffer, wbuffer) == 0); lfs2_file_close(&lfs2, &file) => 0; } lfs2_unmount(&lfs2) => 0; '''