mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 00:32:38 +01:00 
			
		
		
		
	Even with adding better reentrance testing, the bad-block tests are still very useful at isolating the block eviction logic. This also required rewriting a bit of the internal testing wirework to allow custom block devices which opens up quite a bit more straegies for testing.
		
			
				
	
	
		
			376 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			TOML
		
	
	
	
	
	
			
		
		
	
	
			376 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			TOML
		
	
	
	
	
	
| # special bad-block block device hook for simulating blocks
 | |
| # that are no longer writable
 | |
| code = '''
 | |
| lfs_block_t *bbbd_badblocks;
 | |
| size_t bbbd_badblocks_count;
 | |
| 
 | |
| int bbbd_read(const struct lfs_config *c, lfs_block_t block,
 | |
|         lfs_off_t off, void *buffer, lfs_size_t size) {
 | |
|     for (size_t i = 0; i < bbbd_badblocks_count; i++) {
 | |
|         if (bbbd_badblocks[i] == block) {
 | |
|             return LFS_ERR_CORRUPT;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return lfs_testbd_read(c, block, off, buffer, size);
 | |
| }
 | |
| 
 | |
| int bbbd_prog(const struct lfs_config *c, lfs_block_t block,
 | |
|         lfs_off_t off, const void *buffer, lfs_size_t size) {
 | |
|     for (size_t i = 0; i < bbbd_badblocks_count; i++) {
 | |
|         if (bbbd_badblocks[i] == block) {
 | |
|             return LFS_ERR_CORRUPT;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return lfs_testbd_prog(c, block, off, buffer, size);
 | |
| }
 | |
| 
 | |
| int bbbd_erase(const struct lfs_config *c, lfs_block_t block) {
 | |
|     for (size_t i = 0; i < bbbd_badblocks_count; i++) {
 | |
|         if (bbbd_badblocks[i] == block) {
 | |
|             return LFS_ERR_CORRUPT;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return lfs_testbd_erase(c, block);
 | |
| }
 | |
| '''
 | |
| 
 | |
| [[case]] # single bad blocks
 | |
| define.LFS_BD_PROG = 'bbbd_prog'
 | |
| define.NAMEMULT = 64
 | |
| define.FILEMULT = 1
 | |
| code = '''
 | |
|     for (lfs_block_t badblock = 2; badblock < LFS_BLOCK_COUNT; badblock++) {
 | |
|         bbbd_badblocks = &(lfs_block_t){badblock};
 | |
|         bbbd_badblocks_count = 1;
 | |
|         
 | |
|         lfs_format(&lfs, &cfg) => 0;
 | |
| 
 | |
|         lfs_mount(&lfs, &cfg) => 0;
 | |
|         for (int i = 1; i < 10; i++) {
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j] = '0'+i;
 | |
|             }
 | |
|             buffer[NAMEMULT] = '\0';
 | |
|             lfs_mkdir(&lfs, (char*)buffer) => 0;
 | |
| 
 | |
|             buffer[NAMEMULT] = '/';
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j+NAMEMULT+1] = '0'+i;
 | |
|             }
 | |
|             buffer[2*NAMEMULT+1] = '\0';
 | |
|             lfs_file_open(&lfs, &file, (char*)buffer,
 | |
|                     LFS_O_WRONLY | LFS_O_CREAT) => 0;
 | |
|             
 | |
|             size = NAMEMULT;
 | |
|             for (int j = 0; j < i*FILEMULT; j++) {
 | |
|                 lfs_file_write(&lfs, &file, buffer, size) => size;
 | |
|             }
 | |
| 
 | |
|             lfs_file_close(&lfs, &file) => 0;
 | |
|         }
 | |
|         lfs_unmount(&lfs) => 0;
 | |
| 
 | |
|         lfs_mount(&lfs, &cfg) => 0;
 | |
|         for (int i = 1; i < 10; i++) {
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j] = '0'+i;
 | |
|             }
 | |
|             buffer[NAMEMULT] = '\0';
 | |
|             lfs_stat(&lfs, (char*)buffer, &info) => 0;
 | |
|             info.type => LFS_TYPE_DIR;
 | |
| 
 | |
|             buffer[NAMEMULT] = '/';
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j+NAMEMULT+1] = '0'+i;
 | |
|             }
 | |
|             buffer[2*NAMEMULT+1] = '\0';
 | |
|             lfs_file_open(&lfs, &file, (char*)buffer, LFS_O_RDONLY) => 0;
 | |
|             
 | |
|             size = NAMEMULT;
 | |
|             for (int j = 0; j < i*FILEMULT; j++) {
 | |
|                 uint8_t rbuffer[1024];
 | |
|                 lfs_file_read(&lfs, &file, rbuffer, size) => size;
 | |
|                 memcmp(buffer, rbuffer, size) => 0;
 | |
|             }
 | |
| 
 | |
|             lfs_file_close(&lfs, &file) => 0;
 | |
|         }
 | |
|         lfs_unmount(&lfs) => 0;
 | |
|     }
 | |
| '''
 | |
| 
 | |
| [[case]] # single persistent blocks (can't erase)
 | |
| define.LFS_BD_ERASE = 'bbbd_erase'
 | |
| define.NAMEMULT = 64
 | |
| define.FILEMULT = 1
 | |
| code = '''
 | |
|     for (lfs_block_t badblock = 2; badblock < LFS_BLOCK_COUNT; badblock++) {
 | |
|         bbbd_badblocks = &(lfs_block_t){badblock};
 | |
|         bbbd_badblocks_count = 1;
 | |
|         
 | |
|         lfs_format(&lfs, &cfg) => 0;
 | |
| 
 | |
|         lfs_mount(&lfs, &cfg) => 0;
 | |
|         for (int i = 1; i < 10; i++) {
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j] = '0'+i;
 | |
|             }
 | |
|             buffer[NAMEMULT] = '\0';
 | |
|             lfs_mkdir(&lfs, (char*)buffer) => 0;
 | |
| 
 | |
|             buffer[NAMEMULT] = '/';
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j+NAMEMULT+1] = '0'+i;
 | |
|             }
 | |
|             buffer[2*NAMEMULT+1] = '\0';
 | |
|             lfs_file_open(&lfs, &file, (char*)buffer,
 | |
|                     LFS_O_WRONLY | LFS_O_CREAT) => 0;
 | |
|             
 | |
|             size = NAMEMULT;
 | |
|             for (int j = 0; j < i*FILEMULT; j++) {
 | |
|                 lfs_file_write(&lfs, &file, buffer, size) => size;
 | |
|             }
 | |
| 
 | |
|             lfs_file_close(&lfs, &file) => 0;
 | |
|         }
 | |
|         lfs_unmount(&lfs) => 0;
 | |
| 
 | |
|         lfs_mount(&lfs, &cfg) => 0;
 | |
|         for (int i = 1; i < 10; i++) {
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j] = '0'+i;
 | |
|             }
 | |
|             buffer[NAMEMULT] = '\0';
 | |
|             lfs_stat(&lfs, (char*)buffer, &info) => 0;
 | |
|             info.type => LFS_TYPE_DIR;
 | |
| 
 | |
|             buffer[NAMEMULT] = '/';
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j+NAMEMULT+1] = '0'+i;
 | |
|             }
 | |
|             buffer[2*NAMEMULT+1] = '\0';
 | |
|             lfs_file_open(&lfs, &file, (char*)buffer, LFS_O_RDONLY) => 0;
 | |
|             
 | |
|             size = NAMEMULT;
 | |
|             for (int j = 0; j < i*FILEMULT; j++) {
 | |
|                 uint8_t rbuffer[1024];
 | |
|                 lfs_file_read(&lfs, &file, rbuffer, size) => size;
 | |
|                 memcmp(buffer, rbuffer, size) => 0;
 | |
|             }
 | |
| 
 | |
|             lfs_file_close(&lfs, &file) => 0;
 | |
|         }
 | |
|         lfs_unmount(&lfs) => 0;
 | |
|     }
 | |
| '''
 | |
| 
 | |
| [[case]] # single unreadable blocks (can't read)
 | |
| define.LFS_BD_READ = 'bbbd_read'
 | |
| define.NAMEMULT = 64
 | |
| define.FILEMULT = 1
 | |
| code = '''
 | |
|     for (lfs_block_t badblock = 2; badblock < LFS_BLOCK_COUNT; badblock++) {
 | |
|         bbbd_badblocks = &(lfs_block_t){badblock};
 | |
|         bbbd_badblocks_count = 1;
 | |
|         
 | |
|         lfs_format(&lfs, &cfg) => 0;
 | |
| 
 | |
|         lfs_mount(&lfs, &cfg) => 0;
 | |
|         for (int i = 1; i < 10; i++) {
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j] = '0'+i;
 | |
|             }
 | |
|             buffer[NAMEMULT] = '\0';
 | |
|             lfs_mkdir(&lfs, (char*)buffer) => 0;
 | |
| 
 | |
|             buffer[NAMEMULT] = '/';
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j+NAMEMULT+1] = '0'+i;
 | |
|             }
 | |
|             buffer[2*NAMEMULT+1] = '\0';
 | |
|             lfs_file_open(&lfs, &file, (char*)buffer,
 | |
|                     LFS_O_WRONLY | LFS_O_CREAT) => 0;
 | |
|             
 | |
|             size = NAMEMULT;
 | |
|             for (int j = 0; j < i*FILEMULT; j++) {
 | |
|                 lfs_file_write(&lfs, &file, buffer, size) => size;
 | |
|             }
 | |
| 
 | |
|             lfs_file_close(&lfs, &file) => 0;
 | |
|         }
 | |
|         lfs_unmount(&lfs) => 0;
 | |
| 
 | |
|         lfs_mount(&lfs, &cfg) => 0;
 | |
|         for (int i = 1; i < 10; i++) {
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j] = '0'+i;
 | |
|             }
 | |
|             buffer[NAMEMULT] = '\0';
 | |
|             lfs_stat(&lfs, (char*)buffer, &info) => 0;
 | |
|             info.type => LFS_TYPE_DIR;
 | |
| 
 | |
|             buffer[NAMEMULT] = '/';
 | |
|             for (int j = 0; j < NAMEMULT; j++) {
 | |
|                 buffer[j+NAMEMULT+1] = '0'+i;
 | |
|             }
 | |
|             buffer[2*NAMEMULT+1] = '\0';
 | |
|             lfs_file_open(&lfs, &file, (char*)buffer, LFS_O_RDONLY) => 0;
 | |
|             
 | |
|             size = NAMEMULT;
 | |
|             for (int j = 0; j < i*FILEMULT; j++) {
 | |
|                 uint8_t rbuffer[1024];
 | |
|                 lfs_file_read(&lfs, &file, rbuffer, size) => size;
 | |
|                 memcmp(buffer, rbuffer, size) => 0;
 | |
|             }
 | |
| 
 | |
|             lfs_file_close(&lfs, &file) => 0;
 | |
|         }
 | |
|         lfs_unmount(&lfs) => 0;
 | |
|     }
 | |
| '''
 | |
| 
 | |
| [[case]] # region corruption (causes cascading failures)
 | |
| define.LFS_BD_PROG  = '"BADTYPE == 0 ? bbbd_prog  : lfs_testbd_prog "'
 | |
| define.LFS_BD_ERASE = '"BADTYPE == 1 ? bbbd_erase : lfs_testbd_erase"'
 | |
| define.LFS_BD_READ  = '"BADTYPE == 2 ? bbbd_read  : lfs_testbd_read "'
 | |
| define.BADTYPE = 'range(3)'
 | |
| define.NAMEMULT = 64
 | |
| define.FILEMULT = 1
 | |
| code = '''
 | |
|     bbbd_badblocks_count = LFS_BLOCK_COUNT/2;
 | |
|     bbbd_badblocks = malloc(bbbd_badblocks_count*sizeof(lfs_block_t));
 | |
|     for (size_t i = 0; i < bbbd_badblocks_count; i++) {
 | |
|         bbbd_badblocks[i] = i+2;
 | |
|     }
 | |
|     
 | |
|     lfs_format(&lfs, &cfg) => 0;
 | |
| 
 | |
|     lfs_mount(&lfs, &cfg) => 0;
 | |
|     for (int i = 1; i < 10; i++) {
 | |
|         for (int j = 0; j < NAMEMULT; j++) {
 | |
|             buffer[j] = '0'+i;
 | |
|         }
 | |
|         buffer[NAMEMULT] = '\0';
 | |
|         lfs_mkdir(&lfs, (char*)buffer) => 0;
 | |
| 
 | |
|         buffer[NAMEMULT] = '/';
 | |
|         for (int j = 0; j < NAMEMULT; j++) {
 | |
|             buffer[j+NAMEMULT+1] = '0'+i;
 | |
|         }
 | |
|         buffer[2*NAMEMULT+1] = '\0';
 | |
|         lfs_file_open(&lfs, &file, (char*)buffer,
 | |
|                 LFS_O_WRONLY | LFS_O_CREAT) => 0;
 | |
|         
 | |
|         size = NAMEMULT;
 | |
|         for (int j = 0; j < i*FILEMULT; j++) {
 | |
|             lfs_file_write(&lfs, &file, buffer, size) => size;
 | |
|         }
 | |
| 
 | |
|         lfs_file_close(&lfs, &file) => 0;
 | |
|     }
 | |
|     lfs_unmount(&lfs) => 0;
 | |
| 
 | |
|     lfs_mount(&lfs, &cfg) => 0;
 | |
|     for (int i = 1; i < 10; i++) {
 | |
|         for (int j = 0; j < NAMEMULT; j++) {
 | |
|             buffer[j] = '0'+i;
 | |
|         }
 | |
|         buffer[NAMEMULT] = '\0';
 | |
|         lfs_stat(&lfs, (char*)buffer, &info) => 0;
 | |
|         info.type => LFS_TYPE_DIR;
 | |
| 
 | |
|         buffer[NAMEMULT] = '/';
 | |
|         for (int j = 0; j < NAMEMULT; j++) {
 | |
|             buffer[j+NAMEMULT+1] = '0'+i;
 | |
|         }
 | |
|         buffer[2*NAMEMULT+1] = '\0';
 | |
|         lfs_file_open(&lfs, &file, (char*)buffer, LFS_O_RDONLY) => 0;
 | |
|         
 | |
|         size = NAMEMULT;
 | |
|         for (int j = 0; j < i*FILEMULT; j++) {
 | |
|             uint8_t rbuffer[1024];
 | |
|             lfs_file_read(&lfs, &file, rbuffer, size) => size;
 | |
|             memcmp(buffer, rbuffer, size) => 0;
 | |
|         }
 | |
| 
 | |
|         lfs_file_close(&lfs, &file) => 0;
 | |
|     }
 | |
|     lfs_unmount(&lfs) => 0;
 | |
| 
 | |
|     free(bbbd_badblocks);
 | |
| '''
 | |
| 
 | |
| [[case]] # alternating corruption (causes cascading failures)
 | |
| define.LFS_BD_PROG  = '"BADTYPE == 0 ? bbbd_prog  : lfs_testbd_prog "'
 | |
| define.LFS_BD_ERASE = '"BADTYPE == 1 ? bbbd_erase : lfs_testbd_erase"'
 | |
| define.LFS_BD_READ  = '"BADTYPE == 2 ? bbbd_read  : lfs_testbd_read "'
 | |
| define.BADTYPE = 'range(3)'
 | |
| define.NAMEMULT = 64
 | |
| define.FILEMULT = 1
 | |
| code = '''
 | |
|     bbbd_badblocks_count = LFS_BLOCK_COUNT/2;
 | |
|     bbbd_badblocks = malloc(bbbd_badblocks_count*sizeof(lfs_block_t));
 | |
|     for (size_t i = 0; i < bbbd_badblocks_count; i++) {
 | |
|         bbbd_badblocks[i] = (2*i) + 2;
 | |
|     }
 | |
|     
 | |
|     lfs_format(&lfs, &cfg) => 0;
 | |
| 
 | |
|     lfs_mount(&lfs, &cfg) => 0;
 | |
|     for (int i = 1; i < 10; i++) {
 | |
|         for (int j = 0; j < NAMEMULT; j++) {
 | |
|             buffer[j] = '0'+i;
 | |
|         }
 | |
|         buffer[NAMEMULT] = '\0';
 | |
|         lfs_mkdir(&lfs, (char*)buffer) => 0;
 | |
| 
 | |
|         buffer[NAMEMULT] = '/';
 | |
|         for (int j = 0; j < NAMEMULT; j++) {
 | |
|             buffer[j+NAMEMULT+1] = '0'+i;
 | |
|         }
 | |
|         buffer[2*NAMEMULT+1] = '\0';
 | |
|         lfs_file_open(&lfs, &file, (char*)buffer,
 | |
|                 LFS_O_WRONLY | LFS_O_CREAT) => 0;
 | |
|         
 | |
|         size = NAMEMULT;
 | |
|         for (int j = 0; j < i*FILEMULT; j++) {
 | |
|             lfs_file_write(&lfs, &file, buffer, size) => size;
 | |
|         }
 | |
| 
 | |
|         lfs_file_close(&lfs, &file) => 0;
 | |
|     }
 | |
|     lfs_unmount(&lfs) => 0;
 | |
| 
 | |
|     lfs_mount(&lfs, &cfg) => 0;
 | |
|     for (int i = 1; i < 10; i++) {
 | |
|         for (int j = 0; j < NAMEMULT; j++) {
 | |
|             buffer[j] = '0'+i;
 | |
|         }
 | |
|         buffer[NAMEMULT] = '\0';
 | |
|         lfs_stat(&lfs, (char*)buffer, &info) => 0;
 | |
|         info.type => LFS_TYPE_DIR;
 | |
| 
 | |
|         buffer[NAMEMULT] = '/';
 | |
|         for (int j = 0; j < NAMEMULT; j++) {
 | |
|             buffer[j+NAMEMULT+1] = '0'+i;
 | |
|         }
 | |
|         buffer[2*NAMEMULT+1] = '\0';
 | |
|         lfs_file_open(&lfs, &file, (char*)buffer, LFS_O_RDONLY) => 0;
 | |
|         
 | |
|         size = NAMEMULT;
 | |
|         for (int j = 0; j < i*FILEMULT; j++) {
 | |
|             uint8_t rbuffer[1024];
 | |
|             lfs_file_read(&lfs, &file, rbuffer, size) => size;
 | |
|             memcmp(buffer, rbuffer, size) => 0;
 | |
|         }
 | |
| 
 | |
|         lfs_file_close(&lfs, &file) => 0;
 | |
|     }
 | |
|     lfs_unmount(&lfs) => 0;
 | |
| 
 | |
|     free(bbbd_badblocks);
 | |
| '''
 |