Migrated bad-block tests
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.
This commit is contained in:
+95
-29
@@ -19,6 +19,7 @@
|
|||||||
# x config chaining correct
|
# x config chaining correct
|
||||||
# - why can't gdb see my defines?
|
# - why can't gdb see my defines?
|
||||||
# - say no to internal?
|
# - say no to internal?
|
||||||
|
# - buffering stdout issues?
|
||||||
|
|
||||||
import toml
|
import toml
|
||||||
import glob
|
import glob
|
||||||
@@ -55,8 +56,79 @@ GLOBALS = """
|
|||||||
#include "filebd/lfs_filebd.h"
|
#include "filebd/lfs_filebd.h"
|
||||||
#include "rambd/lfs_rambd.h"
|
#include "rambd/lfs_rambd.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern const char *lfs_testbd_disk;
|
||||||
|
typedef union {
|
||||||
|
lfs_filebd_t filebd;
|
||||||
|
lfs_rambd_t rambd;
|
||||||
|
} lfs_testbd_t;
|
||||||
|
struct lfs_testbd_config {
|
||||||
|
struct lfs_filebd_config filecfg;
|
||||||
|
struct lfs_rambd_config ramcfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static int lfs_testbd_createcfg(const struct lfs_config *cfg,
|
||||||
|
const struct lfs_testbd_config *bdcfg) {
|
||||||
|
if (lfs_testbd_disk) {
|
||||||
|
return lfs_filebd_createcfg(cfg, lfs_testbd_disk, &bdcfg->filecfg);
|
||||||
|
} else {
|
||||||
|
return lfs_rambd_createcfg(cfg, &bdcfg->ramcfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static void lfs_testbd_destroy(const struct lfs_config *cfg) {
|
||||||
|
if (lfs_testbd_disk) {
|
||||||
|
lfs_filebd_destroy(cfg);
|
||||||
|
} else {
|
||||||
|
lfs_rambd_destroy(cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static int lfs_testbd_read(const struct lfs_config *cfg, lfs_block_t block,
|
||||||
|
lfs_off_t off, void *buffer, lfs_size_t size) {
|
||||||
|
if (lfs_testbd_disk) {
|
||||||
|
return lfs_filebd_read(cfg, block, off, buffer, size);
|
||||||
|
} else {
|
||||||
|
return lfs_rambd_read(cfg, block, off, buffer, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block,
|
||||||
|
lfs_off_t off, const void *buffer, lfs_size_t size) {
|
||||||
|
if (lfs_testbd_disk) {
|
||||||
|
return lfs_filebd_prog(cfg, block, off, buffer, size);
|
||||||
|
} else {
|
||||||
|
return lfs_rambd_prog(cfg, block, off, buffer, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
||||||
|
if (lfs_testbd_disk) {
|
||||||
|
return lfs_filebd_erase(cfg, block);
|
||||||
|
} else {
|
||||||
|
return lfs_rambd_erase(cfg, block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static int lfs_testbd_sync(const struct lfs_config *cfg) {
|
||||||
|
if (lfs_testbd_disk) {
|
||||||
|
return lfs_filebd_sync(cfg);
|
||||||
|
} else {
|
||||||
|
return lfs_rambd_sync(cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
DEFINES = {
|
DEFINES = {
|
||||||
|
"LFS_BD_READ": "lfs_testbd_read",
|
||||||
|
"LFS_BD_PROG": "lfs_testbd_prog",
|
||||||
|
"LFS_BD_ERASE": "lfs_testbd_erase",
|
||||||
|
"LFS_BD_SYNC": "lfs_testbd_sync",
|
||||||
"LFS_READ_SIZE": 16,
|
"LFS_READ_SIZE": 16,
|
||||||
"LFS_PROG_SIZE": "LFS_READ_SIZE",
|
"LFS_PROG_SIZE": "LFS_READ_SIZE",
|
||||||
"LFS_BLOCK_SIZE": 512,
|
"LFS_BLOCK_SIZE": 512,
|
||||||
@@ -68,11 +140,8 @@ DEFINES = {
|
|||||||
}
|
}
|
||||||
PROLOGUE = """
|
PROLOGUE = """
|
||||||
// prologue
|
// prologue
|
||||||
extern const char *LFS_DISK;
|
|
||||||
|
|
||||||
__attribute__((unused)) lfs_t lfs;
|
__attribute__((unused)) lfs_t lfs;
|
||||||
__attribute__((unused)) lfs_filebd_t filebd;
|
__attribute__((unused)) lfs_testbd_t bd;
|
||||||
__attribute__((unused)) lfs_rambd_t rambd;
|
|
||||||
__attribute__((unused)) lfs_file_t file;
|
__attribute__((unused)) lfs_file_t file;
|
||||||
__attribute__((unused)) lfs_dir_t dir;
|
__attribute__((unused)) lfs_dir_t dir;
|
||||||
__attribute__((unused)) struct lfs_info info;
|
__attribute__((unused)) struct lfs_info info;
|
||||||
@@ -82,12 +151,11 @@ PROLOGUE = """
|
|||||||
__attribute__((unused)) int err;
|
__attribute__((unused)) int err;
|
||||||
|
|
||||||
__attribute__((unused)) const struct lfs_config cfg = {
|
__attribute__((unused)) const struct lfs_config cfg = {
|
||||||
.context = LFS_DISK ? (void*)&filebd : (void*)&rambd,
|
.context = &bd,
|
||||||
.read = LFS_DISK ? &lfs_filebd_read : &lfs_rambd_read,
|
.read = LFS_BD_READ,
|
||||||
.prog = LFS_DISK ? &lfs_filebd_prog : &lfs_rambd_prog,
|
.prog = LFS_BD_PROG,
|
||||||
.erase = LFS_DISK ? &lfs_filebd_erase : &lfs_rambd_erase,
|
.erase = LFS_BD_ERASE,
|
||||||
.sync = LFS_DISK ? &lfs_filebd_sync : &lfs_rambd_sync,
|
.sync = LFS_BD_SYNC,
|
||||||
|
|
||||||
.read_size = LFS_READ_SIZE,
|
.read_size = LFS_READ_SIZE,
|
||||||
.prog_size = LFS_PROG_SIZE,
|
.prog_size = LFS_PROG_SIZE,
|
||||||
.block_size = LFS_BLOCK_SIZE,
|
.block_size = LFS_BLOCK_SIZE,
|
||||||
@@ -97,26 +165,16 @@ PROLOGUE = """
|
|||||||
.lookahead_size = LFS_LOOKAHEAD_SIZE,
|
.lookahead_size = LFS_LOOKAHEAD_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
__attribute__((unused)) const struct lfs_filebd_config filecfg = {
|
__attribute__((unused)) const struct lfs_testbd_config bdcfg = {
|
||||||
.erase_value = LFS_ERASE_VALUE,
|
.filecfg.erase_value = LFS_ERASE_VALUE,
|
||||||
};
|
.ramcfg.erase_value = LFS_ERASE_VALUE,
|
||||||
__attribute__((unused)) const struct lfs_rambd_config ramcfg = {
|
|
||||||
.erase_value = LFS_ERASE_VALUE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (LFS_DISK) {
|
lfs_testbd_createcfg(&cfg, &bdcfg) => 0;
|
||||||
lfs_filebd_createcfg(&cfg, LFS_DISK, &filecfg);
|
|
||||||
} else {
|
|
||||||
lfs_rambd_createcfg(&cfg, &ramcfg);
|
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
EPILOGUE = """
|
EPILOGUE = """
|
||||||
// epilogue
|
// epilogue
|
||||||
if (LFS_DISK) {
|
lfs_testbd_destroy(&cfg);
|
||||||
lfs_filebd_destroy(&cfg);
|
|
||||||
} else {
|
|
||||||
lfs_rambd_destroy(&cfg);
|
|
||||||
}
|
|
||||||
"""
|
"""
|
||||||
PASS = '\033[32m✓\033[0m'
|
PASS = '\033[32m✓\033[0m'
|
||||||
FAIL = '\033[31m✗\033[0m'
|
FAIL = '\033[31m✗\033[0m'
|
||||||
@@ -363,15 +421,20 @@ class TestSuite:
|
|||||||
if re.match(r'code\s*=\s*(\'\'\'|""")', line):
|
if re.match(r'code\s*=\s*(\'\'\'|""")', line):
|
||||||
code_linenos.append(i+2)
|
code_linenos.append(i+2)
|
||||||
|
|
||||||
|
code_linenos.reverse()
|
||||||
|
|
||||||
# grab global config
|
# grab global config
|
||||||
self.defines = config.get('define', {})
|
self.defines = config.get('define', {})
|
||||||
|
self.code = config.get('code', None)
|
||||||
|
if self.code is not None:
|
||||||
|
self.code_lineno = code_linenos.pop()
|
||||||
|
|
||||||
# create initial test cases
|
# create initial test cases
|
||||||
self.cases = []
|
self.cases = []
|
||||||
for i, (case, lineno) in enumerate(zip(config['case'], linenos)):
|
for i, (case, lineno) in enumerate(zip(config['case'], linenos)):
|
||||||
# code lineno?
|
# code lineno?
|
||||||
if 'code' in case:
|
if 'code' in case:
|
||||||
case['code_lineno'] = code_linenos.pop(0)
|
case['code_lineno'] = code_linenos.pop()
|
||||||
# give our case's config a copy of our "global" config
|
# give our case's config a copy of our "global" config
|
||||||
for k, v in config.items():
|
for k, v in config.items():
|
||||||
if k not in case:
|
if k not in case:
|
||||||
@@ -452,8 +515,11 @@ class TestSuite:
|
|||||||
# build test files
|
# build test files
|
||||||
tf = open(self.path + '.test.c.t', 'w')
|
tf = open(self.path + '.test.c.t', 'w')
|
||||||
tf.write(GLOBALS)
|
tf.write(GLOBALS)
|
||||||
tfs = {None: tf}
|
if self.code is not None:
|
||||||
|
tf.write('#line %d "%s"\n' % (self.code_lineno, self.path))
|
||||||
|
tf.write(self.code)
|
||||||
|
|
||||||
|
tfs = {None: tf}
|
||||||
for case in self.cases:
|
for case in self.cases:
|
||||||
if case.in_ not in tfs:
|
if case.in_ not in tfs:
|
||||||
tfs[case.in_] = open(self.path+'.'+
|
tfs[case.in_] = open(self.path+'.'+
|
||||||
@@ -469,11 +535,11 @@ class TestSuite:
|
|||||||
case.build(tfs[case.in_], **args)
|
case.build(tfs[case.in_], **args)
|
||||||
|
|
||||||
tf.write('\n')
|
tf.write('\n')
|
||||||
tf.write('const char *LFS_DISK = NULL;\n')
|
tf.write('const char *lfs_testbd_disk;\n')
|
||||||
tf.write('int main(int argc, char **argv) {\n')
|
tf.write('int main(int argc, char **argv) {\n')
|
||||||
tf.write(4*' '+'int case_ = (argc >= 2) ? atoi(argv[1]) : 0;\n')
|
tf.write(4*' '+'int case_ = (argc >= 2) ? atoi(argv[1]) : 0;\n')
|
||||||
tf.write(4*' '+'int perm = (argc >= 3) ? atoi(argv[2]) : 0;\n')
|
tf.write(4*' '+'int perm = (argc >= 3) ? atoi(argv[2]) : 0;\n')
|
||||||
tf.write(4*' '+'LFS_DISK = (argc >= 4) ? argv[3] : NULL;\n')
|
tf.write(4*' '+'lfs_testbd_disk = (argc >= 4) ? argv[3] : NULL;\n')
|
||||||
for perm in self.perms:
|
for perm in self.perms:
|
||||||
# test declaration
|
# test declaration
|
||||||
tf.write(4*' '+'extern void test_case%d(%s);\n' % (
|
tf.write(4*' '+'extern void test_case%d(%s);\n' % (
|
||||||
|
|||||||
@@ -0,0 +1,375 @@
|
|||||||
|
# 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);
|
||||||
|
'''
|
||||||
Reference in New Issue
Block a user