mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 00:32:38 +01:00 
			
		
		
		
	Before: If an entry is found, lfs_dir_read returns 1 If at end of directory, lfs_dir_read returns 0 After: If an entry is found, lfs_dir_read returns 0 If at end of directory, lfs_dir_read returns LFS_ERR_NOENT --- lfs_dir_read is a bit of an odd function. It's supposed to match lfs_file_read, but instead of reading bytes, it reads directory entries. Its POSIX equivalent, readdir, indicates whether or not we reached the end of the directory by returning a NULL pointer: struct dirent *readdir(DIR *dirp); But this API needed to change for littlefs, since we don't use errno, instead returning errors as signed integers through all API functions, including lfs_dir_read. So, in an effort to match lfs_file_read, lfs_dir_read returned the "number" of directory entries read, limited to either 0 or 1. Perhaps unsurprisingly, this turned out to be confusing to users, and a better API was proposed hathach to instead return either 0 or LFS_ERR_NOENT, an error which can't occur for other reasons in lfs_dir_read. Suggested by hathach
		
			
				
	
	
		
			245 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			TOML
		
	
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			TOML
		
	
	
	
	
	
| 
 | |
| [[case]] # interspersed file test
 | |
| define.SIZE = [10, 100]
 | |
| define.FILES = [4, 10, 26] 
 | |
| code = '''
 | |
|     lfs_file_t files[FILES];
 | |
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
 | |
|     lfs_format(&lfs, &cfg) => 0;
 | |
|     lfs_mount(&lfs, &cfg) => 0;
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         sprintf(path, "%c", alphas[j]);
 | |
|         lfs_file_open(&lfs, &files[j], path,
 | |
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
 | |
|     }
 | |
| 
 | |
|     for (int i = 0; i < SIZE; i++) {
 | |
|         for (int j = 0; j < FILES; j++) {
 | |
|             lfs_file_write(&lfs, &files[j], &alphas[j], 1) => 1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         lfs_file_close(&lfs, &files[j]);
 | |
|     }
 | |
| 
 | |
|     lfs_dir_open(&lfs, &dir, "/") => 0;
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, ".") == 0);
 | |
|     assert(info.type == LFS_TYPE_DIR);
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, "..") == 0);
 | |
|     assert(info.type == LFS_TYPE_DIR);
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         sprintf(path, "%c", alphas[j]);
 | |
|         lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|         assert(strcmp(info.name, path) == 0);
 | |
|         assert(info.type == LFS_TYPE_REG);
 | |
|         assert(info.size == SIZE);
 | |
|     }
 | |
|     lfs_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
 | |
|     lfs_dir_close(&lfs, &dir) => 0;
 | |
| 
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         sprintf(path, "%c", alphas[j]);
 | |
|         lfs_file_open(&lfs, &files[j], path, LFS_O_RDONLY) => 0;
 | |
|     }
 | |
| 
 | |
|     for (int i = 0; i < 10; i++) {
 | |
|         for (int j = 0; j < FILES; j++) {
 | |
|             lfs_file_read(&lfs, &files[j], buffer, 1) => 1;
 | |
|             assert(buffer[0] == alphas[j]);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         lfs_file_close(&lfs, &files[j]);
 | |
|     }
 | |
|     
 | |
|     lfs_unmount(&lfs) => 0;
 | |
| '''
 | |
| 
 | |
| [[case]] # interspersed remove file test
 | |
| define.SIZE = [10, 100]
 | |
| define.FILES = [4, 10, 26]
 | |
| code = '''
 | |
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
 | |
|     lfs_format(&lfs, &cfg) => 0;
 | |
|     lfs_mount(&lfs, &cfg) => 0;
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         sprintf(path, "%c", alphas[j]);
 | |
|         lfs_file_open(&lfs, &file, path,
 | |
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
 | |
|         for (int i = 0; i < SIZE; i++) {
 | |
|             lfs_file_write(&lfs, &file, &alphas[j], 1) => 1;
 | |
|         }
 | |
|         lfs_file_close(&lfs, &file);
 | |
|     }
 | |
|     lfs_unmount(&lfs) => 0;
 | |
| 
 | |
|     lfs_mount(&lfs, &cfg) => 0;
 | |
|     lfs_file_open(&lfs, &file, "zzz", LFS_O_WRONLY | LFS_O_CREAT) => 0;
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         lfs_file_write(&lfs, &file, (const void*)"~", 1) => 1;
 | |
|         lfs_file_sync(&lfs, &file) => 0;
 | |
| 
 | |
|         sprintf(path, "%c", alphas[j]);
 | |
|         lfs_remove(&lfs, path) => 0;
 | |
|     }
 | |
|     lfs_file_close(&lfs, &file);
 | |
| 
 | |
|     lfs_dir_open(&lfs, &dir, "/") => 0;
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, ".") == 0);
 | |
|     assert(info.type == LFS_TYPE_DIR);
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, "..") == 0);
 | |
|     assert(info.type == LFS_TYPE_DIR);
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, "zzz") == 0);
 | |
|     assert(info.type == LFS_TYPE_REG);
 | |
|     assert(info.size == FILES);
 | |
|     lfs_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
 | |
|     lfs_dir_close(&lfs, &dir) => 0;
 | |
| 
 | |
|     lfs_file_open(&lfs, &file, "zzz", LFS_O_RDONLY) => 0;
 | |
|     for (int i = 0; i < FILES; i++) {
 | |
|         lfs_file_read(&lfs, &file, buffer, 1) => 1;
 | |
|         assert(buffer[0] == '~');
 | |
|     }
 | |
|     lfs_file_close(&lfs, &file);
 | |
|     
 | |
|     lfs_unmount(&lfs) => 0;
 | |
| '''
 | |
| 
 | |
| [[case]] # remove inconveniently test
 | |
| define.SIZE = [10, 100]
 | |
| code = '''
 | |
|     lfs_format(&lfs, &cfg) => 0;
 | |
|     lfs_mount(&lfs, &cfg) => 0;
 | |
|     lfs_file_t files[3];
 | |
|     lfs_file_open(&lfs, &files[0], "e", LFS_O_WRONLY | LFS_O_CREAT) => 0;
 | |
|     lfs_file_open(&lfs, &files[1], "f", LFS_O_WRONLY | LFS_O_CREAT) => 0;
 | |
|     lfs_file_open(&lfs, &files[2], "g", LFS_O_WRONLY | LFS_O_CREAT) => 0;
 | |
| 
 | |
|     for (int i = 0; i < SIZE/2; i++) {
 | |
|         lfs_file_write(&lfs, &files[0], (const void*)"e", 1) => 1;
 | |
|         lfs_file_write(&lfs, &files[1], (const void*)"f", 1) => 1;
 | |
|         lfs_file_write(&lfs, &files[2], (const void*)"g", 1) => 1;
 | |
|     }
 | |
| 
 | |
|     lfs_remove(&lfs, "f") => 0;
 | |
| 
 | |
|     for (int i = 0; i < SIZE/2; i++) {
 | |
|         lfs_file_write(&lfs, &files[0], (const void*)"e", 1) => 1;
 | |
|         lfs_file_write(&lfs, &files[1], (const void*)"f", 1) => 1;
 | |
|         lfs_file_write(&lfs, &files[2], (const void*)"g", 1) => 1;
 | |
|     }
 | |
| 
 | |
|     lfs_file_close(&lfs, &files[0]);
 | |
|     lfs_file_close(&lfs, &files[1]);
 | |
|     lfs_file_close(&lfs, &files[2]);
 | |
| 
 | |
|     lfs_dir_open(&lfs, &dir, "/") => 0;
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, ".") == 0);
 | |
|     assert(info.type == LFS_TYPE_DIR);
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, "..") == 0);
 | |
|     assert(info.type == LFS_TYPE_DIR);
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, "e") == 0);
 | |
|     assert(info.type == LFS_TYPE_REG);
 | |
|     assert(info.size == SIZE);
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, "g") == 0);
 | |
|     assert(info.type == LFS_TYPE_REG);
 | |
|     assert(info.size == SIZE);
 | |
|     lfs_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
 | |
|     lfs_dir_close(&lfs, &dir) => 0;
 | |
| 
 | |
|     lfs_file_open(&lfs, &files[0], "e", LFS_O_RDONLY) => 0;
 | |
|     lfs_file_open(&lfs, &files[1], "g", LFS_O_RDONLY) => 0;
 | |
|     for (int i = 0; i < SIZE; i++) {
 | |
|         lfs_file_read(&lfs, &files[0], buffer, 1) => 1;
 | |
|         assert(buffer[0] == 'e');
 | |
|         lfs_file_read(&lfs, &files[1], buffer, 1) => 1;
 | |
|         assert(buffer[0] == 'g');
 | |
|     }
 | |
|     lfs_file_close(&lfs, &files[0]);
 | |
|     lfs_file_close(&lfs, &files[1]);
 | |
|     
 | |
|     lfs_unmount(&lfs) => 0;
 | |
| '''
 | |
| 
 | |
| [[case]] # reentrant interspersed file test
 | |
| define.SIZE = [10, 100]
 | |
| define.FILES = [4, 10, 26] 
 | |
| reentrant = true
 | |
| code = '''
 | |
|     lfs_file_t files[FILES];
 | |
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz";
 | |
| 
 | |
|     err = lfs_mount(&lfs, &cfg);
 | |
|     if (err) {
 | |
|         lfs_format(&lfs, &cfg) => 0;
 | |
|         lfs_mount(&lfs, &cfg) => 0;
 | |
|     }
 | |
| 
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         sprintf(path, "%c", alphas[j]);
 | |
|         lfs_file_open(&lfs, &files[j], path,
 | |
|                 LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) => 0;
 | |
|     }
 | |
| 
 | |
|     for (int i = 0; i < SIZE; i++) {
 | |
|         for (int j = 0; j < FILES; j++) {
 | |
|             size = lfs_file_size(&lfs, &files[j]);
 | |
|             assert((int)size >= 0);
 | |
|             if ((int)size <= i) {
 | |
|                 lfs_file_write(&lfs, &files[j], &alphas[j], 1) => 1;
 | |
|                 lfs_file_sync(&lfs, &files[j]) => 0;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         lfs_file_close(&lfs, &files[j]);
 | |
|     }
 | |
| 
 | |
|     lfs_dir_open(&lfs, &dir, "/") => 0;
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, ".") == 0);
 | |
|     assert(info.type == LFS_TYPE_DIR);
 | |
|     lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|     assert(strcmp(info.name, "..") == 0);
 | |
|     assert(info.type == LFS_TYPE_DIR);
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         sprintf(path, "%c", alphas[j]);
 | |
|         lfs_dir_read(&lfs, &dir, &info) => 0;
 | |
|         assert(strcmp(info.name, path) == 0);
 | |
|         assert(info.type == LFS_TYPE_REG);
 | |
|         assert(info.size == SIZE);
 | |
|     }
 | |
|     lfs_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT;
 | |
|     lfs_dir_close(&lfs, &dir) => 0;
 | |
| 
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         sprintf(path, "%c", alphas[j]);
 | |
|         lfs_file_open(&lfs, &files[j], path, LFS_O_RDONLY) => 0;
 | |
|     }
 | |
| 
 | |
|     for (int i = 0; i < 10; i++) {
 | |
|         for (int j = 0; j < FILES; j++) {
 | |
|             lfs_file_read(&lfs, &files[j], buffer, 1) => 1;
 | |
|             assert(buffer[0] == alphas[j]);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (int j = 0; j < FILES; j++) {
 | |
|         lfs_file_close(&lfs, &files[j]);
 | |
|     }
 | |
|     
 | |
|     lfs_unmount(&lfs) => 0;
 | |
| '''
 |