Commit f952b88b authored by Rusty Russell's avatar Rusty Russell

From: Joseph Adams <joeyadams3.14159@gmail.com>

The ccanlint patch is rather intrusive.  First, it adds a new field to
all the ccanlint tests, "key".  key is a shorter, still unique
description of the test (e.g. "valgrind").  The names I chose as keys
for all the tests are somewhat arbitrary and often don't reflect the
name of the .c source file (because some of those names are just too
darn long).  Second, it adds two new options to ccanlint:

   -l: list tests ccanlint performs
   -x: exclude tests (e.g. -x trailing_whitespace,valgrind)

It also adds a consistency check making sure all tests have unique
keys and names.

The primary goal of the ccanlint patch was so I could exclude the
valgrind test, which takes a really long time for some modules (I
think btree takes the longest, at around 2 minutes).  I'm not sure I
did it 100% correctly, so you'll want to review it first.
parent 7b877620
......@@ -9,6 +9,7 @@ CORE_OBJS := tools/ccanlint/ccanlint.o \
tools/tools.o \
tools/compile.o \
ccan/str_talloc/str_talloc.o ccan/grab_file/grab_file.o \
ccan/btree/btree.o \
ccan/talloc/talloc.o ccan/noerr/noerr.o \
ccan/read_write_all/read_write_all.o
......
......@@ -26,6 +26,9 @@
#include <string.h>
#include <err.h>
#include <ctype.h>
#include <ccan/btree/btree.h>
#include <ccan/str/str.h>
#include <ccan/str_talloc/str_talloc.h>
#include <ccan/talloc/talloc.h>
static unsigned int verbose = 0;
......@@ -33,6 +36,7 @@ static LIST_HEAD(compulsory_tests);
static LIST_HEAD(normal_tests);
static LIST_HEAD(finished_tests);
bool safe_mode = false;
static struct btree *exclude;
static void usage(const char *name)
{
......@@ -40,7 +44,9 @@ static void usage(const char *name)
" -v: verbose mode\n"
" -s: simply give one line summary\n"
" -d: use this directory instead of the current one\n"
" -n: do not compile anything\n",
" -n: do not compile anything\n"
" -l: list tests ccanlint performs\n"
" -x: exclude tests (e.g. -x trailing_whitespace,valgrind)\n",
name);
exit(1);
}
......@@ -73,6 +79,9 @@ bool ask(const char *question)
static const char *should_skip(struct manifest *m, struct ccanlint *i)
{
if (btree_lookup(exclude, i->key))
return "excluded on command line";
if (i->skip_fail)
return "dependency failed";
......@@ -212,6 +221,7 @@ static inline struct ccanlint *get_next_test(struct list_head *test)
static void init_tests(void)
{
const struct ccanlint *i;
struct btree *keys, *names;
#undef REGISTER_TEST
#define REGISTER_TEST(name, ...) register_test(&normal_tests, &name, __VA_ARGS__)
......@@ -220,6 +230,25 @@ static void init_tests(void)
#define REGISTER_TEST(name, ...) register_test(&compulsory_tests, &name, __VA_ARGS__)
#include "generated-compulsory-tests"
/* 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);
}
btree_delete(keys);
btree_delete(names);
if (!verbose)
return;
......@@ -246,6 +275,37 @@ static void init_tests(void)
}
}
static void print_test(const struct ccanlint *i)
{
int space = 25 - strlen(i->key);
if (space >= 2) {
printf(" %s", i->key);
while (space--)
putchar(' ');
} else {
printf(" %s ", i->key);
}
printf("%s\n", i->name);
}
static void list_tests(void)
{
const struct ccanlint *i;
init_tests();
printf("Compulsory tests:\n");
list_for_each(&compulsory_tests, i, list)
print_test(i);
printf("Normal tests:\n");
list_for_each(&normal_tests, i, list)
print_test(i);
exit(0);
}
int main(int argc, char *argv[])
{
int c;
......@@ -254,10 +314,12 @@ int main(int argc, char *argv[])
struct manifest *m;
struct ccanlint *i;
const char *prefix = "", *dir = ".";
exclude = btree_new(btree_strcmp);
/* I'd love to use long options, but that's not standard. */
/* FIXME: getopt_long ccan package? */
while ((c = getopt(argc, argv, "sd:vn")) != -1) {
while ((c = getopt(argc, argv, "sd:vnlx:")) != -1) {
switch (c) {
case 'd':
dir = optarg;
......@@ -265,6 +327,8 @@ int main(int argc, char *argv[])
optarg),
": ");
break;
case 'l':
list_tests();
case 's':
summary = true;
break;
......@@ -274,6 +338,12 @@ int main(int argc, char *argv[])
case 'n':
safe_mode = true;
break;
case 'x': {
char **exclude_strs = strsplit(NULL, optarg, ",", NULL);
size_t i;
for (i = 0; exclude_strs[i]; i++)
btree_insert(exclude, exclude_strs[i]);
} break;
default:
usage(argv[0]);
}
......
......@@ -40,6 +40,9 @@ struct manifest *get_manifest(const void *ctx, const char *dir);
struct ccanlint {
struct list_node list;
/* More concise unique name of test. */
const char *key;
/* Unique name of test */
const char *name;
......
......@@ -62,6 +62,7 @@ static const char *describe_build(struct manifest *m, void *check_result)
}
struct ccanlint build = {
.key = "build",
.name = "Module can be built",
.total_score = 1,
.check = do_build,
......
......@@ -50,6 +50,7 @@ static const char *describe_objs_build(struct manifest *m, void *check_result)
}
struct ccanlint build_objs = {
.key = "build-objs",
.name = "Module object files can be built",
.check = check_objs_build,
.describe = describe_objs_build,
......
......@@ -84,6 +84,7 @@ static const char *describe_use_build(struct manifest *m, void *check_result)
}
struct ccanlint check_build = {
.key = "check-build",
.name = "Module can be used",
.total_score = 1,
.check = check_use_build,
......
......@@ -83,6 +83,7 @@ static const char *describe_depends_built(struct manifest *m,
}
struct ccanlint depends_built = {
.key = "depends-built",
.name = "CCAN dependencies are built",
.total_score = 1,
.check = check_depends_built,
......
......@@ -66,6 +66,7 @@ static const char *describe_depends_exist(struct manifest *m,
}
struct ccanlint depends_exist = {
.key = "depends-exist",
.name = "CCAN dependencies are present",
.total_score = 1,
.check = check_depends_exist,
......
......@@ -57,6 +57,7 @@ static const char *describe_includes_build(struct manifest *m,
}
struct ccanlint includes_build = {
.key = "include-main",
.name = "Can compile against main header",
.total_score = 1,
.check = check_includes_build,
......
......@@ -56,6 +56,7 @@ static const char *describe_compile_test_helpers(struct manifest *m,
}
struct ccanlint compile_test_helpers = {
.key = "compile-helpers",
.name = "Compiling test helper files",
.total_score = 1,
.check = do_compile_test_helpers,
......
......@@ -182,6 +182,7 @@ static const char *describe_compile_tests(struct manifest *m,
}
struct ccanlint compile_tests = {
.key = "compile",
.name = "Compile tests succeed",
.score = score_compile_tests,
.check = do_compile_tests,
......
......@@ -71,6 +71,7 @@ static void create_info_template(struct manifest *m, void *check_result)
}
struct ccanlint has_info = {
.key = "info",
.name = "Has _info file",
.check = check_has_info,
.describe = describe_has_info,
......
......@@ -35,6 +35,7 @@ static const char *describe_has_main_header(struct manifest *m,
}
struct ccanlint has_main_header = {
.key = "has-main-header",
.name = "No main header file",
.check = check_has_main_header,
.describe = describe_has_main_header,
......
......@@ -124,6 +124,7 @@ static void handle_no_tests(struct manifest *m, void *check_result)
}
struct ccanlint has_tests = {
.key = "has-tests",
.name = "Has tests",
.check = check_has_tests,
.describe = describe_has_tests,
......
......@@ -124,6 +124,7 @@ static void run_under_debugger(struct manifest *m, void *check_result)
}
struct ccanlint run_tests = {
.key = "run",
.name = "run and api tests run successfully",
.score = score_run_tests,
.check = do_run_tests,
......
......@@ -123,6 +123,7 @@ static unsigned int has_info_documentation_score(struct manifest *m,
}
struct ccanlint has_info_documentation = {
.key = "info-documentation",
.name = "Documentation in _info file",
.total_score = 3,
.score = has_info_documentation_score,
......
......@@ -132,6 +132,7 @@ static const char *describe_idempotent(struct manifest *m, void *check_result)
}
struct ccanlint idempotent = {
.key = "idempotent",
.name = "Headers are #ifndef/#define idempotent wrapped",
.total_score = 1,
.check = check_idempotent,
......
......@@ -127,6 +127,7 @@ static void run_under_debugger_vg(struct manifest *m, void *check_result)
}
struct ccanlint run_tests_vg = {
.key = "valgrind",
.name = "run and api tests under valgrind",
.score = score_run_tests_vg,
.check = do_run_tests_vg,
......
......@@ -40,6 +40,7 @@ static const char *describe_trailing_whitespace(struct manifest *m,
}
struct ccanlint trailing_whitespace = {
.key = "trailing-whitespace",
.name = "No lines with unnecessary trailing whitespace",
.total_score = 1,
.check = check_trailing_whitespace,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment