#include "ccanlint.h"
#include "../tools.h"
#include <unistd.h>
-#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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);
}
/**
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);
#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.
/* 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;
.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);
.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);
.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);
.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);
.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);
.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);
.name = "Module has _info file",
.check = check_has_info,
.handle = create_info_template,
+ .needs = ""
};
-REGISTER_TEST(has_info, NULL);
+REGISTER_TEST(has_info);
.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);
.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);
.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);
.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);
.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);
.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);
.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);
.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);
#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);
.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);
#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;
.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);
.name = "Module headers are #ifndef/#define wrapped",
.check = check_idempotent,
.handle = handle_idem,
+ .needs = ""
};
-REGISTER_TEST(idempotent, NULL);
+REGISTER_TEST(idempotent);
#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;
.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);
.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);
.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);
#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)
{
.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);
.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);