Browse Source

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.
Rusty Russell 15 years ago
parent
commit
016a19d260

+ 71 - 68
tools/ccanlint/ccanlint.c

@@ -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);

+ 3 - 5
tools/ccanlint/ccanlint.h

@@ -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;

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 4 - 1
tools/ccanlint/tests/has_info_documentation.c

@@ -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);

+ 4 - 1
tools/ccanlint/tests/has_tests.c

@@ -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);

+ 2 - 1
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);

+ 4 - 1
tools/ccanlint/tests/license.c

@@ -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);

+ 2 - 1
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);

+ 2 - 1
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);

+ 7 - 3
tools/ccanlint/tests/run_tests_valgrind.c

@@ -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);

+ 2 - 1
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);