From 60824f8a0f758dc7808eb31cc83434ea78f44ed1 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 1 Dec 2011 16:45:51 +1030 Subject: [PATCH] ccanlint: get rid of separate class of compulsory tests. It's reduced to a flag which means we stop processing the module. We have to enhance our dependencies a bit, but they've always been quite good. This simplifies things quite a bit. --- .gitignore | 3 +- tools/ccanlint/Makefile | 17 +- tools/ccanlint/ccanlint.c | 196 ++++++++---------- tools/ccanlint/ccanlint.h | 3 + .../{compulsory_tests => tests}/build.h | 0 tools/ccanlint/tests/depends_build.c | 2 +- .../tests/depends_build_without_features.c | 4 +- .../depends_exist.c | 1 + tools/ccanlint/tests/examples_compile.c | 2 +- tools/ccanlint/tests/hash_if.c | 2 +- tools/ccanlint/tests/headers_idempotent.c | 2 +- .../{compulsory_tests => tests}/info_exists.c | 3 +- .../module_builds.c | 2 +- tools/ccanlint/tests/no_trailing_whitespace.c | 2 +- .../objects_build.c | 1 + .../tests/objects_build_without_features.c | 2 +- tools/ccanlint/tests/tests_compile.c | 2 +- tools/ccanlint/tests/tests_compile_coverage.c | 2 +- tools/ccanlint/tests/tests_exist.c | 2 +- 19 files changed, 109 insertions(+), 139 deletions(-) rename tools/ccanlint/{compulsory_tests => tests}/build.h (100%) rename tools/ccanlint/{compulsory_tests => tests}/depends_exist.c (98%) rename tools/ccanlint/{compulsory_tests => tests}/info_exists.c (97%) rename tools/ccanlint/{compulsory_tests => tests}/module_builds.c (98%) rename tools/ccanlint/{compulsory_tests => tests}/objects_build.c (98%) diff --git a/.gitignore b/.gitignore index 6237a284..6b2b9fba 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,7 @@ tools/doc_extract tools/namespacize tools/run_tests tools/ccanlint/ccanlint -tools/ccanlint/generated-compulsory-tests -tools/ccanlint/generated-normal-tests +tools/ccanlint/generated-testlist inter-depends test-depends lib-depends diff --git a/tools/ccanlint/Makefile b/tools/ccanlint/Makefile index ee371e05..11d09e87 100644 --- a/tools/ccanlint/Makefile +++ b/tools/ccanlint/Makefile @@ -1,6 +1,5 @@ -COMPULSORY_TEST_CFILES := $(wildcard tools/ccanlint/compulsory_tests/*.c) -NORMAL_TEST_CFILES := $(wildcard tools/ccanlint/tests/*.c) -TEST_OBJS := $(NORMAL_TEST_CFILES:.c=.o) $(COMPULSORY_TEST_CFILES:.c=.o) +TEST_CFILES := $(wildcard tools/ccanlint/tests/*.c) +TEST_OBJS := $(TEST_CFILES:.c=.o) CORE_OBJS := \ ccan/asort/asort.o \ @@ -33,20 +32,16 @@ CORE_OBJS := \ OBJS := $(CORE_OBJS) $(TEST_OBJS) # FIXME: write a trivial C program to do this -tools/ccanlint/generated-normal-tests: $(NORMAL_TEST_CFILES) - cat $^ | grep ^REGISTER_TEST > $@ -tools/ccanlint/generated-compulsory-tests: $(COMPULSORY_TEST_CFILES) +tools/ccanlint/generated-testlist: $(TEST_CFILES) cat $^ | grep ^REGISTER_TEST > $@ -$(TEST_OBJS): tools/ccanlint/generated-normal-tests tools/ccanlint/generated-compulsory-tests +$(TEST_OBJS): tools/ccanlint/generated-testlist # Otherwise, ccanlint.c et al. may fail to build -$(CORE_OBJS): tools/ccanlint/generated-normal-tests tools/ccanlint/generated-compulsory-tests config.h +$(CORE_OBJS): tools/ccanlint/generated-testlist config.h tools/ccanlint/ccanlint: $(OBJS) ccanlint-clean: - $(RM) tools/ccanlint/generated-compulsory-tests - $(RM) tools/ccanlint/generated-normal-tests + $(RM) tools/ccanlint/generated-testlist $(RM) tools/ccanlint/ccanlint - diff --git a/tools/ccanlint/ccanlint.c b/tools/ccanlint/ccanlint.c index 63724d2e..b35f11a7 100644 --- a/tools/ccanlint/ccanlint.c +++ b/tools/ccanlint/ccanlint.c @@ -33,10 +33,13 @@ #include #include #include +#include + +/* Defines struct tlist_ccanlint. */ +TLIST_TYPE(ccanlint, struct ccanlint); int verbose = 0; -static struct list_head compulsory_tests; -static struct list_head normal_tests; +static struct tlist_ccanlint tests = TLIST_INIT(tests); bool safe_mode = false; static struct btree *cmdline_exclude; static struct btree *info_exclude; @@ -182,9 +185,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 ccanlint *test) { - list_add(h, &test->list); + tlist_add(&tests, test, list); test->options = talloc_array(NULL, char *, 1); test->options[0] = NULL; test->skip = NULL; @@ -194,14 +197,14 @@ static void register_test(struct list_head *h, struct ccanlint *test) /** * get_next_test - retrieves the next test to be processed **/ -static inline struct ccanlint *get_next_test(struct list_head *test) +static inline struct ccanlint *get_next_test(void) { struct ccanlint *i; - if (list_empty(test)) + if (tlist_empty(&tests)) return NULL; - list_for_each(test, i, list) { + tlist_for_each(&tests, i, list) { if (i->num_depends == 0) return i; } @@ -212,11 +215,7 @@ 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) + tlist_for_each(&tests, i, list) if (streq(i->key, key)) return i; @@ -232,91 +231,74 @@ bool is_excluded(const char *name) #undef REGISTER_TEST #define REGISTER_TEST(name, ...) extern struct ccanlint name -#include "generated-normal-tests" -#include "generated-compulsory-tests" +#include "generated-testlist" static void init_tests(void) { struct ccanlint *c; struct btree *keys, *names; - struct list_head *list; - list_head_init(&normal_tests); - list_head_init(&compulsory_tests); + tlist_init(&tests); #undef REGISTER_TEST -#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) -#include "generated-compulsory-tests" +#define REGISTER_TEST(name) register_test(&name) +#include "generated-testlist" /* Initialize dependency lists. */ - foreach_ptr(list, &compulsory_tests, &normal_tests) { - list_for_each(list, c, list) { - list_head_init(&c->dependencies); - c->num_depends = 0; - } + tlist_for_each(&tests, c, list) { + list_head_init(&c->dependencies); + c->num_depends = 0; } /* Resolve dependencies. */ - foreach_ptr(list, &compulsory_tests, &normal_tests) { - list_for_each(list, c, list) { - char **deps = strsplit(NULL, c->needs, " "); - 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); + tlist_for_each(&tests, c, list) { + char **deps = strsplit(NULL, c->needs, " "); + 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); - 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); - } + tlist_for_each(&tests, 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); } static void print_test_depends(void) { - struct list_head *list; - - foreach_ptr(list, &compulsory_tests, &normal_tests) { - struct ccanlint *c; - printf("\%s Tests\n", - list == &compulsory_tests ? "Compulsory" : "Normal"); - - list_for_each(list, c, list) { - if (!list_empty(&c->dependencies)) { - const struct dependent *d; - printf("These depend on %s:\n", c->key); - list_for_each(&c->dependencies, d, node) - printf("\t%s\n", d->dependent->key); - } + struct ccanlint *c; + printf("Tests:\n"); + + tlist_for_each(&tests, c, list) { + if (!list_empty(&c->dependencies)) { + const struct dependent *d; + printf("These depend on %s:\n", c->key); + list_for_each(&c->dependencies, d, node) + printf("\t%s\n", d->dependent->key); } } } @@ -333,11 +315,8 @@ static char *keep_test(const char *testname, void *unused) init_tests(); if (streq(testname, "all")) { - struct list_head *list; - foreach_ptr(list, &compulsory_tests, &normal_tests) { - list_for_each(list, i, list) - i->keep_results = true; - } + tlist_for_each(&tests, i, list) + i->keep_results = true; } else { i = find_test(testname); if (!i) @@ -356,34 +335,29 @@ static char *skip_test(const char *testname, void *unused) return NULL; } -static void print_tests(struct list_head *tests, const char *type) +static char *list_tests(void *arg) { struct ccanlint *i; - printf("%s tests:\n", type); + init_tests(); + + printf("Tests:\n"); /* This makes them print in topological order. */ - while ((i = get_next_test(tests)) != NULL) { + while ((i = get_next_test()) != NULL) { const struct dependent *d; printf(" %-25s %s\n", i->key, i->name); list_del(&i->list); list_for_each(&i->dependencies, d, node) d->dependent->num_depends--; } -} - -static char *list_tests(void *arg) -{ - init_tests(); - print_tests(&compulsory_tests, "Compulsory"); - print_tests(&normal_tests, "Normal"); exit(0); } -static void test_dgraph_vertices(struct list_head *tests, const char *style) +static void test_dgraph_vertices(const char *style) { const struct ccanlint *i; - list_for_each(tests, i, list) { + tlist_for_each(&tests, i, list) { /* * todo: escape labels in case ccanlint test keys have * characters interpreted as GraphViz syntax. @@ -392,12 +366,12 @@ static void test_dgraph_vertices(struct list_head *tests, const char *style) } } -static void test_dgraph_edges(struct list_head *tests) +static void test_dgraph_edges(void) { const struct ccanlint *i; const struct dependent *d; - list_for_each(tests, i, list) + tlist_for_each(&tests, i, list) list_for_each(&i->dependencies, d, node) printf("\t\"%p\" -> \"%p\"\n", d->dependent, i); } @@ -407,11 +381,8 @@ static char *test_dependency_graph(void *arg) init_tests(); puts("digraph G {"); - test_dgraph_vertices(&compulsory_tests, ", style=filled, fillcolor=yellow"); - test_dgraph_vertices(&normal_tests, ""); - - test_dgraph_edges(&compulsory_tests); - test_dgraph_edges(&normal_tests); + test_dgraph_vertices(""); + test_dgraph_edges(); puts("}"); @@ -552,12 +523,10 @@ static bool depends_on(struct ccanlint *i, struct ccanlint *target) static void skip_unrelated_tests(struct ccanlint *target) { struct ccanlint *i; - struct list_head *list; - foreach_ptr(list, &compulsory_tests, &normal_tests) - list_for_each(list, i, list) - if (!depends_on(i, target)) - i->skip = "not relevant to target"; + tlist_for_each(&tests, i, list) + if (!depends_on(i, target)) + i->skip = "not relevant to target"; } static char *demangle_string(char *string) @@ -726,6 +695,8 @@ int main(int argc, char *argv[]) for (i = 1; i < argc; i++) { unsigned int score, total_score; + bool added_info_options = false; + dir = argv[i]; if (dir[0] != '/') @@ -762,26 +733,25 @@ int main(int argc, char *argv[]) if (symlink(talloc_asprintf(m, "%s/test", dir), testlink) != 0) err(1, "Creating test symlink in %s", temp_dir(NULL)); - /* If you don't pass the compulsory tests, score is 0. */ score = total_score = 0; - while ((t = get_next_test(&compulsory_tests)) != NULL) { + while ((t = get_next_test()) != NULL) { if (!run_test(t, summary, &score, &total_score, m, prefix)) { - warnx("%s%s failed", prefix, t->name); - printf("%sTotal score: 0/%u\n", - prefix, total_score); pass = false; - goto next; + if (t->compulsory) { + warnx("%s%s failed", prefix, t->name); + printf("%sTotal score: 0/%u\n", + prefix, total_score); + goto next; + } } - } - /* --target overrides known FAIL from _info */ - if (m->info_file) - add_info_options(m->info_file, !target); - - while ((t = get_next_test(&normal_tests)) != NULL) - pass &= run_test(t, summary, &score, &total_score, m, - prefix); + /* --target overrides known FAIL from _info */ + if (!added_info_options && m->info_file) { + add_info_options(m->info_file, !target); + added_info_options = true; + } + } printf("%sTotal score: %u/%u\n", prefix, score, total_score); next: ; diff --git a/tools/ccanlint/ccanlint.h b/tools/ccanlint/ccanlint.h index 452b44f7..16600cff 100644 --- a/tools/ccanlint/ccanlint.h +++ b/tools/ccanlint/ccanlint.h @@ -91,6 +91,9 @@ struct ccanlint { /* Can we run this test? Return string explaining why, if not. */ const char *(*can_run)(struct manifest *m); + /* Should we stop immediately if test fails? */ + bool compulsory; + /* keep is set if you should keep the results. * If timeleft is set to 0, means it timed out. * score is the result, and a talloc context freed after all our diff --git a/tools/ccanlint/compulsory_tests/build.h b/tools/ccanlint/tests/build.h similarity index 100% rename from tools/ccanlint/compulsory_tests/build.h rename to tools/ccanlint/tests/build.h diff --git a/tools/ccanlint/tests/depends_build.c b/tools/ccanlint/tests/depends_build.c index e7faa1f1..ea5c3926 100644 --- a/tools/ccanlint/tests/depends_build.c +++ b/tools/ccanlint/tests/depends_build.c @@ -13,7 +13,7 @@ #include #include #include -#include "../compulsory_tests/build.h" +#include "build.h" static const char *can_build(struct manifest *m) { diff --git a/tools/ccanlint/tests/depends_build_without_features.c b/tools/ccanlint/tests/depends_build_without_features.c index 9982d27b..dfa96d72 100644 --- a/tools/ccanlint/tests/depends_build_without_features.c +++ b/tools/ccanlint/tests/depends_build_without_features.c @@ -14,7 +14,7 @@ #include #include #include "reduce_features.h" -#include "../compulsory_tests/build.h" +#include "build.h" static const char *can_build(struct manifest *m) { @@ -55,7 +55,7 @@ struct ccanlint depends_build_without_features = { .name = "Module's CCAN dependencies can be found or built (reduced features)", .check = check_depends_built_without_features, .can_run = can_build, - .needs = "depends_exist reduce_features" + .needs = "depends_build reduce_features" }; REGISTER_TEST(depends_build_without_features); diff --git a/tools/ccanlint/compulsory_tests/depends_exist.c b/tools/ccanlint/tests/depends_exist.c similarity index 98% rename from tools/ccanlint/compulsory_tests/depends_exist.c rename to tools/ccanlint/tests/depends_exist.c index b1694058..ff67857f 100644 --- a/tools/ccanlint/compulsory_tests/depends_exist.c +++ b/tools/ccanlint/tests/depends_exist.c @@ -84,6 +84,7 @@ static void check_depends_exist(struct manifest *m, struct ccanlint depends_exist = { .key = "depends_exist", .name = "Module's CCAN dependencies can be found", + .compulsory = true, .check = check_depends_exist, .needs = "info_exists" }; diff --git a/tools/ccanlint/tests/examples_compile.c b/tools/ccanlint/tests/examples_compile.c index d52ee789..3cbb23fd 100644 --- a/tools/ccanlint/tests/examples_compile.c +++ b/tools/ccanlint/tests/examples_compile.c @@ -12,7 +12,7 @@ #include #include #include -#include "../compulsory_tests/build.h" +#include "build.h" static const char *can_run(struct manifest *m) { diff --git a/tools/ccanlint/tests/hash_if.c b/tools/ccanlint/tests/hash_if.c index 35608ef1..9e10c304 100644 --- a/tools/ccanlint/tests/hash_if.c +++ b/tools/ccanlint/tests/hash_if.c @@ -71,7 +71,7 @@ struct ccanlint hash_if = { .key = "hash_if", .name = "Features are checked with #if not #ifdef", .check = check_hash_if, - .needs = "" + .needs = "info_exists" }; REGISTER_TEST(hash_if); diff --git a/tools/ccanlint/tests/headers_idempotent.c b/tools/ccanlint/tests/headers_idempotent.c index f23784e4..4b98b246 100644 --- a/tools/ccanlint/tests/headers_idempotent.c +++ b/tools/ccanlint/tests/headers_idempotent.c @@ -195,7 +195,7 @@ struct ccanlint headers_idempotent = { .name = "Module headers are #ifndef/#define wrapped", .check = check_idempotent, .handle = handle_idem, - .needs = "" + .needs = "info_exists main_header_exists" }; REGISTER_TEST(headers_idempotent); diff --git a/tools/ccanlint/compulsory_tests/info_exists.c b/tools/ccanlint/tests/info_exists.c similarity index 97% rename from tools/ccanlint/compulsory_tests/info_exists.c rename to tools/ccanlint/tests/info_exists.c index ac840119..80edb5aa 100644 --- a/tools/ccanlint/compulsory_tests/info_exists.c +++ b/tools/ccanlint/tests/info_exists.c @@ -29,7 +29,7 @@ static void check_has_info(struct manifest *m, } } -static const char template[] = +static const char template[] = "#include \n" "#include \"config.h\"\n" "\n" @@ -78,6 +78,7 @@ static void create_info_template(struct manifest *m, struct score *score) struct ccanlint info_exists = { .key = "info_exists", .name = "Module has _info file", + .compulsory = true, .check = check_has_info, .handle = create_info_template, .needs = "" diff --git a/tools/ccanlint/compulsory_tests/module_builds.c b/tools/ccanlint/tests/module_builds.c similarity index 98% rename from tools/ccanlint/compulsory_tests/module_builds.c rename to tools/ccanlint/tests/module_builds.c index 23985d2c..52059af7 100644 --- a/tools/ccanlint/compulsory_tests/module_builds.c +++ b/tools/ccanlint/tests/module_builds.c @@ -81,10 +81,10 @@ static void do_build(struct manifest *m, struct ccanlint module_builds = { .key = "module_builds", .name = "Module can be built from object files", + .compulsory = true, .check = do_build, .can_run = can_build, .needs = "objects_build" }; REGISTER_TEST(module_builds); - diff --git a/tools/ccanlint/tests/no_trailing_whitespace.c b/tools/ccanlint/tests/no_trailing_whitespace.c index f046a248..5d3b5ca1 100644 --- a/tools/ccanlint/tests/no_trailing_whitespace.c +++ b/tools/ccanlint/tests/no_trailing_whitespace.c @@ -53,7 +53,7 @@ struct ccanlint no_trailing_whitespace = { .key = "no_trailing_whitespace", .name = "Module's source code has no trailing whitespace", .check = check_trailing_whitespace, - .needs = "" + .needs = "info_exists" }; diff --git a/tools/ccanlint/compulsory_tests/objects_build.c b/tools/ccanlint/tests/objects_build.c similarity index 98% rename from tools/ccanlint/compulsory_tests/objects_build.c rename to tools/ccanlint/tests/objects_build.c index 2132b173..8fc11266 100644 --- a/tools/ccanlint/compulsory_tests/objects_build.c +++ b/tools/ccanlint/tests/objects_build.c @@ -71,6 +71,7 @@ static void check_objs_build(struct manifest *m, struct ccanlint objects_build = { .key = "objects_build", .name = "Module object files can be built", + .compulsory = true, .check = check_objs_build, .can_run = can_build, .needs = "depends_exist" diff --git a/tools/ccanlint/tests/objects_build_without_features.c b/tools/ccanlint/tests/objects_build_without_features.c index 477d3025..770dd475 100644 --- a/tools/ccanlint/tests/objects_build_without_features.c +++ b/tools/ccanlint/tests/objects_build_without_features.c @@ -1,7 +1,7 @@ #include #include #include "reduce_features.h" -#include "../compulsory_tests/build.h" +#include "build.h" static void check_objs_build_without_features(struct manifest *m, bool keep, diff --git a/tools/ccanlint/tests/tests_compile.c b/tools/ccanlint/tests/tests_compile.c index bfa412a6..ee1a6b2c 100644 --- a/tools/ccanlint/tests/tests_compile.c +++ b/tools/ccanlint/tests/tests_compile.c @@ -221,6 +221,6 @@ struct ccanlint tests_compile_without_features = { .name = "Module tests compile (without features)", .check = do_compile_tests_without_features, .can_run = features_reduced, - .needs = "tests_helpers_compile_without_features objects_build_without_features" + .needs = "module_builds tests_helpers_compile_without_features objects_build_without_features" }; REGISTER_TEST(tests_compile_without_features); diff --git a/tools/ccanlint/tests/tests_compile_coverage.c b/tools/ccanlint/tests/tests_compile_coverage.c index a1028110..accb9ffd 100644 --- a/tools/ccanlint/tests/tests_compile_coverage.c +++ b/tools/ccanlint/tests/tests_compile_coverage.c @@ -14,7 +14,7 @@ #include #include #include -#include "../compulsory_tests/build.h" +#include "build.h" #include "tests_compile.h" /* Note: we already test safe_mode in run_tests.c */ diff --git a/tools/ccanlint/tests/tests_exist.c b/tools/ccanlint/tests/tests_exist.c index 523fe99f..57fd4e11 100644 --- a/tools/ccanlint/tests/tests_exist.c +++ b/tools/ccanlint/tests/tests_exist.c @@ -132,6 +132,6 @@ struct ccanlint tests_exist = { .key = "tests_exist", .name = "Module has test directory with tests in it", .check = check_tests_exist, - .needs = "" + .needs = "info_exists" }; -- 2.39.2