#include <err.h>
#include <string.h>
#include <ctype.h>
-#include "build-coverage.h"
/* Note: we already test safe_mode in run_tests.c */
static const char *can_run_coverage(struct manifest *m)
{
unsigned int timeleft = default_timeout_ms;
- char *output = run_command(m, &timeleft, "gcov -h");
+ char *output;
- if (output)
+ if (!run_command(m, &timeleft, &output, "gcov -h"))
return talloc_asprintf(m, "No gcov support: %s", output);
return NULL;
}
-static char *build_module_objs_with_coverage(struct manifest *m, bool keep,
- char **modobjs)
+static bool build_module_objs_with_coverage(struct manifest *m, bool keep,
+ struct score *score,
+ char **modobjs)
{
struct ccan_file *i;
char *fullfile = talloc_asprintf(m, "%s/%s", m->dir, i->name);
i->cov_compiled = maybe_temp_file(m, "", keep, fullfile);
- err = compile_object(m, fullfile, ccan_dir, "",
- i->cov_compiled);
- if (err) {
+ if (!compile_object(m, fullfile, ccan_dir, "",
+ i->cov_compiled, &err)) {
+ score_file_error(score, i, 0, err);
talloc_free(i->cov_compiled);
- return err;
+ i->cov_compiled = NULL;
+ return false;
}
*modobjs = talloc_asprintf_append(*modobjs,
" %s", i->cov_compiled);
}
- return NULL;
+ return true;
}
+/* FIXME: Merge this into one place. */
static char *obj_list(const struct manifest *m, const char *modobjs)
{
- char *list;
+ char *list = talloc_strdup(m, "");
struct ccan_file *i;
-
- /* We expect to be linked with tap, unless that's us. */
- if (!streq(m->basename, "tap"))
- list = talloc_asprintf(m, "%s/ccan/tap.o", ccan_dir);
- else
- list = talloc_strdup(m, "");
+ struct manifest *subm;
/* Objects from any other C files. */
list_for_each(&m->other_test_c_files, i, list)
list = talloc_append_string(list, modobjs);
/* Other ccan modules (don't need coverage versions of those). */
- list_for_each(&m->dep_dirs, i, list) {
- if (i->compiled)
- list = talloc_asprintf_append(list, " %s", i->compiled);
+ list_for_each(&m->deps, subm, list) {
+ if (subm->compiled)
+ list = talloc_asprintf_append(list, " %s",
+ subm->compiled);
}
return list;
static char *lib_list(const struct manifest *m)
{
unsigned int i, num;
- char **libs = get_libs(m, ".", &num, &m->info_file->compiled);
+ char **libs = get_libs(m, m->dir, &num, &m->info_file->compiled);
char *ret = talloc_strdup(m, "");
for (i = 0; i < num; i++)
return ret;
}
-/* Grrr... gcov drops a turd in the current directory. */
-void move_gcov_turd(const char *dir,
- struct ccan_file *file, const char *extension)
-{
- char *base, *gcovfile, *gcovdest;
-
- base = talloc_basename(file, file->name);
- gcovfile = talloc_asprintf(file, "%s/%.*s%s",
- dir, strlen(base)-2, base, extension);
- gcovdest = talloc_asprintf(file, "%s/%.*s%s",
- talloc_dirname(base, file->cov_compiled),
- strlen(base)-2, base, extension);
- if (!move_file(gcovfile, gcovdest))
- err(1, "Could not move %s to %s", gcovfile, gcovdest);
- talloc_free(base);
-}
-
static char *cov_compile(const void *ctx,
struct manifest *m,
struct ccan_file *file,
const char *modobjs,
bool keep)
{
- char *errmsg;
- char path[PATH_MAX];
+ char *output;
file->cov_compiled = maybe_temp_file(ctx, "", keep, file->fullname);
- errmsg = compile_and_link(ctx, file->fullname, ccan_dir,
- obj_list(m, modobjs),
- COVERAGE_CFLAGS,
- lib_list(m), file->cov_compiled);
- if (errmsg) {
+ if (!compile_and_link(ctx, file->fullname, ccan_dir,
+ obj_list(m, modobjs),
+ COVERAGE_CFLAGS,
+ lib_list(m), file->cov_compiled, &output)) {
talloc_free(file->cov_compiled);
- return errmsg;
+ file->cov_compiled = NULL;
+ return output;
}
-
- move_gcov_turd(getcwd(path, sizeof(path)), file, ".gcno");
+ talloc_free(output);
return NULL;
}
-struct compile_tests_result {
- struct list_node list;
- const char *filename;
- const char *description;
- const char *output;
-};
-
-static void *do_compile_coverage_tests(struct manifest *m,
- bool keep,
- unsigned int *timeleft)
+/* FIXME: Coverage from testable examples as well. */
+static void do_compile_coverage_tests(struct manifest *m,
+ bool keep,
+ unsigned int *timeleft,
+ struct score *score)
{
- struct list_head *list = talloc(m, struct list_head);
char *cmdout, *modobjs = NULL;
struct ccan_file *i;
- struct compile_tests_result *res;
-
- list_head_init(list);
- if (!list_empty(&m->api_tests)) {
- cmdout = build_module_objs_with_coverage(m, keep, &modobjs);
- if (cmdout) {
- res = talloc(list, struct compile_tests_result);
- res->filename = "Module objects with coverage";
- res->description = "failed to compile";
- res->output = talloc_steal(res, cmdout);
- list_add_tail(list, &res->list);
- return list;
- }
+ if (!list_empty(&m->api_tests)
+ && !build_module_objs_with_coverage(m, keep, score, &modobjs)) {
+ score->error = "Failed to compile module objects with coverage";
+ return;
}
list_for_each(&m->run_tests, i, list) {
- compile_tests.total_score++;
cmdout = cov_compile(m, m, i, NULL, keep);
if (cmdout) {
- res = talloc(list, struct compile_tests_result);
- res->filename = i->name;
- res->description = "failed to compile";
- res->output = talloc_steal(res, cmdout);
- list_add_tail(list, &res->list);
+ score->error = "Failed to compile test with coverage";
+ score_file_error(score, i, 0, cmdout);
}
}
list_for_each(&m->api_tests, i, list) {
- compile_tests.total_score++;
cmdout = cov_compile(m, m, i, modobjs, keep);
if (cmdout) {
- res = talloc(list, struct compile_tests_result);
- res->filename = i->name;
- res->description = "failed to compile";
- res->output = talloc_steal(res, cmdout);
- list_add_tail(list, &res->list);
+ score->error = "Failed to compile test with coverage";
+ score_file_error(score, i, 0, cmdout);
}
}
-
- if (list_empty(list)) {
- talloc_free(list);
- list = NULL;
+ if (!score->error) {
+ score->pass = true;
+ score->score = score->total;
}
-
- return list;
-}
-
-static const char *describe_compile_coverage_tests(struct manifest *m,
- void *check_result)
-{
- struct list_head *list = check_result;
- struct compile_tests_result *i;
- char *descrip;
-
- descrip = talloc_strdup(list,
- "Compilation of tests for coverage failed:\n");
-
- list_for_each(list, i, list)
- descrip = talloc_asprintf_append(descrip, "%s %s\n%s",
- i->filename, i->description,
- i->output);
- return descrip;
}
struct ccanlint compile_coverage_tests = {
.key = "compile-coverage-tests",
.name = "Module tests compile with profiling",
.check = do_compile_coverage_tests,
- .describe = describe_compile_coverage_tests,
.can_run = can_run_coverage,
};