ccanlint: list dependencies by key
authorRusty Russell <rusty@rustcorp.com.au>
Fri, 7 Jan 2011 11:49:49 +0000 (22:19 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 7 Jan 2011 11:49:49 +0000 (22:19 +1030)
Joey Adams also pointed out that we should use strings for the dependency
lists.  Moving them into the structure also somewhat simplifies it.

25 files changed:
tools/ccanlint/ccanlint.c
tools/ccanlint/ccanlint.h
tools/ccanlint/compulsory_tests/build.c
tools/ccanlint/compulsory_tests/build_objs.c
tools/ccanlint/compulsory_tests/check_build.c
tools/ccanlint/compulsory_tests/check_depends_built.c
tools/ccanlint/compulsory_tests/check_depends_exist.c
tools/ccanlint/compulsory_tests/check_includes_build.c
tools/ccanlint/compulsory_tests/has_info.c
tools/ccanlint/compulsory_tests/has_main_header.c
tools/ccanlint/tests/build-coverage.c
tools/ccanlint/tests/compile_test_helpers.c
tools/ccanlint/tests/compile_tests.c
tools/ccanlint/tests/depends_accurate.c
tools/ccanlint/tests/examples_compile.c
tools/ccanlint/tests/examples_run.c
tools/ccanlint/tests/has_examples.c
tools/ccanlint/tests/has_info_documentation.c
tools/ccanlint/tests/has_tests.c
tools/ccanlint/tests/idempotent.c
tools/ccanlint/tests/license.c
tools/ccanlint/tests/run-coverage.c
tools/ccanlint/tests/run_tests.c
tools/ccanlint/tests/run_tests_valgrind.c
tools/ccanlint/tests/trailing_whitespace.c

index 5b45f4d2f2b2ca7294f7e2859d76cd7409e63b19..7515a7c6f7af15eebe184699c3e731a7ce37c555 100644 (file)
@@ -20,7 +20,6 @@
 #include "ccanlint.h"
 #include "../tools.h"
 #include <unistd.h>
-#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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);
index 41a4606c40fe260644ce24471a5eca66225ca686..19d53dbf12e4f5fb7bcd340e65087d10a452ebfb 100644 (file)
@@ -4,11 +4,6 @@
 #include <stdbool.h>
 #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;
index 557b708bf7144c2237caa0c44d93c9771cf8d04b..cf128f6a7c3587e6dbaf1103efa3f00cb49b2285 100644 (file)
@@ -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);
index 9393f62f11eb4507dc3ca76330e279a03fb136c8..7696b4641edf6fc649806a5af1e12c66b09d6d72 100644 (file)
@@ -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);
index 39f16c2e0e8fd15f2bd21e5c354014c68ed67ea4..db2e16d54a4f8cd89fdec478094ff0a279d3f592 100644 (file)
@@ -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);
index 41b9a8cae3ff19d28b106501a7fb46d0213aa7da..c4c649dd9e2fe44d168c656fe54349dc360c7922 100644 (file)
@@ -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);
index ffbf4539bf6f07ad31a3e8aaaf8390ceb8b2f9f0..12eaf021410153c5567ea1abd22a98afa5ba0b51 100644 (file)
@@ -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);
index 017194e6a890abab8d54457b649cc90d33c4820c..56930e3051b7f3a8c865d925611da6e18d497470 100644 (file)
@@ -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);
index 5b71efa4fc9fd9c1304098a5e134d51a3c513e29..b61ee0aefb79670bfa913f68a5311d18e5e65b05 100644 (file)
@@ -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);
index 338f7af789fece9a2b99f222002d0d777908288e..259aa347ccaff19122e243231697354c694c3a0f 100644 (file)
@@ -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);
index 927cd8b077dbaf813af63e5f7f696421096e0652..55eca373dc0ca44d63bd87c8cb3506c7d16fe29e 100644 (file)
@@ -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);
index 0169f6024f21b3e263d5423bd168d16c498b539c..aa62e37a5fbb0aef71204648506c5eaec6182af2 100644 (file)
@@ -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);
index e1e8f82061f4ae81661677e842c437acf1532374..c61a9e5a8aeee5a702ad171c7e81c81aa2e25952 100644 (file)
@@ -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);
index 85301772c8193d259ac97f42195b8408480d914e..a6d3a73a85dd94b6b4289f4c14dd1100b260f80b 100644 (file)
@@ -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);
index ff9e529b645a8d46b39f4c4a2e2c976221402905..a3ab73a967e0557f567a00f02d518aa26032bcff 100644 (file)
@@ -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);
index 7fe41654b443cdf28da5c7f6e910efc9d33e1d2e..077ea2487b431a1f365702f94b9ff4f78473df5d 100644 (file)
@@ -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);
index 1e4f65c3396cd825b5a619d2608b6b5bd6ce05d9..a1d54c480ffecdfcd80150df1bfff838ba39eb28 100644 (file)
@@ -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);
index a6aafc66e6c304a739ba287e6ff70b5c11bdafc0..b98177d8a783087fc8436a124b09744e45ff6276 100644 (file)
@@ -15,6 +15,8 @@
 #include <ccan/noerr/noerr.h>
 #include <ccan/grab_file/grab_file.h>
 
+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);
index 36adee60998a0c8477c415875620324e34603bd0..0e90d16ff737a717765727f27c7a8ddb68c6170e 100644 (file)
@@ -10,6 +10,8 @@
 #include <err.h>
 #include <ccan/talloc/talloc.h>
 
+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);
index 944fd24820d7160e4756c08ee19ec2db3a977fab..a5210e2fecf3235426474527a7127fe968bd3c92 100644 (file)
@@ -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);
index bc0ee45464a688dcc8a6738be4b62b0e7faf0ad8..1ffee9e25d6719b269e675db8a8eaf856f3d3dab 100644 (file)
@@ -11,6 +11,8 @@
 #include <ccan/talloc/talloc.h>
 #include <ccan/str/str.h>
 
+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);
index 1e34039834083df8c7aead5404fec0edcf702b8c..a3e83c1ca939fbc8454cadf9092dec32659c7e35 100644 (file)
@@ -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);
index 3821b36a761259ae2c480dba3fc193b99861c3e5..35790ece120a926f2f92c814d97e267921b29c86 100644 (file)
@@ -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);
index 6e18338d19f0c2edf3a119d4805f5fe02913f6ed..d3cdb9c78c5929be4fa53300bdcc71eaaa2457a9 100644 (file)
@@ -17,6 +17,8 @@
 #include <string.h>
 #include <ctype.h>
 
+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);
index 2a301ea8b1c077af8bb369e1d2c64cf893080a8d..2b430e8c308f2b1fa5aba609f7c731bbd505abd2 100644 (file)
@@ -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);