diff --git a/bd/lfs_filebd.h b/bd/lfs_filebd.h index 1a9456c..0ed1909 100644 --- a/bd/lfs_filebd.h +++ b/bd/lfs_filebd.h @@ -18,11 +18,13 @@ extern "C" // Block device specific tracing +#ifndef LFS_FILEBD_TRACE #ifdef LFS_FILEBD_YES_TRACE #define LFS_FILEBD_TRACE(...) LFS_TRACE(__VA_ARGS__) #else #define LFS_FILEBD_TRACE(...) #endif +#endif // filebd config (optional) struct lfs_filebd_config { diff --git a/bd/lfs_rambd.h b/bd/lfs_rambd.h index 3a70bc6..b7629a9 100644 --- a/bd/lfs_rambd.h +++ b/bd/lfs_rambd.h @@ -18,11 +18,13 @@ extern "C" // Block device specific tracing +#ifndef LFS_RAMBD_TRACE #ifdef LFS_RAMBD_YES_TRACE #define LFS_RAMBD_TRACE(...) LFS_TRACE(__VA_ARGS__) #else #define LFS_RAMBD_TRACE(...) #endif +#endif // rambd config (optional) struct lfs_rambd_config { diff --git a/bd/lfs_testbd.h b/bd/lfs_testbd.h index 61679e5..06794e7 100644 --- a/bd/lfs_testbd.h +++ b/bd/lfs_testbd.h @@ -21,11 +21,13 @@ extern "C" // Block device specific tracing +#ifndef LFS_TESTBD_TRACE #ifdef LFS_TESTBD_YES_TRACE #define LFS_TESTBD_TRACE(...) LFS_TRACE(__VA_ARGS__) #else #define LFS_TESTBD_TRACE(...) #endif +#endif // Mode determining how "bad blocks" behave during testing. This simulates // some real-world circumstances such as progs not sticking (prog-noop), diff --git a/runners/test_runner.c b/runners/test_runner.c index 38c6896..185fa8a 100644 --- a/runners/test_runner.c +++ b/runners/test_runner.c @@ -4,6 +4,7 @@ #include #include +#include // disk geometries struct test_geometry { @@ -126,6 +127,9 @@ static test_define_t *override_defines = NULL; static size_t override_count = 0; static size_t override_cap = 0; +static const char *test_persist = NULL; +FILE *test_trace = NULL; + // note, these skips are different than filtered tests static bool test_suite_skip(const struct test_suite *suite) { return (test_suite && strcmp(suite->name, test_suite) != 0) @@ -491,7 +495,12 @@ static void run(void) { .power_cycles = 0, }; - lfs_testbd_createcfg(&cfg, NULL, &bdcfg) => 0; + int err = lfs_testbd_createcfg(&cfg, test_persist, &bdcfg); + if (err) { + fprintf(stderr, "error: " + "could not create block device: %d\n", err); + exit(-1); + } // run the test printf("running %s#%zu\n", test_suites[i]->cases[j]->id, perm); @@ -501,7 +510,12 @@ static void run(void) { printf("finished %s#%zu\n", test_suites[i]->cases[j]->id, perm); // cleanup - lfs_testbd_destroy(&cfg) => 0; + err = lfs_testbd_destroy(&cfg); + if (err) { + fprintf(stderr, "error: " + "could not destroy block device: %d\n", err); + exit(-1); + } test_define_geometry(NULL); test_define_case(NULL, 0); @@ -532,9 +546,11 @@ enum opt_flags { OPT_SKIP = 4, OPT_COUNT = 5, OPT_EVERY = 6, + OPT_PERSIST = 'p', + OPT_TRACE = 't', }; -const char *short_opts = "hYlLD:G:nrV"; +const char *short_opts = "hYlLD:G:nrVp:t:"; const struct option long_opts[] = { {"help", no_argument, NULL, OPT_HELP}, @@ -552,6 +568,8 @@ const struct option long_opts[] = { {"skip", required_argument, NULL, OPT_SKIP}, {"count", required_argument, NULL, OPT_COUNT}, {"every", required_argument, NULL, OPT_EVERY}, + {"persist", required_argument, NULL, OPT_PERSIST}, + {"trace", required_argument, NULL, OPT_TRACE}, {NULL, 0, NULL, 0}, }; @@ -571,6 +589,8 @@ const char *const help_text[] = { "Skip the first n tests.", "Stop after n tests.", "Only run every n tests, calculated after --skip and --stop.", + "Persist the disk to this file.", + "Redirect trace output to this file.", }; int main(int argc, char **argv) { @@ -727,6 +747,21 @@ invalid_define: } break; } + case OPT_PERSIST: + test_persist = optarg; + break; + case OPT_TRACE: + if (strcmp(optarg, "-") == 0) { + test_trace = stdout; + } else { + test_trace = fopen(optarg, "w"); + if (!test_trace) { + fprintf(stderr, "error: could not open for trace: %d\n", + -errno); + exit(-1); + } + } + break; // done parsing case -1: goto getopt_done; diff --git a/scripts/test_.py b/scripts/test_.py index 9007f1f..e645876 100755 --- a/scripts/test_.py +++ b/scripts/test_.py @@ -14,7 +14,6 @@ import toml TEST_PATHS = ['tests_'] SUITE_PROLOGUE = """ -//////// AUTOGENERATED //////// #include "runners/test_runner.h" #include """ @@ -222,7 +221,21 @@ def compile(**args): suite = TestSuite(paths[0]) if 'output' in args: with openio(args['output'], 'w') as f: - f.write(SUITE_PROLOGUE) + # redirect littlefs tracing + f.write('#define LFS_TRACE_(fmt, ...) do { \\\n') + f.write(8*' '+'extern FILE *test_trace; \\\n') + f.write(8*' '+'if (test_trace) { \\\n') + f.write(12*' '+'fprintf(test_trace, ' + '"%s:%d:trace: " fmt "%s\\n", \\\n') + f.write(20*' '+'__FILE__, __LINE__, __VA_ARGS__); \\\n') + f.write(8*' '+'} \\\n') + f.write(4*' '+'} while (0)\n') + f.write('#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")\n') + f.write('#define LFS_TESTBD_TRACE(...) ' + 'LFS_TRACE_(__VA_ARGS__, "")\n') + f.write('\n') + + f.write('%s\n' % SUITE_PROLOGUE.strip()) f.write('\n') if suite.code is not None: if suite.code_lineno is not None: @@ -380,6 +393,21 @@ def compile(**args): # write out a test source if 'output' in args: with openio(args['output'], 'w') as f: + # redirect littlefs tracing + f.write('#define LFS_TRACE_(fmt, ...) do { \\\n') + f.write(8*' '+'extern FILE *test_trace; \\\n') + f.write(8*' '+'if (test_trace) { \\\n') + f.write(12*' '+'fprintf(test_trace, ' + '"%s:%d:trace: " fmt "%s\\n", \\\n') + f.write(20*' '+'__FILE__, __LINE__, __VA_ARGS__); \\\n') + f.write(8*' '+'} \\\n') + f.write(4*' '+'} while (0)\n') + f.write('#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")\n') + f.write('#define LFS_TESTBD_TRACE(...) ' + 'LFS_TRACE_(__VA_ARGS__, "")\n') + f.write('\n') + + # copy source f.write('#line 1 "%s"\n' % args['source']) with open(args['source']) as sf: shutil.copyfileobj(sf, f)