From 24908e18c8db7543084e16707b7b82ef5a094d7a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 30 Aug 2010 10:51:48 +0930 Subject: [PATCH] ccanlint: use up to three -v to mean more verbosity. eg. -v dumps percentage of coverage, -vv dumps per-line data, -vvv dumps every command executed. --- tools/ccanlint/ccanlint.c | 30 ++++++---- tools/ccanlint/ccanlint.h | 5 ++ tools/ccanlint/compulsory_tests/has_tests.c | 3 +- tools/ccanlint/compulsory_tests/run_tests.c | 12 ---- tools/ccanlint/tests/run-coverage.c | 62 +++++++++++++++------ tools/ccanlint/tests/trailing_whitespace.c | 3 + 6 files changed, 75 insertions(+), 40 deletions(-) diff --git a/tools/ccanlint/ccanlint.c b/tools/ccanlint/ccanlint.c index d65a4a43..77917057 100644 --- a/tools/ccanlint/ccanlint.c +++ b/tools/ccanlint/ccanlint.c @@ -31,7 +31,7 @@ #include #include -static unsigned int verbose = 0; +unsigned int verbose = 0; static LIST_HEAD(compulsory_tests); static LIST_HEAD(normal_tests); static LIST_HEAD(finished_tests); @@ -42,7 +42,7 @@ static unsigned int timeout; static void usage(const char *name) { fprintf(stderr, "Usage: %s [-s] [-n] [-v] [-t ] [-d ] [-x ] [-k ]*\n" - " -v: verbose mode\n" + " -v: verbose mode (can specify more than once)\n" " -s: simply give one line summary\n" " -d: use this directory instead of the current one\n" " -n: do not compile anything\n" @@ -106,7 +106,7 @@ static bool run_test(struct ccanlint *i, unsigned int this_score, timeleft; const struct dependent *d; const char *skip; - bool failed; + bool bad, good; //one less test to run through list_for_each(&i->dependencies, d, node) @@ -146,10 +146,12 @@ static bool run_test(struct ccanlint *i, else this_score = 0; - failed = (this_score == 0); + bad = (this_score == 0); + good = (this_score >= i->total_score); - if (verbose) { - printf(" %s: %s", i->name, failed ? "FAIL" : "OK"); + if (verbose || (bad && !quiet)) { + printf(" %s: %s", i->name, + bad ? "FAIL" : good ? "PASS" : "PARTIAL"); if (i->total_score) printf(" (+%u/%u)", this_score, i->total_score); @@ -157,8 +159,9 @@ static bool run_test(struct ccanlint *i, } if (!quiet && result) { - if (i->describe && (failed || verbose)) - printf(" %s\n", i->describe(m, result)); + const char *desc; + if (i->describe && (desc = i->describe(m, result)) != NULL) + printf(" %s\n", desc); if (i->handle) i->handle(m, result); } @@ -171,14 +174,14 @@ static bool run_test(struct ccanlint *i, list_del(&i->list); list_add_tail(&finished_tests, &i->list); - if (failed) { + if (bad) { /* Skip any tests which depend on this one. */ list_for_each(&i->dependencies, d, node) { d->dependent->skip = true; d->dependent->skip_fail = true; } } - return !failed; + return good; } static void register_test(struct list_head *h, struct ccanlint *test, ...) @@ -387,12 +390,19 @@ int main(int argc, char *argv[]) if (optind < argc) usage(argv[0]); + if (verbose >= 3) + tools_verbose = true; + /* We move into temporary directory, so gcov dumps its files there. */ if (chdir(temp_dir(talloc_autofree_context())) != 0) err(1, "Error changing to %s temporary dir", temp_dir(NULL)); m = get_manifest(talloc_autofree_context(), dir); + /* Create a symlink from temp dir back to src dir's test directory. */ + symlink(talloc_asprintf(m, "%s/test", dir), + talloc_asprintf(m, "%s/test", temp_dir(NULL))); + /* If you don't pass the compulsory tests, you don't even get a score */ if (verbose) printf("Compulsory tests:\n"); diff --git a/tools/ccanlint/ccanlint.h b/tools/ccanlint/ccanlint.h index 247d0d0d..3a79fb94 100644 --- a/tools/ccanlint/ccanlint.h +++ b/tools/ccanlint/ccanlint.h @@ -11,6 +11,11 @@ #define REGISTER_TEST(name, ...) +/* 1 == Describe results for partial failures. + 2 == Describe gory details. + 3 == Describe every action. */ +extern unsigned int verbose; + struct manifest { char *dir; /* The module name, ie. final element of dir name */ diff --git a/tools/ccanlint/compulsory_tests/has_tests.c b/tools/ccanlint/compulsory_tests/has_tests.c index 04dd4495..f6ef4968 100644 --- a/tools/ccanlint/compulsory_tests/has_tests.c +++ b/tools/ccanlint/compulsory_tests/has_tests.c @@ -51,7 +51,8 @@ static const char *describe_has_tests(struct manifest *m, void *check_result) "warnings, and then run: it is expected to use libtap to report its\n" "results in a simple and portable format. It should #include the C\n" "files from the module directly (so it can probe the internals): the\n" - "module will not be linked in.\n\n" + "module will not be linked in. The test will be run in a temporary\n" + "directory, with the test directory symlinked under test/.\n\n" "api tests are just like a run test, except it is a guarantee of API\n" "stability: this test should pass on all future versions of the\n" diff --git a/tools/ccanlint/compulsory_tests/run_tests.c b/tools/ccanlint/compulsory_tests/run_tests.c index 9f1f4a4a..e2ab9226 100644 --- a/tools/ccanlint/compulsory_tests/run_tests.c +++ b/tools/ccanlint/compulsory_tests/run_tests.c @@ -35,15 +35,6 @@ static void *do_run_tests(struct manifest *m, struct run_tests_result *res; struct ccan_file *i; char *cmdout; - char *olddir; - - /* We run tests in the module directory, so any paths - * referenced can all be module-local. */ - olddir = talloc_getcwd(m); - if (!olddir) - err(1, "Could not save cwd"); - if (chdir(m->dir) != 0) - err(1, "Could not chdir to %s", m->dir); list_head_init(list); @@ -74,9 +65,6 @@ static void *do_run_tests(struct manifest *m, list = NULL; } - if (chdir(olddir) != 0) - err(1, "Could not chdir to %s", olddir); - return list; } diff --git a/tools/ccanlint/tests/run-coverage.c b/tools/ccanlint/tests/run-coverage.c index 9e976990..a46b02e0 100644 --- a/tools/ccanlint/tests/run-coverage.c +++ b/tools/ccanlint/tests/run-coverage.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -18,7 +19,7 @@ struct coverage_result { float uncovered; const char *what; - const char *output; + char *output; }; static bool find_source_file(struct manifest *m, const char *filename) @@ -38,7 +39,8 @@ static bool find_source_file(struct manifest *m, const char *filename) /* FIXME: Don't know how stable this is. Read cov files directly? */ static void analyze_coverage(struct manifest *m, - struct coverage_result *res, const char *output) + struct coverage_result *res, const char *output, + bool full_gcov) { char **lines = strsplit(res, output, "\n", NULL); float covered_lines = 0.0; @@ -49,6 +51,7 @@ static void analyze_coverage(struct manifest *m, Output looks like: File '../../../ccan/tdb2/private.h' Lines executed:0.00% of 8 + /home/ccan/ccan/tdb2/test/run-simple-delete.c:creating 'run-simple-delete.c.gcov' File '../../../ccan/tdb2/tdb.c' Lines executed:0.00% of 450 @@ -71,6 +74,28 @@ static void analyze_coverage(struct manifest *m, errx(1, "Could not parse line '%s'", lines[i]); total_lines += of; covered_lines += ex / 100.0 * of; + } else if (full_gcov && strstr(lines[i], ":creating '")) { + char *file, *filename, *apostrophe; + apostrophe = strchr(lines[i], '\''); + filename = apostrophe + 1; + apostrophe = strchr(filename, '\''); + *apostrophe = '\0'; + if (lines_matter) { + file = grab_file(res, filename, NULL); + if (!file) { + res->what = talloc_asprintf(res, + "Reading %s", + filename); + res->output = talloc_strdup(res, + strerror(errno)); + return; + } + res->output = talloc_append_string(res->output, + file); + } + if (tools_verbose) + printf("Unlinking %s", filename); + unlink(filename); } } @@ -88,24 +113,18 @@ static void *do_run_coverage_tests(struct manifest *m, struct coverage_result *res; struct ccan_file *i; char *cmdout; - char *olddir; char *covcmd; bool ok; - - /* We run tests in the module directory, so any paths - * referenced can all be module-local. */ - olddir = talloc_getcwd(m); - if (!olddir) - err(1, "Could not save cwd"); - if (chdir(m->dir) != 0) - err(1, "Could not chdir to %s", m->dir); + bool full_gcov = (verbose > 1); res = talloc(m, struct coverage_result); res->what = NULL; + res->output = talloc_strdup(res, ""); res->uncovered = 1.0; /* This tells gcov where we put those .gcno files. */ - covcmd = talloc_asprintf(m, "gcov -n -o %s", + covcmd = talloc_asprintf(m, "gcov %s -o %s", + full_gcov ? "" : "-n", talloc_dirname(res, m->info_file->compiled)); /* Run them all. */ @@ -116,7 +135,7 @@ static void *do_run_coverage_tests(struct manifest *m, res->output = talloc_steal(res, cmdout); return res; } - covcmd = talloc_asprintf_append(covcmd, " %s", i->name); + covcmd = talloc_asprintf_append(covcmd, " %s", i->fullname); } list_for_each(&m->api_tests, i, list) { @@ -126,7 +145,7 @@ static void *do_run_coverage_tests(struct manifest *m, res->output = talloc_steal(res, cmdout); return res; } - covcmd = talloc_asprintf_append(covcmd, " %s", i->name); + covcmd = talloc_asprintf_append(covcmd, " %s", i->fullname); } /* Now run gcov: we want output even if it succeeds. */ @@ -137,7 +156,8 @@ static void *do_run_coverage_tests(struct manifest *m, return res; } - analyze_coverage(m, res, cmdout); + analyze_coverage(m, res, cmdout, full_gcov); + return res; } @@ -161,12 +181,20 @@ static const char *describe_run_coverage_tests(struct manifest *m, void *check_result) { struct coverage_result *res = check_result; + bool full_gcov = (verbose > 1); + char *ret; if (res->what) return talloc_asprintf(m, "%s: %s", res->what, res->output); - return talloc_asprintf(m, "Tests achieved %0.2f%% coverage", - (1.0 - res->uncovered) * 100); + if (!verbose) + return NULL; + + ret = talloc_asprintf(m, "Tests achieved %0.2f%% coverage", + (1.0 - res->uncovered) * 100); + if (full_gcov) + ret = talloc_asprintf_append(ret, "\n%s", res->output); + return ret; } struct ccanlint run_coverage_tests = { diff --git a/tools/ccanlint/tests/trailing_whitespace.c b/tools/ccanlint/tests/trailing_whitespace.c index 80bf42c4..439fc06d 100644 --- a/tools/ccanlint/tests/trailing_whitespace.c +++ b/tools/ccanlint/tests/trailing_whitespace.c @@ -3,6 +3,7 @@ #include #include +/* FIXME: only print full analysis if verbose >= 2. */ static char *report_on_trailing_whitespace(const char *line) { const char *e = strchr(line, 0); @@ -36,6 +37,8 @@ static void *check_trailing_whitespace(struct manifest *m, static const char *describe_trailing_whitespace(struct manifest *m, void *check_result) { + if (!verbose) + return NULL; return talloc_asprintf(check_result, "Some source files have trailing whitespace:\n" "%s", (char *)check_result); -- 2.39.2