From: Joseph Adams <joeyadams3.14159@gmail.com>
authorRusty Russell <rusty@rustcorp.com.au>
Fri, 9 Apr 2010 01:28:21 +0000 (10:58 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 9 Apr 2010 01:28:21 +0000 (10:58 +0930)
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.

19 files changed:
tools/ccanlint/Makefile
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/compile_test_helpers.c
tools/ccanlint/compulsory_tests/compile_tests.c
tools/ccanlint/compulsory_tests/has_info.c
tools/ccanlint/compulsory_tests/has_main_header.c
tools/ccanlint/compulsory_tests/has_tests.c
tools/ccanlint/compulsory_tests/run_tests.c
tools/ccanlint/tests/has_info_documentation.c
tools/ccanlint/tests/idempotent.c
tools/ccanlint/tests/run_tests_valgrind.c
tools/ccanlint/tests/trailing_whitespace.c

index 9efed3a5c7361e95dfc0cf7d2c5217bf970a72aa..5398d380d0c9a4626dcffa14718a3d9f93940db6 100644 (file)
@@ -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
 
index 330866d15f1f9365ba336893bb7e36382ccb55fa..85f68a3d21a540c939dbe250831cbe717cef7a22 100644 (file)
@@ -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]);
                }
index 876fc64c5484040afe0959492cdb028bd036dd55..cf277393d8c05db444c1733bfd5add2a728d4d4f 100644 (file)
@@ -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;
 
index d2b22ac5ef51726cc2c06c14d97b19239d1e6e5e..8b530131eb05b91711f81fd4c0060661a91b92b2 100644 (file)
@@ -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,
index 4c0b6bba8dd97487c3070d22c00944a540f6f65c..0768bc6fb70ec685b93e07430e076e582b6648b2 100644 (file)
@@ -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,
index 21189645280d4d2b5d6da1c8eaa9ed01218120d1..a0b596693c492824cade2404ba0f0ed1b6693249 100644 (file)
@@ -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,
index d902a98525c30c7641f6d26ad33be165fbabee25..854f4bc8fe40443cc86bed5b30f3519281218ab9 100644 (file)
@@ -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,
index 656901e74c65054eec3c3ffae255ff0a0e564393..28f581c5758e01b3aa335e3744757996d1f659a8 100644 (file)
@@ -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,
index b61d0baa8b8049c4d057e749d65e742e99caa41b..72df8ca8d2c5e54c07a0cbfa0a11e78cbf47c7bf 100644 (file)
@@ -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,
index fc88b1b0e7bca75b429256d59773354b5831b92f..5c7a9ec6d271428529d447b2be6b7ab42e21cba4 100644 (file)
@@ -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,
index 6444fc17f02b2c017b5a7bf9b2134be58235fe4b..a614adb3ea5df1cff665d554ed35260edf42f1ac 100644 (file)
@@ -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,
index 974967bfa2377361a6b984ed9d50c739c996dc8e..a5c825265b3266bf9f6b00edc624345d255dd97f 100644 (file)
@@ -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,
index 071c7157ba54b29fa7c822f0d5a31ab5fc8e048f..b404aef80d1d40b94346ee5b018a06823838fbde 100644 (file)
@@ -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,
index 46998d58cb0bb40148f050aa0c64c0bc6413e7f3..930b412970353a05042623f65c91e263e37b003c 100644 (file)
@@ -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,
index 16a07aee1cca555647bd2e0731ecee11f31c5eb2..2fd87a8c5c4978204926440aa4f6ef02c27cbdbf 100644 (file)
@@ -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,
index 17e4207eeaff856c3cf20b999bc5de02d212320d..aed229340dea38fe4555d8132396515167053d9f 100644 (file)
@@ -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,
index e9d7cf56a3533f5d892f12a48f4d226147ba2e0c..6ed1767606239d7e4f8dde94c7211a52ba44ee65 100644 (file)
@@ -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,
index 2191f80e3dcfc2ecd2d118fe4c3df6ab26a9b85a..6312a0a864327988c53b39f080eb0b6daedcaecc 100644 (file)
@@ -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,
index e5d2102ec295c389db2a6627de5a7ce762c3c9de..f5bf5b9fec7f2be5929c25d085926d6b174fd585 100644 (file)
@@ -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,