#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tests_pass.h" bool do_valgrind = false; static const char *can_run(struct manifest *m) { unsigned int timeleft = default_timeout_ms; char *output; if (safe_mode) return "Safe mode enabled"; if (!is_excluded("tests_pass_valgrind") && run_command(m, &timeleft, &output, "valgrind -q true")) do_valgrind = true; return NULL; } static const char *concat(struct score *score, char *bits[]) { unsigned int i; char *ret = tal_strdup(score, ""); for (i = 0; bits[i]; i++) { if (i) ret = tal_strcat(score, take(ret), " "); ret = tal_strcat(score, take(ret), bits[i]); } return ret; } static void run_test(void *ctx, struct manifest *m, unsigned int *timeleft, struct ccan_file *i) { if (do_valgrind) { const char *options; options = concat(ctx, per_file_options(&tests_pass_valgrind, i)); if (!streq(options, "FAIL")) { /* FIXME: Valgrind's output sucks. XML is * unreadable by humans *and* doesn't support * children reporting. */ i->valgrind_log = tal_fmt(m, "%s.valgrind-log", i->compiled[COMPILE_NORMAL]); run_command_async(i, *timeleft, "valgrind -q" " --leak-check=full" " --log-fd=3 %s %s" " 3> %s", options, i->compiled[COMPILE_NORMAL], i->valgrind_log); return; } } run_command_async(i, *timeleft, "%s", i->compiled[COMPILE_NORMAL]); } static void do_run_tests(struct manifest *m, unsigned int *timeleft, struct score *score) { struct list_head *list; struct ccan_file *i; char *cmdout; bool ok; score->total = 0; foreach_ptr(list, &m->run_tests, &m->api_tests) { list_for_each(list, i, list) { score->total++; if (verbose >= 2) printf(" %s...\n", i->name); run_test(score, m, timeleft, i); } } while ((i = collect_command(&ok, &cmdout)) != NULL) { if (!ok) score_file_error(score, i, 0, "%s", cmdout); else score->score++; if (verbose >= 2) printf(" ...%s\n", i->name); } if (score->score == score->total) score->pass = true; } /* Gcc's warn_unused_result is fascist bullshit. */ #define doesnt_matter() static void run_under_debugger(struct manifest *m, struct score *score) { char *command; struct file_error *first; first = list_top(&score->per_file_errors, struct file_error, list); if (!ask("Should I run the first failing test under the debugger?")) return; command = tal_fmt(m, "gdb -ex 'break tap.c:139' -ex 'run' %s", first->file->compiled[COMPILE_NORMAL]); if (system(command)) doesnt_matter(); } struct ccanlint tests_pass = { .key = "tests_pass", .name = "Module's run and api tests pass", .check = do_run_tests, .handle = run_under_debugger, .can_run = can_run, .needs = "tests_compile" }; REGISTER_TEST(tests_pass);