mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Added tests, cleanup, and fixed a small issue with updating file flags
Related to changes to custom attribute and open file syncing
This commit is contained in:
		
							
								
								
									
										3
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -2527,6 +2527,7 @@ static int lfs_file_rawopencfg(lfs_t *lfs, lfs_file_t *file, | ||||
| #ifndef LFS_READONLY | ||||
|     } else if (flags & LFS_O_TRUNC) { | ||||
|         // truncate if requested | ||||
|         // always mark dirty in case we have custom attributes | ||||
|         tag = LFS_MKTAG(LFS_TYPE_INLINESTRUCT, file->id, 0); | ||||
|         file->flags |= LFS_F_DIRTY; | ||||
| #endif | ||||
| @@ -2878,7 +2879,7 @@ static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file) { | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 file->flags &= ~(LFS_F_DIRTY | LFS_F_WRITING | LFS_F_READING); | ||||
|                 f->flags &= ~(LFS_F_DIRTY | LFS_F_WRITING | LFS_F_READING); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
							
								
								
									
										8
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -294,10 +294,10 @@ struct lfs_file_config { | ||||
|     void *buffer; | ||||
|  | ||||
|     // Optional list of custom attributes related to the file. If the file | ||||
|     // is opened with read access, these attributes will be read from disk | ||||
|     // during the open call. If the file is opened with write access, the | ||||
|     // attributes will be written to disk every file sync or close. This | ||||
|     // write occurs atomically with update to the file's contents. | ||||
|     // is opened for reading, these attributes will be read from disk during | ||||
|     // open. If the file is open for writing, these attribute will be atomically | ||||
|     // written to disk when the file is written to disk. Note that these | ||||
|     // attributes are not written unless the file is modified. | ||||
|     // | ||||
|     // Custom attributes are uniquely identified by an 8-bit type and limited | ||||
|     // to LFS_ATTR_MAX bytes. If the stored attribute is larger than the | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
|  | ||||
| [[case]] # interspersed file test | ||||
| define.SIZE = [10, 100] | ||||
| define.FILES = [4, 10, 26]  | ||||
| define.FILES = [4, 10, 26] | ||||
| code = ''' | ||||
|     lfs_file_t files[FILES]; | ||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||
| @@ -55,7 +55,7 @@ code = ''' | ||||
|     for (int j = 0; j < FILES; j++) { | ||||
|         lfs_file_close(&lfs, &files[j]); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| @@ -108,7 +108,7 @@ code = ''' | ||||
|         assert(buffer[0] == '~'); | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file); | ||||
|      | ||||
|  | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| @@ -168,13 +168,13 @@ code = ''' | ||||
|     } | ||||
|     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]  | ||||
| define.FILES = [4, 10, 26] | ||||
| reentrant = true | ||||
| code = ''' | ||||
|     lfs_file_t files[FILES]; | ||||
| @@ -239,6 +239,268 @@ code = ''' | ||||
|     for (int j = 0; j < FILES; j++) { | ||||
|         lfs_file_close(&lfs, &files[j]); | ||||
|     } | ||||
|      | ||||
|  | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # open same file reading from separate file handles | ||||
| define.READERS = 3 | ||||
| define.SIZE = [10, 100, 1000, 10000] | ||||
| define.RDMODE = ['LFS_O_RDONLY', 'LFS_O_RDWR'] | ||||
| code = ''' | ||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "shared", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||
|     for (int j = 0; j < SIZE; j++) { | ||||
|         lfs_file_write(&lfs, &file, &alphas[j % 26], 1) => 1; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // open all files | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_t readers[READERS]; | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         lfs_file_open(&lfs, &readers[i], "shared", RDMODE) => 0; | ||||
|     } | ||||
|  | ||||
|     // perform operations while all readers are open | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         for (int j = 0; j < SIZE; j++) { | ||||
|             lfs_file_read(&lfs, &readers[i], buffer, 1) => 1; | ||||
|             assert(buffer[0] == alphas[j % 26]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         lfs_file_close(&lfs, &readers[i]) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # open same file reading and writing from separate file handles | ||||
| define.READERS = 3 | ||||
| define.SIZE = [10, 100, 1000, 10000] | ||||
| define.RDMODE = ['LFS_O_RDONLY', 'LFS_O_RDWR'] | ||||
| define.WRMODE = ['LFS_O_WRONLY', 'LFS_O_RDWR'] | ||||
| code = ''' | ||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||
|     const char nums[] = "0123456789"; | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_open(&lfs, &file, "shared", LFS_O_CREAT | LFS_O_WRONLY) => 0; | ||||
|     for (int j = 0; j < SIZE; j++) { | ||||
|         lfs_file_write(&lfs, &file, &alphas[j % 26], 1) => 1; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // open all files | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_t writer; | ||||
|     lfs_file_t readers[READERS]; | ||||
|     lfs_file_open(&lfs, &writer, "shared", WRMODE) => 0; | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         lfs_file_open(&lfs, &readers[i], "shared", RDMODE) => 0; | ||||
|     } | ||||
|  | ||||
|     // perform operations while all readers are open | ||||
|     for (int j = 0; j < SIZE; j++) { | ||||
|         lfs_file_write(&lfs, &writer, &nums[j % 10], 1) => 1; | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         for (int j = 0; j < SIZE/2; j++) { | ||||
|             lfs_file_read(&lfs, &readers[i], buffer, 1) => 1; | ||||
|             assert(buffer[0] == alphas[j % 26]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // sync, now write should reflect in all open files | ||||
|     lfs_file_sync(&lfs, &writer) => 0; | ||||
|  | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         for (int j = SIZE/2; j < SIZE; j++) { | ||||
|             lfs_file_read(&lfs, &readers[i], buffer, 1) => 1; | ||||
|             assert(buffer[0] == nums[j % 10]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // double check our writer reflects its own changes | ||||
|     if (WRMODE == LFS_O_RDWR) { | ||||
|         lfs_file_rewind(&lfs, &writer) => 0; | ||||
|         for (int j = 0; j < SIZE; j++) { | ||||
|             lfs_file_read(&lfs, &writer, buffer, 1) => 1; | ||||
|             assert(buffer[0] == nums[j % 10]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         lfs_file_close(&lfs, &readers[i]) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|  | ||||
| [[case]] # check that attributes are updated in open files | ||||
| define.READERS = 3 | ||||
| define.SIZE = 10 | ||||
| define.RDMODE = ['LFS_O_RDONLY', 'LFS_O_RDWR'] | ||||
| define.WRMODE = ['LFS_O_WRONLY', 'LFS_O_RDWR'] | ||||
| code = ''' | ||||
|     const char alphas[] = "abcdefghijklmnopqrstuvwxyz"; | ||||
|     const char nums[] = "0123456789"; | ||||
|     lfs_format(&lfs, &cfg) => 0; | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     const struct lfs_file_config filecfg = { | ||||
|         .attr_count = 3, | ||||
|         .attrs = (struct lfs_attr[]){ | ||||
|             {'A', "a",   1}, | ||||
|             {'B', "bb",  2}, | ||||
|             {'C', "ccc", 3}, | ||||
|         }, | ||||
|     }; | ||||
|     lfs_file_opencfg(&lfs, &file, "shared", | ||||
|             LFS_O_CREAT | LFS_O_WRONLY, &filecfg) => 0; | ||||
|     for (int j = 0; j < SIZE; j++) { | ||||
|         lfs_file_write(&lfs, &file, &alphas[j % 26], 1) => 1; | ||||
|     } | ||||
|     lfs_file_close(&lfs, &file) => 0; | ||||
|     lfs_unmount(&lfs) => 0; | ||||
|  | ||||
|     // open all files | ||||
|     lfs_mount(&lfs, &cfg) => 0; | ||||
|     lfs_file_t writer; | ||||
|     const struct lfs_file_config writercfg = { | ||||
|         .attr_count = 3, | ||||
|         .attrs = (struct lfs_attr[]){ | ||||
|             {'A', &(uint8_t[1]){0}, 1}, | ||||
|             {'B', &(uint8_t[2]){0}, 2}, | ||||
|             {'C', &(uint8_t[3]){0}, 3}}}; | ||||
|     lfs_file_t readers[READERS]; | ||||
|     const struct lfs_file_config readercfgs[READERS] = { | ||||
|         {   .attr_count = 3, | ||||
|             .attrs = (struct lfs_attr[]){ | ||||
|                 {'A', &(uint8_t[1]){0}, 1}, | ||||
|                 {'B', &(uint8_t[2]){0}, 2}, | ||||
|                 {'C', &(uint8_t[3]){0}, 3}}}, | ||||
|         {   .attr_count = 3, | ||||
|             .attrs = (struct lfs_attr[]){ | ||||
|                 {'A', &(uint8_t[1]){0}, 1}, | ||||
|                 {'B', &(uint8_t[2]){0}, 2}, | ||||
|                 {'C', &(uint8_t[3]){0}, 3}}}, | ||||
|         {   .attr_count = 3, | ||||
|             .attrs = (struct lfs_attr[]){ | ||||
|                 {'A', &(uint8_t[1]){0}, 1}, | ||||
|                 {'B', &(uint8_t[2]){0}, 2}, | ||||
|                 {'C', &(uint8_t[3]){0}, 3}}}}; | ||||
|     lfs_file_opencfg(&lfs, &writer, "shared", | ||||
|             WRMODE, &writercfg) => 0; | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         lfs_file_opencfg(&lfs, &readers[i], "shared", | ||||
|                 RDMODE, &readercfgs[i]) => 0; | ||||
|     } | ||||
|  | ||||
|     // perform operations while all readers are open | ||||
|     writercfg.attrs[0].size = 1; | ||||
|     memcpy(writercfg.attrs[0].buffer, "0", 1); | ||||
|     writercfg.attrs[1].size = 2; | ||||
|     memcpy(writercfg.attrs[1].buffer, "11", 2); | ||||
|     writercfg.attrs[2].size = 3; | ||||
|     memcpy(writercfg.attrs[2].buffer, "222", 3); | ||||
|     for (int j = 0; j < SIZE; j++) { | ||||
|         lfs_file_write(&lfs, &writer, &nums[j % 10], 1) => 1; | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         assert(readercfgs[i].attrs[0].size == 1); | ||||
|         assert(memcmp(readercfgs[i].attrs[0].buffer, "a", 1) == 0); | ||||
|         assert(readercfgs[i].attrs[1].size == 2); | ||||
|         assert(memcmp(readercfgs[i].attrs[1].buffer, "bb", 2) == 0); | ||||
|         assert(readercfgs[i].attrs[2].size == 3); | ||||
|         assert(memcmp(readercfgs[i].attrs[2].buffer, "ccc", 3) == 0); | ||||
|         for (int j = 0; j < SIZE; j++) { | ||||
|             lfs_file_read(&lfs, &readers[i], buffer, 1) => 1; | ||||
|             assert(buffer[0] == alphas[j % 26]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // sync, now write should reflect in all open files | ||||
|     lfs_file_sync(&lfs, &writer) => 0; | ||||
|  | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         assert(readercfgs[i].attrs[0].size == 1); | ||||
|         assert(memcmp(readercfgs[i].attrs[0].buffer, "0", 1) == 0); | ||||
|         assert(readercfgs[i].attrs[1].size == 2); | ||||
|         assert(memcmp(readercfgs[i].attrs[1].buffer, "11", 2) == 0); | ||||
|         assert(readercfgs[i].attrs[2].size == 3); | ||||
|         assert(memcmp(readercfgs[i].attrs[2].buffer, "222", 3) == 0); | ||||
|         lfs_file_rewind(&lfs, &readers[i]) => 0; | ||||
|         for (int j = 0; j < SIZE; j++) { | ||||
|             lfs_file_read(&lfs, &readers[i], buffer, 1) => 1; | ||||
|             assert(buffer[0] == nums[j % 10]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // double check our writer reflects its own changes | ||||
|     if (WRMODE == LFS_O_RDWR) { | ||||
|         assert(writercfg.attrs[0].size == 1); | ||||
|         assert(memcmp(writercfg.attrs[0].buffer, "0", 1) == 0); | ||||
|         assert(writercfg.attrs[1].size == 2); | ||||
|         assert(memcmp(writercfg.attrs[1].buffer, "11", 2) == 0); | ||||
|         assert(writercfg.attrs[2].size == 3); | ||||
|         assert(memcmp(writercfg.attrs[2].buffer, "222", 3) == 0); | ||||
|         lfs_file_rewind(&lfs, &writer) => 0; | ||||
|         for (int j = 0; j < SIZE; j++) { | ||||
|             lfs_file_read(&lfs, &writer, buffer, 1) => 1; | ||||
|             assert(buffer[0] == nums[j % 10]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // now try explicit lfs_setattr calls, this should still update open files | ||||
|     lfs_setattr(&lfs, "shared", 'A', "A",   1) => 0; | ||||
|     lfs_setattr(&lfs, "shared", 'B', "BB",  2) => 0; | ||||
|     lfs_setattr(&lfs, "shared", 'C', "CCC", 3) => 0; | ||||
|  | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         assert(readercfgs[i].attrs[0].size == 1); | ||||
|         assert(memcmp(readercfgs[i].attrs[0].buffer, "A", 1) == 0); | ||||
|         assert(readercfgs[i].attrs[1].size == 2); | ||||
|         assert(memcmp(readercfgs[i].attrs[1].buffer, "BB", 2) == 0); | ||||
|         assert(readercfgs[i].attrs[2].size == 3); | ||||
|         assert(memcmp(readercfgs[i].attrs[2].buffer, "CCC", 3) == 0); | ||||
|         lfs_file_rewind(&lfs, &readers[i]) => 0; | ||||
|         for (int j = 0; j < SIZE; j++) { | ||||
|             lfs_file_read(&lfs, &readers[i], buffer, 1) => 1; | ||||
|             assert(buffer[0] == nums[j % 10]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (WRMODE == LFS_O_RDWR) { | ||||
|         assert(writercfg.attrs[0].size == 1); | ||||
|         assert(memcmp(writercfg.attrs[0].buffer, "A", 1) == 0); | ||||
|         assert(writercfg.attrs[1].size == 2); | ||||
|         assert(memcmp(writercfg.attrs[1].buffer, "BB", 2) == 0); | ||||
|         assert(writercfg.attrs[2].size == 3); | ||||
|         assert(memcmp(writercfg.attrs[2].buffer, "CCC", 3) == 0); | ||||
|         lfs_file_rewind(&lfs, &writer) => 0; | ||||
|         for (int j = 0; j < SIZE; j++) { | ||||
|             lfs_file_read(&lfs, &writer, buffer, 1) => 1; | ||||
|             assert(buffer[0] == nums[j % 10]); | ||||
|         } | ||||
|     } else if (WRMODE == LFS_O_WRONLY) { | ||||
|         // this should NOT update wronly attributes, these may be | ||||
|         // stored in read-only memory | ||||
|         assert(writercfg.attrs[0].size == 1); | ||||
|         assert(memcmp(writercfg.attrs[0].buffer, "0", 1) == 0); | ||||
|         assert(writercfg.attrs[1].size == 2); | ||||
|         assert(memcmp(writercfg.attrs[1].buffer, "11", 2) == 0); | ||||
|         assert(writercfg.attrs[2].size == 3); | ||||
|         assert(memcmp(writercfg.attrs[2].buffer, "222", 3) == 0); | ||||
|     } | ||||
|  | ||||
|     for (int i = 0; i < READERS; i++) { | ||||
|         lfs_file_close(&lfs, &readers[i]) => 0; | ||||
|     } | ||||
|     lfs_unmount(&lfs) => 0; | ||||
| ''' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user