From 016a19d260cd7f4afeb5b2b2cc28c8bbed1cd170 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 7 Jan 2011 22:19:49 +1030 Subject: [PATCH] ccanlint: list dependencies by key Joey Adams also pointed out that we should use strings for the dependency lists. Moving them into the structure also somewhat simplifies it. --- tools/ccanlint/ccanlint.c | 139 +++++++++--------- tools/ccanlint/ccanlint.h | 8 +- tools/ccanlint/compulsory_tests/build.c | 3 +- tools/ccanlint/compulsory_tests/build_objs.c | 3 +- tools/ccanlint/compulsory_tests/check_build.c | 3 +- .../compulsory_tests/check_depends_built.c | 3 +- .../compulsory_tests/check_depends_exist.c | 3 +- .../compulsory_tests/check_includes_build.c | 3 +- tools/ccanlint/compulsory_tests/has_info.c | 3 +- .../compulsory_tests/has_main_header.c | 3 +- tools/ccanlint/tests/build-coverage.c | 3 +- tools/ccanlint/tests/compile_test_helpers.c | 3 +- tools/ccanlint/tests/compile_tests.c | 3 +- tools/ccanlint/tests/depends_accurate.c | 3 +- tools/ccanlint/tests/examples_compile.c | 3 +- tools/ccanlint/tests/examples_run.c | 3 +- tools/ccanlint/tests/has_examples.c | 3 +- tools/ccanlint/tests/has_info_documentation.c | 5 +- tools/ccanlint/tests/has_tests.c | 5 +- tools/ccanlint/tests/idempotent.c | 3 +- tools/ccanlint/tests/license.c | 5 +- tools/ccanlint/tests/run-coverage.c | 3 +- tools/ccanlint/tests/run_tests.c | 3 +- tools/ccanlint/tests/run_tests_valgrind.c | 10 +- tools/ccanlint/tests/trailing_whitespace.c | 3 +- 25 files changed, 131 insertions(+), 98 deletions(-) diff --git a/tools/ccanlint/ccanlint.c b/tools/ccanlint/ccanlint.c index 5b45f4d2..7515a7c6 100644 --- a/tools/ccanlint/ccanlint.c +++ b/tools/ccanlint/ccanlint.c @@ -20,7 +20,6 @@ #include "ccanlint.h" #include "../tools.h" #include -#include #include #include #include @@ -192,30 +191,9 @@ static bool run_test(struct ccanlint *i, return score->pass; } -static void register_test(struct list_head *h, struct ccanlint *test, ...) +static void register_test(struct list_head *h, struct ccanlint *test) { - va_list ap; - struct ccanlint *depends; - struct dependent *dchild; - list_add(h, &test->list); - - va_start(ap, test); - /* Careful: we might have been initialized by a dependent. */ - if (test->dependencies.n.next == NULL) - list_head_init(&test->dependencies); - - //dependent(s) args (if any), last one is NULL - while ((depends = va_arg(ap, struct ccanlint *)) != NULL) { - dchild = malloc(sizeof(*dchild)); - dchild->dependent = test; - /* The thing we depend on might not be initialized yet! */ - if (depends->dependencies.n.next == NULL) - list_head_init(&depends->dependencies); - list_add_tail(&depends->dependencies, &dchild->node); - test->num_depends++; - } - va_end(ap); } /** @@ -235,78 +213,103 @@ static inline struct ccanlint *get_next_test(struct list_head *test) errx(1, "Can't make process; test dependency cycle"); } +static struct ccanlint *find_test(const char *key) +{ + struct ccanlint *i; + + list_for_each(&compulsory_tests, i, list) + if (streq(i->key, key)) + return i; + + list_for_each(&normal_tests, i, list) + if (streq(i->key, key)) + return i; + + return NULL; +} + +#undef REGISTER_TEST +#define REGISTER_TEST(name, ...) extern struct ccanlint name +#include "generated-normal-tests" +#include "generated-compulsory-tests" + static void init_tests(void) { - const struct ccanlint *i; + struct ccanlint *c; struct btree *keys, *names; + struct list_head *list; #undef REGISTER_TEST -#define REGISTER_TEST(name, ...) register_test(&normal_tests, &name, __VA_ARGS__, NULL) +#define REGISTER_TEST(name) register_test(&normal_tests, &name) #include "generated-normal-tests" #undef REGISTER_TEST -#define REGISTER_TEST(name, ...) register_test(&compulsory_tests, &name, __VA_ARGS__, NULL) +#define REGISTER_TEST(name) register_test(&compulsory_tests, &name) #include "generated-compulsory-tests" + /* Initialize dependency lists. */ + foreach_ptr(list, &compulsory_tests, &normal_tests) { + list_for_each(list, c, list) { + list_head_init(&c->dependencies); + } + } + + /* Resolve dependencies. */ + foreach_ptr(list, &compulsory_tests, &normal_tests) { + list_for_each(list, c, list) { + char **deps = strsplit(NULL, c->needs, " ", NULL); + unsigned int i; + + for (i = 0; deps[i]; i++) { + struct ccanlint *dep; + struct dependent *dchild; + + dep = find_test(deps[i]); + if (!dep) + errx(1, "BUG: unknown dep '%s' for %s", + deps[i], c->key); + dchild = talloc(NULL, struct dependent); + dchild->dependent = c; + list_add_tail(&dep->dependencies, + &dchild->node); + c->num_depends++; + } + talloc_free(deps); + } + } + /* Self-consistency check: make sure no two tests have the same key or name. */ keys = btree_new(btree_strcmp); names = btree_new(btree_strcmp); - list_for_each(&compulsory_tests, i, list) { - if (!btree_insert(keys, i->key)) - errx(1, "BUG: Duplicate test key '%s'", i->key); - if (!btree_insert(keys, i->name)) - errx(1, "BUG: Duplicate test name '%s'", i->name); - } - list_for_each(&normal_tests, i, list) { - if (!btree_insert(keys, i->key)) - errx(1, "BUG: Duplicate test key '%s'", i->key); - if (!btree_insert(keys, i->name)) - errx(1, "BUG: Duplicate test name '%s'", i->name); + foreach_ptr(list, &compulsory_tests, &normal_tests) { + list_for_each(list, c, list) { + if (!btree_insert(keys, c->key)) + errx(1, "BUG: Duplicate test key '%s'", + c->key); + if (!btree_insert(names, c->name)) + errx(1, "BUG: Duplicate test name '%s'", + c->name); + } } btree_delete(keys); btree_delete(names); - + if (!verbose) return; - printf("\nCompulsory Tests\n"); - list_for_each(&compulsory_tests, i, list) { - printf("%s depends on %u others\n", i->name, i->num_depends); - if (!list_empty(&i->dependencies)) { - const struct dependent *d; - printf("These depend on us:\n"); - list_for_each(&i->dependencies, d, node) - printf("\t%s\n", d->dependent->name); - } - } + foreach_ptr(list, &compulsory_tests, &normal_tests) { + printf("\%s Tests\n", + list == &compulsory_tests ? "Compulsory" : "Normal"); - printf("\nNormal Tests\n"); - list_for_each(&normal_tests, i, list) { - printf("%s depends on %u others\n", i->name, i->num_depends); - if (!list_empty(&i->dependencies)) { + if (!list_empty(&c->dependencies)) { const struct dependent *d; printf("These depend on us:\n"); - list_for_each(&i->dependencies, d, node) + list_for_each(&c->dependencies, d, node) printf("\t%s\n", d->dependent->name); } } } -static struct ccanlint *find_test(const char *key) -{ - struct ccanlint *i; - - list_for_each(&compulsory_tests, i, list) - if (streq(i->key, key)) - return i; - - list_for_each(&normal_tests, i, list) - if (streq(i->key, key)) - return i; - - return NULL; -} - static char *keep_test(const char *testname, void *unused) { struct ccanlint *i = find_test(testname); diff --git a/tools/ccanlint/ccanlint.h b/tools/ccanlint/ccanlint.h index 41a4606c..19d53dbf 100644 --- a/tools/ccanlint/ccanlint.h +++ b/tools/ccanlint/ccanlint.h @@ -4,11 +4,6 @@ #include #include "../doc_extract.h" -#define REGISTER_TEST(name, ...) extern struct ccanlint name -#include "generated-compulsory-tests" -#include "generated-normal-tests" -#undef REGISTER_TEST - #define REGISTER_TEST(name, ...) /* 0 == Describe failed tests. @@ -92,6 +87,9 @@ struct ccanlint { /* If not set, we'll give an error if they try to set options. */ bool takes_options; + /* comma-separated list of dependency keys. */ + const char *needs; + /* Internal use fields: */ /* Who depends on us? */ struct list_head dependencies; diff --git a/tools/ccanlint/compulsory_tests/build.c b/tools/ccanlint/compulsory_tests/build.c index 557b708b..cf128f6a 100644 --- a/tools/ccanlint/compulsory_tests/build.c +++ b/tools/ccanlint/compulsory_tests/build.c @@ -78,6 +78,7 @@ struct ccanlint build = { .name = "Module can be built from object files", .check = do_build, .can_run = can_build, + .needs = "objects_build" }; -REGISTER_TEST(build, &build_objs, NULL); +REGISTER_TEST(build); diff --git a/tools/ccanlint/compulsory_tests/build_objs.c b/tools/ccanlint/compulsory_tests/build_objs.c index 9393f62f..7696b464 100644 --- a/tools/ccanlint/compulsory_tests/build_objs.c +++ b/tools/ccanlint/compulsory_tests/build_objs.c @@ -62,6 +62,7 @@ struct ccanlint build_objs = { .name = "Module object files can be built", .check = check_objs_build, .can_run = can_build, + .needs = "depends_exist" }; -REGISTER_TEST(build_objs, &depends_exist, NULL); +REGISTER_TEST(build_objs); diff --git a/tools/ccanlint/compulsory_tests/check_build.c b/tools/ccanlint/compulsory_tests/check_build.c index 39f16c2e..db2e16d5 100644 --- a/tools/ccanlint/compulsory_tests/check_build.c +++ b/tools/ccanlint/compulsory_tests/check_build.c @@ -88,6 +88,7 @@ struct ccanlint check_build = { .name = "Module can be linked against trivial program", .check = check_use_build, .can_run = can_build, + .needs = "module_builds depends_build" }; -REGISTER_TEST(check_build, &build, &depends_built, NULL); +REGISTER_TEST(check_build); diff --git a/tools/ccanlint/compulsory_tests/check_depends_built.c b/tools/ccanlint/compulsory_tests/check_depends_built.c index 41b9a8ca..c4c649dd 100644 --- a/tools/ccanlint/compulsory_tests/check_depends_built.c +++ b/tools/ccanlint/compulsory_tests/check_depends_built.c @@ -105,6 +105,7 @@ struct ccanlint depends_built = { .name = "Module's CCAN dependencies can be found or built", .check = check_depends_built, .can_run = can_build, + .needs = "depends_exist" }; -REGISTER_TEST(depends_built, &depends_exist, NULL); +REGISTER_TEST(depends_built); diff --git a/tools/ccanlint/compulsory_tests/check_depends_exist.c b/tools/ccanlint/compulsory_tests/check_depends_exist.c index ffbf4539..12eaf021 100644 --- a/tools/ccanlint/compulsory_tests/check_depends_exist.c +++ b/tools/ccanlint/compulsory_tests/check_depends_exist.c @@ -72,6 +72,7 @@ struct ccanlint depends_exist = { .key = "depends_exist", .name = "Module's CCAN dependencies can be found", .check = check_depends_exist, + .needs = "info_exists" }; -REGISTER_TEST(depends_exist, &has_info, NULL); +REGISTER_TEST(depends_exist); diff --git a/tools/ccanlint/compulsory_tests/check_includes_build.c b/tools/ccanlint/compulsory_tests/check_includes_build.c index 017194e6..56930e30 100644 --- a/tools/ccanlint/compulsory_tests/check_includes_build.c +++ b/tools/ccanlint/compulsory_tests/check_includes_build.c @@ -72,6 +72,7 @@ struct ccanlint includes_build = { .name = "Modules main header compiles", .check = check_includes_build, .can_run = can_build, + .needs = "depends_exist main_header_exists" }; -REGISTER_TEST(includes_build, &depends_exist, &has_main_header, NULL); +REGISTER_TEST(includes_build); diff --git a/tools/ccanlint/compulsory_tests/has_info.c b/tools/ccanlint/compulsory_tests/has_info.c index 5b71efa4..b61ee0ae 100644 --- a/tools/ccanlint/compulsory_tests/has_info.c +++ b/tools/ccanlint/compulsory_tests/has_info.c @@ -79,6 +79,7 @@ struct ccanlint has_info = { .name = "Module has _info file", .check = check_has_info, .handle = create_info_template, + .needs = "" }; -REGISTER_TEST(has_info, NULL); +REGISTER_TEST(has_info); diff --git a/tools/ccanlint/compulsory_tests/has_main_header.c b/tools/ccanlint/compulsory_tests/has_main_header.c index 338f7af7..259aa347 100644 --- a/tools/ccanlint/compulsory_tests/has_main_header.c +++ b/tools/ccanlint/compulsory_tests/has_main_header.c @@ -37,6 +37,7 @@ struct ccanlint has_main_header = { .key = "main_header_exists", .name = "Module has main header file", .check = check_has_main_header, + .needs = "" }; -REGISTER_TEST(has_main_header, NULL); +REGISTER_TEST(has_main_header); diff --git a/tools/ccanlint/tests/build-coverage.c b/tools/ccanlint/tests/build-coverage.c index 927cd8b0..55eca373 100644 --- a/tools/ccanlint/tests/build-coverage.c +++ b/tools/ccanlint/tests/build-coverage.c @@ -147,6 +147,7 @@ struct ccanlint compile_coverage_tests = { .name = "Module tests compile with " COVERAGE_CFLAGS, .check = do_compile_coverage_tests, .can_run = can_run_coverage, + .needs = "tests_compile" }; -REGISTER_TEST(compile_coverage_tests, &compile_tests, NULL); +REGISTER_TEST(compile_coverage_tests); diff --git a/tools/ccanlint/tests/compile_test_helpers.c b/tools/ccanlint/tests/compile_test_helpers.c index 0169f602..aa62e37a 100644 --- a/tools/ccanlint/tests/compile_test_helpers.c +++ b/tools/ccanlint/tests/compile_test_helpers.c @@ -69,6 +69,7 @@ struct ccanlint compile_test_helpers = { .name = "Module test helper objects compile", .check = do_compile_test_helpers, .can_run = can_run, + .needs = "depends_build tests_exist" }; -REGISTER_TEST(compile_test_helpers, &depends_built, &has_tests, NULL); +REGISTER_TEST(compile_test_helpers); diff --git a/tools/ccanlint/tests/compile_tests.c b/tools/ccanlint/tests/compile_tests.c index e1e8f820..c61a9e5a 100644 --- a/tools/ccanlint/tests/compile_tests.c +++ b/tools/ccanlint/tests/compile_tests.c @@ -135,6 +135,7 @@ struct ccanlint compile_tests = { .name = "Module tests compile", .check = do_compile_tests, .can_run = can_build, + .needs = "tests_helpers_compile objects_build" }; -REGISTER_TEST(compile_tests, &compile_test_helpers, &build_objs, NULL); +REGISTER_TEST(compile_tests); diff --git a/tools/ccanlint/tests/depends_accurate.c b/tools/ccanlint/tests/depends_accurate.c index 85301772..a6d3a73a 100644 --- a/tools/ccanlint/tests/depends_accurate.c +++ b/tools/ccanlint/tests/depends_accurate.c @@ -90,6 +90,7 @@ struct ccanlint depends_accurate = { .key = "depends_accurate", .name = "Module's CCAN dependencies are the only CCAN files #included", .check = check_depends_accurate, + .needs = "depends_exist" }; -REGISTER_TEST(depends_accurate, &depends_exist, NULL); +REGISTER_TEST(depends_accurate); diff --git a/tools/ccanlint/tests/examples_compile.c b/tools/ccanlint/tests/examples_compile.c index ff9e529b..a3ab73a9 100644 --- a/tools/ccanlint/tests/examples_compile.c +++ b/tools/ccanlint/tests/examples_compile.c @@ -619,6 +619,7 @@ struct ccanlint examples_compile = { .name = "Module examples compile", .check = build_examples, .can_run = can_run, + .needs = "examples_exist module_builds" }; -REGISTER_TEST(examples_compile, &has_examples, &build, NULL); +REGISTER_TEST(examples_compile); diff --git a/tools/ccanlint/tests/examples_run.c b/tools/ccanlint/tests/examples_run.c index 7fe41654..077ea248 100644 --- a/tools/ccanlint/tests/examples_run.c +++ b/tools/ccanlint/tests/examples_run.c @@ -276,6 +276,7 @@ struct ccanlint examples_run = { .name = "Module examples with expected output give that output", .check = run_examples, .can_run = can_run, + .needs = "examples_compile" }; -REGISTER_TEST(examples_run, &examples_compile, NULL); +REGISTER_TEST(examples_run); diff --git a/tools/ccanlint/tests/has_examples.c b/tools/ccanlint/tests/has_examples.c index 1e4f65c3..a1d54c48 100644 --- a/tools/ccanlint/tests/has_examples.c +++ b/tools/ccanlint/tests/has_examples.c @@ -113,6 +113,7 @@ struct ccanlint has_examples = { .key = "examples_exist", .name = "_info and main header file have Example: sections", .check = extract_examples, + .needs = "info_exists" }; -REGISTER_TEST(has_examples, &has_info, NULL); +REGISTER_TEST(has_examples); diff --git a/tools/ccanlint/tests/has_info_documentation.c b/tools/ccanlint/tests/has_info_documentation.c index a6aafc66..b98177d8 100644 --- a/tools/ccanlint/tests/has_info_documentation.c +++ b/tools/ccanlint/tests/has_info_documentation.c @@ -15,6 +15,8 @@ #include #include +extern struct ccanlint has_info_documentation; + static void create_info_template_doc(struct manifest *m, struct score *score) { int fd = open("_info.new", O_WRONLY|O_CREAT|O_EXCL, 0666); @@ -94,6 +96,7 @@ struct ccanlint has_info_documentation = { .key = "info_documentation_exists", .name = "Module has documentation in _info", .check = check_has_info_documentation, + .needs = "info_exists" }; -REGISTER_TEST(has_info_documentation, &has_info, NULL); +REGISTER_TEST(has_info_documentation); diff --git a/tools/ccanlint/tests/has_tests.c b/tools/ccanlint/tests/has_tests.c index 36adee60..0e90d16f 100644 --- a/tools/ccanlint/tests/has_tests.c +++ b/tools/ccanlint/tests/has_tests.c @@ -10,6 +10,8 @@ #include #include +extern struct ccanlint has_tests; + static void handle_no_tests(struct manifest *m, struct score *score) { FILE *run; @@ -128,6 +130,7 @@ struct ccanlint has_tests = { .key = "tests_exist", .name = "Module has test directory with tests in it", .check = check_has_tests, + .needs = "" }; -REGISTER_TEST(has_tests, NULL); +REGISTER_TEST(has_tests); diff --git a/tools/ccanlint/tests/idempotent.c b/tools/ccanlint/tests/idempotent.c index 944fd248..a5210e2f 100644 --- a/tools/ccanlint/tests/idempotent.c +++ b/tools/ccanlint/tests/idempotent.c @@ -198,6 +198,7 @@ struct ccanlint idempotent = { .name = "Module headers are #ifndef/#define wrapped", .check = check_idempotent, .handle = handle_idem, + .needs = "" }; -REGISTER_TEST(idempotent, NULL); +REGISTER_TEST(idempotent); diff --git a/tools/ccanlint/tests/license.c b/tools/ccanlint/tests/license.c index bc0ee454..1ffee9e2 100644 --- a/tools/ccanlint/tests/license.c +++ b/tools/ccanlint/tests/license.c @@ -11,6 +11,8 @@ #include #include +struct ccanlint has_license; + static struct doc_section *find_license(const struct manifest *m) { struct doc_section *d; @@ -151,6 +153,7 @@ struct ccanlint has_license = { .key = "license_exists", .name = "Module has License: entry in _info, and LICENSE symlink/file", .check = check_has_license, + .needs = "info_exists" }; -REGISTER_TEST(has_license, &has_info, NULL); +REGISTER_TEST(has_license); diff --git a/tools/ccanlint/tests/run-coverage.c b/tools/ccanlint/tests/run-coverage.c index 1e340398..a3e83c1c 100644 --- a/tools/ccanlint/tests/run-coverage.c +++ b/tools/ccanlint/tests/run-coverage.c @@ -166,6 +166,7 @@ struct ccanlint run_coverage_tests = { .key = "tests_coverage", .name = "Module's tests cover all the code", .check = do_run_coverage_tests, + .needs = "tests_compile_coverage tests_pass" }; -REGISTER_TEST(run_coverage_tests, &compile_coverage_tests, &run_tests, NULL); +REGISTER_TEST(run_coverage_tests); diff --git a/tools/ccanlint/tests/run_tests.c b/tools/ccanlint/tests/run_tests.c index 3821b36a..35790ece 100644 --- a/tools/ccanlint/tests/run_tests.c +++ b/tools/ccanlint/tests/run_tests.c @@ -71,6 +71,7 @@ struct ccanlint run_tests = { .check = do_run_tests, .handle = run_under_debugger, .can_run = can_run, + .needs = "tests_compile" }; -REGISTER_TEST(run_tests, &compile_tests, NULL); +REGISTER_TEST(run_tests); diff --git a/tools/ccanlint/tests/run_tests_valgrind.c b/tools/ccanlint/tests/run_tests_valgrind.c index 6e18338d..d3cdb9c7 100644 --- a/tools/ccanlint/tests/run_tests_valgrind.c +++ b/tools/ccanlint/tests/run_tests_valgrind.c @@ -17,6 +17,8 @@ #include #include +struct ccanlint run_tests_vg; + /* Note: we already test safe_mode in run_tests.c */ static const char *can_run_vg(struct manifest *m) { @@ -183,15 +185,17 @@ struct ccanlint run_tests_vg = { .can_run = can_run_vg, .check = do_run_tests_vg, .handle = run_under_debugger_vg, - .takes_options = true + .takes_options = true, + .needs = "tests_pass" }; -REGISTER_TEST(run_tests_vg, &run_tests, NULL); +REGISTER_TEST(run_tests_vg); struct ccanlint run_tests_vg_leak = { .key = "tests_pass_valgrind_noleaks", .name = "Module's run and api tests leak memory", .check = do_leakcheck_vg, + .needs = "tests_pass_valgrind" }; -REGISTER_TEST(run_tests_vg_leak, &run_tests_vg, NULL); +REGISTER_TEST(run_tests_vg_leak); diff --git a/tools/ccanlint/tests/trailing_whitespace.c b/tools/ccanlint/tests/trailing_whitespace.c index 2a301ea8..2b430e8c 100644 --- a/tools/ccanlint/tests/trailing_whitespace.c +++ b/tools/ccanlint/tests/trailing_whitespace.c @@ -53,7 +53,8 @@ struct ccanlint trailing_whitespace = { .key = "no_trailing_whitespace", .name = "Module's source code has no trailing whitespace", .check = check_trailing_whitespace, + .needs = "" }; -REGISTER_TEST(trailing_whitespace, NULL); +REGISTER_TEST(trailing_whitespace); -- 2.39.2