Don't run dependent tests if one fails.
[ccan] / tools / ccanlint / tests / check_depends.c
1 #include <tools/ccanlint/ccanlint.h>
2 #include <tools/tools.h>
3 #include <ccan/talloc/talloc.h>
4 #include <ccan/str/str.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <unistd.h>
9 #include <limits.h>
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <err.h>
14 #include <string.h>
15 #include <ctype.h>
16
17 static bool expect_obj_file(const char *dir)
18 {
19         char *olddir;
20         struct manifest *dep_man;
21         bool has_c_files;
22
23         olddir = talloc_getcwd(dir);
24         if (!olddir)
25                 err(1, "Getting current directory");
26
27         /* We will fail below if this doesn't exist. */
28         if (chdir(dir) != 0)
29                 return false;
30
31         dep_man = get_manifest(dir);
32         if (chdir(olddir) != 0)
33                 err(1, "Returning to original directory '%s'", olddir);
34         talloc_free(olddir);
35
36         /* If it has C files, we expect an object file built from them. */
37         has_c_files = !list_empty(&dep_man->c_files);
38         talloc_free(dep_man);
39         return has_c_files;
40 }
41
42 /* FIXME: recursive ccanlint if they ask for it. */
43 static char *add_dep(char *sofar, struct manifest *m, const char *dep)
44 {
45         char *file, *dir;
46         struct stat st;
47         bool need_obj;
48
49         dir = talloc_asprintf(m, "../%s", dep);
50         need_obj = expect_obj_file(dir);
51
52         if (need_obj) {
53                 file = talloc_asprintf(m, "../%s.o", dep);
54                 if (stat(file, &st) == 0) {
55                         struct ccan_file *f = new_ccan_file(m, file);
56                         list_add_tail(&m->dep_obj_files, &f->list);
57                         return sofar;
58                 }
59         }
60
61         if (stat(dir, &st) == 0) {
62                 if (!need_obj)
63                         return sofar;
64
65                 return talloc_asprintf_append(sofar,
66                                               "ccan/%s: isn't built (no %s)\n",
67                                               dep, file);
68         }
69
70         return talloc_asprintf_append(sofar,
71                                       "ccan/%s: could not find directory %s\n",
72                                       dep, dir);
73 }
74
75 static void *check_depends(struct manifest *m)
76 {
77         unsigned int i;
78         char *report = NULL;
79         char **deps;
80
81         if (safe_mode)
82                 deps = get_safe_ccan_deps(m, "..", m->basename, true);
83         else
84                 deps = get_deps(m, "..", m->basename, true);
85
86         for (i = 0; deps[i]; i++) {
87                 if (!strstarts(deps[i], "ccan/"))
88                         continue;
89
90                 report = add_dep(report, m, deps[i] + strlen("ccan/"));
91         }
92         return report;
93 }
94
95 static const char *describe_depends(struct manifest *m, void *check_result)
96 {
97         return talloc_asprintf(check_result, 
98                                "The following dependencies are needed:\n"
99                                "%s\n", (char *)check_result);
100 }
101
102 struct ccanlint depends = {
103         .name = "CCAN dependencies are built",
104         .total_score = 1,
105         .check = check_depends,
106         .describe = describe_depends,
107 };
108
109 REGISTER_TEST(depends, NULL);