| |
| [[case]] # simple file test |
| code = ''' |
| lfs_format(&lfs, &cfg) => 0; |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "hello", |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| size = strlen("Hello World!")+1; |
| strcpy((char*)buffer, "Hello World!"); |
| lfs_file_write(&lfs, &file, buffer, size) => size; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; |
| lfs_file_read(&lfs, &file, buffer, size) => size; |
| assert(strcmp((char*)buffer, "Hello World!") == 0); |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| [[case]] # larger files |
| define.SIZE = [32, 8192, 262144, 0, 7, 8193] |
| define.CHUNKSIZE = [31, 16, 33, 1, 1023] |
| code = ''' |
| lfs_format(&lfs, &cfg) => 0; |
| |
| // write |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| buffer[b] = rand() & 0xff; |
| } |
| lfs_file_write(&lfs, &file, buffer, chunk) => chunk; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // read |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; |
| lfs_file_size(&lfs, &file) => SIZE; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| [[case]] # rewriting files |
| define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] |
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] |
| define.CHUNKSIZE = [31, 16, 1] |
| code = ''' |
| lfs_format(&lfs, &cfg) => 0; |
| |
| // write |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| buffer[b] = rand() & 0xff; |
| } |
| lfs_file_write(&lfs, &file, buffer, chunk) => chunk; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // read |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; |
| lfs_file_size(&lfs, &file) => SIZE1; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // rewrite |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY) => 0; |
| srand(2); |
| for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| buffer[b] = rand() & 0xff; |
| } |
| lfs_file_write(&lfs, &file, buffer, chunk) => chunk; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // read |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; |
| lfs_file_size(&lfs, &file) => lfs_max(SIZE1, SIZE2); |
| srand(2); |
| for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| if (SIZE1 > SIZE2) { |
| srand(1); |
| for (lfs_size_t b = 0; b < SIZE2; b++) { |
| rand(); |
| } |
| for (lfs_size_t i = SIZE2; i < SIZE1; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| } |
| lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| [[case]] # appending files |
| define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] |
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] |
| define.CHUNKSIZE = [31, 16, 1] |
| code = ''' |
| lfs_format(&lfs, &cfg) => 0; |
| |
| // write |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| buffer[b] = rand() & 0xff; |
| } |
| lfs_file_write(&lfs, &file, buffer, chunk) => chunk; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // read |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; |
| lfs_file_size(&lfs, &file) => SIZE1; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // append |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_APPEND) => 0; |
| srand(2); |
| for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| buffer[b] = rand() & 0xff; |
| } |
| lfs_file_write(&lfs, &file, buffer, chunk) => chunk; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // read |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; |
| lfs_file_size(&lfs, &file) => SIZE1 + SIZE2; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| srand(2); |
| for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| [[case]] # truncating files |
| define.SIZE1 = [32, 8192, 131072, 0, 7, 8193] |
| define.SIZE2 = [32, 8192, 131072, 0, 7, 8193] |
| define.CHUNKSIZE = [31, 16, 1] |
| code = ''' |
| lfs_format(&lfs, &cfg) => 0; |
| |
| // write |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| buffer[b] = rand() & 0xff; |
| } |
| lfs_file_write(&lfs, &file, buffer, chunk) => chunk; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // read |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; |
| lfs_file_size(&lfs, &file) => SIZE1; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE1; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE1-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // truncate |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_TRUNC) => 0; |
| srand(2); |
| for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| buffer[b] = rand() & 0xff; |
| } |
| lfs_file_write(&lfs, &file, buffer, chunk) => chunk; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| // read |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; |
| lfs_file_size(&lfs, &file) => SIZE2; |
| srand(2); |
| for (lfs_size_t i = 0; i < SIZE2; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE2-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| [[case]] # reentrant file writing |
| define.SIZE = [32, 0, 7, 2049] |
| define.CHUNKSIZE = [31, 16, 65] |
| reentrant = true |
| code = ''' |
| err = lfs_mount(&lfs, &cfg); |
| if (err) { |
| lfs_format(&lfs, &cfg) => 0; |
| lfs_mount(&lfs, &cfg) => 0; |
| } |
| |
| err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY); |
| assert(err == LFS_ERR_NOENT || err == 0); |
| if (err == 0) { |
| // can only be 0 (new file) or full size |
| size = lfs_file_size(&lfs, &file); |
| assert(size == 0 || size == SIZE); |
| lfs_file_close(&lfs, &file) => 0; |
| } |
| |
| // write |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_WRONLY | LFS_O_CREAT) => 0; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| buffer[b] = rand() & 0xff; |
| } |
| lfs_file_write(&lfs, &file, buffer, chunk) => chunk; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| |
| // read |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; |
| lfs_file_size(&lfs, &file) => SIZE; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| [[case]] # reentrant file writing with syncs |
| define = [ |
| # append (O(n)) |
| {MODE='LFS_O_APPEND', SIZE=[32, 0, 7, 2049], CHUNKSIZE=[31, 16, 65]}, |
| # truncate (O(n^2)) |
| {MODE='LFS_O_TRUNC', SIZE=[32, 0, 7, 200], CHUNKSIZE=[31, 16, 65]}, |
| # rewrite (O(n^2)) |
| {MODE=0, SIZE=[32, 0, 7, 200], CHUNKSIZE=[31, 16, 65]}, |
| ] |
| reentrant = true |
| code = ''' |
| err = lfs_mount(&lfs, &cfg); |
| if (err) { |
| lfs_format(&lfs, &cfg) => 0; |
| lfs_mount(&lfs, &cfg) => 0; |
| } |
| |
| err = lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY); |
| assert(err == LFS_ERR_NOENT || err == 0); |
| if (err == 0) { |
| // with syncs we could be any size, but it at least must be valid data |
| size = lfs_file_size(&lfs, &file); |
| assert(size <= SIZE); |
| srand(1); |
| for (lfs_size_t i = 0; i < size; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, size-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| } |
| |
| // write |
| lfs_file_open(&lfs, &file, "avacado", |
| LFS_O_WRONLY | LFS_O_CREAT | MODE) => 0; |
| size = lfs_file_size(&lfs, &file); |
| assert(size <= SIZE); |
| srand(1); |
| lfs_size_t skip = (MODE == LFS_O_APPEND) ? size : 0; |
| for (lfs_size_t b = 0; b < skip; b++) { |
| rand(); |
| } |
| for (lfs_size_t i = skip; i < SIZE; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| buffer[b] = rand() & 0xff; |
| } |
| lfs_file_write(&lfs, &file, buffer, chunk) => chunk; |
| lfs_file_sync(&lfs, &file) => 0; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| |
| // read |
| lfs_file_open(&lfs, &file, "avacado", LFS_O_RDONLY) => 0; |
| lfs_file_size(&lfs, &file) => SIZE; |
| srand(1); |
| for (lfs_size_t i = 0; i < SIZE; i += CHUNKSIZE) { |
| lfs_size_t chunk = lfs_min(CHUNKSIZE, SIZE-i); |
| lfs_file_read(&lfs, &file, buffer, chunk) => chunk; |
| for (lfs_size_t b = 0; b < chunk; b++) { |
| assert(buffer[b] == (rand() & 0xff)); |
| } |
| } |
| lfs_file_read(&lfs, &file, buffer, CHUNKSIZE) => 0; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| [[case]] # many files |
| define.N = 300 |
| code = ''' |
| lfs_format(&lfs, &cfg) => 0; |
| // create N files of 7 bytes |
| lfs_mount(&lfs, &cfg) => 0; |
| for (int i = 0; i < N; i++) { |
| sprintf(path, "file_%03d", i); |
| lfs_file_open(&lfs, &file, path, |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| char wbuffer[1024]; |
| size = 7; |
| snprintf(wbuffer, size, "Hi %03d", i); |
| lfs_file_write(&lfs, &file, wbuffer, size) => size; |
| lfs_file_close(&lfs, &file) => 0; |
| |
| char rbuffer[1024]; |
| lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; |
| lfs_file_read(&lfs, &file, rbuffer, size) => size; |
| assert(strcmp(rbuffer, wbuffer) == 0); |
| lfs_file_close(&lfs, &file) => 0; |
| } |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| [[case]] # many files with power cycle |
| define.N = 300 |
| code = ''' |
| lfs_format(&lfs, &cfg) => 0; |
| // create N files of 7 bytes |
| lfs_mount(&lfs, &cfg) => 0; |
| for (int i = 0; i < N; i++) { |
| sprintf(path, "file_%03d", i); |
| lfs_file_open(&lfs, &file, path, |
| LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; |
| char wbuffer[1024]; |
| size = 7; |
| snprintf(wbuffer, size, "Hi %03d", i); |
| lfs_file_write(&lfs, &file, wbuffer, size) => size; |
| lfs_file_close(&lfs, &file) => 0; |
| lfs_unmount(&lfs) => 0; |
| |
| char rbuffer[1024]; |
| lfs_mount(&lfs, &cfg) => 0; |
| lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; |
| lfs_file_read(&lfs, &file, rbuffer, size) => size; |
| assert(strcmp(rbuffer, wbuffer) == 0); |
| lfs_file_close(&lfs, &file) => 0; |
| } |
| lfs_unmount(&lfs) => 0; |
| ''' |
| |
| [[case]] # many files with power loss |
| define.N = 300 |
| reentrant = true |
| code = ''' |
| err = lfs_mount(&lfs, &cfg); |
| if (err) { |
| lfs_format(&lfs, &cfg) => 0; |
| lfs_mount(&lfs, &cfg) => 0; |
| } |
| // create N files of 7 bytes |
| for (int i = 0; i < N; i++) { |
| sprintf(path, "file_%03d", i); |
| err = lfs_file_open(&lfs, &file, path, LFS_O_WRONLY | LFS_O_CREAT); |
| char wbuffer[1024]; |
| size = 7; |
| snprintf(wbuffer, size, "Hi %03d", i); |
| if ((lfs_size_t)lfs_file_size(&lfs, &file) != size) { |
| lfs_file_write(&lfs, &file, wbuffer, size) => size; |
| } |
| lfs_file_close(&lfs, &file) => 0; |
| |
| char rbuffer[1024]; |
| lfs_file_open(&lfs, &file, path, LFS_O_RDONLY) => 0; |
| lfs_file_read(&lfs, &file, rbuffer, size) => size; |
| assert(strcmp(rbuffer, wbuffer) == 0); |
| lfs_file_close(&lfs, &file) => 0; |
| } |
| lfs_unmount(&lfs) => 0; |
| ''' |