# Test basic file operations after = ['test_dirs', 'test_btree'] # test creation/deletion [cases.test_files_create] defines.REMOUNT = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; // create a file lfsr_file_t file; lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT) => 0; lfsr_file_close(&lfs, &file) => 0; // remount? if (REMOUNT) { lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; } // check our file with stat struct lfs_info info; lfsr_stat(&lfs, "hello", &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == 0); // and with dir read lfsr_dir_t dir; lfsr_dir_open(&lfs, &dir, "/") => 0; lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == 0); lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; lfsr_dir_close(&lfs, &dir) => 0; // try reading our file lfsr_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; // is size correct? lfsr_file_size(&lfs, &file) => 0; // try reading uint8_t rbuf[8192]; lfsr_file_read(&lfs, &file, rbuf, sizeof(rbuf)) => 0; lfsr_file_close(&lfs, &file) => 0; lfsr_unmount(&lfs) => 0; ''' # test we can write some data, should be inlined [cases.test_files_hello] defines.REMOUNT = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; // create a file lfsr_file_t file; lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT) => 0; uint8_t wbuf[8192]; strcpy((char*)wbuf, "Hello World!"); lfs_size_t wsize = strlen((const char*)wbuf); lfsr_file_write(&lfs, &file, wbuf, wsize) => wsize; lfsr_file_close(&lfs, &file) => 0; // remount? if (REMOUNT) { lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; } // check our file with stat struct lfs_info info; lfsr_stat(&lfs, "hello", &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == wsize); // and with dir read lfsr_dir_t dir; lfsr_dir_open(&lfs, &dir, "/") => 0; lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == wsize); lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; lfsr_dir_close(&lfs, &dir) => 0; // try reading our file lfsr_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; // is size correct? lfsr_file_size(&lfs, &file) => wsize; // try reading uint8_t rbuf[8192]; memset(rbuf, 0xaa, sizeof(rbuf)); lfsr_file_read(&lfs, &file, rbuf, sizeof(rbuf)) => wsize; assert(memcmp(rbuf, wbuf, wsize) == 0); lfsr_file_close(&lfs, &file) => 0; lfsr_unmount(&lfs) => 0; ''' # test we can rewrite a file [cases.test_files_trunc] defines.REMOUNT = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; // create a file lfsr_file_t file; lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; uint8_t wbuf[8192]; strcpy((char*)wbuf, "Oh no!"); lfs_size_t wsize = strlen((const char*)wbuf); lfsr_file_write(&lfs, &file, wbuf, wsize) => wsize; lfsr_file_close(&lfs, &file) => 0; // remount? if (REMOUNT) { lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; } // rewrite the file lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0; strcpy((char*)wbuf, "Hello World!"); wsize = strlen((const char*)wbuf); lfsr_file_write(&lfs, &file, wbuf, wsize) => wsize; lfsr_file_close(&lfs, &file) => 0; // check our file with stat struct lfs_info info; lfsr_stat(&lfs, "hello", &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == wsize); // and with dir read lfsr_dir_t dir; lfsr_dir_open(&lfs, &dir, "/") => 0; lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == wsize); lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; lfsr_dir_close(&lfs, &dir) => 0; // try reading our file lfsr_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; // is size correct? lfsr_file_size(&lfs, &file) => wsize; // try reading uint8_t rbuf[8192]; memset(rbuf, 0xaa, sizeof(rbuf)); lfsr_file_read(&lfs, &file, rbuf, sizeof(rbuf)) => wsize; assert(memcmp(rbuf, wbuf, wsize) == 0); lfsr_file_close(&lfs, &file) => 0; lfsr_unmount(&lfs) => 0; ''' # check for LFS_F_EXCL errors [cases.test_files_excl] defines.REMOUNT = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; // create a file lfsr_file_t file; lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; uint8_t wbuf[8192]; strcpy((char*)wbuf, "Hello World!"); lfs_size_t wsize = strlen((const char*)wbuf); lfsr_file_write(&lfs, &file, wbuf, wsize) => wsize; lfsr_file_close(&lfs, &file) => 0; // remount? if (REMOUNT) { lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; } // try to recreate file, this should error lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; // remount? if (REMOUNT) { lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; } // check our file with stat struct lfs_info info; lfsr_stat(&lfs, "hello", &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == wsize); // and with dir read lfsr_dir_t dir; lfsr_dir_open(&lfs, &dir, "/") => 0; lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == wsize); lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; lfsr_dir_close(&lfs, &dir) => 0; // try reading our file lfsr_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; // is size correct? lfsr_file_size(&lfs, &file) => wsize; // try reading uint8_t rbuf[8192]; memset(rbuf, 0xaa, sizeof(rbuf)); lfsr_file_read(&lfs, &file, rbuf, sizeof(rbuf)) => wsize; assert(memcmp(rbuf, wbuf, wsize) == 0); lfsr_file_close(&lfs, &file) => 0; lfsr_unmount(&lfs) => 0; ''' # a file is not a directory [cases.test_files_file_not_dir] defines.REMOUNT = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; // create a file lfsr_file_t file; lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; uint8_t wbuf[8192]; strcpy((char*)wbuf, "Hello World!"); lfs_size_t wsize = strlen((const char*)wbuf); lfsr_file_write(&lfs, &file, wbuf, wsize) => wsize; lfsr_file_close(&lfs, &file) => 0; // remount? if (REMOUNT) { lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; } // try to open our file as a directory lfsr_dir_t dir; lfsr_dir_open(&lfs, &dir, "hello") => LFS_ERR_NOTDIR; // try to create a directory on top of our file lfsr_mkdir(&lfs, "hello") => LFS_ERR_EXIST; // try to rename a directory onto our file lfsr_mkdir(&lfs, "not_hello") => 0; lfsr_rename(&lfs, "not_hello", "hello") => LFS_ERR_ISDIR; // remount? if (REMOUNT) { lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; } // check our file with stat struct lfs_info info; lfsr_stat(&lfs, "hello", &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == wsize); // and with dir read lfsr_dir_open(&lfs, &dir, "/") => 0; lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == wsize); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "not_hello") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; lfsr_dir_close(&lfs, &dir) => 0; // try reading our file lfsr_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; // is size correct? lfsr_file_size(&lfs, &file) => wsize; // try reading uint8_t rbuf[8192]; memset(rbuf, 0xaa, sizeof(rbuf)); lfsr_file_read(&lfs, &file, rbuf, sizeof(rbuf)) => wsize; assert(memcmp(rbuf, wbuf, wsize) == 0); lfsr_file_close(&lfs, &file) => 0; lfsr_unmount(&lfs) => 0; ''' # a directory is not a file [cases.test_files_dir_not_file] defines.REMOUNT = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; // create a directory lfsr_mkdir(&lfs, "hello") => 0; // try reading our directory as a file lfsr_file_t file; lfsr_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => LFS_ERR_ISDIR; // try writing our directory as a file lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY) => LFS_ERR_ISDIR; lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_TRUNC) => LFS_ERR_ISDIR; lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => LFS_ERR_ISDIR; // try rename a file on top of our directory lfsr_file_open(&lfs, &file, "not_hello", LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; uint8_t wbuf[8192]; strcpy((char*)wbuf, "Hello World!"); lfs_size_t wsize = strlen((const char*)wbuf); lfsr_file_write(&lfs, &file, wbuf, wsize) => wsize; lfsr_file_close(&lfs, &file) => 0; lfsr_rename(&lfs, "not_hello", "hello") => LFS_ERR_ISDIR; // remount? if (REMOUNT) { lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; } // check our dir with stat struct lfs_info info; lfsr_stat(&lfs, "hello", &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_DIR); // and with dir read lfsr_dir_t dir; lfsr_dir_open(&lfs, &dir, "/") => 0; lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "not_hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == wsize); lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; lfsr_dir_close(&lfs, &dir) => 0; // did we corrupt our renaming file? // try reading our file lfsr_file_open(&lfs, &file, "not_hello", LFS_O_RDONLY) => 0; // is size correct? lfsr_file_size(&lfs, &file) => wsize; // try reading uint8_t rbuf[8192]; memset(rbuf, 0xaa, sizeof(rbuf)); lfsr_file_read(&lfs, &file, rbuf, sizeof(rbuf)) => wsize; assert(memcmp(rbuf, wbuf, wsize) == 0); lfsr_file_close(&lfs, &file) => 0; lfsr_unmount(&lfs) => 0; ''' # try writing larger files # # note: # - at 2*CACHE_SIZE we need a shrub # - at BLOCK_SIZE/2 we need a block pointer # - at 2*BLOCK_SIZE we need a btree # [cases.test_files_more] defines.SIZE = [ '0', 'CACHE_SIZE/2', '2*CACHE_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] defines.REMOUNT = [false, true] defines.CACHE_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; lfsr_mount(&lfs, CFG) => 0; // create a file lfsr_file_t file; lfsr_file_open(&lfs, &file, "hello", LFS_O_WRONLY | LFS_O_CREAT) => 0; uint8_t wbuf[SIZE]; uint32_t prng = 42; for (lfs_size_t i = 0; i < SIZE; i++) { wbuf[i] = 'a' + (TEST_PRNG(&prng) % 26); } lfsr_file_write(&lfs, &file, wbuf, SIZE) => SIZE; lfsr_file_close(&lfs, &file) => 0; // remount? if (REMOUNT) { lfsr_unmount(&lfs) => 0; lfsr_mount(&lfs, CFG) => 0; } // check our file with stat struct lfs_info info; lfsr_stat(&lfs, "hello", &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == SIZE); // and with dir read lfsr_dir_t dir; lfsr_dir_open(&lfs, &dir, "/") => 0; lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, ".") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "..") == 0); assert(info.type == LFS_TYPE_DIR); lfsr_dir_read(&lfs, &dir, &info) => 0; assert(strcmp(info.name, "hello") == 0); assert(info.type == LFS_TYPE_REG); assert(info.size == SIZE); lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; lfsr_dir_close(&lfs, &dir) => 0; // try reading our file lfsr_file_open(&lfs, &file, "hello", LFS_O_RDONLY) => 0; // is size correct? lfsr_file_size(&lfs, &file) => SIZE; // try reading uint8_t rbuf[2*SIZE]; memset(rbuf, 0xaa, 2*SIZE); lfsr_file_read(&lfs, &file, rbuf, 2*SIZE) => SIZE; assert(memcmp(rbuf, wbuf, SIZE) == 0); lfsr_file_close(&lfs, &file) => 0; lfsr_unmount(&lfs) => 0; ''' # TODO # [cases.test_files_rm] # [cases.test_files_mv] # [cases.test_files_mvrm] # [cases.test_files_rmed] # [cases.test_files_mved] # [cases.test_files_mvrmed] # [cases.test_files_multi_readers] # [cases.test_files_multi_readers_one_writer] # [cases.test_files_multi_writers] # [cases.test_files_multi_readers_multi_writers] # [cases.test_files_many] # [cases.test_files_interleaved] # [cases.test_files_interleaved_fuzz] # [cases.test_files_interleaved_fuzz_fuzz] # [cases.test_files_dtree_fuzz] # [cases.test_files_dtree_fuzz_fuzz]